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