source: trunk/qmake/option.cpp@ 25

Last change on this file since 25 was 8, checked in by dmik, 20 years ago

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

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