1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the qmake application of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
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
52
QT_BEGIN_NAMESPACE
53
54
//convenience
55
const char *Option::application_argv0 = 0;
56
QString Option::prf_ext;
57
QString Option::js_ext;
58
QString Option::prl_ext;
59
QString Option::libtool_ext;
60
QString Option::pkgcfg_ext;
61
QString Option::ui_ext;
62
QStringList Option::h_ext;
63
QString Option::cpp_moc_ext;
64
QString Option::h_moc_ext;
65
QStringList Option::cpp_ext;
66
QStringList Option::c_ext;
67
QString Option::obj_ext;
68
QString Option::lex_ext;
69
QString Option::yacc_ext;
70
QString Option::pro_ext;
71
QString Option::mmp_ext;
72
QString Option::dir_sep;
73
QString Option::dirlist_sep;
74
QString Option::h_moc_mod;
75
QString Option::cpp_moc_mod;
76
QString Option::yacc_mod;
77
QString Option::lex_mod;
78
QString Option::sysenv_mod;
79
QString Option::res_ext;
80
char Option::field_sep;
81
82
//mode
83
Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
84
85
//all modes
86
QString Option::qmake_abslocation;
87
int Option::warn_level = WarnLogic | WarnDeprecated;
88
int Option::debug_level = 0;
89
QFile Option::output;
90
QString Option::output_dir;
91
Option::QMAKE_RECURSIVE Option::recursive = Option::QMAKE_RECURSIVE_DEFAULT;
92
QStringList Option::before_user_vars;
93
QStringList Option::after_user_vars;
94
QStringList Option::user_configs;
95
QStringList Option::after_user_configs;
96
QString Option::user_template;
97
QString Option::user_template_prefix;
98
QStringList Option::shellPath;
99
Option::HOST_MODE Option::host_mode = Option::HOST_UNKNOWN_MODE;
100
Option::TARG_MODE Option::target_mode = Option::TARG_UNKNOWN_MODE;
101
bool Option::target_mode_overridden = false;
102
103
//QMAKE_*_PROPERTY stuff
104
QStringList Option::prop::properties;
105
106
//QMAKE_GENERATE_PROJECT stuff
107
bool Option::projfile::do_pwd = true;
108
QStringList Option::projfile::project_dirs;
109
110
//QMAKE_GENERATE_MAKEFILE stuff
111
QString Option::mkfile::qmakespec;
112
int Option::mkfile::cachefile_depth = -1;
113
bool Option::mkfile::do_deps = true;
114
bool Option::mkfile::do_mocs = true;
115
bool Option::mkfile::do_dep_heuristics = true;
116
bool Option::mkfile::do_preprocess = false;
117
bool Option::mkfile::do_stub_makefile = false;
118
bool Option::mkfile::do_cache = true;
119
QString Option::mkfile::cachefile;
120
QStringList Option::mkfile::project_files;
121
QString Option::mkfile::qmakespec_commandline;
122
123
static Option::QMAKE_MODE default_mode(QString progname)
124
{
125
    int s = progname.lastIndexOf(QDir::separator());
126
    if(s != -1)
127
        progname = progname.right(progname.length() - (s + 1));
128
    if(progname == "qmakegen")
129
        return Option::QMAKE_GENERATE_PROJECT;
130
    else if(progname == "qt-config")
131
        return Option::QMAKE_QUERY_PROPERTY;
132
    return Option::QMAKE_GENERATE_MAKEFILE;
133
}
134
135
static QString detectProjectFile(const QString &path)
136
{
137
    QString ret;
138
    QDir dir(path);
139
    if(dir.exists(dir.dirName() + Option::pro_ext)) {
140
        ret = dir.filePath(dir.dirName()) + Option::pro_ext;
141
    } else { //last try..
142
        QStringList profiles = dir.entryList(QStringList("*" + Option::pro_ext));
143
        if(profiles.count() == 1)
144
            ret = dir.filePath(profiles.at(0));
145
    }
146
    return ret;
147
}
148
149
QString project_builtin_regx();
150
bool usage(const char *a0)
151
{
152
    fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
153
            "\n"
154
            "QMake has two modes, one mode for generating project files based on\n"
155
            "some heuristics, and the other for generating makefiles. Normally you\n"
156
            "shouldn't need to specify a mode, as makefile generation is the default\n"
157
            "mode for qmake, but you may use this to test qmake on an existing project\n"
158
            "\n"
159
            "Mode:\n"
160
            "  -project       Put qmake into project file generation mode%s\n"
161
            "                 In this mode qmake interprets files as files to\n"
162
            "                 be built,\n"
163
            "                 defaults to %s\n"
164
            "                 Note: The created .pro file probably will \n"
165
            "                 need to be edited. For example add the QT variable to \n"
166
            "                 specify what modules are required.\n"
167
            "  -makefile      Put qmake into makefile generation mode%s\n"
168
            "                 In this mode qmake interprets files as project files to\n"
169
            "                 be processed, if skipped qmake will try to find a project\n"
170
            "                 file in your current working directory\n"
171
            "\n"
172
            "Warnings Options:\n"
173
            "  -Wnone         Turn off all warnings; specific ones may be re-enabled by\n"
174
            "                 later -W options\n"
175
            "  -Wall          Turn on all warnings\n"
176
            "  -Wparser       Turn on parser warnings\n"
177
            "  -Wlogic        Turn on logic warnings (on by default)\n"
178
            "  -Wdeprecated   Turn on deprecation warnings (on by default)\n"
179
            "\n"
180
            "Options:\n"
181
            "   * You can place any variable assignment in options and it will be     *\n"
182
            "   * processed as if it was in [files]. These assignments will be parsed *\n"
183
            "   * before [files].                                                     *\n"
184
            "  -o file        Write output to file\n"
185
            "  -d             Increase debug level\n"
186
            "  -t templ       Overrides TEMPLATE as templ\n"
187
            "  -tp prefix     Overrides TEMPLATE so that prefix is prefixed into the value\n"
188
            "  -help          This help\n"
189
            "  -v             Version information\n"
190
            "  -after         All variable assignments after this will be\n"
191
            "                 parsed after [files]\n"
192
            "  -norecursive   Don't do a recursive search\n"
193
            "  -recursive     Do a recursive search\n"
194
            "  -set <prop> <value> Set persistent property\n"
195
            "  -unset <prop>  Unset persistent property\n"
196
            "  -query <prop>  Query persistent property. Show all if <prop> is empty.\n"
197
            "  -cache file    Use file as cache           [makefile mode only]\n"
198
            "  -spec spec     Use spec as QMAKESPEC       [makefile mode only]\n"
199
            "  -nocache       Don't use a cache file      [makefile mode only]\n"
200
            "  -nodepend      Don't generate dependencies [makefile mode only]\n"
201
            "  -nomoc         Don't generate moc targets  [makefile mode only]\n"
202
            "  -nopwd         Don't look for files in pwd [project mode only]\n"
203
            ,a0,
204
            default_mode(a0) == Option::QMAKE_GENERATE_PROJECT  ? " (default)" : "", project_builtin_regx().toLatin1().constData(),
205
            default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : ""
206
        );
