source: vendor/trolltech/current/qmake/option.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 18.2 KB
Line 
1/****************************************************************************
2** $Id: option.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of Option class.
5**
6** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
7**
8** This file is part of qmake.
9**
10** This file may be distributed under the terms of the Q Public License
11** as defined by Trolltech AS of Norway and appearing in the file
12** LICENSE.QPL included in the packaging of this file.
13**
14** This file may be distributed and/or modified under the terms of the
15** GNU General Public License version 2 as published by the Free Software
16** Foundation and appearing in the file LICENSE.GPL included in the
17** packaging of this file.
18**
19** Licensees holding valid Qt Enterprise Edition licenses may use this
20** file in accordance with the Qt Commercial License Agreement provided
21** with the Software.
22**
23** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25**
26** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
27** information about Qt Commercial License Agreements.
28** See http://www.trolltech.com/qpl/ for QPL licensing information.
29** See http://www.trolltech.com/gpl/ for GPL licensing information.
30**
31** Contact info@trolltech.com if any conditions of this licensing are
32** not clear to you.
33**
34**********************************************************************/
35
36#include "option.h"
37#include <qdir.h>
38#include <qregexp.h>
39#include <stdlib.h>
40#include <stdarg.h>
41
42//convenience
43QString Option::prf_ext;
44QString Option::prl_ext;
45QString Option::libtool_ext;
46QString Option::pkgcfg_ext;
47QString Option::ui_ext;
48QStringList Option::h_ext;
49QString Option::cpp_moc_ext;
50QString Option::h_moc_ext;
51QStringList Option::cpp_ext;
52QString Option::obj_ext;
53QString Option::lex_ext;
54QString Option::yacc_ext;
55QString Option::dir_sep;
56QString Option::h_moc_mod;
57QString Option::cpp_moc_mod;
58QString Option::yacc_mod;
59QString Option::lex_mod;
60
61//mode
62Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
63
64//all modes
65int Option::warn_level = WarnLogic;
66int Option::debug_level = 0;
67QFile Option::output;
68QString Option::output_dir;
69QStringList Option::before_user_vars;
70QStringList Option::after_user_vars;
71QString Option::user_template;
72QString Option::user_template_prefix;
73#if defined(Q_OS_WIN32)
74Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE;
75#elif defined(Q_OS_MAC9)
76Option::TARG_MODE Option::target_mode = Option::TARG_MAC9_MODE;
77#elif defined(Q_OS_MACX)
78Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE;
79#elif defined(Q_OS_QNX6)
80Option::TARG_MODE Option::target_mode = Option::TARG_QNX6_MODE;
81#else
82Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE;
83#endif
84
85//QMAKE_*_PROPERTY stuff
86QStringList Option::prop::properties;
87
88//QMAKE_GENERATE_PROJECT stuff
89bool Option::projfile::do_pwd = TRUE;
90bool Option::projfile::do_recursive = TRUE;
91QStringList Option::projfile::project_dirs;
92
93//QMAKE_GENERATE_MAKEFILE stuff
94QString Option::mkfile::qmakespec;
95int Option::mkfile::cachefile_depth = -1;
96bool Option::mkfile::do_deps = TRUE;
97bool Option::mkfile::do_mocs = TRUE;
98bool Option::mkfile::do_dep_heuristics = TRUE;
99bool Option::mkfile::do_preprocess = FALSE;
100bool Option::mkfile::do_cache = TRUE;
101QString Option::mkfile::cachefile;
102QStringList Option::mkfile::project_files;
103QString Option::mkfile::qmakespec_commandline;
104
105static Option::QMAKE_MODE default_mode(QString progname)
106{
107 int s = progname.findRev(Option::dir_sep);
108 if(s != -1)
109 progname = progname.right(progname.length() - (s + 1));
110 if(progname == "qmakegen")
111 return Option::QMAKE_GENERATE_PROJECT;
112 else if(progname == "qt-config")
113 return Option::QMAKE_QUERY_PROPERTY;
114 return Option::QMAKE_GENERATE_MAKEFILE;
115}
116
117QString project_builtin_regx();
118bool usage(const char *a0)
119{
120 fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
121 "\n"
122 " QMake has two modes, one mode for generating project files based on\n"
123 "some heuristics, and the other for generating makefiles. Normally you\n"
124 "shouldn't need to specify a mode, as makefile generation is the default\n"
125 "mode for qmake, but you may use this to test qmake on an existing project\n"
126 "\n"
127 "Mode:\n"
128 "\t-project Put qmake into project file generation mode%s\n"
129 "\t In this mode qmake interprets files as files to\n"
130 "\t be built,\n"
131 "\t defaults to %s\n"
132 "\t-makefile Put qmake into makefile generation mode%s\n"
133 "\t In this mode qmake interprets files as project files to\n"
134 "\t be processed, if skipped qmake will try to find a project\n"
135 "\t file in your current working directory\n"
136 "\n"
137 "Warnings Options:\n"
138 "\t-Wnone Turn off all warnings\n"
139 "\t-Wall Turn on all warnings\n"
140 "\t-Wparser Turn on parser warnings\n"
141 "\t-Wlogic Turn on logic warnings\n"
142 "\n"
143 "Options:\n"
144 "\t * You can place any variable assignment in options and it will be *\n"
145 "\t * processed as if it was in [files]. These assignments will be parsed *\n"
146 "\t * before [files]. *\n"
147 "\t-o file Write output to file\n"
148 "\t-unix Run in unix mode\n"
149 "\t-win32 Run in win32 mode\n"
150 "\t-macx Run in Mac OS X mode\n"
151 "\t-d Increase debug level\n"
152 "\t-t templ Overrides TEMPLATE as templ\n"
153 "\t-tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n"
154 "\t-help This help\n"
155 "\t-v Version information\n"
156 "\t-after All variable assignments after this will be\n"
157 "\t parsed after [files]\n"
158 "\t-cache file Use file as cache [makefile mode only]\n"
159 "\t-spec spec Use spec as QMAKESPEC [makefile mode only]\n"
160 "\t-nocache Don't use a cache file [makefile mode only]\n"
161 "\t-nodepend Don't generate dependencies [makefile mode only]\n"
162 "\t-nomoc Don't generate moc targets [makefile mode only]\n"
163 "\t-nopwd Don't look for files in pwd [ project mode only]\n"
164 "\t-norecursive Don't do a recursive search [ project mode only]\n"
165 ,a0,
166 default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "", project_builtin_regx().latin1(),
167 default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : "");
168 return FALSE;
169}
170
171enum {
172 QMAKE_CMDLINE_SUCCESS,
173 QMAKE_CMDLINE_SHOW_USAGE,
174 QMAKE_CMDLINE_BAIL
175};
176int
177Option::internalParseCommandLine(int argc, char **argv, int skip)
178{
179 bool before = TRUE;
180 for(int x = skip; x < argc; x++) {
181 if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */
182 QString opt = argv[x] + 1;
183
184 //first param is a mode, or we default
185 if(x == 1) {
186 bool specified = TRUE;
187 if(opt == "project") {
188 Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
189 } else if(opt == "prl") {
190 Option::mkfile::do_deps = FALSE;
191 Option::mkfile::do_mocs = FALSE;
192 Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
193 } else if(opt == "set") {
194 Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
195 } else if(opt == "query") {
196 Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
197 } else if(opt == "makefile") {
198 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
199 } else {
200 specified = FALSE;
201 }
202 if(specified)
203 continue;
204 }
205 //all modes
206 if(opt == "o" || opt == "output") {
207 Option::output.setName(argv[++x]);
208 } else if(opt == "after") {
209 before = FALSE;
210 } else if(opt == "t" || opt == "template") {
211 Option::user_template = argv[++x];
212 } else if(opt == "tp" || opt == "template_prefix") {
213 Option::user_template_prefix = argv[++x];
214 } else if(opt == "mac9") {
215 Option::target_mode = TARG_MAC9_MODE;
216 } else if(opt == "macx") {
217 Option::target_mode = TARG_MACX_MODE;
218 } else if(opt == "unix") {
219 Option::target_mode = TARG_UNIX_MODE;
220 } else if(opt == "win32") {
221 Option::target_mode = TARG_WIN_MODE;
222 } else if(opt == "d") {
223 Option::debug_level++;
224 } else if(opt == "version" || opt == "v" || opt == "-version") {
225 fprintf(stderr, "Qmake version: %s (Qt %s)\n", qmake_version(), QT_VERSION_STR);
226 fprintf(stderr, "Qmake is free software from Trolltech AS.\n");
227 return QMAKE_CMDLINE_BAIL;
228 } else if(opt == "h" || opt == "help") {
229 return QMAKE_CMDLINE_SHOW_USAGE;
230 } else if(opt == "Wall") {
231 Option::warn_level |= WarnAll;
232 } else if(opt == "Wparser") {
233 Option::warn_level |= WarnParser;
234 } else if(opt == "Wlogic") {
235 Option::warn_level |= WarnLogic;
236 } else if(opt == "Wnone") {
237 Option::warn_level = WarnNone;
238 } else {
239 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
240 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
241 if(opt == "nodepend") {
242 Option::mkfile::do_deps = FALSE;
243 } else if(opt == "nomoc") {
244 Option::mkfile::do_mocs = FALSE;
245 } else if(opt == "nocache") {
246 Option::mkfile::do_cache = FALSE;
247 } else if(opt == "nodependheuristics") {
248 Option::mkfile::do_dep_heuristics = FALSE;
249 } else if(opt == "E") {
250 Option::mkfile::do_preprocess = TRUE;
251 } else if(opt == "cache") {
252 Option::mkfile::cachefile = argv[++x];
253 } else if(opt == "platform" || opt == "spec") {
254 Option::mkfile::qmakespec = argv[++x];
255 Option::mkfile::qmakespec_commandline = argv[x];
256 } else {
257 fprintf(stderr, "***Unknown option -%s\n", opt.latin1());
258 return QMAKE_CMDLINE_SHOW_USAGE;
259 }
260 } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
261 if(opt == "nopwd") {
262 Option::projfile::do_pwd = FALSE;
263 } else if(opt == "r") {
264 Option::projfile::do_recursive = TRUE;
265 } else if(opt == "norecursive") {
266 Option::projfile::do_recursive = FALSE;
267 } else {
268 fprintf(stderr, "***Unknown option -%s\n", opt.latin1());
269 return QMAKE_CMDLINE_SHOW_USAGE;
270 }
271 }
272 }
273 } else {
274 QString arg = argv[x];
275 if(arg.find('=') != -1) {
276 if(before)
277 Option::before_user_vars.append(arg);
278 else
279 Option::after_user_vars.append(arg);
280 } else {
281 bool handled = TRUE;
282 if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
283 Option::qmake_mode == Option::QMAKE_SET_PROPERTY) {
284 Option::prop::properties.append(arg);
285 } else {
286 QFileInfo fi(arg);
287 if(!fi.convertToAbs()) //strange
288 arg = fi.filePath();
289 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
290 Option::qmake_mode == Option::QMAKE_GENERATE_PRL)
291 Option::mkfile::project_files.append(arg);
292 else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
293 Option::projfile::project_dirs.append(arg);
294 else
295 handled = FALSE;
296 }
297 if(!handled)
298 return QMAKE_CMDLINE_SHOW_USAGE;
299 }
300 }
301 }
302 return QMAKE_CMDLINE_SUCCESS;
303}
304
305
306bool
307Option::parseCommandLine(int argc, char **argv)
308{
309 Option::cpp_moc_mod = "";
310 Option::h_moc_mod = "moc_";
311 Option::lex_mod = "_lex";
312 Option::yacc_mod = "_yacc";
313 Option::prl_ext = ".prl";
314 Option::libtool_ext = ".la";
315 Option::pkgcfg_ext = ".pc";
316 Option::prf_ext = ".prf";
317 Option::ui_ext = ".ui";
318 Option::h_ext << ".h" << ".hpp" << ".hh" << ".H" << ".hxx";
319 Option::cpp_moc_ext = ".moc";
320 Option::h_moc_ext = ".cpp";
321 Option::cpp_ext << ".cpp" << ".cc" << ".cxx" << ".C";
322 Option::lex_ext = ".l";
323 Option::yacc_ext = ".y";
324
325 if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
326 Option::qmake_mode = default_mode(argv[0]);
327 if(const char *envflags = getenv("QMAKEFLAGS")) {
328 int env_argc = 0, env_size = 0, currlen=0;
329 char quote = 0, **env_argv = NULL;
330 for(int i = 0; envflags[i]; i++) {
331 if(!quote && (envflags[i] == '\'' || envflags[i] == '"')) {
332 quote = envflags[i];
333 } else if(envflags[i] == quote) {
334 quote = 0;
335 } else if(!quote && envflags[i] == ' ') {
336 if(currlen && env_argv && env_argv[env_argc]) {
337 env_argv[env_argc][currlen] = '\0';
338 currlen = 0;
339 env_argc++;
340 }
341 } else {
342 if(!env_argv || env_argc > env_size) {
343 env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10));
344 for(int i2 = env_argc; i2 < env_size; i2++)
345 env_argv[i2] = NULL;
346 }
347 if(!env_argv[env_argc]) {
348 currlen = 0;
349 env_argv[env_argc] = (char*)malloc(255);
350 }
351 if(currlen < 255)
352 env_argv[env_argc][currlen++] = envflags[i];
353 }
354 }
355 if(env_argv[env_argc]) {
356 env_argv[env_argc][currlen] = '\0';
357 currlen = 0;
358 env_argc++;
359 }
360 internalParseCommandLine(env_argc, env_argv);
361 for(int i2 = 0; i2 < env_size; i2++) {
362 if(env_argv[i2])
363 free(env_argv[i2]);
364 }
365 free(env_argv);
366 }
367 {
368 int ret = internalParseCommandLine(argc, argv, 1);
369 if(ret != QMAKE_CMDLINE_SUCCESS)
370 return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : FALSE;
371 }
372
373 //last chance for defaults
374 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
375 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
376 if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty())
377 Option::mkfile::qmakespec = getenv("QMAKESPEC");
378
379 //try REALLY hard to do it for them, lazy..
380 if(Option::mkfile::project_files.isEmpty()) {
381 QString pwd = QDir::currentDirPath(),
382 proj = pwd + "/" + pwd.right(pwd.length() - (pwd.findRev('/') + 1)) + ".pro";
383 if(QFile::exists(proj)) {
384 Option::mkfile::project_files.append(proj);
385 } else { //last try..
386 QDir d(pwd, "*.pro");
387 if(d.count() != 1)
388 return usage(argv[0]);
389 Option::mkfile::project_files.append(pwd + "/" + d[0]);
390 }
391 }
392 }
393
394 //defaults for globals
395 if(Option::target_mode == Option::TARG_WIN_MODE) {
396 Option::dir_sep = "\\";
397 Option::obj_ext = ".obj";
398 } else {
399 if(Option::target_mode == Option::TARG_MAC9_MODE)
400 Option::dir_sep = ":";
401 else
402 Option::dir_sep = "/";
403 Option::obj_ext = ".o";
404 }
405 return TRUE;
406}
407
408bool Option::postProcessProject(QMakeProject *project)
409{
410 Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"];
411 if(cpp_ext.isEmpty())
412 cpp_ext << ".cpp"; //something must be there
413 Option::h_ext = project->variables()["QMAKE_EXT_H"];
414 if(h_ext.isEmpty())
415 h_ext << ".h";
416
417 if(!project->isEmpty("QMAKE_EXT_PKGCONFIG"))
418 Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG");
419 if(!project->isEmpty("QMAKE_EXT_LIBTOOL"))
420 Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL");
421 if(!project->isEmpty("QMAKE_EXT_PRL"))
422 Option::prl_ext = project->first("QMAKE_EXT_PRL");
423 if(!project->isEmpty("QMAKE_EXT_PRF"))
424 Option::prf_ext = project->first("QMAKE_EXT_PRF");
425 if(!project->isEmpty("QMAKE_EXT_UI"))
426 Option::ui_ext = project->first("QMAKE_EXT_UI");
427 if(!project->isEmpty("QMAKE_EXT_CPP_MOC"))
428 Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC");
429 if(!project->isEmpty("QMAKE_EXT_H_MOC"))
430 Option::h_moc_ext = project->first("QMAKE_EXT_H_MOC");
431 if(!project->isEmpty("QMAKE_EXT_LEX"))
432 Option::lex_ext = project->first("QMAKE_EXT_LEX");
433 if(!project->isEmpty("QMAKE_EXT_YACC"))
434 Option::yacc_ext = project->first("QMAKE_EXT_YACC");
435 if(!project->isEmpty("QMAKE_EXT_OBJ"))
436 Option::obj_ext = project->first("QMAKE_EXT_OBJ");
437 if(!project->isEmpty("QMAKE_H_MOD_MOC"))
438 Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC");
439 if(!project->isEmpty("QMAKE_CPP_MOD_MOC"))
440 Option::cpp_moc_mod = project->first("QMAKE_CPP_MOD_MOC");
441 if(!project->isEmpty("QMAKE_MOD_LEX"))
442 Option::lex_mod = project->first("QMAKE_MOD_LEX");
443 if(!project->isEmpty("QMAKE_MOD_YACC"))
444 Option::yacc_mod = project->first("QMAKE_MOD_YACC");
445 if(!project->isEmpty("QMAKE_DIR_SEP"))
446 Option::dir_sep = project->first("QMAKE_DIR_SEP");
447 return TRUE;
448}
449
450void fixEnvVariables(QString &x)
451{
452 int rep;
453 QRegExp reg_var("\\$\\(.*\\)");
454 reg_var.setMinimal( TRUE );
455 while((rep = reg_var.search(x)) != -1)
456 x.replace(rep, reg_var.matchedLength(), QString(getenv(x.mid(rep + 2, reg_var.matchedLength() - 3).latin1())));
457}
458static QString fixPath(QString x)
459{
460#if 0
461 QFileInfo fi(x);
462 if(fi.isDir()) {
463 QDir dir(x);
464 x = dir.canonicalPath();
465 } else {
466 QString dir = fi.dir().canonicalPath();
467 if(!dir.isEmpty() && dir.right(1) != Option::dir_sep)
468 dir += Option::dir_sep;
469 x = dir + fi.fileName();
470 }
471#endif
472 return QDir::cleanDirPath(x);
473}
474
475
476QString
477Option::fixPathToTargetOS(const QString& in, bool fix_env, bool canonical)
478{
479 QString tmp(in);
480 if(fix_env)
481 fixEnvVariables(tmp);
482 if(canonical)
483 tmp = fixPath(tmp);
484 QString rep;
485 if(Option::target_mode == TARG_MAC9_MODE)
486 tmp = tmp.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
487 else if(Option::target_mode == TARG_WIN_MODE)
488 tmp = tmp.replace('/', Option::dir_sep);
489 else
490 tmp = tmp.replace('\\', Option::dir_sep);
491 return tmp;
492}
493
494QString
495Option::fixPathToLocalOS(const QString& in, bool fix_env, bool canonical)
496{
497 QString tmp(in);
498 if(fix_env)
499 fixEnvVariables(tmp);
500 if(canonical)
501 tmp = fixPath(tmp);
502#if defined(Q_OS_WIN32)
503 return tmp.replace('/', '\\');
504#else
505 return tmp.replace('\\', '/');
506#endif
507}
508
509const char *qmake_version()
510{
511 static char *ret = NULL;
512 if(ret)
513 return ret;
514 ret = (char *)malloc(15);
515 sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
516 return ret;
517}
518
519void debug_msg(int level, const char *fmt, ...)
520{
521 if(Option::debug_level < level)
522 return;
523 fprintf(stderr, "DEBUG %d: ", level);
524 {
525 va_list ap;
526 va_start(ap, fmt);
527 vfprintf(stderr, fmt, ap);
528 va_end(ap);
529 }
530 fprintf(stderr, "\n");
531}
532
533void warn_msg(QMakeWarn type, const char *fmt, ...)
534{
535 if(!(Option::warn_level & type))
536 return;
537 fprintf(stderr, "WARNING: ");
538 {
539 va_list ap;
540 va_start(ap, fmt);
541 vfprintf(stderr, fmt, ap);
542 va_end(ap);
543 }
544 fprintf(stderr, "\n");
545}
Note: See TracBrowser for help on using the repository browser.