source: trunk/qmake/option.cpp@ 27

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

qmake: Added os2 mode (default on OS/2).

File size: 29.3 KB
RevLine 
[2]1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (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** 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 qt-sales@nokia.com.
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;
[27]100#elif defined(Q_OS_OS2)
101Option::TARG_MODE Option::target_mode = Option::TARG_OS2_MODE;
[2]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"
[27]175 " -os2 Run in OS/2 mode\n"
[2]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;
[27]248 } else if(opt == "os2") {
249 Option::target_mode = TARG_OS2_MODE;
[2]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#ifdef 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#endif
360
361int
362Option::init(int argc, char **argv)
363{
364 Option::application_argv0 = 0;
365 Option::cpp_moc_mod = "";
366 Option::h_moc_mod = "moc_";
367 Option::lex_mod = "_lex";
368 Option::yacc_mod = "_yacc";
369 Option::prl_ext = ".prl";
370 Option::libtool_ext = ".la";
371 Option::pkgcfg_ext = ".pc";
372 Option::prf_ext = ".prf";
373 Option::js_ext = ".js";
374 Option::ui_ext = ".ui";
375 Option::h_ext << ".h" << ".hpp" << ".hh" << ".hxx";
376 Option::c_ext << ".c";
377#ifndef Q_OS_WIN
378 Option::h_ext << ".H";
379#endif
380 Option::cpp_moc_ext = ".moc";
381 Option::h_moc_ext = ".cpp";
382 Option::cpp_ext << ".cpp" << ".cc" << ".cxx";
383#ifndef Q_OS_WIN
384 Option::cpp_ext << ".C";
385#endif
386 Option::lex_ext = ".l";
387 Option::yacc_ext = ".y";
388 Option::pro_ext = ".pro";
389#ifdef Q_OS_WIN
390 Option::dirlist_sep = ";";
391 Option::shellPath = detectShellPath();
392#else
393 Option::dirlist_sep = ":";
394#endif
395 Option::sysenv_mod = "QMAKE_ENV_";
396 Option::field_sep = ' ';
397
398 if(argc && argv) {
399 Option::application_argv0 = argv[0];
400 QString argv0 = argv[0];
401 if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
402 Option::qmake_mode = default_mode(argv0);
403 if(!argv0.isEmpty() && !QFileInfo(argv0).isRelative()) {
404 Option::qmake_abslocation = argv0;
405 } else if (argv0.contains(QLatin1Char('/'))
406#ifdef Q_OS_WIN
407 || argv0.contains(QLatin1Char('\\'))
408#endif
409 ) { //relative PWD
410 Option::qmake_abslocation = QDir::current().absoluteFilePath(argv0);
411 } else { //in the PATH
412 QByteArray pEnv = qgetenv("PATH");
413 QDir currentDir = QDir::current();
414#ifdef Q_OS_WIN
415 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";"));
416#else
417 QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":"));
418#endif
419 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
420 if ((*p).isEmpty())
421 continue;
422 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
423#ifdef Q_OS_WIN
424 candidate += ".exe";
425#endif
426 if (QFile::exists(candidate)) {
427 Option::qmake_abslocation = candidate;
428 break;
429 }
430 }
431 }
432 if(!Option::qmake_abslocation.isNull())
433 Option::qmake_abslocation = QDir::cleanPath(Option::qmake_abslocation);
434 } else {
435 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
436 }
437
438 const QByteArray envflags = qgetenv("QMAKEFLAGS");
439 if (!envflags.isNull()) {
440 int env_argc = 0, env_size = 0, currlen=0;
441 char quote = 0, **env_argv = NULL;
442 for (int i = 0; i < envflags.size(); ++i) {
443 if (!quote && (envflags.at(i) == '\'' || envflags.at(i) == '"')) {
444 quote = envflags.at(i);
445 } else if (envflags.at(i) == quote) {
446 quote = 0;
447 } else if (!quote && envflags.at(i) == ' ') {
448 if (currlen && env_argv && env_argv[env_argc]) {
449 env_argv[env_argc][currlen] = '\0';
450 currlen = 0;
451 env_argc++;
452 }
453 } else {
454 if(!env_argv || env_argc > env_size) {
455 env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10));
456 for(int i2 = env_argc; i2 < env_size; i2++)
457 env_argv[i2] = NULL;
458 }
459 if(!env_argv[env_argc]) {
460 currlen = 0;
461 env_argv[env_argc] = (char*)malloc(255);
462 }
463 if(currlen < 255)
464 env_argv[env_argc][currlen++] = envflags.at(i);
465 }
466 }
467 if(env_argv) {
468 if(env_argv[env_argc]) {
469 env_argv[env_argc][currlen] = '\0';
470 currlen = 0;
471 env_argc++;
472 }
473 parseCommandLine(env_argc, env_argv);
474 for(int i2 = 0; i2 < env_size; i2++) {
475 if(env_argv[i2])
476 free(env_argv[i2]);
477 }
478 free(env_argv);
479 }
480 }
481 if(argc && argv) {
482 int ret = parseCommandLine(argc, argv, 1);
483 if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
484 if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0)
485 usage(argv[0]);
486 return ret;
487 //return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false;
488 }
489 }
490
491 //last chance for defaults
492 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
493 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
494 if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty())
495 Option::mkfile::qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").constData());
496
497 //try REALLY hard to do it for them, lazy..
498 if(Option::mkfile::project_files.isEmpty()) {
499 QString pwd = qmake_getpwd(),
500 proj = pwd + "/" + pwd.right(pwd.length() - (pwd.lastIndexOf('/') + 1)) + Option::pro_ext;
501 if(QFile::exists(proj)) {
502 Option::mkfile::project_files.append(proj);
503 } else { //last try..
504 QStringList profiles = QDir(pwd).entryList(QStringList("*" + Option::pro_ext));
505 if(profiles.count() == 1)
506 Option::mkfile::project_files.append(pwd + "/" + profiles[0]);
507 }
508#ifndef QT_BUILD_QMAKE_LIBRARY
509 if(Option::mkfile::project_files.isEmpty()) {
510 usage(argv[0]);
511 return Option::QMAKE_CMDLINE_ERROR;
512 }
513#endif
514 }
515 }
516
517 //defaults for globals
[27]518 if(Option::target_mode == Option::TARG_WIN_MODE ||
519 Option::target_mode == Option::TARG_OS2_MODE) {
[2]520 Option::dir_sep = "\\";
521 Option::obj_ext = ".obj";
522 Option::res_ext = ".res";
523 } else {
524 if(Option::target_mode == Option::TARG_MAC9_MODE)
525 Option::dir_sep = ":";
526 else
527 Option::dir_sep = "/";
528 Option::obj_ext = ".o";
529 }
530 Option::qmake_abslocation = Option::fixPathToTargetOS(Option::qmake_abslocation);
531 return QMAKE_CMDLINE_SUCCESS;
532}
533
534bool Option::postProcessProject(QMakeProject *project)
535{
536 Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"];
537 if(cpp_ext.isEmpty())
538 cpp_ext << ".cpp"; //something must be there
539 Option::h_ext = project->variables()["QMAKE_EXT_H"];
540 if(h_ext.isEmpty())
541 h_ext << ".h";
542 Option::c_ext = project->variables()["QMAKE_EXT_C"];
543 if(c_ext.isEmpty())
544 c_ext << ".c"; //something must be there
545
546 if(!project->isEmpty("QMAKE_EXT_RES"))
547 Option::res_ext = project->first("QMAKE_EXT_RES");
548 if(!project->isEmpty("QMAKE_EXT_PKGCONFIG"))
549 Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG");
550 if(!project->isEmpty("QMAKE_EXT_LIBTOOL"))
551 Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL");
552 if(!project->isEmpty("QMAKE_EXT_PRL"))
553 Option::prl_ext = project->first("QMAKE_EXT_PRL");
554 if(!project->isEmpty("QMAKE_EXT_PRF"))
555 Option::prf_ext = project->first("QMAKE_EXT_PRF");
556 if(!project->isEmpty("QMAKE_EXT_JS"))
557 Option::prf_ext = project->first("QMAKE_EXT_JS");
558 if(!project->isEmpty("QMAKE_EXT_UI"))
559 Option::ui_ext = project->first("QMAKE_EXT_UI");
560 if(!project->isEmpty("QMAKE_EXT_CPP_MOC"))
561 Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC");
562 if(!project->isEmpty("QMAKE_EXT_H_MOC"))
563 Option::h_moc_ext = project->first("QMAKE_EXT_H_MOC");
564 if(!project->isEmpty("QMAKE_EXT_LEX"))
565 Option::lex_ext = project->first("QMAKE_EXT_LEX");
566 if(!project->isEmpty("QMAKE_EXT_YACC"))
567 Option::yacc_ext = project->first("QMAKE_EXT_YACC");
568 if(!project->isEmpty("QMAKE_EXT_OBJ"))
569 Option::obj_ext = project->first("QMAKE_EXT_OBJ");
570 if(!project->isEmpty("QMAKE_H_MOD_MOC"))
571 Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC");
572 if(!project->isEmpty("QMAKE_CPP_MOD_MOC"))
573 Option::cpp_moc_mod = project->first("QMAKE_CPP_MOD_MOC");
574 if(!project->isEmpty("QMAKE_MOD_LEX"))
575 Option::lex_mod = project->first("QMAKE_MOD_LEX");
576 if(!project->isEmpty("QMAKE_MOD_YACC"))
577 Option::yacc_mod = project->first("QMAKE_MOD_YACC");
578 if(!project->isEmpty("QMAKE_DIR_SEP"))
579 Option::dir_sep = project->first("QMAKE_DIR_SEP");
580 if(!project->isEmpty("QMAKE_DIRLIST_SEP"))
581 Option::dirlist_sep = project->first("QMAKE_DIRLIST_SEP");
582 if(!project->isEmpty("QMAKE_MOD_SYSTEM_ENV"))
583 Option::sysenv_mod = project->first("QMAKE_MOD_SYSTEM_ENV");
584 return true;
585}
586
587QString
588Option::fixString(QString string, uchar flags)
589{
590 const QString orig_string = string;
591 static QHash<FixStringCacheKey, QString> *cache = 0;
592 if(!cache) {
593 cache = new QHash<FixStringCacheKey, QString>;
594 qmakeAddCacheClear(qmakeDeleteCacheClear_QHashFixStringCacheKeyQString, (void**)&cache);
595 }
596 FixStringCacheKey cacheKey(string, flags);
597 if(cache->contains(cacheKey)) {
598 const QString ret = cache->value(cacheKey);
599 //qDebug() << "Fix (cached) " << orig_string << "->" << ret;
600 return ret;
601 }
602
603 //fix the environment variables
604 if(flags & Option::FixEnvVars) {
605 int rep;
606 QRegExp reg_var("\\$\\(.*\\)");
607 reg_var.setMinimal(true);
608 while((rep = reg_var.indexIn(string)) != -1)
609 string.replace(rep, reg_var.matchedLength(),
610 QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
611 }
612
613 //canonicalize it (and treat as a path)
614 if(flags & Option::FixPathCanonicalize) {
615#if 0
616 string = QFileInfo(string).canonicalFilePath();
617#endif
618 string = QDir::cleanPath(string);
619 }
620
621 if(string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':'))
622 string[0] = string[0].toLower();
623
624 //fix separators
625 Q_ASSERT(!((flags & Option::FixPathToLocalSeparators) && (flags & Option::FixPathToTargetSeparators)));
626 if(flags & Option::FixPathToLocalSeparators) {
627#if defined(Q_OS_WIN32)
628 string = string.replace('/', '\\');
629#else
630 string = string.replace('\\', '/');
631#endif
632 } else if(flags & Option::FixPathToTargetSeparators) {
633 string = string.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
634 }
635
636 if (string.startsWith("\"") && string.endsWith("\"") ||
637 string.startsWith("\'") && string.endsWith("\'"))
638 string = string.mid(1, string.length()-2);
639
640 //cache
641 //qDebug() << "Fix" << orig_string << "->" << string;
642 cache->insert(cacheKey, string);
643 return string;
644}
645
646const char *qmake_version()
647{
648 static char *ret = NULL;
649 if(ret)
650 return ret;
651 ret = (char *)malloc(15);
652 qmakeAddCacheClear(qmakeFreeCacheClear, (void**)&ret);
653#if defined(_MSC_VER) && _MSC_VER >= 1400
654 sprintf_s(ret, 15, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
655#else
656 sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
657#endif
658 return ret;
659}
660
661void debug_msg_internal(int level, const char *fmt, ...)
662{
663 if(Option::debug_level < level)
664 return;
665 fprintf(stderr, "DEBUG %d: ", level);
666 {
667 va_list ap;
668 va_start(ap, fmt);
669 vfprintf(stderr, fmt, ap);
670 va_end(ap);
671 }
672 fprintf(stderr, "\n");
673}
674
675void warn_msg(QMakeWarn type, const char *fmt, ...)
676{
677 if(!(Option::warn_level & type))
678 return;
679 fprintf(stderr, "WARNING: ");
680 {
681 va_list ap;
682 va_start(ap, fmt);
683 vfprintf(stderr, fmt, ap);
684 va_end(ap);
685 }
686 fprintf(stderr, "\n");
687}
688
689class QMakeCacheClearItem {
690private:
691 qmakeCacheClearFunc func;
692 void **data;
693public:
694 QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
695 ~QMakeCacheClearItem() {
696 (*func)(*data);
697 *data = 0;
698 }
699};
700static QList<QMakeCacheClearItem*> cache_items;
701
702void
703qmakeClearCaches()
704{
705 qDeleteAll(cache_items);
706 cache_items.clear();
707}
708
709void
710qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
711{
712 cache_items.append(new QMakeCacheClearItem(func, data));
713}
714
715#ifdef Q_OS_WIN
716# include <windows.h>
717
718QT_USE_NAMESPACE
719#endif
720
721QString qmake_libraryInfoFile()
722{
723 QString ret;
724#if defined( Q_OS_WIN )
725 QFileInfo filePath;
726 QT_WA({
727 unsigned short module_name[256];
728 GetModuleFileNameW(0, reinterpret_cast<wchar_t *>(module_name), sizeof(module_name));
729 filePath = QString::fromUtf16(module_name);
730 }, {
731 char module_name[256];
732 GetModuleFileNameA(0, module_name, sizeof(module_name));
733 filePath = QString::fromLocal8Bit(module_name);
734 });
735 ret = filePath.filePath();
736#else
737 QString argv0 = QFile::decodeName(QByteArray(Option::application_argv0));
738 QString absPath;
739
740 if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
741 /*
742 If argv0 starts with a slash, it is already an absolute
743 file path.
744 */
745 absPath = argv0;
746 } else if (argv0.contains(QLatin1Char('/'))) {
747 /*
748 If argv0 contains one or more slashes, it is a file path
749 relative to the current directory.
750 */
751 absPath = QDir::current().absoluteFilePath(argv0);
752 } else {
753 /*
754 Otherwise, the file path has to be determined using the
755 PATH environment variable.
756 */
757 QByteArray pEnv = qgetenv("PATH");
758 QDir currentDir = QDir::current();
759 QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1String(":"));
760 for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
761 if ((*p).isEmpty())
762 continue;
763 QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
764 QFileInfo candidate_fi(candidate);
765 if (candidate_fi.exists() && !candidate_fi.isDir()) {
766 absPath = candidate;
767 break;
768 }
769 }
770 }
771
772 absPath = QDir::cleanPath(absPath);
773
774 QFileInfo fi(absPath);
775 ret = fi.exists() ? fi.canonicalFilePath() : QString();
776#endif
777 if(!ret.isEmpty())
778 ret = QDir(QFileInfo(ret).absolutePath()).filePath("qt.conf");
779 return ret;
780}
781
782QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.