207
    return false;
208
}
209
210
int
211
Option::parseCommandLine(int argc, char **argv, int skip)
212
{
213
    bool before = true;
214
    for(int x = skip; x < argc; x++) {
215
        if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */
216
            QString opt = argv[x] + 1;
217
218
            //first param is a mode, or we default
219
            if(x == 1) {
220
                bool specified = true;
221
                if(opt == "project") {
222
                    Option::recursive = Option::QMAKE_RECURSIVE_YES;
223
                    Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
224
                } else if(opt == "prl") {
225
                    Option::mkfile::do_deps = false;
226
                    Option::mkfile::do_mocs = false;
227
                    Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
228
                } else if(opt == "set") {
229
                    Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
230
                } else if(opt == "unset") {
231
                    Option::qmake_mode = Option::QMAKE_UNSET_PROPERTY;
232
                } else if(opt == "query") {
233
                    Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
234
                } else if(opt == "makefile") {
235
                    Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
236
                } else {
237
                    specified = false;
238
                }
239
                if(specified)
240
                    continue;
241
            }
242
            //all modes
243
            if(opt == "o" || opt == "output") {
244
                Option::output.setFileName(argv[++x]);
245
            } else if(opt == "after") {
246
                before = false;
247
            } else if(opt == "t" || opt == "template") {
248
                Option::user_template = argv[++x];
249
            } else if(opt == "tp" || opt == "template_prefix") {
250
                Option::user_template_prefix = argv[++x];
251
            } else if(opt == "macx") {
252
                fprintf(stderr, "-macx is deprecated.\n");
253
                Option::host_mode = HOST_MACX_MODE;
254
                Option::target_mode = TARG_MACX_MODE;
255
                Option::target_mode_overridden = true;
256
            } else if(opt == "unix") {
257
                fprintf(stderr, "-unix is deprecated.\n");
258
                Option::host_mode = HOST_UNIX_MODE;
259
                Option::target_mode = TARG_UNIX_MODE;
260
                Option::target_mode_overridden = true;
261
            } else if(opt == "win32") {
262
                fprintf(stderr, "-win32 is deprecated.\n");
263
                Option::host_mode = HOST_WIN_MODE;
264
                Option::target_mode = TARG_WIN_MODE;
265
                Option::target_mode_overridden = true;
266
            } else if(opt == "integrity") {
267
                Option::target_mode = TARG_INTEGRITY_MODE;
268
            } else if(opt == "d") {
269
                Option::debug_level++;
270
            } else if(opt == "version" || opt == "v" || opt == "-version") {
271
                fprintf(stdout,
272
                        "QMake version %s\n"
273
                        "Using Qt version %s in %s\n",
274
                        qmake_version(), QT_VERSION_STR,
275
                        QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData());
276
#ifdef QMAKE_OPENSOURCE_VERSION
277
                fprintf(stdout, "QMake is Open Source software from Nokia Corporation and/or its subsidiary(-ies).\n");
278
#endif
279
                return Option::QMAKE_CMDLINE_BAIL;
280
            } else if(opt == "h" || opt == "help") {
281
                return Option::QMAKE_CMDLINE_SHOW_USAGE;
282
            } else if(opt == "Wall") {
283
                Option::warn_level |= WarnAll;
284
            } else if(opt == "Wparser") {
285
                Option::warn_level |= WarnParser;
286
            } else if(opt == "Wlogic") {
287
                Option::warn_level |= WarnLogic;
288
            } else if(opt == "Wdeprecated") {
289
                Option::warn_level |= WarnDeprecated;
290
            } else if(opt == "Wnone") {
291
                Option::warn_level = WarnNone;
292
            } else if(opt == "r" || opt == "recursive") {
293
                Option::recursive = Option::QMAKE_RECURSIVE_YES;
294
            } else if(opt == "nr" || opt == "norecursive") {
295
                Option::recursive = Option::QMAKE_RECURSIVE_NO;
296
            } else if(opt == "config") {
297
                Option::user_configs += argv[++x];
298
            } else {
299
                if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
300
                   Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
301
                    if(opt == "nodepend" || opt == "nodepends") {
302
                        Option::mkfile::do_deps = false;
303
                    } else if(opt == "nomoc") {
304
                        Option::mkfile::do_mocs = false;
305
                    } else if(opt == "nocache") {
306
                        Option::mkfile::do_cache = false;
307
                    } else if(opt == "createstub") {
308
                        Option::mkfile::do_stub_makefile = true;
309
                    } else if(opt == "nodependheuristics") {
310
                        Option::mkfile::do_dep_heuristics = false;
311
                    } else if(opt == "E") {
312
                        fprintf(stderr, "-E is deprecated. Use -d instead.\n");
313
                        Option::mkfile::do_preprocess = true;
314
                    } else if(opt == "cache") {
315
                        Option::mkfile::cachefile = argv[++x];
316
                    } else if(opt == "platform" || opt == "spec") {
317
                        Option::mkfile::qmakespec = argv[++x];
318
                        Option::mkfile::qmakespec_commandline = argv[x];
319
                    } else {
320
                        fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
321
                        return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
322
                    }
323
                } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
324
                    if(opt == "nopwd") {
325
                        Option::projfile::do_pwd = false;
326
                    } else {
327
                        fprintf(stderr, "***Unknown option -%s\n", opt.toLatin1().constData());
328
                        return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
329
                    }
330
                }
331
            }
