source: branches/vendor/nokia/qt/4.6.3/qmake/option.cpp@ 768

Last change on this file since 768 was 767, checked in by Dmitry A. Kuminov, 15 years ago

vendor: Merged in qt-everywhere-opensource-src-4.6.3 from Nokia.

File size: 28.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the qmake application of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "option.h"
43#include "cachekeys.h"
44#include <qdir.h>
45#include <qregexp.h>
46#include <qhash.h>
47#include <qdebug.h>
48#include <qsettings.h>
49#include <stdlib.h>
50#include <stdarg.h>
51
52QT_BEGIN_NAMESPACE
53
54//convenience
55const char *Option::application_argv0 = 0;
56QString Option::prf_ext;
57QString Option::js_ext;
58QString Option::prl_ext;
59QString Option::libtool_ext;
60QString Option::pkgcfg_ext;
61QString Option::ui_ext;
62QStringList Option::h_ext;
63QString Option::cpp_moc_ext;
64QString Option::h_moc_ext;
65QStringList Option::cpp_ext;
66QStringList Option::c_ext;
67QString Option::obj_ext;
68QString Option::lex_ext;
69QString Option::yacc_ext;
70QString Option::pro_ext;
71QString Option::mmp_ext;
72QString Option::dir_sep;
73QString Option::dirlist_sep;
74QString Option::h_moc_mod;
75QString Option::cpp_moc_mod;
76QString Option::yacc_mod;
77QString Option::lex_mod;
78QString Option::sysenv_mod;
79QString Option::res_ext;
80char Option::field_sep;
81
82//mode
83Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
84
85//all modes
86QString Option::qmake_abslocation;
87int Option::warn_level = WarnLogic;
88int Option::debug_level = 0;
89QFile Option::output;
90QString Option::output_dir;
91bool Option::recursive = false;
92QStringList Option::before_user_vars;
93QStringList Option::after_user_vars;
94QStringList Option::user_configs;
95QStringList Option::after_user_configs;
96QString Option::user_template;
97QString Option::user_template_prefix;
98QStringList Option::shellPath;
99#if defined(Q_OS_WIN32)
100Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE;
101#elif defined(Q_OS_MAC)
102Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE;
103#else
104Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE;
105#endif
106
107//QMAKE_*_PROPERTY stuff
108QStringList Option::prop::properties;
109
110//QMAKE_GENERATE_PROJECT stuff
111bool Option::projfile::do_pwd = true;
112QStringList Option::projfile::project_dirs;
113
114//QMAKE_GENERATE_MAKEFILE stuff
115QString Option::mkfile::qmakespec;
116int Option::mkfile::cachefile_depth = -1;
117bool Option::mkfile::do_deps = true;
118bool Option::mkfile::do_mocs = true;
119bool Option::mkfile::do_dep_heuristics = true;
120bool Option::mkfile::do_preprocess = false;
121bool Option::mkfile::do_stub_makefile = false;
122bool Option::mkfile::do_cache = true;
123QString Option::mkfile::cachefile;
124QStringList Option::mkfile::project_files;
125QString Option::mkfile::qmakespec_commandline;
126
127static Option::QMAKE_MODE default_mode(QString progname)
128{
129 int s = progname.lastIndexOf(Option::dir_sep);
130 if(s != -1)
131 progname = progname.right(progname.length() - (s + 1));
132 if(progname == "qmakegen")
133 return Option::QMAKE_GENERATE_PROJECT;
134 else if(progname == "qt-config")
135 return Option::QMAKE_QUERY_PROPERTY;
136 return Option::QMAKE_GENERATE_MAKEFILE;
137}
138
139QString project_builtin_regx();
140bool usage(const char *a0)
141{
142 fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
143 "\n"
144 "QMake has two modes, one mode for generating project files based on\n"
145 "some heuristics, and the other for generating makefiles. Normally you\n"
146 "shouldn't need to specify a mode, as makefile generation is the default\n"
147 "mode for qmake, but you may use this to test qmake on an existing project\n"
148 "\n"
149 "Mode:\n"
150 " -project Put qmake into project file generation mode%s\n"
151 " In this mode qmake interprets files as files to\n"
152 " be built,\n"
153 " defaults to %s\n"
154 " Note: The created .pro file probably will \n"
155 " need to be edited. For example add the QT variable to \n"
156 " specify what modules are required.\n"
157 " -makefile Put qmake into makefile generation mode%s\n"
158 " In this mode qmake interprets files as project files to\n"
159 " be processed, if skipped qmake will try to find a project\n"
160 " file in your current working directory\n"
161 "\n"
162 "Warnings Options:\n"
163 " -Wnone Turn off all warnings\n"
164 " -Wall Turn on all warnings\n"
165 " -Wparser Turn on parser warnings\n"
166 " -Wlogic Turn on logic warnings\n"
167 "\n"
168 "Options:\n"
169 " * You can place any variable assignment in options and it will be *\n"
170 " * processed as if it was in [files]. These assignments will be parsed *\n"
171 " * before [files]. *\n"
172 " -o file Write output to file\n"
173 " -unix Run in unix mode\n"
174 " -win32 Run in win32 mode\n"
175 " -macx Run in Mac OS X mode\n"
176 " -d Increase debug level\n"
177 " -t templ Overrides TEMPLATE as templ\n"
178 " -tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n"
179 " -help This help\n"
180 " -v Version information\n"
181 " -after All variable assignments after this will be\n"
182 " parsed after [files]\n"
183 " -norecursive Don't do a recursive search\n"
184 " -recursive Do a recursive search\n"
185 " -set <prop> <value> Set persistent property\n"
186 " -query <prop> Query persistent property. Show all if <prop> is empty.\n"
187 " -cache file Use file as cache [makefile mode only]\n"
188 " -spec spec Use spec as QMAKESPEC [makefile mode only]\n"
189 " -nocache Don't use a cache file [makefile mode only]\n"
190 " -nodepend Don't generate dependencies [makefile mode only]\n"
191 " -nomoc Don't generate moc targets [makefile mode only]\n"
192 " -nopwd Don't look for files in pwd [project mode only]\n"
193 ,a0,
194 default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "", project_builtin_regx().toLatin1().constData(),
195 default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : ""
196 );
197 return false;
198}
199
200int
201Option::parseCommandLine(int argc, char **argv, int skip)
202{
203 bool before = true;
204 for(int x = skip; x < argc; x++) {
205 if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */
206 QString opt = argv[x] + 1;
207
208 //first param is a mode, or we default
209 if(x == 1) {
210 bool specified = true;
211 if(opt == "project") {
212 Option::recursive = true;
213 Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
214 } else if(opt == "prl") {
215 Option::mkfile::do_deps = false;
216 Option::mkfile::do_mocs = false;
217 Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
218 } else if(opt == "set") {
219 Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
220 } else if(opt == "query") {
221 Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
222 } else if(opt == "makefile") {
223 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
224 } else {
225 specified = false;
226 }
227 if(specified)
228 continue;
229 }
230 //all modes
231 if(opt == "o" || opt == "output") {
232 Option::output.setFileName(argv[++x]);
233 } else if(opt == "after") {
234 before = false;
235 } else if(opt == "t" || opt == "template") {
236 Option::user_template = argv[++x];
237 } else if(opt == "tp" || opt == "template_prefix") {
238 Option::user_template_prefix = argv[++x];
239 } else if(opt == "mac9") {
240 Option::target_mode = TARG_MAC9_MODE;
241 } else if(opt == "macx") {
242 Option::target_mode = TARG_MACX_MODE;
243 } else if(opt == "unix") {
244 Option::target_mode = TARG_UNIX_MODE;
245 } else if(opt == "win32") {
246 Option::target_mode = TARG_WIN_MODE;
247 } else if(opt == "d") {
248 Option::debug_level++;
249 } else if(opt == "version" || opt == "v" || opt == "-version") {
250 fprintf(stdout,
251 "QMake version %s\n"
252 "Using Qt version %s in %s\n",
253 qmake_version(), QT_VERSION_STR,
254 QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData());
255#ifdef QMAKE_OPENSOURCE_VERSION
256 fprintf(stdout, "QMake is Open Source software from Nokia Corporation and/or its subsidiary(-ies).\n");
257#endif
258 return Option::QMAKE_CMDLINE_BAIL;
259 } else if(opt == "h" || opt == "help") {
260 return Option::QMAKE_CMDLINE_SHOW_USAGE;
261 } else if(opt == "Wall") {
262 Option::warn_level |= WarnAll;
263 } else if(opt == "Wparser") {
264 Option::warn_level |= WarnParser;
265 } else if(opt == "Wlogic") {
266 Option::warn_level |= WarnLogic;
267 } else if(opt == "Wnone") {
268 Option::warn_level = WarnNone;
269 } else if(opt == "r" || opt == "recursive") {
270 Option::recursive = true;
271 } else if(opt == "norecursive") {
272 Option::recursive = false;
273 } else if(opt == "config") {
274 Option::user_configs += argv[++x];
275 } else {
276 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
277 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
278 if(opt == "nodepend" || opt == "nodepends") {
279 Option::mkfile::do_deps = false;
280 } else if(opt == "nomoc") {
281 Option::mkfile::do_mocs = false;
282 } else if(opt == "nocache") {
283 Option::mkfile::do_cache = false;
284 } else if(opt == "createstub") {
285 Option::mkfile::do_stub_makefile = true;
286 } else if(opt == "nodependheuristics") {
287 Option::mkfile::do_dep_heuristics = false;
288 } else if(opt == "E") {
289 Option::mkfile::do_preprocess = true;
290 } else if(opt == "cache") {
291 Option::mkfile::cachefile = argv[++x];
292 } else if(opt == "platform" || opt == "spec") {
293 Option::mkfile::qmakespec = argv[++x];
294 Option::mkfile::qmakespec_commandline = argv[x];
295 } else {
296 fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
297 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
298 }
299 } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
300 if(opt == "nopwd") {
301 Option::projfile::do_pwd = false;
302 } else {
303 fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
304 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
305 }
306 }
307 }
308 } else {
309 QString arg = argv[x];
310 if(arg.indexOf('=') != -1) {
311 if(before)
312 Option::before_user_vars.append(arg);
313 else
314 Option::after_user_vars.append(arg);
315 } else {
316 bool handled = true;
317 if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
318 Option::qmake_mode == Option::QMAKE_SET_PROPERTY) {
319 Option::prop::properties.append(arg);
320 } else {
321 QFileInfo fi(arg);
322 if(!fi.makeAbsolute()) //strange
323 arg = fi.filePath();
324 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
325 Option::qmake_mode == Option::QMAKE_GENERATE_PRL)
326 Option::mkfile::project_files.append(arg);
327 else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
328 Option::projfile::project_dirs.append(arg);
329 else
330 handled = false;
331 }
332 if(!handled) {
333 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
334 }
335 }
336 }
337 }
338
339 return Option::QMAKE_CMDLINE_SUCCESS;
340}
341
342#ifdef Q_OS_WIN
343static QStringList detectShellPath()
344{
345 QStringList paths;
346 QString path = qgetenv("PATH");
347 QStringList pathlist = path.toLower().split(";");
348 for (int i = 0; i < pathlist.count(); i++) {
349 QString maybeSh = pathlist.at(i) + "/sh.exe";
350 if (QFile::exists(maybeSh)) {
351 paths.append(maybeSh);
352 }
353 }
354 return paths;
355}
356#endif
357
358int
359Option::init(int argc, char **argv)
360{
361 Option::application_argv0 = 0;
362 Option::cpp_moc_mod = "";
363 Option::h_moc_mod = "moc_";
364 Option::lex_mod = "_lex";
365 Option::yacc_mod = "_yacc";
366 Option::prl_ext = ".prl";
367 Option::libtool_ext = ".la";
368 Option::pkgcfg_ext = ".pc";
369 Option::prf_ext = ".prf";
370 Option::js_ext = ".js";
371 Option::ui_ext = ".ui";
372 Option::h_ext << ".h" << ".hpp" << ".hh" << ".hxx";
373 Option::c_ext << ".c";
374#ifndef Q_OS_WIN
375 Option::h_ext << ".H";
376#endif
377 Option::cpp_moc_ext = ".moc";
378 Option::h_moc_ext = ".cpp";
379 Option::cpp_ext << ".cpp" << ".cc" << ".cxx";
380#ifndef Q_OS_WIN
381 Option::cpp_ext << ".C";
382#endif
383 Option::lex_ext = ".l";
384 Option::yacc_ext = ".y";
385 Option::pro_ext = ".pro";
386 Option::mmp_ext = ".mmp";
387#ifdef Q_OS_WIN
388 Option::dirlist_sep = ";";
389 Option::shellPath = detectShellPath();
390#else
391 Option::dirlist_sep = ":";
392#endif
393 Option::sysenv_mod = "QMAKE_ENV_";
394 Option::field_sep = ' ';
395
396 if(argc && argv) {
397 Option::application_argv0 = argv[0];
398 QString argv0 = argv[0];
399 if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
400 Option::qmake_mode = default_mode(argv0);
401 if(!argv0.isEmpty() && !QFileInfo(argv0).isRelative()) {
402 Option::qmake_abslocation = argv0;
403 } else if (argv0.contains(QLatin1Char('/'))
404#ifdef Q_OS_WIN
405 || argv0.contains(QLatin1Char('\\'))
406#endif
407 ) { //relative PWD
408 Option::qmake_abslocation = QDir::current().absoluteFilePath(argv0);
409 } else { //in the PATH
410 QByteArray pEnv = qgetenv("PATH");
411 QDir currentDir = QDir::current();
412#ifdef Q_OS_WIN
413 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";"));
414#else
415 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":"));
416#endif
417 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
418 if ((*p).isEmpty())
419 continue;
420 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
421#ifdef Q_OS_WIN
422 candidate += ".exe";
423#endif
424 if (QFile::exists(candidate)) {
425 Option::qmake_abslocation = candidate;
426 break;
427 }
428 }
429 }
430 if(!Option::qmake_abslocation.isNull())
431 Option::qmake_abslocation = QDir::cleanPath(Option::qmake_abslocation);
432 } else {
433 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
434 }
435
436 const QByteArray envflags = qgetenv("QMAKEFLAGS");
437 if (!envflags.isNull()) {
438 int env_argc = 0, env_size = 0, currlen=0;
439 char quote = 0, **env_argv = NULL;
440 for (int i = 0; i < envflags.size(); ++i) {
441 if (!quote && (envflags.at(i) == '\'' || envflags.at(i) == '"')) {
442 quote = envflags.at(i);
443 } else if (envflags.at(i) == quote) {
444 quote = 0;
445 } else if (!quote && envflags.at(i) == ' ') {
446 if (currlen && env_argv && env_argv[env_argc]) {
447 env_argv[env_argc][currlen] = '\0';
448 currlen = 0;
449 env_argc++;
450 }
451 } else {
452 if(!env_argv || env_argc > env_size) {
453 env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10));
454 for(int i2 = env_argc; i2 < env_size; i2++)
455 env_argv[i2] = NULL;
456 }
457 if(!env_argv[env_argc]) {
458 currlen = 0;
459 env_argv[env_argc] = (char*)malloc(255);
460 }
461 if(currlen < 255)
462 env_argv[env_argc][currlen++] = envflags.at(i);
463 }
464 }
465 if(env_argv) {
466 if(env_argv[env_argc]) {
467 env_argv[env_argc][currlen] = '\0';
468 currlen = 0;
469 env_argc++;
470 }
471 parseCommandLine(env_argc, env_argv);
472 for(int i2 = 0; i2 < env_size; i2++) {
473 if(env_argv[i2])
474 free(env_argv[i2]);
475 }
476 free(env_argv);
477 }
478 }
479 if(argc && argv) {
480 int ret = parseCommandLine(argc, argv, 1);
481 if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
482 if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0)
483 usage(argv[0]);
484 return ret;
485 //return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false;
486 }
487 }
488
489 //last chance for defaults
490 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
491 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
492 if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty())
493 Option::mkfile::qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").constData());
494
495 //try REALLY hard to do it for them, lazy..
496 if(Option::mkfile::project_files.isEmpty()) {
497 QString pwd = qmake_getpwd(),
498 proj = pwd + "/" + pwd.right(pwd.length() - (pwd.lastIndexOf('/') + 1)) + Option::pro_ext;
499 if(QFile::exists(proj)) {
500 Option::mkfile::project_files.append(proj);
501 } else { //last try..
502 QStringList profiles = QDir(pwd).entryList(QStringList("*" + Option::pro_ext));
503 if(profiles.count() == 1)
504 Option::mkfile::project_files.append(pwd + "/" + profiles[0]);
505 }
506#ifndef QT_BUILD_QMAKE_LIBRARY
507 if(Option::mkfile::project_files.isEmpty()) {
508 usage(argv[0]);
509 return Option::QMAKE_CMDLINE_ERROR;
510 }
511#endif
512 }
513 }
514
515 //defaults for globals
516 if(Option::target_mode == Option::TARG_WIN_MODE) {
517 Option::dir_sep = "\\";
518 Option::obj_ext = ".obj";
519 Option::res_ext = ".res";
520 } else {
521 if(Option::target_mode == Option::TARG_MAC9_MODE)
522 Option::dir_sep = ":";
523 else
524 Option::dir_sep = "/";
525 Option::obj_ext = ".o";
526 }
527 Option::qmake_abslocation = Option::fixPathToTargetOS(Option::qmake_abslocation);
528 return QMAKE_CMDLINE_SUCCESS;
529}
530
531bool Option::postProcessProject(QMakeProject *project)
532{
533 Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"];
534 if(cpp_ext.isEmpty())
535 cpp_ext << ".cpp"; //something must be there
536 Option::h_ext = project->variables()["QMAKE_EXT_H"];
537 if(h_ext.isEmpty())
538 h_ext << ".h";
539 Option::c_ext = project->variables()["QMAKE_EXT_C"];
540 if(c_ext.isEmpty())
541 c_ext << ".c"; //something must be there
542
543 if(!project->isEmpty("QMAKE_EXT_RES"))
544 Option::res_ext = project->first("QMAKE_EXT_RES");
545 if(!project->isEmpty("QMAKE_EXT_PKGCONFIG"))
546 Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG");
547 if(!project->isEmpty("QMAKE_EXT_LIBTOOL"))
548 Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL");
549 if(!project->isEmpty("QMAKE_EXT_PRL"))
550 Option::prl_ext = project->first("QMAKE_EXT_PRL");
551 if(!project->isEmpty("QMAKE_EXT_PRF"))
552 Option::prf_ext = project->first("QMAKE_EXT_PRF");
553 if(!project->isEmpty("QMAKE_EXT_JS"))
554 Option::prf_ext = project->first("QMAKE_EXT_JS");
555 if(!project->isEmpty("QMAKE_EXT_UI"))
556 Option::ui_ext = project->first("QMAKE_EXT_UI");
557 if(!project->isEmpty("QMAKE_EXT_CPP_MOC"))
558 Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC");
559 if(!project->isEmpty("QMAKE_EXT_H_MOC"))
560 Option::h_moc_ext = project->first("QMAKE_EXT_H_MOC");
561 if(!project->isEmpty("QMAKE_EXT_LEX"))
562 Option::lex_ext = project->first("QMAKE_EXT_LEX");
563 if(!project->isEmpty("QMAKE_EXT_YACC"))
564 Option::yacc_ext = project->first("QMAKE_EXT_YACC");
565 if(!project->isEmpty("QMAKE_EXT_OBJ"))
566 Option::obj_ext = project->first("QMAKE_EXT_OBJ");
567 if(!project->isEmpty("QMAKE_H_MOD_MOC"))
568 Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC");
569 if(!project->isEmpty("QMAKE_CPP_MOD_MOC"))
570 Option::cpp_moc_mod = project->first("QMAKE_CPP_MOD_MOC");
571 if(!project->isEmpty("QMAKE_MOD_LEX"))
572 Option::lex_mod = project->first("QMAKE_MOD_LEX");
573 if(!project->isEmpty("QMAKE_MOD_YACC"))
574 Option::yacc_mod = project->first("QMAKE_MOD_YACC");
575 if(!project->isEmpty("QMAKE_DIR_SEP"))
576 Option::dir_sep = project->first("QMAKE_DIR_SEP");
577 if(!project->isEmpty("QMAKE_DIRLIST_SEP"))
578 Option::dirlist_sep = project->first("QMAKE_DIRLIST_SEP");
579 if(!project->isEmpty("QMAKE_MOD_SYSTEM_ENV"))
580 Option::sysenv_mod = project->first("QMAKE_MOD_SYSTEM_ENV");
581 return true;
582}
583
584QString
585Option::fixString(QString string, uchar flags)
586{
587 const QString orig_string = string;
588 static QHash<FixStringCacheKey, QString> *cache = 0;
589 if(!cache) {
590 cache = new QHash<FixStringCacheKey, QString>;
591 qmakeAddCacheClear(qmakeDeleteCacheClear_QHashFixStringCacheKeyQString, (void**)&cache);
592 }
593 FixStringCacheKey cacheKey(string, flags);
594 if(cache->contains(cacheKey)) {
595 const QString ret = cache->value(cacheKey);
596 //qDebug() << "Fix (cached) " << orig_string << "->" << ret;
597 return ret;
598 }
599
600 //fix the environment variables
601 if(flags & Option::FixEnvVars) {
602 int rep;
603 QRegExp reg_var("\\$\\(.*\\)");
604 reg_var.setMinimal(true);
605 while((rep = reg_var.indexIn(string)) != -1)
606 string.replace(rep, reg_var.matchedLength(),
607 QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
608 }
609
610 //canonicalize it (and treat as a path)
611 if(flags & Option::FixPathCanonicalize) {
612#if 0
613 string = QFileInfo(string).canonicalFilePath();
614#endif
615 string = QDir::cleanPath(string);
616 }
617
618 if(string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':'))
619 string[0] = string[0].toLower();
620
621 //fix separators
622 Q_ASSERT(!((flags & Option::FixPathToLocalSeparators) && (flags & Option::FixPathToTargetSeparators)));
623 if(flags & Option::FixPathToLocalSeparators) {
624#if defined(Q_OS_WIN32)
625 string = string.replace('/', '\\');
626#else
627 string = string.replace('\\', '/');
628#endif
629 } else if(flags & Option::FixPathToTargetSeparators) {
630 string = string.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
631 }
632
633 if ((string.startsWith("\"") && string.endsWith("\"")) ||
634 (string.startsWith("\'") && string.endsWith("\'")))
635 string = string.mid(1, string.length()-2);
636
637 //cache
638 //qDebug() << "Fix" << orig_string << "->" << string;
639 cache->insert(cacheKey, string);
640 return string;
641}
642
643const char *qmake_version()
644{
645 static char *ret = NULL;
646 if(ret)
647 return ret;
648 ret = (char *)malloc(15);
649 qmakeAddCacheClear(qmakeFreeCacheClear, (void**)&ret);
650#if defined(_MSC_VER) && _MSC_VER >= 1400
651 sprintf_s(ret, 15, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
652#else
653 sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
654#endif
655 return ret;
656}
657
658void debug_msg_internal(int level, const char *fmt, ...)
659{
660 if(Option::debug_level < level)
661 return;
662 fprintf(stderr, "DEBUG %d: ", level);
663 {
664 va_list ap;
665 va_start(ap, fmt);
666 vfprintf(stderr, fmt, ap);
667 va_end(ap);
668 }
669 fprintf(stderr, "\n");
670}
671
672void warn_msg(QMakeWarn type, const char *fmt, ...)
673{
674 if(!(Option::warn_level & type))
675 return;
676 fprintf(stderr, "WARNING: ");
677 {
678 va_list ap;
679 va_start(ap, fmt);
680 vfprintf(stderr, fmt, ap);
681 va_end(ap);
682 }
683 fprintf(stderr, "\n");
684}
685
686class QMakeCacheClearItem {
687private:
688 qmakeCacheClearFunc func;
689 void **data;
690public:
691 QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
692 ~QMakeCacheClearItem() {
693 (*func)(*data);
694 *data = 0;
695 }
696};
697static QList<QMakeCacheClearItem*> cache_items;
698
699void
700qmakeClearCaches()
701{
702 qDeleteAll(cache_items);
703 cache_items.clear();
704}
705
706void
707qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
708{
709 cache_items.append(new QMakeCacheClearItem(func, data));
710}
711
712#ifdef Q_OS_WIN
713# include <windows.h>
714
715QT_USE_NAMESPACE
716#endif
717
718QString qmake_libraryInfoFile()
719{
720 QString ret;
721#if defined( Q_OS_WIN )
722 wchar_t module_name[MAX_PATH];
723 GetModuleFileName(0, module_name, MAX_PATH);
724 QFileInfo filePath = QString::fromWCharArray(module_name);
725 ret = filePath.filePath();
726#else
727 QString argv0 = QFile::decodeName(QByteArray(Option::application_argv0));
728 QString absPath;
729
730 if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
731 /*
732 If argv0 starts with a slash, it is already an absolute
733 file path.
734 */
735 absPath = argv0;
736 } else if (argv0.contains(QLatin1Char('/'))) {
737 /*
738 If argv0 contains one or more slashes, it is a file path
739 relative to the current directory.
740 */
741 absPath = QDir::current().absoluteFilePath(argv0);
742 } else {
743 /*
744 Otherwise, the file path has to be determined using the
745 PATH environment variable.
746 */
747 QByteArray pEnv = qgetenv("PATH");
748 QDir currentDir = QDir::current();
749 QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1String(":"));
750 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
751 if ((*p).isEmpty())
752 continue;
753 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
754 QFileInfo candidate_fi(candidate);
755 if (candidate_fi.exists() && !candidate_fi.isDir()) {
756 absPath = candidate;
757 break;
758 }
759 }
760 }
761
762 absPath = QDir::cleanPath(absPath);
763
764 QFileInfo fi(absPath);
765 ret = fi.exists() ? fi.canonicalFilePath() : QString();
766#endif
767 if(!ret.isEmpty())
768 ret = QDir(QFileInfo(ret).absolutePath()).filePath("qt.conf");
769 return ret;
770}
771
772QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.