source: trunk/qmake/option.cpp@ 500

Last change on this file since 500 was 29, checked in by Dmitry A. Kuminov, 16 years ago

qmake: More OS/2-specific fixes. Enabled GNUMakefileGenerator (turned on by MAKEFILE_GENERATOR=GNUMAKE).

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