332
        } else {
333
            QString arg = argv[x];
334
            if(arg.indexOf('=') != -1) {
335
                if(before)
336
                    Option::before_user_vars.append(arg);
337
                else
338
                    Option::after_user_vars.append(arg);
339
            } else {
340
                bool handled = true;
341
                if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
342
                    Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
343
                    Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY) {
344
                    Option::prop::properties.append(arg);
345
                } else {
346
                    QFileInfo fi(arg);
347
                    if(!fi.makeAbsolute()) //strange
348
                        arg = fi.filePath();
349
                    if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
350
                       Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
351
                        if(fi.isDir()) {
352
                            QString proj = detectProjectFile(arg);
353
                            if (!proj.isNull())
354
                                arg = proj;
355
                        }
356
                        Option::mkfile::project_files.append(arg);
357
                    } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
358
                        Option::projfile::project_dirs.append(arg);
359
                    } else {
360
                        handled = false;
361
                    }
362
                }
363
                if(!handled) {
364
                    return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
365
                }
366
            }
367
        }
368
    }
369
370
    return Option::QMAKE_CMDLINE_SUCCESS;
371
}
372
373
#ifdef Q_OS_WIN
374
static QStringList detectShellPath()
375
{
376
    QStringList paths;
377
    QString path = qgetenv("PATH");
378
    QStringList pathlist = path.toLower().split(";");
379
    for (int i = 0; i < pathlist.count(); i++) {
380
        QString maybeSh = pathlist.at(i) + "/sh.exe";
381
        if (QFile::exists(maybeSh)) {
382
            paths.append(maybeSh);
383
        }
384
    }
385
    return paths;
386
}
387
#endif
388
389
int
390
Option::init(int argc, char **argv)
391
{
392
    Option::application_argv0 = 0;
393
    Option::cpp_moc_mod = "";
394
    Option::h_moc_mod = "moc_";
395
    Option::lex_mod = "_lex";
396
    Option::yacc_mod = "_yacc";
397
    Option::prl_ext = ".prl";
398
    Option::libtool_ext = ".la";
399
    Option::pkgcfg_ext = ".pc";
400
    Option::prf_ext = ".prf";
401
    Option::js_ext = ".js";
402
    Option::ui_ext = ".ui";
403
    Option::h_ext << ".h" << ".hpp" << ".hh" << ".hxx";
404
    Option::c_ext << ".c";
405
#ifndef Q_OS_WIN
406
    Option::h_ext << ".H";
407
#endif
408
    Option::cpp_moc_ext = ".moc";
409
    Option::h_moc_ext = ".cpp";
410
    Option::cpp_ext << ".cpp" << ".cc" << ".cxx";
411
#ifndef Q_OS_WIN
412
    Option::cpp_ext << ".C";
413
#endif
414
    Option::lex_ext = ".l";
415
    Option::yacc_ext = ".y";
416
    Option::pro_ext = ".pro";
417
    Option::mmp_ext = ".mmp";
418
#ifdef Q_OS_WIN
419
    Option::dirlist_sep = ";";
420
    Option::shellPath = detectShellPath();
421
    Option::res_ext = ".res";
422
#else
423
    Option::dirlist_sep = ":";
424
    Option::shellPath = QStringList("sh");
425
#endif
426
    Option::sysenv_mod = "QMAKE_ENV_";
427
    Option::field_sep = ' ';
428
429
    if(argc && argv) {
430
        Option::application_argv0 = argv[0];
431
        QString argv0 = argv[0];
432
        if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
433
            Option::qmake_mode = default_mode(argv0);
434
        if(!argv0.isEmpty() && !QFileInfo(argv0).isRelative()) {
435
            Option::qmake_abslocation = argv0;
436
        } else if (argv0.contains(QLatin1Char('/'))
437
#ifdef Q_OS_WIN
438
		   || argv0.contains(QLatin1Char('\\'))
439
#endif
440
	    ) { //relative PWD
441
            Option::qmake_abslocation = QDir::current().absoluteFilePath(argv0);
442
        } else { //in the PATH
443
            QByteArray pEnv = qgetenv("PATH");
444
            QDir currentDir = QDir::current();
445
#ifdef Q_OS_WIN
446
            QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";"));
447
#else
448
            QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":"));
