source: trunk/qmake/option.cpp@ 670

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

trunk: Merged in qt 4.6.2 sources.

File size: 30.4 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_OS2)
102Option::TARG_MODE Option::target_mode = Option::TARG_OS2_MODE;
103#elif defined(Q_OS_MAC)
104Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE;
105#else
106Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE;
107#endif
108
109//QMAKE_*_PROPERTY stuff
110QStringList Option::prop::properties;
111
112//QMAKE_GENERATE_PROJECT stuff
113bool Option::projfile::do_pwd = true;
114QStringList Option::projfile::project_dirs;
115
116//QMAKE_GENERATE_MAKEFILE stuff
117QString Option::mkfile::qmakespec;
118int Option::mkfile::cachefile_depth = -1;
119bool Option::mkfile::do_deps = true;
120bool Option::mkfile::do_mocs = true;
121bool Option::mkfile::do_dep_heuristics = true;
122bool Option::mkfile::do_preprocess = false;
123bool Option::mkfile::do_stub_makefile = false;
124bool Option::mkfile::do_cache = true;
125QString Option::mkfile::cachefile;
126QStringList Option::mkfile::project_files;
127QString Option::mkfile::qmakespec_commandline;
128
129static Option::QMAKE_MODE default_mode(QString progname)
130{
131 int s = progname.lastIndexOf(Option::dir_sep);
132 if(s != -1)
133 progname = progname.right(progname.length() - (s + 1));
134 if(progname == "qmakegen")
135 return Option::QMAKE_GENERATE_PROJECT;
136 else if(progname == "qt-config")
137 return Option::QMAKE_QUERY_PROPERTY;
138 return Option::QMAKE_GENERATE_MAKEFILE;
139}
140
141QString project_builtin_regx();
142bool usage(const char *a0)
143{
144 fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
145 "\n"
146 "QMake has two modes, one mode for generating project files based on\n"
147 "some heuristics, and the other for generating makefiles. Normally you\n"
148 "shouldn't need to specify a mode, as makefile generation is the default\n"
149 "mode for qmake, but you may use this to test qmake on an existing project\n"
150 "\n"
151 "Mode:\n"
152 " -project Put qmake into project file generation mode%s\n"
153 " In this mode qmake interprets files as files to\n"
154 " be built,\n"
155 " defaults to %s\n"
156 " Note: The created .pro file probably will \n"
157 " need to be edited. For example add the QT variable to \n"
158 " specify what modules are required.\n"
159 " -makefile Put qmake into makefile generation mode%s\n"
160 " In this mode qmake interprets files as project files to\n"
161 " be processed, if skipped qmake will try to find a project\n"
162 " file in your current working directory\n"
163 "\n"
164 "Warnings Options:\n"
165 " -Wnone Turn off all warnings\n"
166 " -Wall Turn on all warnings\n"
167 " -Wparser Turn on parser warnings\n"
168 " -Wlogic Turn on logic warnings\n"
169 "\n"
170 "Options:\n"
171 " * You can place any variable assignment in options and it will be *\n"
172 " * processed as if it was in [files]. These assignments will be parsed *\n"
173 " * before [files]. *\n"
174 " -o file Write output to file\n"
175 " -unix Run in unix mode\n"
176 " -win32 Run in win32 mode\n"
177 " -os2 Run in OS/2 mode\n"
178 " -macx Run in Mac OS X mode\n"
179 " -d Increase debug level\n"
180 " -t templ Overrides TEMPLATE as templ\n"
181 " -tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n"
182 " -help This help\n"
183 " -v Version information\n"
184 " -after All variable assignments after this will be\n"
185 " parsed after [files]\n"
186 " -norecursive Don't do a recursive search\n"
187 " -recursive Do a recursive search\n"
188 " -set <prop> <value> Set persistent property\n"
189 " -query <prop> Query persistent property. Show all if <prop> is empty.\n"
190 " -cache file Use file as cache [makefile mode only]\n"
191 " -spec spec Use spec as QMAKESPEC [makefile mode only]\n"
192 " -nocache Don't use a cache file [makefile mode only]\n"
193 " -nodepend Don't generate dependencies [makefile mode only]\n"
194 " -nomoc Don't generate moc targets [makefile mode only]\n"
195 " -nopwd Don't look for files in pwd [project mode only]\n"
196 ,a0,
197 default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "", project_builtin_regx().toLatin1().constData(),
198 default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : ""
199 );
200 return false;
201}
202
203int
204Option::parseCommandLine(int argc, char **argv, int skip)
205{
206 bool before = true;
207 for(int x = skip; x < argc; x++) {
208 if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */
209 QString opt = argv[x] + 1;
210
211 //first param is a mode, or we default
212 if(x == 1) {
213 bool specified = true;
214 if(opt == "project") {
215 Option::recursive = true;
216 Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
217 } else if(opt == "prl") {
218 Option::mkfile::do_deps = false;
219 Option::mkfile::do_mocs = false;
220 Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
221 } else if(opt == "set") {
222 Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
223 } else if(opt == "query") {
224 Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
225 } else if(opt == "makefile") {
226 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
227 } else {
228 specified = false;
229 }
230 if(specified)
231 continue;
232 }
233 //all modes
234 if(opt == "o" || opt == "output") {
235 Option::output.setFileName(argv[++x]);
236 } else if(opt == "after") {
237 before = false;
238 } else if(opt == "t" || opt == "template") {
239 Option::user_template = argv[++x];
240 } else if(opt == "tp" || opt == "template_prefix") {
241 Option::user_template_prefix = argv[++x];
242 } else if(opt == "mac9") {
243 Option::target_mode = TARG_MAC9_MODE;
244 } else if(opt == "macx") {
245 Option::target_mode = TARG_MACX_MODE;
246 } else if(opt == "unix") {
247 Option::target_mode = TARG_UNIX_MODE;
248 } else if(opt == "win32") {
249 Option::target_mode = TARG_WIN_MODE;
250 } else if(opt == "os2") {
251 Option::target_mode = TARG_OS2_MODE;
252 } else if(opt == "d") {
253 Option::debug_level++;
254 } else if(opt == "version" || opt == "v" || opt == "-version") {
255 fprintf(stdout,
256 "QMake version %s\n"
257 "Using Qt version %s in %s\n",
258 qmake_version(), QT_VERSION_STR,
259 QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData());
260#ifdef QMAKE_OPENSOURCE_VERSION
261 fprintf(stdout, "QMake is Open Source software from Nokia Corporation and/or its subsidiary(-ies).\n");
262#endif
263 return Option::QMAKE_CMDLINE_BAIL;
264 } else if(opt == "h" || opt == "help") {
265 return Option::QMAKE_CMDLINE_SHOW_USAGE;
266 } else if(opt == "Wall") {
267 Option::warn_level |= WarnAll;
268 } else if(opt == "Wparser") {
269 Option::warn_level |= WarnParser;
270 } else if(opt == "Wlogic") {
271 Option::warn_level |= WarnLogic;
272 } else if(opt == "Wnone") {
273 Option::warn_level = WarnNone;
274 } else if(opt == "r" || opt == "recursive") {
275 Option::recursive = true;
276 } else if(opt == "norecursive") {
277 Option::recursive = false;
278 } else if(opt == "config") {
279 Option::user_configs += argv[++x];
280 } else {
281 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
282 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
283 if(opt == "nodepend" || opt == "nodepends") {
284 Option::mkfile::do_deps = false;
285 } else if(opt == "nomoc") {
286 Option::mkfile::do_mocs = false;
287 } else if(opt == "nocache") {
288 Option::mkfile::do_cache = false;
289 } else if(opt == "createstub") {
290 Option::mkfile::do_stub_makefile = true;
291 } else if(opt == "nodependheuristics") {
292 Option::mkfile::do_dep_heuristics = false;
293 } else if(opt == "E") {
294 Option::mkfile::do_preprocess = true;
295 } else if(opt == "cache") {
296 Option::mkfile::cachefile = argv[++x];
297 } else if(opt == "platform" || opt == "spec") {
298 Option::mkfile::qmakespec = argv[++x];
299 Option::mkfile::qmakespec_commandline = argv[x];
300 } else {
301 fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
302 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
303 }
304 } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
305 if(opt == "nopwd") {
306 Option::projfile::do_pwd = false;
307 } else {
308 fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
309 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
310 }
311 }
312 }
313 } else {
314 QString arg = argv[x];
315 if(arg.indexOf('=') != -1) {
316 if(before)
317 Option::before_user_vars.append(arg);
318 else
319 Option::after_user_vars.append(arg);
320 } else {
321 bool handled = true;
322 if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
323 Option::qmake_mode == Option::QMAKE_SET_PROPERTY) {
324 Option::prop::properties.append(arg);
325 } else {
326 QFileInfo fi(arg);
327 if(!fi.makeAbsolute()) //strange
328 arg = fi.filePath();
329 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
330 Option::qmake_mode == Option::QMAKE_GENERATE_PRL)
331 Option::mkfile::project_files.append(arg);
332 else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
333 Option::projfile::project_dirs.append(arg);
334 else
335 handled = false;
336 }
337 if(!handled) {
338 return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
339 }
340 }
341 }
342 }
343
344 return Option::QMAKE_CMDLINE_SUCCESS;
345}
346
347#if defined(Q_OS_WIN)
348static QStringList detectShellPath()
349{
350 QStringList paths;
351 QString path = qgetenv("PATH");
352 QStringList pathlist = path.toLower().split(";");
353 for (int i = 0; i < pathlist.count(); i++) {
354 QString maybeSh = pathlist.at(i) + "/sh.exe";
355 if (QFile::exists(maybeSh)) {
356 paths.append(maybeSh);
357 }
358 }
359 return paths;
360}
361#elif defined(Q_OS_OS2)
362static QStringList detectShellPath()
363{
364 /* @todo check if sh is actually the active shell of the process; relying on
365 * the presence of sh.exe in PATH as done for Windows above is obviously not
366 * enough */
367 return QStringList();
368}
369#endif
370
371int
372Option::init(int argc, char **argv)
373{
374 Option::application_argv0 = 0;
375 Option::cpp_moc_mod = "";
376 Option::h_moc_mod = "moc_";
377 Option::lex_mod = "_lex";
378 Option::yacc_mod = "_yacc";
379 Option::prl_ext = ".prl";
380 Option::libtool_ext = ".la";
381 Option::pkgcfg_ext = ".pc";
382 Option::prf_ext = ".prf";
383 Option::js_ext = ".js";
384 Option::ui_ext = ".ui";
385 Option::h_ext << ".h" << ".hpp" << ".hh" << ".hxx";
386 Option::c_ext << ".c";
387#if !defined(Q_OS_WIN) && !defined(Q_OS_OS2)
388 Option::h_ext << ".H";
389#endif
390 Option::cpp_moc_ext = ".moc";
391 Option::h_moc_ext = ".cpp";
392 Option::cpp_ext << ".cpp" << ".cc" << ".cxx";
393#if !defined(Q_OS_WIN) && !defined(Q_OS_OS2)
394 Option::cpp_ext << ".C";
395#endif
396 Option::lex_ext = ".l";
397 Option::yacc_ext = ".y";
398 Option::pro_ext = ".pro";
399 Option::mmp_ext = ".mmp";
400#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
401 Option::dirlist_sep = ";";
402 Option::shellPath = detectShellPath();
403#else
404 Option::dirlist_sep = ":";
405#endif
406 Option::sysenv_mod = "QMAKE_ENV_";
407 Option::field_sep = ' ';
408
409 if(argc && argv) {
410 Option::application_argv0 = argv[0];
411 QString argv0 = argv[0];
412 if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
413 Option::qmake_mode = default_mode(argv0);
414 if(!argv0.isEmpty() && !QFileInfo(argv0).isRelative()) {
415 Option::qmake_abslocation = argv0;
416 } else if (argv0.contains(QLatin1Char('/'))
417#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
418 || argv0.contains(QLatin1Char('\\'))
419#endif
420 ) { //relative PWD
421 Option::qmake_abslocation = QDir::current().absoluteFilePath(argv0);
422 } else { //in the PATH
423 QByteArray pEnv = qgetenv("PATH");
424 QDir currentDir = QDir::current();
425#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
426 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";"));
427#else
428 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":"));
429#endif
430 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
431 if ((*p).isEmpty())
432 continue;
433 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
434#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
435 candidate += ".exe";
436#endif
437 if (QFile::exists(candidate)) {
438 Option::qmake_abslocation = candidate;
439 break;
440 }
441 }
442 }
443 if(!Option::qmake_abslocation.isNull())
444 Option::qmake_abslocation = QDir::cleanPath(Option::qmake_abslocation);
445 } else {
446 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
447 }
448
449 const QByteArray envflags = qgetenv("QMAKEFLAGS");
450 if (!envflags.isNull()) {
451 int env_argc = 0, env_size = 0, currlen=0;
452 char quote = 0, **env_argv = NULL;
453 for (int i = 0; i < envflags.size(); ++i) {
454 if (!quote && (envflags.at(i) == '\'' || envflags.at(i) == '"')) {
455 quote = envflags.at(i);
456 } else if (envflags.at(i) == quote) {
457 quote = 0;
458 } else if (!quote && envflags.at(i) == ' ') {
459 if (currlen && env_argv && env_argv[env_argc]) {
460 env_argv[env_argc][currlen] = '\0';
461 currlen = 0;
462 env_argc++;
463 }
464 } else {
465 if(!env_argv || env_argc > env_size) {
466 env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10));
467 for(int i2 = env_argc; i2 < env_size; i2++)
468 env_argv[i2] = NULL;
469 }
470 if(!env_argv[env_argc]) {
471 currlen = 0;
472 env_argv[env_argc] = (char*)malloc(255);
473 }
474 if(currlen < 255)
475 env_argv[env_argc][currlen++] = envflags.at(i);
476 }
477 }
478 if(env_argv) {
479 if(env_argv[env_argc]) {
480 env_argv[env_argc][currlen] = '\0';
481 currlen = 0;
482 env_argc++;
483 }
484 parseCommandLine(env_argc, env_argv);
485 for(int i2 = 0; i2 < env_size; i2++) {
486 if(env_argv[i2])
487 free(env_argv[i2]);
488 }
489 free(env_argv);
490 }
491 }
492 if(argc && argv) {
493 int ret = parseCommandLine(argc, argv, 1);
494 if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
495 if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0)
496 usage(argv[0]);
497 return ret;
498 //return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false;
499 }
500 }
501
502 //last chance for defaults
503 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
504 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
505 if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty())
506 Option::mkfile::qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").constData());
507
508 //try REALLY hard to do it for them, lazy..
509 if(Option::mkfile::project_files.isEmpty()) {
510 QString pwd = qmake_getpwd(),
511 proj = pwd + "/" + pwd.right(pwd.length() - (pwd.lastIndexOf('/') + 1)) + Option::pro_ext;
512 if(QFile::exists(proj)) {
513 Option::mkfile::project_files.append(proj);
514 } else { //last try..
515 QStringList profiles = QDir(pwd).entryList(QStringList("*" + Option::pro_ext));
516 if(profiles.count() == 1)
517 Option::mkfile::project_files.append(pwd + "/" + profiles[0]);
518 }
519#ifndef QT_BUILD_QMAKE_LIBRARY
520 if(Option::mkfile::project_files.isEmpty()) {
521 usage(argv[0]);
522 return Option::QMAKE_CMDLINE_ERROR;
523 }
524#endif
525 }
526 }
527
528 //defaults for globals
529 if(Option::target_mode == Option::TARG_WIN_MODE ||
530 Option::target_mode == Option::TARG_OS2_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";
540 }
541 Option::qmake_abslocation = Option::fixPathToTargetOS(Option::qmake_abslocation);
542 return QMAKE_CMDLINE_SUCCESS;
543}
544
545bool Option::postProcessProject(QMakeProject *project)
546{
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
556
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;
596}
597
598QString
599Option::fixString(QString string, uchar flags)
600{
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);
606 }
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;
612 }
613
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()));
622 }
623
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);
630 }
631
632 if(string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':'))
633 string[0] = string[0].toLower();
634
635 //fix separators
636 Q_ASSERT(!((flags & Option::FixPathToLocalSeparators) && (flags & Option::FixPathToTargetSeparators)));
637 if(flags & Option::FixPathToLocalSeparators) {
638#if defined(Q_OS_WIN) || defined(Q_OS_OS2)
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);
645 }
646
647 if (string.startsWith("\"") && string.endsWith("\"") ||
648 string.startsWith("\'") && string.endsWith("\'"))
649 string = string.mid(1, string.length()-2);
650
651 //cache
652 //qDebug() << "Fix" << orig_string << "->" << string;
653 cache->insert(cacheKey, string);
654 return string;
655}
656
657const char *qmake_version()
658{
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;
670}
671
672void debug_msg_internal(int level, const char *fmt, ...)
673{
674 if(Option::debug_level < level)
675 return;
676 fprintf(stderr, "DEBUG %d: ", level);
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
686void warn_msg(QMakeWarn type, const char *fmt, ...)
687{
688 if(!(Option::warn_level & type))
689 return;
690 fprintf(stderr, "WARNING: ");
691 {
692 va_list ap;
693 va_start(ap, fmt);
694 vfprintf(stderr, fmt, ap);
695 va_end(ap);
696 }
697 fprintf(stderr, "\n");
698}
699
700class QMakeCacheClearItem {
701private:
702 qmakeCacheClearFunc func;
703 void **data;
704public:
705 QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
706 ~QMakeCacheClearItem() {
707 (*func)(*data);
708 *data = 0;
709 }
710};
711static QList<QMakeCacheClearItem*> cache_items;
712
713void
714qmakeClearCaches()
715{
716 qDeleteAll(cache_items);
717 cache_items.clear();
718}
719
720void
721qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
722{
723 cache_items.append(new QMakeCacheClearItem(func, data));
724}
725
726#ifdef Q_OS_WIN
727# include <windows.h>
728
729QT_USE_NAMESPACE
730#endif
731
732#ifdef Q_OS_OS2
733# include <qt_os2.h>
734
735QT_USE_NAMESPACE
736#endif
737
738QString qmake_libraryInfoFile()
739{
740 QString ret;
741#if defined(Q_OS_WIN)
742 wchar_t module_name[MAX_PATH];
743 GetModuleFileName(0, module_name, MAX_PATH);
744 QFileInfo filePath = QString::fromWCharArray(module_name);
745 ret = filePath.filePath();
746#elif defined(Q_OS_OS2)
747 QFileInfo filePath;
748 static char appFileName[CCHMAXPATH] = "\0";
749 if (!appFileName[0]) {
750 PPIB ppib;
751 DosGetInfoBlocks(NULL, &ppib);
752 DosQueryModuleName(ppib->pib_hmte, sizeof(appFileName), appFileName);
753 }
754 ret = QFileInfo(QString::fromLocal8Bit(appFileName)).absolutePath() +
755 QLatin1String("/qt.conf");
756 if (!QFile::exists(ret)) {
757 // search in the system-wide location
758 ret = QString::fromLocal8Bit(qgetenv("ETC"));
759 if (ret.isEmpty())
760 ret = QDir::rootPath();
761 ret = ret + QLatin1String("/qtsys.conf");
762 }
763 return QDir::cleanPath(ret);
764#else
765 QString argv0 = QFile::decodeName(QByteArray(Option::application_argv0));
766 QString absPath;
767
768 if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
769 /*
770 If argv0 starts with a slash, it is already an absolute
771 file path.
772 */
773 absPath = argv0;
774 } else if (argv0.contains(QLatin1Char('/'))) {
775 /*
776 If argv0 contains one or more slashes, it is a file path
777 relative to the current directory.
778 */
779 absPath = QDir::current().absoluteFilePath(argv0);
780 } else {
781 /*
782 Otherwise, the file path has to be determined using the
783 PATH environment variable.
784 */
785 QByteArray pEnv = qgetenv("PATH");
786 QDir currentDir = QDir::current();
787 QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1String(":"));
788 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
789 if ((*p).isEmpty())
790 continue;
791 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
792 QFileInfo candidate_fi(candidate);
793 if (candidate_fi.exists() && !candidate_fi.isDir()) {
794 absPath = candidate;
795 break;
796 }
797 }
798 }
799
800 absPath = QDir::cleanPath(absPath);
801
802 QFileInfo fi(absPath);
803 ret = fi.exists() ? fi.canonicalFilePath() : QString();
804#endif
805#if !defined(Q_OS_OS2)
806 if(!ret.isEmpty())
807 ret = QDir(QFileInfo(ret).absolutePath()).filePath("qt.conf");
808 return ret;
809#endif
810}
811
812QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.