00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "option.h"
00037 #include <qdir.h>
00038 #include <qregexp.h>
00039 #include <stdlib.h>
00040 #include <stdarg.h>
00041
00042
00043 QString Option::prf_ext;
00044 QString Option::prl_ext;
00045 QString Option::libtool_ext;
00046 QString Option::pkgcfg_ext;
00047 QString Option::ui_ext;
00048 QStringList Option::h_ext;
00049 QString Option::cpp_moc_ext;
00050 QString Option::h_moc_ext;
00051 QStringList Option::cpp_ext;
00052 QString Option::obj_ext;
00053 QString Option::lex_ext;
00054 QString Option::yacc_ext;
00055 QString Option::dir_sep;
00056 QString Option::h_moc_mod;
00057 QString Option::cpp_moc_mod;
00058 QString Option::yacc_mod;
00059 QString Option::lex_mod;
00060
00061
00062 Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
00063
00064
00065 int Option::warn_level = WarnLogic;
00066 int Option::debug_level = 0;
00067 QFile Option::output;
00068 QString Option::output_dir;
00069 QStringList Option::before_user_vars;
00070 QStringList Option::after_user_vars;
00071 QString Option::user_template;
00072 QString Option::user_template_prefix;
00073 #if defined(Q_OS_WIN32)
00074 Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE;
00075 #elif defined(Q_OS_MAC9)
00076 Option::TARG_MODE Option::target_mode = Option::TARG_MAC9_MODE;
00077 #elif defined(Q_OS_MACX)
00078 Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE;
00079 #elif defined(Q_OS_QNX6)
00080 Option::TARG_MODE Option::target_mode = Option::TARG_QNX6_MODE;
00081 #else
00082 Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE;
00083 #endif
00084
00085
00086 QStringList Option::prop::properties;
00087
00088
00089 bool Option::projfile::do_pwd = TRUE;
00090 bool Option::projfile::do_recursive = TRUE;
00091 QStringList Option::projfile::project_dirs;
00092
00093
00094 QString Option::mkfile::qmakespec;
00095 int Option::mkfile::cachefile_depth = -1;
00096 bool Option::mkfile::do_deps = TRUE;
00097 bool Option::mkfile::do_mocs = TRUE;
00098 bool Option::mkfile::do_dep_heuristics = TRUE;
00099 bool Option::mkfile::do_preprocess = FALSE;
00100 bool Option::mkfile::do_cache = TRUE;
00101 QString Option::mkfile::cachefile;
00102 QStringList Option::mkfile::project_files;
00103 QString Option::mkfile::qmakespec_commandline;
00104
00105 static Option::QMAKE_MODE default_mode(QString progname)
00106 {
00107 int s = progname.findRev(Option::dir_sep);
00108 if(s != -1)
00109 progname = progname.right(progname.length() - (s + 1));
00110 if(progname == "qmakegen")
00111 return Option::QMAKE_GENERATE_PROJECT;
00112 else if(progname == "qt-config")
00113 return Option::QMAKE_QUERY_PROPERTY;
00114 return Option::QMAKE_GENERATE_MAKEFILE;
00115 }
00116
00117 QString project_builtin_regx();
00118 bool usage(const char *a0)
00119 {
00120 fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
00121 "\n"
00122 " QMake has two modes, one mode for generating project files based on\n"
00123 "some heuristics, and the other for generating makefiles. Normally you\n"
00124 "shouldn't need to specify a mode, as makefile generation is the default\n"
00125 "mode for qmake, but you may use this to test qmake on an existing project\n"
00126 "\n"
00127 "Mode:\n"
00128 "\t-project Put qmake into project file generation mode%s\n"
00129 "\t In this mode qmake interprets files as files to\n"
00130 "\t be built,\n"
00131 "\t defaults to %s\n"
00132 "\t-makefile Put qmake into makefile generation mode%s\n"
00133 "\t In this mode qmake interprets files as project files to\n"
00134 "\t be processed, if skipped qmake will try to find a project\n"
00135 "\t file in your current working directory\n"
00136 "\n"
00137 "Warnings Options:\n"
00138 "\t-Wnone Turn off all warnings\n"
00139 "\t-Wall Turn on all warnings\n"
00140 "\t-Wparser Turn on parser warnings\n"
00141 "\t-Wlogic Turn on logic warnings\n"
00142 "\n"
00143 "Options:\n"
00144 "\t * You can place any variable assignment in options and it will be *\n"
00145 "\t * processed as if it was in [files]. These assignments will be parsed *\n"
00146 "\t * before [files]. *\n"
00147 "\t-o file Write output to file\n"
00148 "\t-unix Run in unix mode\n"
00149 "\t-win32 Run in win32 mode\n"
00150 "\t-macx Run in Mac OS X mode\n"
00151 "\t-d Increase debug level\n"
00152 "\t-t templ Overrides TEMPLATE as templ\n"
00153 "\t-tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n"
00154 "\t-help This help\n"
00155 "\t-v Version information\n"
00156 "\t-after All variable assignments after this will be\n"
00157 "\t parsed after [files]\n"
00158 "\t-cache file Use file as cache [makefile mode only]\n"
00159 "\t-spec spec Use spec as QMAKESPEC [makefile mode only]\n"
00160 "\t-nocache Don't use a cache file [makefile mode only]\n"
00161 "\t-nodepend Don't generate dependencies [makefile mode only]\n"
00162 "\t-nomoc Don't generate moc targets [makefile mode only]\n"
00163 "\t-nopwd Don't look for files in pwd [ project mode only]\n"
00164 "\t-norecursive Don't do a recursive search [ project mode only]\n"
00165 ,a0,
00166 default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "", project_builtin_regx().latin1(),
00167 default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : "");
00168 return FALSE;
00169 }
00170
00171 enum {
00172 QMAKE_CMDLINE_SUCCESS,
00173 QMAKE_CMDLINE_SHOW_USAGE,
00174 QMAKE_CMDLINE_BAIL
00175 };
00176 int
00177 Option::internalParseCommandLine(int argc, char **argv, int skip)
00178 {
00179 bool before = TRUE;
00180 for(int x = skip; x < argc; x++) {
00181 if(*argv[x] == '-' && strlen(argv[x]) > 1) {
00182 QString opt = argv[x] + 1;
00183
00184
00185 if(x == 1) {
00186 bool specified = TRUE;
00187 if(opt == "project") {
00188 Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
00189 } else if(opt == "prl") {
00190 Option::mkfile::do_deps = FALSE;
00191 Option::mkfile::do_mocs = FALSE;
00192 Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
00193 } else if(opt == "set") {
00194 Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
00195 } else if(opt == "query") {
00196 Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
00197 } else if(opt == "makefile") {
00198 Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
00199 } else {
00200 specified = FALSE;
00201 }
00202 if(specified)
00203 continue;
00204 }
00205
00206 if(opt == "o" || opt == "output") {
00207 Option::output.setName(argv[++x]);
00208 } else if(opt == "after") {
00209 before = FALSE;
00210 } else if(opt == "t" || opt == "template") {
00211 Option::user_template = argv[++x];
00212 } else if(opt == "tp" || opt == "template_prefix") {
00213 Option::user_template_prefix = argv[++x];
00214 } else if(opt == "mac9") {
00215 Option::target_mode = TARG_MAC9_MODE;
00216 } else if(opt == "macx") {
00217 Option::target_mode = TARG_MACX_MODE;
00218 } else if(opt == "unix") {
00219 Option::target_mode = TARG_UNIX_MODE;
00220 } else if(opt == "win32") {
00221 Option::target_mode = TARG_WIN_MODE;
00222 } else if(opt == "d") {
00223 Option::debug_level++;
00224 } else if(opt == "version" || opt == "v" || opt == "-version") {
00225 fprintf(stderr, "Qmake version: %s (Qt %s)\n", qmake_version(), QT_VERSION_STR);
00226 fprintf(stderr, "Qmake is free software from Trolltech AS.\n");
00227 return QMAKE_CMDLINE_BAIL;
00228 } else if(opt == "h" || opt == "help") {
00229 return QMAKE_CMDLINE_SHOW_USAGE;
00230 } else if(opt == "Wall") {
00231 Option::warn_level |= WarnAll;
00232 } else if(opt == "Wparser") {
00233 Option::warn_level |= WarnParser;
00234 } else if(opt == "Wlogic") {
00235 Option::warn_level |= WarnLogic;
00236 } else if(opt == "Wnone") {
00237 Option::warn_level = WarnNone;
00238 } else {
00239 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
00240 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
00241 if(opt == "nodepend") {
00242 Option::mkfile::do_deps = FALSE;
00243 } else if(opt == "nomoc") {
00244 Option::mkfile::do_mocs = FALSE;
00245 } else if(opt == "nocache") {
00246 Option::mkfile::do_cache = FALSE;
00247 } else if(opt == "nodependheuristics") {
00248 Option::mkfile::do_dep_heuristics = FALSE;
00249 } else if(opt == "E") {
00250 Option::mkfile::do_preprocess = TRUE;
00251 } else if(opt == "cache") {
00252 Option::mkfile::cachefile = argv[++x];
00253 } else if(opt == "platform" || opt == "spec") {
00254 Option::mkfile::qmakespec = argv[++x];
00255 Option::mkfile::qmakespec_commandline = argv[x];
00256 } else {
00257 fprintf(stderr, "***Unknown option -%s\n", opt.latin1());
00258 return QMAKE_CMDLINE_SHOW_USAGE;
00259 }
00260 } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
00261 if(opt == "nopwd") {
00262 Option::projfile::do_pwd = FALSE;
00263 } else if(opt == "r") {
00264 Option::projfile::do_recursive = TRUE;
00265 } else if(opt == "norecursive") {
00266 Option::projfile::do_recursive = FALSE;
00267 } else {
00268 fprintf(stderr, "***Unknown option -%s\n", opt.latin1());
00269 return QMAKE_CMDLINE_SHOW_USAGE;
00270 }
00271 }
00272 }
00273 } else {
00274 QString arg = argv[x];
00275 if(arg.find('=') != -1) {
00276 if(before)
00277 Option::before_user_vars.append(arg);
00278 else
00279 Option::after_user_vars.append(arg);
00280 } else {
00281 bool handled = TRUE;
00282 if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
00283 Option::qmake_mode == Option::QMAKE_SET_PROPERTY) {
00284 Option::prop::properties.append(arg);
00285 } else {
00286 QFileInfo fi(arg);
00287 if(!fi.convertToAbs())
00288 arg = fi.filePath();
00289 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
00290 Option::qmake_mode == Option::QMAKE_GENERATE_PRL)
00291 Option::mkfile::project_files.append(arg);
00292 else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
00293 Option::projfile::project_dirs.append(arg);
00294 else
00295 handled = FALSE;
00296 }
00297 if(!handled)
00298 return QMAKE_CMDLINE_SHOW_USAGE;
00299 }
00300 }
00301 }
00302 return QMAKE_CMDLINE_SUCCESS;
00303 }
00304
00305
00306 bool
00307 Option::parseCommandLine(int argc, char **argv)
00308 {
00309 Option::cpp_moc_mod = "";
00310 Option::h_moc_mod = "moc_";
00311 Option::lex_mod = "_lex";
00312 Option::yacc_mod = "_yacc";
00313 Option::prl_ext = ".prl";
00314 Option::libtool_ext = ".la";
00315 Option::pkgcfg_ext = ".pc";
00316 Option::prf_ext = ".prf";
00317 Option::ui_ext = ".ui";
00318 Option::h_ext << ".h" << ".hpp" << ".hh" << ".H" << ".hxx";
00319 Option::cpp_moc_ext = ".moc";
00320 Option::h_moc_ext = ".cpp";
00321 Option::cpp_ext << ".cpp" << ".cc" << ".cxx" << ".C";
00322 Option::lex_ext = ".l";
00323 Option::yacc_ext = ".y";
00324
00325 if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
00326 Option::qmake_mode = default_mode(argv[0]);
00327 if(const char *envflags = getenv("QMAKEFLAGS")) {
00328 int env_argc = 0, env_size = 0, currlen=0;
00329 char quote = 0, **env_argv = NULL;
00330 for(int i = 0; envflags[i]; i++) {
00331 if(!quote && (envflags[i] == '\'' || envflags[i] == '"')) {
00332 quote = envflags[i];
00333 } else if(envflags[i] == quote) {
00334 quote = 0;
00335 } else if(!quote && envflags[i] == ' ') {
00336 if(currlen && env_argv && env_argv[env_argc]) {
00337 env_argv[env_argc][currlen] = '\0';
00338 currlen = 0;
00339 env_argc++;
00340 }
00341 } else {
00342 if(!env_argv || env_argc > env_size) {
00343 env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10));
00344 for(int i2 = env_argc; i2 < env_size; i2++)
00345 env_argv[i2] = NULL;
00346 }
00347 if(!env_argv[env_argc]) {
00348 currlen = 0;
00349 env_argv[env_argc] = (char*)malloc(255);
00350 }
00351 if(currlen < 255)
00352 env_argv[env_argc][currlen++] = envflags[i];
00353 }
00354 }
00355 if(env_argv[env_argc]) {
00356 env_argv[env_argc][currlen] = '\0';
00357 currlen = 0;
00358 env_argc++;
00359 }
00360 internalParseCommandLine(env_argc, env_argv);
00361 for(int i2 = 0; i2 < env_size; i2++) {
00362 if(env_argv[i2])
00363 free(env_argv[i2]);
00364 }
00365 free(env_argv);
00366 }
00367 {
00368 int ret = internalParseCommandLine(argc, argv, 1);
00369 if(ret != QMAKE_CMDLINE_SUCCESS)
00370 return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : FALSE;
00371 }
00372
00373
00374 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
00375 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
00376 if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty())
00377 Option::mkfile::qmakespec = getenv("QMAKESPEC");
00378
00379
00380 if(Option::mkfile::project_files.isEmpty()) {
00381 QString pwd = QDir::currentDirPath(),
00382 proj = pwd + "/" + pwd.right(pwd.length() - (pwd.findRev('/') + 1)) + ".pro";
00383 if(QFile::exists(proj)) {
00384 Option::mkfile::project_files.append(proj);
00385 } else {
00386 QDir d(pwd, "*.pro");
00387 if(d.count() != 1)
00388 return usage(argv[0]);
00389 Option::mkfile::project_files.append(pwd + "/" + d[0]);
00390 }
00391 }
00392 }
00393
00394
00395 if(Option::target_mode == Option::TARG_WIN_MODE) {
00396 Option::dir_sep = "\\";
00397 Option::obj_ext = ".obj";
00398 } else {
00399 if(Option::target_mode == Option::TARG_MAC9_MODE)
00400 Option::dir_sep = ":";
00401 else
00402 Option::dir_sep = "/";
00403 Option::obj_ext = ".o";
00404 }
00405 return TRUE;
00406 }
00407
00408 bool Option::postProcessProject(QMakeProject *project)
00409 {
00410 Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"];
00411 if(cpp_ext.isEmpty())
00412 cpp_ext << ".cpp";
00413 Option::h_ext = project->variables()["QMAKE_EXT_H"];
00414 if(h_ext.isEmpty())
00415 h_ext << ".h";
00416
00417 if(!project->isEmpty("QMAKE_EXT_PKGCONFIG"))
00418 Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG");
00419 if(!project->isEmpty("QMAKE_EXT_LIBTOOL"))
00420 Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL");
00421 if(!project->isEmpty("QMAKE_EXT_PRL"))
00422 Option::prl_ext = project->first("QMAKE_EXT_PRL");
00423 if(!project->isEmpty("QMAKE_EXT_PRF"))
00424 Option::prf_ext = project->first("QMAKE_EXT_PRF");
00425 if(!project->isEmpty("QMAKE_EXT_UI"))
00426 Option::ui_ext = project->first("QMAKE_EXT_UI");
00427 if(!project->isEmpty("QMAKE_EXT_CPP_MOC"))
00428 Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC");
00429 if(!project->isEmpty("QMAKE_EXT_H_MOC"))
00430 Option::h_moc_ext = project->first("QMAKE_EXT_H_MOC");
00431 if(!project->isEmpty("QMAKE_EXT_LEX"))
00432 Option::lex_ext = project->first("QMAKE_EXT_LEX");
00433 if(!project->isEmpty("QMAKE_EXT_YACC"))
00434 Option::yacc_ext = project->first("QMAKE_EXT_YACC");
00435 if(!project->isEmpty("QMAKE_EXT_OBJ"))
00436 Option::obj_ext = project->first("QMAKE_EXT_OBJ");
00437 if(!project->isEmpty("QMAKE_H_MOD_MOC"))
00438 Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC");
00439 if(!project->isEmpty("QMAKE_CPP_MOD_MOC"))
00440 Option::cpp_moc_mod = project->first("QMAKE_CPP_MOD_MOC");
00441 if(!project->isEmpty("QMAKE_MOD_LEX"))
00442 Option::lex_mod = project->first("QMAKE_MOD_LEX");
00443 if(!project->isEmpty("QMAKE_MOD_YACC"))
00444 Option::yacc_mod = project->first("QMAKE_MOD_YACC");
00445 if(!project->isEmpty("QMAKE_DIR_SEP"))
00446 Option::dir_sep = project->first("QMAKE_DIR_SEP");
00447 return TRUE;
00448 }
00449
00450 void fixEnvVariables(QString &x)
00451 {
00452 int rep;
00453 QRegExp reg_var("\\$\\(.*\\)");
00454 reg_var.setMinimal( TRUE );
00455 while((rep = reg_var.search(x)) != -1)
00456 x.replace(rep, reg_var.matchedLength(), QString(getenv(x.mid(rep + 2, reg_var.matchedLength() - 3).latin1())));
00457 }
00458 static QString fixPath(QString x)
00459 {
00460 #if 0
00461 QFileInfo fi(x);
00462 if(fi.isDir()) {
00463 QDir dir(x);
00464 x = dir.canonicalPath();
00465 } else {
00466 QString dir = fi.dir().canonicalPath();
00467 if(!dir.isEmpty() && dir.right(1) != Option::dir_sep)
00468 dir += Option::dir_sep;
00469 x = dir + fi.fileName();
00470 }
00471 #endif
00472 return QDir::cleanDirPath(x);
00473 }
00474
00475
00476 QString
00477 Option::fixPathToTargetOS(const QString& in, bool fix_env, bool canonical)
00478 {
00479 QString tmp(in);
00480 if(fix_env)
00481 fixEnvVariables(tmp);
00482 if(canonical)
00483 tmp = fixPath(tmp);
00484 QString rep;
00485 if(Option::target_mode == TARG_MAC9_MODE)
00486 tmp = tmp.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
00487 else if(Option::target_mode == TARG_WIN_MODE)
00488 tmp = tmp.replace('/', Option::dir_sep);
00489 else
00490 tmp = tmp.replace('\\', Option::dir_sep);
00491 return tmp;
00492 }
00493
00494 QString
00495 Option::fixPathToLocalOS(const QString& in, bool fix_env, bool canonical)
00496 {
00497 QString tmp(in);
00498 if(fix_env)
00499 fixEnvVariables(tmp);
00500 if(canonical)
00501 tmp = fixPath(tmp);
00502 #if defined(Q_OS_WIN32)
00503 return tmp.replace('/', '\\');
00504 #else
00505 return tmp.replace('\\', '/');
00506 #endif
00507 }
00508
00509 const char *qmake_version()
00510 {
00511 static char *ret = NULL;
00512 if(ret)
00513 return ret;
00514 ret = (char *)malloc(15);
00515 sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
00516 return ret;
00517 }
00518
00519 void debug_msg(int level, const char *fmt, ...)
00520 {
00521 if(Option::debug_level < level)
00522 return;
00523 fprintf(stderr, "DEBUG %d: ", level);
00524 {
00525 va_list ap;
00526 va_start(ap, fmt);
00527 vfprintf(stderr, fmt, ap);
00528 va_end(ap);
00529 }
00530 fprintf(stderr, "\n");
00531 }
00532
00533 void warn_msg(QMakeWarn type, const char *fmt, ...)
00534 {
00535 if(!(Option::warn_level & type))
00536 return;
00537 fprintf(stderr, "WARNING: ");
00538 {
00539 va_list ap;
00540 va_start(ap, fmt);
00541 vfprintf(stderr, fmt, ap);
00542 va_end(ap);
00543 }
00544 fprintf(stderr, "\n");
00545 }