449
#endif
450
            for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
451
                if ((*p).isEmpty())
452
                    continue;
453
                QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
454
#ifdef Q_OS_WIN
455
                candidate += ".exe";
456
#endif
457
                if (QFile::exists(candidate)) {
458
                    Option::qmake_abslocation = candidate;
459
                    break;
460
                }
461
            }
462
        }
463
        if(!Option::qmake_abslocation.isNull())
464
            Option::qmake_abslocation = QDir::cleanPath(Option::qmake_abslocation);
465
    } else {
466
        Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
467
    }
468
469
    const QByteArray envflags = qgetenv("QMAKEFLAGS");
470
    if (!envflags.isNull()) {
471
        int env_argc = 0, env_size = 0, currlen=0;
472
        char quote = 0, **env_argv = NULL;
473
        for (int i = 0; i < envflags.size(); ++i) {
474
            if (!quote && (envflags.at(i) == '\'' || envflags.at(i) == '"')) {
475
                quote = envflags.at(i);
476
            } else if (envflags.at(i) == quote) {
477
                quote = 0;
478
            } else if (!quote && envflags.at(i) == ' ') {
479
                if (currlen && env_argv && env_argv[env_argc]) {
480
                    env_argv[env_argc][currlen] = '\0';
481
                    currlen = 0;
482
                    env_argc++;
483
                }
484
            } else {
485
                if(!env_argv || env_argc > env_size) {
486
                    env_argv = (char **)realloc(env_argv, sizeof(char *)*(env_size+=10));
487
                    for(int i2 = env_argc; i2 < env_size; i2++)
488
                        env_argv[i2] = NULL;
489
                }
490
                if(!env_argv[env_argc]) {
491
                    currlen = 0;
492
                    env_argv[env_argc] = (char*)malloc(255);
493
                }
494
                if(currlen < 255)
495
                    env_argv[env_argc][currlen++] = envflags.at(i);
496
            }
497
        }
498
        if(env_argv) {
499
            if(env_argv[env_argc]) {
500
                env_argv[env_argc][currlen] = '\0';
501
                currlen = 0;
502
                env_argc++;
503
            }
504
            parseCommandLine(env_argc, env_argv);
505
            for(int i2 = 0; i2 < env_size; i2++) {
506
                if(env_argv[i2])
507
                    free(env_argv[i2]);
508
            }
509
            free(env_argv);
510
        }
511
    }
