Fix regression introduced in 98a05681851db9d88b1364af52be543715fbe306
[qt-netbsd.git] / qmake / option.cpp
blobc503b08f8a932acca7ac7266d62aafdfe95397ba
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 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 QString project_builtin_regx();
140 bool usage(const char *a0)
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)" : ""
197 return false;
201 Option::parseCommandLine(int argc, char **argv, int skip)
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;
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;
227 if(specified)
228 continue;
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;
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;
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;
332 if(!handled) {
333 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
339 return Option::QMAKE_CMDLINE_SUCCESS;
342 #ifdef Q_OS_WIN
343 static QStringList detectShellPath()
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);
354 return paths;
356 #endif
359 Option::init(int argc, char **argv)
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 = ' ';
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;
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;
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++;
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;
457 if(!env_argv[env_argc]) {
458 currlen = 0;
459 env_argv[env_argc] = (char*)malloc(255);
461 if(currlen < 255)
462 env_argv[env_argc][currlen++] = envflags.at(i);
465 if(env_argv) {
466 if(env_argv[env_argc]) {
467 env_argv[env_argc][currlen] = '\0';
468 currlen = 0;
469 env_argc++;
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]);
476 free(env_argv);
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;
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());
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]);
506 #ifndef QT_BUILD_QMAKE_LIBRARY
507 if(Option::mkfile::project_files.isEmpty()) {
508 usage(argv[0]);
509 return Option::QMAKE_CMDLINE_ERROR;
511 #endif
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";
527 Option::qmake_abslocation = Option::fixPathToTargetOS(Option::qmake_abslocation);
528 return QMAKE_CMDLINE_SUCCESS;
531 bool Option::postProcessProject(QMakeProject *project)
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
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;
584 QString
585 Option::fixString(QString string, uchar flags)
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);
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;
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()));
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);
618 if(string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':'))
619 string[0] = string[0].toLower();
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);
633 if (string.startsWith("\"") && string.endsWith("\"") ||
634 string.startsWith("\'") && string.endsWith("\'"))
635 string = string.mid(1, string.length()-2);
637 //cache
638 //qDebug() << "Fix" << orig_string << "->" << string;
639 cache->insert(cacheKey, string);
640 return string;
643 const char *qmake_version()
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;
658 void debug_msg_internal(int level, const char *fmt, ...)
660 if(Option::debug_level < level)
661 return;
662 fprintf(stderr, "DEBUG %d: ", level);
664 va_list ap;
665 va_start(ap, fmt);
666 vfprintf(stderr, fmt, ap);
667 va_end(ap);
669 fprintf(stderr, "\n");
672 void warn_msg(QMakeWarn type, const char *fmt, ...)
674 if(!(Option::warn_level & type))
675 return;
676 fprintf(stderr, "WARNING: ");
678 va_list ap;
679 va_start(ap, fmt);
680 vfprintf(stderr, fmt, ap);
681 va_end(ap);
683 fprintf(stderr, "\n");
686 class QMakeCacheClearItem {
687 private:
688 qmakeCacheClearFunc func;
689 void **data;
690 public:
691 QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
692 ~QMakeCacheClearItem() {
693 (*func)(*data);
694 *data = 0;
697 static QList<QMakeCacheClearItem*> cache_items;
699 void
700 qmakeClearCaches()
702 qDeleteAll(cache_items);
703 cache_items.clear();
706 void
707 qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
709 cache_items.append(new QMakeCacheClearItem(func, data));
712 #ifdef Q_OS_WIN
713 # include <windows.h>
715 QT_USE_NAMESPACE
716 #endif
718 QString qmake_libraryInfoFile()
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;
730 if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
732 If argv0 starts with a slash, it is already an absolute
733 file path.
735 absPath = argv0;
736 } else if (argv0.contains(QLatin1Char('/'))) {
738 If argv0 contains one or more slashes, it is a file path
739 relative to the current directory.
741 absPath = QDir::current().absoluteFilePath(argv0);
742 } else {
744 Otherwise, the file path has to be determined using the
745 PATH environment variable.
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;
762 absPath = QDir::cleanPath(absPath);
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;
772 QT_END_NAMESPACE