Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the qmake application of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include "option.h" |
30 | #include "cachekeys.h" |
31 | #include <ioutils.h> |
32 | #include <qdir.h> |
33 | #include <qregexp.h> |
34 | #include <qhash.h> |
35 | #include <qdebug.h> |
36 | #include <qlibraryinfo.h> |
37 | #include <stdlib.h> |
38 | #include <stdarg.h> |
39 | |
40 | QT_BEGIN_NAMESPACE |
41 | |
42 | using namespace QMakeInternal; |
43 | |
44 | EvalHandler Option::evalHandler; |
45 | QMakeGlobals *Option::globals; |
46 | ProFileCache *Option::proFileCache; |
47 | QMakeVfs *Option::vfs; |
48 | QMakeParser *Option::parser; |
49 | |
50 | //convenience |
51 | QString Option::prf_ext; |
52 | QString Option::prl_ext; |
53 | QString Option::libtool_ext; |
54 | QString Option::pkgcfg_ext; |
55 | QString Option::ui_ext; |
56 | QStringList Option::h_ext; |
57 | QString Option::cpp_moc_ext; |
58 | QStringList Option::cpp_ext; |
59 | QStringList Option::c_ext; |
60 | QString Option::objc_ext; |
61 | QString Option::objcpp_ext; |
62 | QString Option::obj_ext; |
63 | QString Option::lex_ext; |
64 | QString Option::yacc_ext; |
65 | QString Option::pro_ext; |
66 | QString Option::dir_sep; |
67 | QString Option::h_moc_mod; |
68 | QString Option::yacc_mod; |
69 | QString Option::lex_mod; |
70 | QString Option::res_ext; |
71 | char Option::field_sep; |
72 | |
73 | //mode |
74 | Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING; |
75 | |
76 | //all modes |
77 | int Option::warn_level = WarnLogic | WarnDeprecated; |
78 | int Option::debug_level = 0; |
79 | QFile Option::output; |
80 | QString Option::output_dir; |
81 | bool Option::recursive = false; |
82 | |
83 | //QMAKE_*_PROPERTY stuff |
84 | QStringList Option::prop::properties; |
85 | |
86 | //QMAKE_GENERATE_PROJECT stuff |
87 | bool Option::projfile::do_pwd = true; |
88 | QStringList Option::projfile::project_dirs; |
89 | |
90 | //QMAKE_GENERATE_MAKEFILE stuff |
91 | int Option::mkfile::cachefile_depth = -1; |
92 | bool Option::mkfile::do_deps = true; |
93 | bool Option::mkfile::do_mocs = true; |
94 | bool Option::mkfile::do_dep_heuristics = true; |
95 | bool Option::mkfile::do_preprocess = false; |
96 | bool Option::mkfile::do_stub_makefile = false; |
97 | QStringList Option::mkfile::project_files; |
98 | |
99 | static Option::QMAKE_MODE default_mode(QString progname) |
100 | { |
101 | int s = progname.lastIndexOf(QDir::separator()); |
102 | if(s != -1) |
103 | progname = progname.right(progname.length() - (s + 1)); |
104 | if(progname == "qmakegen") |
105 | return Option::QMAKE_GENERATE_PROJECT; |
106 | else if(progname == "qt-config") |
107 | return Option::QMAKE_QUERY_PROPERTY; |
108 | return Option::QMAKE_GENERATE_MAKEFILE; |
109 | } |
110 | |
111 | static QString detectProjectFile(const QString &path) |
112 | { |
113 | QString ret; |
114 | QDir dir(path); |
115 | if(dir.exists(dir.dirName() + Option::pro_ext)) { |
116 | ret = dir.filePath(dir.dirName()) + Option::pro_ext; |
117 | } else { //last try.. |
118 | QStringList profiles = dir.entryList(QStringList("*"+ Option::pro_ext)); |
119 | if(profiles.count() == 1) |
120 | ret = dir.filePath(profiles.at(0)); |
121 | } |
122 | return ret; |
123 | } |
124 | |
125 | QString project_builtin_regx(); |
126 | bool usage(const char *a0) |
127 | { |
128 | fprintf(stdout, "Usage: %s [mode] [options] [files]\n" |
129 | "\n" |
130 | "QMake has two modes, one mode for generating project files based on\n" |
131 | "some heuristics, and the other for generating makefiles. Normally you\n" |
132 | "shouldn't need to specify a mode, as makefile generation is the default\n" |
133 | "mode for qmake, but you may use this to test qmake on an existing project\n" |
134 | "\n" |
135 | "Mode:\n" |
136 | " -project Put qmake into project file generation mode%s\n" |
137 | " In this mode qmake interprets files as files to\n" |
138 | " be built,\n" |
139 | " defaults to %s\n" |
140 | " Note: The created .pro file probably will \n" |
141 | " need to be edited. For example add the QT variable to \n" |
142 | " specify what modules are required.\n" |
143 | " -makefile Put qmake into makefile generation mode%s\n" |
144 | " In this mode qmake interprets files as project files to\n" |
145 | " be processed, if skipped qmake will try to find a project\n" |
146 | " file in your current working directory\n" |
147 | "\n" |
148 | "Warnings Options:\n" |
149 | " -Wnone Turn off all warnings; specific ones may be re-enabled by\n" |
150 | " later -W options\n" |
151 | " -Wall Turn on all warnings\n" |
152 | " -Wparser Turn on parser warnings\n" |
153 | " -Wlogic Turn on logic warnings (on by default)\n" |
154 | " -Wdeprecated Turn on deprecation warnings (on by default)\n" |
155 | "\n" |
156 | "Options:\n" |
157 | " * You can place any variable assignment in options and it will be *\n" |
158 | " * processed as if it was in [files]. These assignments will be *\n" |
159 | " * processed before [files] by default. *\n" |
160 | " -o file Write output to file\n" |
161 | " -d Increase debug level\n" |
162 | " -t templ Overrides TEMPLATE as templ\n" |
163 | " -tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n" |
164 | " -help This help\n" |
165 | " -v Version information\n" |
166 | " -early All subsequent variable assignments will be\n" |
167 | " parsed right before default_pre.prf\n" |
168 | " -before All subsequent variable assignments will be\n" |
169 | " parsed right before [files] (the default)\n" |
170 | " -after All subsequent variable assignments will be\n" |
171 | " parsed after [files]\n" |
172 | " -late All subsequent variable assignments will be\n" |
173 | " parsed right after default_post.prf\n" |
174 | " -norecursive Don't do a recursive search\n" |
175 | " -recursive Do a recursive search\n" |
176 | " -set <prop> <value> Set persistent property\n" |
177 | " -unset <prop> Unset persistent property\n" |
178 | " -query <prop> Query persistent property. Show all if <prop> is empty.\n" |
179 | " -qtconf file Use file instead of looking for qt.conf\n" |
180 | " -cache file Use file as cache [makefile mode only]\n" |
181 | " -spec spec Use spec as QMAKESPEC [makefile mode only]\n" |
182 | " -nocache Don't use a cache file [makefile mode only]\n" |
183 | " -nodepend Don't generate dependencies [makefile mode only]\n" |
184 | " -nomoc Don't generate moc targets [makefile mode only]\n" |
185 | " -nopwd Don't look for files in pwd [project mode only]\n" |
186 | ,a0, |
187 | default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)": "", project_builtin_regx().toLatin1().constData(), |
188 | default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)": "" |
189 | ); |
190 | return false; |
191 | } |
192 | |
193 | int |
194 | Option::parseCommandLine(QStringList &args, QMakeCmdLineParserState &state) |
195 | { |
196 | enum { ArgNone, ArgOutput } argState = ArgNone; |
197 | int x = 0; |
198 | while (x < args.count()) { |
199 | switch (argState) { |
200 | case ArgOutput: |
201 | Option::output.setFileName(args.at(x--)); |
202 | args.erase(args.begin() + x, args.begin() + x + 2); |
203 | argState = ArgNone; |
204 | continue; |
205 | default: |
206 | QMakeGlobals::ArgumentReturn cmdRet = globals->addCommandLineArguments(state, args, &x); |
207 | if (cmdRet == QMakeGlobals::ArgumentsOk) |
208 | break; |
209 | if (cmdRet == QMakeGlobals::ArgumentMalformed) { |
210 | fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1))); |
211 | return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR; |
212 | } |
213 | Q_ASSERT(cmdRet == QMakeGlobals::ArgumentUnknown); |
214 | QString arg = args.at(x); |
215 | if (arg.startsWith(QLatin1Char('-'))) { |
216 | if (arg == "-d") { |
217 | Option::debug_level++; |
218 | } else if (arg == "-v"|| arg == "-version"|| arg == "--version") { |
219 | fprintf(stdout, |
220 | "QMake version %s\n" |
221 | "Using Qt version %s in %s\n", |
222 | QMAKE_VERSION_STR, QT_VERSION_STR, |
223 | QLibraryInfo::location(QLibraryInfo::LibrariesPath).toLatin1().constData()); |
224 | #ifdef QMAKE_OPENSOURCE_VERSION |
225 | fprintf(stdout, "QMake is Open Source software from The Qt Company Ltd and/or its subsidiary(-ies).\n"); |
226 | #endif |
227 | return Option::QMAKE_CMDLINE_BAIL; |
228 | } else if (arg == "-h"|| arg == "-help"|| arg == "--help") { |
229 | return Option::QMAKE_CMDLINE_SHOW_USAGE; |
230 | } else if (arg == "-Wall") { |
231 | Option::warn_level |= WarnAll; |
232 | } else if (arg == "-Wparser") { |
233 | Option::warn_level |= WarnParser; |
234 | } else if (arg == "-Wlogic") { |
235 | Option::warn_level |= WarnLogic; |
236 | } else if (arg == "-Wdeprecated") { |
237 | Option::warn_level |= WarnDeprecated; |
238 | } else if (arg == "-Wnone") { |
239 | Option::warn_level = WarnNone; |
240 | } else if (arg == "-r"|| arg == "-recursive") { |
241 | Option::recursive = true; |
242 | args.removeAt(x); |
243 | continue; |
244 | } else if (arg == "-nr"|| arg == "-norecursive") { |
245 | Option::recursive = false; |
246 | args.removeAt(x); |
247 | continue; |
248 | } else if (arg == "-o"|| arg == "-output") { |
249 | argState = ArgOutput; |
250 | } else { |
251 | if (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || |
252 | Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { |
253 | if (arg == "-nodepend"|| arg == "-nodepends") { |
254 | Option::mkfile::do_deps = false; |
255 | } else if (arg == "-nomoc") { |
256 | Option::mkfile::do_mocs = false; |
257 | } else if (arg == "-createstub") { |
258 | Option::mkfile::do_stub_makefile = true; |
259 | } else if (arg == "-nodependheuristics") { |
260 | Option::mkfile::do_dep_heuristics = false; |
261 | } else if (arg == "-E") { |
262 | Option::mkfile::do_preprocess = true; |
263 | } else { |
264 | fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData()); |
265 | return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR; |
266 | } |
267 | } else if (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { |
268 | if (arg == "-nopwd") { |
269 | Option::projfile::do_pwd = false; |
270 | } else { |
271 | fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData()); |
272 | return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR; |
273 | } |
274 | } |
275 | } |
276 | } else { |
277 | bool handled = true; |
278 | if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY || |
279 | Option::qmake_mode == Option::QMAKE_SET_PROPERTY || |
280 | Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY) { |
281 | Option::prop::properties.append(arg); |
282 | } else { |
283 | QFileInfo fi(arg); |
284 | if(!fi.makeAbsolute()) //strange |
285 | arg = fi.filePath(); |
286 | if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || |
287 | Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { |
288 | if(fi.isDir()) { |
289 | QString proj = detectProjectFile(arg); |
290 | if (!proj.isNull()) |
291 | arg = proj; |
292 | } |
293 | Option::mkfile::project_files.append(arg); |
294 | } else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { |
295 | Option::projfile::project_dirs.append(arg); |
296 | } else { |
297 | handled = false; |
298 | } |
299 | } |
300 | if(!handled) { |
301 | return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR; |
302 | } |
303 | args.removeAt(x); |
304 | continue; |
305 | } |
306 | } |
307 | x++; |
308 | } |
309 | if (argState != ArgNone) { |
310 | fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1))); |
311 | return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR; |
312 | } |
313 | return Option::QMAKE_CMDLINE_SUCCESS; |
314 | } |
315 | |
316 | int |
317 | Option::init(int argc, char **argv) |
318 | { |
319 | Option::prf_ext = ".prf"; |
320 | Option::pro_ext = ".pro"; |
321 | Option::field_sep = ' '; |
322 | |
323 | if(argc && argv) { |
324 | QString argv0 = argv[0]; |
325 | #ifdef Q_OS_WIN |
326 | if (!argv0.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive)) |
327 | argv0 += QLatin1String(".exe"); |
328 | #endif |
329 | if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING) |
330 | Option::qmake_mode = default_mode(argv0); |
331 | if (!argv0.isEmpty() && IoUtils::isAbsolutePath(argv0)) { |
332 | globals->qmake_abslocation = argv0; |
333 | } else if (argv0.contains(QLatin1Char('/')) |
334 | #ifdef Q_OS_WIN |
335 | || argv0.contains(QLatin1Char('\\')) |
336 | #endif |
337 | ) { //relative PWD |
338 | globals->qmake_abslocation = QDir::current().absoluteFilePath(argv0); |
339 | } else { //in the PATH |
340 | QByteArray pEnv = qgetenv("PATH"); |
341 | QDir currentDir = QDir::current(); |
342 | #ifdef Q_OS_WIN |
343 | QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";")); |
344 | paths.prepend(QLatin1String(".")); |
345 | #else |
346 | QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":")); |
347 | #endif |
348 | for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) { |
349 | if ((*p).isEmpty()) |
350 | continue; |
351 | QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0); |
352 | if (QFile::exists(candidate)) { |
353 | globals->qmake_abslocation = candidate; |
354 | break; |
355 | } |
356 | } |
357 | } |
358 | if (Q_UNLIKELY(globals->qmake_abslocation.isNull())) { |
359 | // This is rather unlikely to ever happen on a modern system ... |
360 | globals->qmake_abslocation = QLibraryInfo::rawLocation( |
361 | QLibraryInfo::HostBinariesPath, |
362 | QLibraryInfo::EffectivePaths) |
363 | #ifdef Q_OS_WIN |
364 | + "/qmake.exe"; |
365 | #else |
366 | + "/qmake"; |
367 | #endif |
368 | } else { |
369 | globals->qmake_abslocation = QDir::cleanPath(globals->qmake_abslocation); |
370 | } |
371 | } else { |
372 | Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE; |
373 | } |
374 | |
375 | QMakeCmdLineParserState cmdstate(QDir::currentPath()); |
376 | const QByteArray envflags = qgetenv("QMAKEFLAGS"); |
377 | if (!envflags.isNull()) { |
378 | QStringList args; |
379 | QByteArray buf = ""; |
380 | char quote = 0; |
381 | bool hasWord = false; |
382 | for (int i = 0; i < envflags.size(); ++i) { |
383 | char c = envflags.at(i); |
384 | if (!quote && (c == '\'' || c == '"')) { |
385 | quote = c; |
386 | } else if (c == quote) { |
387 | quote = 0; |
388 | } else if (!quote && c == ' ') { |
389 | if (hasWord) { |
390 | args << QString::fromLocal8Bit(buf); |
391 | hasWord = false; |
392 | buf = ""; |
393 | } |
394 | } else { |
395 | buf += c; |
396 | hasWord = true; |
397 | } |
398 | } |
399 | if (hasWord) |
400 | args << QString::fromLocal8Bit(buf); |
401 | parseCommandLine(args, cmdstate); |
402 | cmdstate.flush(); |
403 | } |
404 | if(argc && argv) { |
405 | QStringList args; |
406 | args.reserve(argc - 1); |
407 | for (int i = 1; i < argc; i++) |
408 | args << QString::fromLocal8Bit(argv[i]); |
409 | |
410 | while (!args.isEmpty()) { |
411 | QString opt = args.at(0); |
412 | if (opt == "-project") { |
413 | Option::recursive = true; |
414 | Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT; |
415 | } else if (opt == "-prl") { |
416 | Option::mkfile::do_deps = false; |
417 | Option::mkfile::do_mocs = false; |
418 | Option::qmake_mode = Option::QMAKE_GENERATE_PRL; |
419 | } else if (opt == "-set") { |
420 | Option::qmake_mode = Option::QMAKE_SET_PROPERTY; |
421 | } else if (opt == "-unset") { |
422 | Option::qmake_mode = Option::QMAKE_UNSET_PROPERTY; |
423 | } else if (opt == "-query") { |
424 | Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY; |
425 | } else if (opt == "-makefile") { |
426 | Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE; |
427 | } else { |
428 | break; |
429 | } |
430 | args.takeFirst(); |
431 | break; |
432 | } |
433 | |
434 | int ret = parseCommandLine(args, cmdstate); |
435 | if(ret != Option::QMAKE_CMDLINE_SUCCESS) { |
436 | if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0) |
437 | usage(argv[0]); |
438 | return ret; |
439 | //return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false; |
440 | } |
441 | globals->qmake_args = args; |
442 | globals->qmake_extra_args = cmdstate.extraargs; |
443 | } |
444 | globals->commitCommandLineArguments(cmdstate); |
445 | globals->debugLevel = Option::debug_level; |
446 | |
447 | //last chance for defaults |
448 | if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || |
449 | Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { |
450 | globals->useEnvironment(); |
451 | |
452 | //try REALLY hard to do it for them, lazy.. |
453 | if(Option::mkfile::project_files.isEmpty()) { |
454 | QString proj = detectProjectFile(qmake_getpwd()); |
455 | if(!proj.isNull()) |
456 | Option::mkfile::project_files.append(proj); |
457 | #ifndef QT_BUILD_QMAKE_LIBRARY |
458 | if(Option::mkfile::project_files.isEmpty()) { |
459 | usage(argv[0]); |
460 | return Option::QMAKE_CMDLINE_ERROR; |
461 | } |
462 | #endif |
463 | } |
464 | } |
465 | |
466 | return QMAKE_CMDLINE_SUCCESS; |
467 | } |
468 | |
469 | void Option::prepareProject(const QString &pfile) |
470 | { |
471 | // Canonicalize only the directory, otherwise things will go haywire |
472 | // if the file itself is a symbolic link. |
473 | const QString srcpath = QFileInfo(QFileInfo(pfile).absolutePath()).canonicalFilePath(); |
474 | globals->setDirectories(srcpath, output_dir); |
475 | } |
476 | |
477 | bool Option::postProcessProject(QMakeProject *project) |
478 | { |
479 | Option::cpp_ext = project->values("QMAKE_EXT_CPP").toQStringList(); |
480 | Option::h_ext = project->values("QMAKE_EXT_H").toQStringList(); |
481 | Option::c_ext = project->values("QMAKE_EXT_C").toQStringList(); |
482 | Option::objc_ext = project->first("QMAKE_EXT_OBJC").toQString(); |
483 | Option::objcpp_ext = project->first("QMAKE_EXT_OBJCXX").toQString(); |
484 | Option::res_ext = project->first("QMAKE_EXT_RES").toQString(); |
485 | Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG").toQString(); |
486 | Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL").toQString(); |
487 | Option::prl_ext = project->first("QMAKE_EXT_PRL").toQString(); |
488 | Option::ui_ext = project->first("QMAKE_EXT_UI").toQString(); |
489 | Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC").toQString(); |
490 | Option::lex_ext = project->first("QMAKE_EXT_LEX").toQString(); |
491 | Option::yacc_ext = project->first("QMAKE_EXT_YACC").toQString(); |
492 | Option::obj_ext = project->first("QMAKE_EXT_OBJ").toQString(); |
493 | Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC").toQString(); |
494 | Option::lex_mod = project->first("QMAKE_MOD_LEX").toQString(); |
495 | Option::yacc_mod = project->first("QMAKE_MOD_YACC").toQString(); |
496 | |
497 | Option::dir_sep = project->dirSep().toQString(); |
498 | |
499 | if (!project->buildRoot().isEmpty() && Option::output_dir.startsWith(project->buildRoot())) |
500 | Option::mkfile::cachefile_depth = |
501 | Option::output_dir.mid(project->buildRoot().length()).count('/'); |
502 | |
503 | return true; |
504 | } |
505 | |
506 | QString |
507 | Option::fixString(QString string, uchar flags) |
508 | { |
509 | //const QString orig_string = string; |
510 | static QHash<FixStringCacheKey, QString> *cache = nullptr; |
511 | if(!cache) { |
512 | cache = new QHash<FixStringCacheKey, QString>; |
513 | qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FixStringCacheKey, QString> >, (void**)&cache); |
514 | } |
515 | FixStringCacheKey cacheKey(string, flags); |
516 | |
517 | QHash<FixStringCacheKey, QString>::const_iterator it = cache->constFind(cacheKey); |
518 | |
519 | if (it != cache->constEnd()) { |
520 | //qDebug() << "Fix (cached) " << orig_string << "->" << it.value(); |
521 | return it.value(); |
522 | } |
523 | |
524 | //fix the environment variables |
525 | if(flags & Option::FixEnvVars) { |
526 | int rep; |
527 | static QRegExp reg_var("\\$\\(.*\\)"); |
528 | reg_var.setMinimal(true); |
529 | while((rep = reg_var.indexIn(string)) != -1) |
530 | string.replace(rep, reg_var.matchedLength(), |
531 | QString::fromLocal8Bit(qgetenv(string.mid(rep + 2, reg_var.matchedLength() - 3).toLatin1().constData()).constData())); |
532 | } |
533 | |
534 | //canonicalize it (and treat as a path) |
535 | if(flags & Option::FixPathCanonicalize) { |
536 | #if 0 |
537 | string = QFileInfo(string).canonicalFilePath(); |
538 | #endif |
539 | string = QDir::cleanPath(string); |
540 | } |
541 | |
542 | // either none or only one active flag |
543 | Q_ASSERT(((flags & Option::FixPathToLocalSeparators) != 0) + |
544 | ((flags & Option::FixPathToTargetSeparators) != 0) + |
545 | ((flags & Option::FixPathToNormalSeparators) != 0) <= 1); |
546 | |
547 | //fix separators |
548 | if (flags & Option::FixPathToNormalSeparators) { |
549 | string.replace('\\', '/'); |
550 | } else if (flags & Option::FixPathToLocalSeparators) { |
551 | #if defined(Q_OS_WIN32) |
552 | string.replace('/', '\\'); |
553 | #else |
554 | string.replace('\\', '/'); |
555 | #endif |
556 | } else if(flags & Option::FixPathToTargetSeparators) { |
557 | string.replace('/', Option::dir_sep).replace('\\', Option::dir_sep); |
558 | } |
559 | |
560 | if ((string.startsWith("\"") && string.endsWith( "\"")) || |
561 | (string.startsWith("\'") && string.endsWith( "\'"))) |
562 | string = string.mid(1, string.length()-2); |
563 | |
564 | //cache |
565 | //qDebug() << "Fix" << orig_string << "->" << string; |
566 | cache->insert(cacheKey, string); |
567 | return string; |
568 | } |
569 | |
570 | void debug_msg_internal(int level, const char *fmt, ...) |
571 | { |
572 | if(Option::debug_level < level) |
573 | return; |
574 | fprintf(stderr, "DEBUG %d: ", level); |
575 | { |
576 | va_list ap; |
577 | va_start(ap, fmt); |
578 | vfprintf(stderr, fmt, ap); |
579 | va_end(ap); |
580 | } |
581 | fprintf(stderr, "\n"); |
582 | } |
583 | |
584 | void warn_msg(QMakeWarn type, const char *fmt, ...) |
585 | { |
586 | if(!(Option::warn_level & type)) |
587 | return; |
588 | fprintf(stderr, "WARNING: "); |
589 | { |
590 | va_list ap; |
591 | va_start(ap, fmt); |
592 | vfprintf(stderr, fmt, ap); |
593 | va_end(ap); |
594 | } |
595 | fprintf(stderr, "\n"); |
596 | } |
597 | |
598 | void EvalHandler::message(int type, const QString &msg, const QString &fileName, int lineNo) |
599 | { |
600 | QString pfx; |
601 | if ((type & QMakeHandler::CategoryMask) == QMakeHandler::WarningMessage) { |
602 | int code = (type & QMakeHandler::CodeMask); |
603 | if ((code == QMakeHandler::WarnLanguage && !(Option::warn_level & WarnParser)) |
604 | || (code == QMakeHandler::WarnDeprecated && !(Option::warn_level & WarnDeprecated))) |
605 | return; |
606 | pfx = QString::fromLatin1("WARNING: "); |
607 | } |
608 | if (lineNo > 0) |
609 | fprintf(stderr, "%s%s:%d: %s\n", qPrintable(pfx), qPrintable(fileName), lineNo, qPrintable(msg)); |
610 | else if (lineNo) |
611 | fprintf(stderr, "%s%s: %s\n", qPrintable(pfx), qPrintable(fileName), qPrintable(msg)); |
612 | else |
613 | fprintf(stderr, "%s%s\n", qPrintable(pfx), qPrintable(msg)); |
614 | } |
615 | |
616 | void EvalHandler::fileMessage(int type, const QString &msg) |
617 | { |
618 | Q_UNUSED(type) |
619 | fprintf(stderr, "%s\n", qPrintable(msg)); |
620 | } |
621 | |
622 | void EvalHandler::aboutToEval(ProFile *, ProFile *, EvalFileType) |
623 | { |
624 | } |
625 | |
626 | void EvalHandler::doneWithEval(ProFile *) |
627 | { |
628 | } |
629 | |
630 | class QMakeCacheClearItem { |
631 | private: |
632 | qmakeCacheClearFunc func; |
633 | void **data; |
634 | public: |
635 | QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { } |
636 | ~QMakeCacheClearItem() { |
637 | (*func)(*data); |
638 | *data = nullptr; |
639 | } |
640 | }; |
641 | static QList<QMakeCacheClearItem*> cache_items; |
642 | |
643 | void |
644 | qmakeClearCaches() |
645 | { |
646 | qDeleteAll(cache_items); |
647 | cache_items.clear(); |
648 | } |
649 | |
650 | void |
651 | qmakeAddCacheClear(qmakeCacheClearFunc func, void **data) |
652 | { |
653 | cache_items.append(new QMakeCacheClearItem(func, data)); |
654 | } |
655 | |
656 | QString qmake_libraryInfoFile() |
657 | { |
658 | if (!Option::globals->qtconf.isEmpty()) |
659 | return Option::globals->qtconf; |
660 | if (!Option::globals->qmake_abslocation.isEmpty()) |
661 | return QDir(QFileInfo(Option::globals->qmake_abslocation).absolutePath()).filePath("qt.conf"); |
662 | return QString(); |
663 | } |
664 | |
665 | QT_END_NAMESPACE |
666 |
Warning: That file was not part of the compilation database. It may have many parsing errors.