512
    if(argc && argv) {
513
        int ret = parseCommandLine(argc, argv, 1);
514
        if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
515
            if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0)
516
                usage(argv[0]);
517
            return ret;
518
            //return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false;
519
        }
520
    }
521
522
    //last chance for defaults
523
    if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
524
        Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
525
        if(Option::mkfile::qmakespec.isNull() || Option::mkfile::qmakespec.isEmpty())
526
            Option::mkfile::qmakespec = QString::fromLocal8Bit(qgetenv("QMAKESPEC").constData());
527
528
        //try REALLY hard to do it for them, lazy..
529
        if(Option::mkfile::project_files.isEmpty()) {
530
            QString proj = detectProjectFile(qmake_getpwd());
531
            if(!proj.isNull())
532
                Option::mkfile::project_files.append(proj);
533
#ifndef QT_BUILD_QMAKE_LIBRARY
534
            if(Option::mkfile::project_files.isEmpty()) {
535
                usage(argv[0]);
536
                return Option::QMAKE_CMDLINE_ERROR;
537
            }
538
#endif
539
        }
540
    } else if (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
541
#if defined(Q_OS_MAC)
542
        Option::host_mode = Option::HOST_MACX_MODE;
543
        Option::target_mode = Option::TARG_MACX_MODE;
544
#elif defined(Q_OS_UNIX)
545
        Option::host_mode = Option::HOST_UNIX_MODE;
546
        Option::target_mode = Option::TARG_UNIX_MODE;
547
#else
548
        Option::host_mode = Option::HOST_WIN_MODE;
549
        Option::target_mode = Option::TARG_WIN_MODE;
550
#endif
551
    }
552
553
    //defaults for globals
554
    if (Option::host_mode != Option::HOST_UNKNOWN_MODE)
555
        applyHostMode();
556
    return QMAKE_CMDLINE_SUCCESS;
