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