557
}
558
559
void Option::applyHostMode()
560
{
561
   if (Option::host_mode == Option::HOST_WIN_MODE) {
562
       Option::dir_sep = "\\";
563
       Option::obj_ext = ".obj";
564
   } else {
565
       Option::dir_sep = "/";
566
       Option::obj_ext = ".o";
567
   }
568
}
569
570
bool Option::postProcessProject(QMakeProject *project)
571
{
572
    Option::cpp_ext = project->variables()["QMAKE_EXT_CPP"];
573
    if(cpp_ext.isEmpty())
574
        cpp_ext << ".cpp"; //something must be there
575
    Option::h_ext = project->variables()["QMAKE_EXT_H"];
576
    if(h_ext.isEmpty())
577
        h_ext << ".h";
578
    Option::c_ext = project->variables()["QMAKE_EXT_C"];
579
    if(c_ext.isEmpty())
580
        c_ext << ".c"; //something must be there
581
582
    if(!project->isEmpty("QMAKE_EXT_RES"))
583
        Option::res_ext = project->first("QMAKE_EXT_RES");
584
    if(!project->isEmpty("QMAKE_EXT_PKGCONFIG"))
585
        Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG");
586
    if(!project->isEmpty("QMAKE_EXT_LIBTOOL"))
587
        Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL");
588
    if(!project->isEmpty("QMAKE_EXT_PRL"))
589
        Option::prl_ext = project->first("QMAKE_EXT_PRL");
590
    if(!project->isEmpty("QMAKE_EXT_PRF"))
591
        Option::prf_ext = project->first("QMAKE_EXT_PRF");
592
    if(!project->isEmpty("QMAKE_EXT_JS"))
593
        Option::prf_ext = project->first("QMAKE_EXT_JS");
594
    if(!project->isEmpty("QMAKE_EXT_UI"))
595
        Option::ui_ext = project->first("QMAKE_EXT_UI");
596
    if(!project->isEmpty("QMAKE_EXT_CPP_MOC"))
597
        Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC");
598
    if(!project->isEmpty("QMAKE_EXT_H_MOC"))
599
        Option::h_moc_ext = project->first("QMAKE_EXT_H_MOC");
600
    if(!project->isEmpty("QMAKE_EXT_LEX"))
601
        Option::lex_ext = project->first("QMAKE_EXT_LEX");
602
    if(!project->isEmpty("QMAKE_EXT_YACC"))
603
        Option::yacc_ext = project->first("QMAKE_EXT_YACC");
604
    if(!project->isEmpty("QMAKE_EXT_OBJ"))
605
        Option::obj_ext = project->first("QMAKE_EXT_OBJ");
606
    if(!project->isEmpty("QMAKE_H_MOD_MOC"))
607
        Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC");
608
    if(!project->isEmpty("QMAKE_CPP_MOD_MOC"))
609
        Option::cpp_moc_mod = project->first("QMAKE_CPP_MOD_MOC");
610
    if(!project->isEmpty("QMAKE_MOD_LEX"))
611
        Option::lex_mod = project->first("QMAKE_MOD_LEX");
612
    if(!project->isEmpty("QMAKE_MOD_YACC"))
613
        Option::yacc_mod = project->first("QMAKE_MOD_YACC");
614
    if(!project->isEmpty("QMAKE_DIR_SEP"))
615
        Option::dir_sep = project->first("QMAKE_DIR_SEP");
616
    if(!project->isEmpty("QMAKE_DIRLIST_SEP"))
617
        Option::dirlist_sep = project->first("QMAKE_DIRLIST_SEP");
618
    if(!project->isEmpty("QMAKE_MOD_SYSTEM_ENV"))
619
        Option::sysenv_mod = project->first("QMAKE_MOD_SYSTEM_ENV");
620
    return true;
621
}
622
623
QString
624
Option::fixString(QString string, uchar flags)
625
{
626
    //const QString orig_string = string;
627
    static QHash<FixStringCacheKey, QString> *cache = 0;
628
    if(!cache) {
629
        cache = new QHash<FixStringCacheKey, QString>;
630
        qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FixStringCacheKey, QString> >, (void**)&cache);
631
    }
632
    FixStringCacheKey cacheKey(string, flags);
633
634
    QHash<FixStringCacheKey, QString>::const_iterator it = cache->constFind(cacheKey);
635
636
    if (it != cache->constEnd()) {
637
        //qDebug() << "Fix (cached) " << orig_string << "->" << it.value();
638
        return it.value();
639
    }
640
641
    //fix the environment variables
642
    if(flags & Option::FixEnvVars) {
643
        int rep;
644
        static QRegExp reg_var("\\$\\(.*\\)");
645
        reg_var.setMinimal(true);
646
        while((rep = reg_var.indexIn(string)) != -1)
647
            string.replace(rep, reg_var.matchedLength(),
648
                           QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData()));
649
    }
650
651
    //canonicalize it (and treat as a path)
652
    if(flags & Option::FixPathCanonicalize) {
653
#if 0
654
        string = QFileInfo(string).canonicalFilePath();
655
#endif
656
        string = QDir::cleanPath(string);
657
    }
658
659
    if(string.length() > 2 && string[0].isLetter() && string[1] == QLatin1Char(':'))
660
        string[0] = string[0].toLower();
661
662
    //fix separators
663
    Q_ASSERT(!((flags & Option::FixPathToLocalSeparators) && (flags & Option::FixPathToTargetSeparators)));
664
    if(flags & Option::FixPathToLocalSeparators) {
665
#if defined(Q_OS_WIN32)
666
        string = string.replace('/', '\\');
667
#else
668
        string = string.replace('\\', '/');
669
#endif
670
    } else if(flags & Option::FixPathToTargetSeparators) {
671
        string = string.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
672
    }
673
674
    if ((string.startsWith("\"") && string.endsWith("\"")) ||
675
        (string.startsWith("\'") && string.endsWith("\'")))
676
        string = string.mid(1, string.length()-2);
677
678
    //cache
679
    //qDebug() << "Fix" << orig_string << "->" << string;
680
    cache->insert(cacheKey, string);
681
    return string;
682
}
683
684
const char *qmake_version()
685
{
686
    static char *ret = NULL;
687
    if(ret)
688
        return ret;
689
    ret = (char *)malloc(15);
690
    qmakeAddCacheClear(qmakeFreeCacheClear, (void**)&ret);
691
#if defined(_MSC_VER) && _MSC_VER >= 1400
692
    sprintf_s(ret, 15, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
693
#else
694
    sprintf(ret, "%d.%02d%c", QMAKE_VERSION_MAJOR, QMAKE_VERSION_MINOR, 'a' + QMAKE_VERSION_PATCH);
695
#endif
696
    return ret;
697
}
698
699
void debug_msg_internal(int level, const char *fmt, ...)
700
{
701
    if(Option::debug_level < level)
702
        return;
703
    fprintf(stderr, "DEBUG %d: ", level);
704
    {
705
        va_list ap;
706
        va_start(ap, fmt);
707
        vfprintf(stderr, fmt, ap);
708
        va_end(ap);
709
    }
710
    fprintf(stderr, "\n");
711
}
712
713
void warn_msg(QMakeWarn type, const char *fmt, ...)
714
{
715
    if(!(Option::warn_level & type))
716
        return;
717
    fprintf(stderr, "WARNING: ");
718
    {
719
        va_list ap;
720
        va_start(ap, fmt);
721
        vfprintf(stderr, fmt, ap);
722
        va_end(ap);
723
    }
724
    fprintf(stderr, "\n");
725
}
726
727
class QMakeCacheClearItem {
728
private:
729
    qmakeCacheClearFunc func;
730
    void **data;
731
public:
732
    QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
733
    ~QMakeCacheClearItem() {
734
        (*func)(*data);
735
        *data = 0;
736
    }
737
};
738
static QList<QMakeCacheClearItem*> cache_items;
739
740
void
741
qmakeClearCaches()
742
{
743
    qDeleteAll(cache_items);
744
    cache_items.clear();
745
}
746
747
void
748
qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
749
{
750
    cache_items.append(new QMakeCacheClearItem(func, data));
751
}
752
753
QString qmake_libraryInfoFile()
754
{
755
    if(!Option::qmake_abslocation.isEmpty())
756
        return QDir(QFileInfo(Option::qmake_abslocation).absolutePath()).filePath("qt.conf");
757
    return QString();
758
}
759
760
QT_END_NAMESPACE