Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
4
5#include <depfile_shared.h>
6#include "preprocessor.h"
7#include "moc.h"
8#include "outputrevision.h"
9#include "collectjson.h"
10
11#include <qfile.h>
12#include <qfileinfo.h>
13#include <qdir.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <ctype.h>
17#include <errno.h>
18
19#include <qcoreapplication.h>
20#include <qcommandlineoption.h>
21#include <qcommandlineparser.h>
22
23#include <memory>
24
26
27using namespace Qt::StringLiterals;
28
29/*
30 This function looks at two file names and returns the name of the
31 infile with a path relative to outfile.
32
33 Examples:
34
35 /tmp/abc, /tmp/bcd -> abc
36 xyz/a/bc, xyz/b/ac -> ../a/bc
37 /tmp/abc, xyz/klm -> /tmp/abc
38 */
39
40static QByteArray combinePath(const QString &infile, const QString &outfile)
41{
42 QFileInfo inFileInfo(QDir::current(), infile);
43 QFileInfo outFileInfo(QDir::current(), outfile);
44 const QByteArray relativePath = QFile::encodeName(outFileInfo.dir().relativeFilePath(inFileInfo.filePath()));
45#ifdef Q_OS_WIN
46 // It's a system limitation.
47 // It depends on the Win API function which is used by the program to open files.
48 // cl apparently uses the functions that have the MAX_PATH limitation.
49 if (outFileInfo.dir().absolutePath().length() + relativePath.length() + 1 >= 260)
50 return QFile::encodeName(inFileInfo.absoluteFilePath());
51#endif
52 return relativePath;
53}
54
55
56void error(const char *msg = "Invalid argument")
57{
58 if (msg)
59 fprintf(stderr, "moc: %s\n", msg);
60}
61
62static auto openFileForWriting(const QString &name)
63{
64 struct Closer { void operator()(FILE *handle) const { fclose(handle); } };
65 using R = std::unique_ptr<FILE, Closer>;
66
67#ifdef _MSC_VER
68 FILE *file;
69 if (_wfopen_s(&file, reinterpret_cast<const wchar_t *>(name.utf16()), L"w") != 0)
70 return R{};
71 return R{file};
72#else
73 return R{fopen(QFile::encodeName(name).constData(), "w")};
74#endif
75}
76using File = decltype(openFileForWriting({}));
77
78static inline bool hasNext(const Symbols &symbols, int i)
79{ return (i < symbols.size()); }
80
81static inline const Symbol &next(const Symbols &symbols, int &i)
82{ return symbols.at(i++); }
83
84
87 int lineNum = 1;
88 Token last = PP_NOTOKEN;
89 Token secondlast = last;
90 int i = 0;
91 while (hasNext(symbols, i)) {
92 Symbol sym = next(symbols, i);
93 switch (sym.token) {
94 case PP_NEWLINE:
95 case PP_WHITESPACE:
96 if (last != PP_WHITESPACE) {
97 secondlast = last;
98 last = PP_WHITESPACE;
99 output += ' ';
100 }
101 continue;
103 if (last == PP_STRING_LITERAL)
104 output.chop(1);
105 else if (secondlast == PP_STRING_LITERAL && last == PP_WHITESPACE)
106 output.chop(2);
107 else
108 break;
109 output += sym.lexem().mid(1);
110 secondlast = last;
111 last = PP_STRING_LITERAL;
112 continue;
113 case MOC_INCLUDE_BEGIN:
114 lineNum = 0;
115 continue;
116 case MOC_INCLUDE_END:
117 lineNum = sym.lineNum;
118 continue;
119 default:
120 break;
121 }
122 secondlast = last;
123 last = sym.token;
124
125 const int padding = sym.lineNum - lineNum;
126 if (padding > 0) {
127 output.resize(output.size() + padding);
128 memset(output.data() + output.size() - padding, '\n', padding);
129 lineNum = sym.lineNum;
130 }
131
132 output += sym.lexem();
133 }
134
135 return output;
136}
137
139{
140 QStringList allArguments;
141 hasOptionFiles = false;
142 allArguments.reserve(arguments.size());
143 for (const QString &argument : arguments) {
144 // "@file" doesn't start with a '-' so we can't use QCommandLineParser for it
145 if (argument.startsWith(u'@')) {
146 QString optionsFile = argument;
147 optionsFile.remove(0, 1);
148 if (optionsFile.isEmpty()) {
149 error("The @ option requires an input file");
150 return QStringList();
151 }
152 QFile f(optionsFile);
154 error("Cannot open options file specified with @");
155 return QStringList();
156 }
157 hasOptionFiles = true;
158 while (!f.atEnd()) {
159 QString line = QString::fromLocal8Bit(f.readLine().trimmed());
160 if (!line.isEmpty())
161 allArguments << line;
162 }
163 } else {
164 allArguments << argument;
165 }
166 }
167 return allArguments;
168}
169
170int runMoc(int argc, char **argv)
171{
172 QCoreApplication app(argc, argv);
174
175 bool autoInclude = true;
176 bool defaultInclude = true;
177 Preprocessor pp;
178 Moc moc;
179 pp.macros["Q_MOC_RUN"];
180 pp.macros["__cplusplus"];
181
182 // Don't stumble over GCC extensions
183 Macro dummyVariadicFunctionMacro;
184 dummyVariadicFunctionMacro.isFunction = true;
185 dummyVariadicFunctionMacro.isVariadic = true;
186 dummyVariadicFunctionMacro.arguments += Symbol(0, PP_IDENTIFIER, "__VA_ARGS__");
187 pp.macros["__attribute__"] = dummyVariadicFunctionMacro;
188 pp.macros["__declspec"] = dummyVariadicFunctionMacro;
189
190 QString filename;
192 QFile in;
193 File out;
194
195 // Note that moc isn't translated.
196 // If you use this code as an example for a translated app, make sure to translate the strings.
197 QCommandLineParser parser;
198 parser.setApplicationDescription(QStringLiteral("Qt Meta Object Compiler version %1 (Qt %2)")
199 .arg(mocOutputRevision).arg(QString::fromLatin1(QT_VERSION_STR)));
200 parser.addHelpOption();
201 parser.addVersionOption();
203
204 QCommandLineOption outputOption(QStringLiteral("o"));
205 outputOption.setDescription(QStringLiteral("Write output to file rather than stdout."));
206 outputOption.setValueName(QStringLiteral("file"));
207 outputOption.setFlags(QCommandLineOption::ShortOptionStyle);
208 parser.addOption(outputOption);
209
210 QCommandLineOption includePathOption(QStringLiteral("I"));
211 includePathOption.setDescription(QStringLiteral("Add dir to the include path for header files."));
212 includePathOption.setValueName(QStringLiteral("dir"));
213 includePathOption.setFlags(QCommandLineOption::ShortOptionStyle);
214 parser.addOption(includePathOption);
215
216 QCommandLineOption macFrameworkOption(QStringLiteral("F"));
217 macFrameworkOption.setDescription(QStringLiteral("Add Mac framework to the include path for header files."));
218 macFrameworkOption.setValueName(QStringLiteral("framework"));
219 macFrameworkOption.setFlags(QCommandLineOption::ShortOptionStyle);
220 parser.addOption(macFrameworkOption);
221
222 QCommandLineOption preprocessOption(QStringLiteral("E"));
223 preprocessOption.setDescription(QStringLiteral("Preprocess only; do not generate meta object code."));
224 parser.addOption(preprocessOption);
225
226 QCommandLineOption defineOption(QStringLiteral("D"));
227 defineOption.setDescription(QStringLiteral("Define macro, with optional definition."));
228 defineOption.setValueName(QStringLiteral("macro[=def]"));
229 defineOption.setFlags(QCommandLineOption::ShortOptionStyle);
230 parser.addOption(defineOption);
231
232 QCommandLineOption undefineOption(QStringLiteral("U"));
233 undefineOption.setDescription(QStringLiteral("Undefine macro."));
234 undefineOption.setValueName(QStringLiteral("macro"));
235 undefineOption.setFlags(QCommandLineOption::ShortOptionStyle);
236 parser.addOption(undefineOption);
237
238 QCommandLineOption metadataOption(QStringLiteral("M"));
239 metadataOption.setDescription(QStringLiteral("Add key/value pair to plugin meta data"));
240 metadataOption.setValueName(QStringLiteral("key=value"));
241 metadataOption.setFlags(QCommandLineOption::ShortOptionStyle);
242 parser.addOption(metadataOption);
243
244 QCommandLineOption compilerFlavorOption(QStringLiteral("compiler-flavor"));
245 compilerFlavorOption.setDescription(QStringLiteral("Set the compiler flavor: either \"msvc\" or \"unix\"."));
246 compilerFlavorOption.setValueName(QStringLiteral("flavor"));
247 parser.addOption(compilerFlavorOption);
248
249 QCommandLineOption noIncludeOption(QStringLiteral("i"));
250 noIncludeOption.setDescription(QStringLiteral("Do not generate an #include statement."));
251 parser.addOption(noIncludeOption);
252
253 QCommandLineOption pathPrefixOption(QStringLiteral("p"));
254 pathPrefixOption.setDescription(QStringLiteral("Path prefix for included file."));
255 pathPrefixOption.setValueName(QStringLiteral("path"));
256 pathPrefixOption.setFlags(QCommandLineOption::ShortOptionStyle);
257 parser.addOption(pathPrefixOption);
258
259 QCommandLineOption forceIncludeOption(QStringLiteral("f"));
260 forceIncludeOption.setDescription(QStringLiteral("Force #include <file> (overwrite default)."));
261 forceIncludeOption.setValueName(QStringLiteral("file"));
262 forceIncludeOption.setFlags(QCommandLineOption::ShortOptionStyle);
263 parser.addOption(forceIncludeOption);
264
265 QCommandLineOption prependIncludeOption(QStringLiteral("b"));
266 prependIncludeOption.setDescription(QStringLiteral("Prepend #include <file> (preserve default include)."));
267 prependIncludeOption.setValueName(QStringLiteral("file"));
268 prependIncludeOption.setFlags(QCommandLineOption::ShortOptionStyle);
269 parser.addOption(prependIncludeOption);
270
271 QCommandLineOption includeOption(QStringLiteral("include"));
272 includeOption.setDescription(QStringLiteral("Parse <file> as an #include before the main source(s)."));
273 includeOption.setValueName(QStringLiteral("file"));
274 parser.addOption(includeOption);
275
276 QCommandLineOption noNotesWarningsCompatOption(QStringLiteral("n"));
277 noNotesWarningsCompatOption.setDescription(QStringLiteral("Do not display notes (-nn) or warnings (-nw). Compatibility option."));
278 noNotesWarningsCompatOption.setValueName(QStringLiteral("which"));
279 noNotesWarningsCompatOption.setFlags(QCommandLineOption::ShortOptionStyle);
280 parser.addOption(noNotesWarningsCompatOption);
281
282 QCommandLineOption noNotesOption(QStringLiteral("no-notes"));
283 noNotesOption.setDescription(QStringLiteral("Do not display notes."));
284 parser.addOption(noNotesOption);
285
286 QCommandLineOption noWarningsOption(QStringLiteral("no-warnings"));
287 noWarningsOption.setDescription(QStringLiteral("Do not display warnings (implies --no-notes)."));
288 parser.addOption(noWarningsOption);
289
290 QCommandLineOption ignoreConflictsOption(QStringLiteral("ignore-option-clashes"));
291 ignoreConflictsOption.setDescription(QStringLiteral("Ignore all options that conflict with compilers, like -pthread conflicting with moc's -p option."));
292 parser.addOption(ignoreConflictsOption);
293
294 QCommandLineOption jsonOption(QStringLiteral("output-json"));
295 jsonOption.setDescription(QStringLiteral("In addition to generating C++ code, create a machine-readable JSON file in a file that matches the output file and an extra .json extension."));
296 parser.addOption(jsonOption);
297
298 QCommandLineOption debugIncludesOption(QStringLiteral("debug-includes"));
299 debugIncludesOption.setDescription(QStringLiteral("Display debug messages of each considered include path."));
300 parser.addOption(debugIncludesOption);
301
302 QCommandLineOption collectOption(QStringLiteral("collect-json"));
303 collectOption.setDescription(QStringLiteral("Instead of processing C++ code, collect previously generated JSON output into a single file."));
304 parser.addOption(collectOption);
305
306 QCommandLineOption depFileOption(QStringLiteral("output-dep-file"));
307 depFileOption.setDescription(
308 QStringLiteral("Output a Make-style dep file for build system consumption."));
309 parser.addOption(depFileOption);
310
311 QCommandLineOption depFilePathOption(QStringLiteral("dep-file-path"));
312 depFilePathOption.setDescription(QStringLiteral("Path where to write the dep file."));
313 depFilePathOption.setValueName(QStringLiteral("file"));
314 parser.addOption(depFilePathOption);
315
316 QCommandLineOption depFileRuleNameOption(QStringLiteral("dep-file-rule-name"));
317 depFileRuleNameOption.setDescription(
318 QStringLiteral("The rule name (first line) of the dep file."));
319 depFileRuleNameOption.setValueName(QStringLiteral("rule name"));
320 parser.addOption(depFileRuleNameOption);
321
322 QCommandLineOption requireCompleTypesOption(QStringLiteral("require-complete-types"));
323 requireCompleTypesOption.setDescription(QStringLiteral("Require complete types for better performance"));
324 parser.addOption(requireCompleTypesOption);
325
326 parser.addPositionalArgument(QStringLiteral("[header-file]"),
327 QStringLiteral("Header file to read from, otherwise stdin."));
328 parser.addPositionalArgument(QStringLiteral("[@option-file]"),
329 QStringLiteral("Read additional options from option-file."));
330 parser.addPositionalArgument(QStringLiteral("[MOC generated json file]"),
331 QStringLiteral("MOC generated json output"));
332
333 bool hasOptionFiles = false;
335 if (arguments.isEmpty())
336 return 1;
337
338 parser.process(arguments);
339
340 const QStringList files = parser.positionalArguments();
341 output = parser.value(outputOption);
342 if (parser.isSet(collectOption))
343 return collectJson(files, output, hasOptionFiles);
344
345 if (files.size() > 1) {
346 error(qPrintable("Too many input files specified: '"_L1 + files.join("' '"_L1) + u'\''));
347 parser.showHelp(1);
348 } else if (!files.isEmpty()) {
349 filename = files.first();
350 }
351
352 const bool ignoreConflictingOptions = parser.isSet(ignoreConflictsOption);
353 pp.preprocessOnly = parser.isSet(preprocessOption);
354 pp.setDebugIncludes(parser.isSet(debugIncludesOption));
355 if (parser.isSet(noIncludeOption)) {
356 moc.noInclude = true;
357 autoInclude = false;
358 }
359 if (parser.isSet(requireCompleTypesOption))
360 moc.requireCompleteTypes = true;
361 if (!ignoreConflictingOptions) {
362 if (parser.isSet(forceIncludeOption)) {
363 moc.noInclude = false;
364 autoInclude = false;
365 const auto forceIncludes = parser.values(forceIncludeOption);
366 for (const QString &include : forceIncludes) {
367 moc.includeFiles.append(QFile::encodeName(include));
368 defaultInclude = false;
369 }
370 }
371 const auto prependIncludes = parser.values(prependIncludeOption);
372 for (const QString &include : prependIncludes)
373 moc.includeFiles.prepend(QFile::encodeName(include));
374 if (parser.isSet(pathPrefixOption))
375 moc.includePath = QFile::encodeName(parser.value(pathPrefixOption));
376 }
377
378 const auto includePaths = parser.values(includePathOption);
379 for (const QString &path : includePaths)
381 QString compilerFlavor = parser.value(compilerFlavorOption);
382 if (compilerFlavor.isEmpty() || compilerFlavor == "unix"_L1) {
383 // traditional Unix compilers use both CPATH and CPLUS_INCLUDE_PATH
384 // $CPATH feeds to #include <...> and #include "...", whereas
385 // CPLUS_INCLUDE_PATH is equivalent to GCC's -isystem, so we parse later
386 const auto cpath = qgetenv("CPATH").split(QDir::listSeparator().toLatin1());
387 for (const QByteArray &p : cpath)
388 pp.includes += Preprocessor::IncludePath(p);
389 const auto cplus_include_path = qgetenv("CPLUS_INCLUDE_PATH").split(QDir::listSeparator().toLatin1());
390 for (const QByteArray &p : cplus_include_path)
391 pp.includes += Preprocessor::IncludePath(p);
392 } else if (compilerFlavor == "msvc"_L1) {
393 // MSVC uses one environment variable: INCLUDE
394 const auto include = qgetenv("INCLUDE").split(QDir::listSeparator().toLatin1());
395 for (const QByteArray &p : include)
396 pp.includes += Preprocessor::IncludePath(p);
397 } else {
398 error(qPrintable("Unknown compiler flavor '"_L1 + compilerFlavor +
399 "'; valid values are: msvc, unix."_L1));
400 parser.showHelp(1);
401 }
402
403 const auto macFrameworks = parser.values(macFrameworkOption);
404 for (const QString &path : macFrameworks) {
405 // minimalistic framework support for the mac
407 p.isFrameworkPath = true;
408 pp.includes += p;
409 }
410 const auto defines = parser.values(defineOption);
411 for (const QString &arg : defines) {
412 QByteArray name = arg.toLocal8Bit();
413 QByteArray value("1");
414 const qsizetype eq = name.indexOf('=');
415 if (eq >= 0) {
416 value = name.mid(eq + 1);
417 name = name.left(eq);
418 }
419 if (name.isEmpty()) {
420 error("Missing macro name");
421 parser.showHelp(1);
422 }
423 Macro macro;
425 macro.symbols.removeLast(); // remove the EOF symbol
426 pp.macros.insert(name, macro);
427 }
428 const auto undefines = parser.values(undefineOption);
429 for (const QString &arg : undefines) {
430 QByteArray macro = arg.toLocal8Bit();
431 if (macro.isEmpty()) {
432 error("Missing macro name");
433 parser.showHelp(1);
434 }
435 pp.macros.remove(macro);
436 }
437 const QStringList noNotesCompatValues = parser.values(noNotesWarningsCompatOption);
438 if (parser.isSet(noNotesOption) || noNotesCompatValues.contains("n"_L1))
439 moc.displayNotes = false;
440 if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains("w"_L1))
441 moc.displayWarnings = moc.displayNotes = false;
442
443 if (autoInclude) {
444 qsizetype spos = filename.lastIndexOf(QDir::separator());
445 qsizetype ppos = filename.lastIndexOf(u'.');
446 // spos >= -1 && ppos > spos => ppos >= 0
447 moc.noInclude = (ppos > spos && filename.at(ppos + 1).toLower() != u'h');
448 }
449 if (defaultInclude) {
450 if (moc.includePath.isEmpty()) {
451 if (filename.size()) {
452 if (output.size())
453 moc.includeFiles.append(combinePath(filename, output));
454 else
455 moc.includeFiles.append(QFile::encodeName(filename));
456 }
457 } else {
458 moc.includeFiles.append(combinePath(filename, filename));
459 }
460 }
461
462 if (filename.isEmpty()) {
463 filename = QStringLiteral("standard input");
464 if (!in.open(stdin, QIODevice::ReadOnly)) {
465 fprintf(stderr, "moc: cannot open standard input: %s\n", qPrintable(in.errorString()));
466 return 1;
467 }
468 } else {
469 in.setFileName(filename);
470 if (!in.open(QIODevice::ReadOnly)) {
471 fprintf(stderr, "moc: cannot open %s: %s\n", qPrintable(filename), qPrintable(in.errorString()));
472 return 1;
473 }
474 moc.filename = filename.toLocal8Bit();
475 }
476
477 const auto metadata = parser.values(metadataOption);
478 for (const QString &md : metadata) {
479 qsizetype split = md.indexOf(u'=');
480 QString key = md.left(split);
481 QString value = md.mid(split + 1);
482
483 if (split == -1 || key.isEmpty() || value.isEmpty()) {
484 error("missing key or value for option '-M'");
485 } else if (key.indexOf(u'.') != -1) {
486 // Don't allow keys with '.' for now, since we might need this
487 // format later for more advanced meta data API
488 error("A key cannot contain the letter '.' for option '-M'");
489 } else {
490 QJsonArray array = moc.metaArgs.value(key);
491 array.append(value);
492 moc.metaArgs.insert(key, array);
493 }
494 }
495
496 moc.currentFilenames.push(filename.toLocal8Bit());
497 moc.includes = pp.includes;
498
499 if (Q_UNLIKELY(parser.isSet(debugIncludesOption))) {
500 fprintf(stderr, "debug-includes: include search list:\n");
501
502 for (auto &includePath : pp.includes) {
503 fprintf(stderr, "debug-includes: '%s' framework: %d \n",
504 includePath.path.constData(),
505 includePath.isFrameworkPath);
506 }
507 fprintf(stderr, "debug-includes: end of search list.\n");
508 }
509
510 // 1. preprocess
511 const auto includeFiles = parser.values(includeOption);
512 QStringList validIncludesFiles;
513 for (const QString &includeName : includeFiles) {
514 QByteArray rawName = pp.resolveInclude(QFile::encodeName(includeName), moc.filename);
515 if (rawName.isEmpty()) {
516 fprintf(stderr, "Warning: Failed to resolve include \"%s\" for moc file %s\n",
517 includeName.toLocal8Bit().constData(),
518 moc.filename.isEmpty() ? "<standard input>" : moc.filename.constData());
519 } else {
520 QFile f(QFile::decodeName(rawName));
521 if (f.open(QIODevice::ReadOnly)) {
522 moc.symbols += Symbol(0, MOC_INCLUDE_BEGIN, rawName);
523 moc.symbols += pp.preprocessed(rawName, &f);
524 moc.symbols += Symbol(0, MOC_INCLUDE_END, rawName);
525 validIncludesFiles.append(includeName);
526 } else {
527 fprintf(stderr, "Warning: Cannot open %s included by moc file %s: %s\n",
528 rawName.constData(),
529 moc.filename.isEmpty() ? "<standard input>" : moc.filename.constData(),
530 f.errorString().toLocal8Bit().constData());
531 }
532 }
533 }
534 moc.symbols += pp.preprocessed(moc.filename, &in);
535
536 if (!pp.preprocessOnly) {
537 // 2. parse
538 moc.parse();
539 }
540
541 // 3. and output meta object code
542
543 File jsonOutput;
544
545 bool outputToFile = true;
546 if (output.size()) { // output file specified
548 if (!out)
549 {
550 const auto fopen_errno = errno;
551 fprintf(stderr, "moc: Cannot create %s. Error: %s\n",
552 QFile::encodeName(output).constData(),
553 strerror(fopen_errno));
554 return 1;
555 }
556
557 if (parser.isSet(jsonOption)) {
558 const QString jsonOutputFileName = output + ".json"_L1;
559 jsonOutput = openFileForWriting(jsonOutputFileName);
560 if (!jsonOutput) {
561 const auto fopen_errno = errno;
562 fprintf(stderr, "moc: Cannot create JSON output file %s. Error: %s\n",
563 QFile::encodeName(jsonOutputFileName).constData(),
564 strerror(fopen_errno));
565 }
566 }
567 } else { // use stdout
568 out.reset(stdout);
569 outputToFile = false;
570 }
571
572 if (pp.preprocessOnly) {
573 fprintf(out.get(), "%s\n", composePreprocessorOutput(moc.symbols).constData());
574 } else {
575 if (moc.classList.isEmpty())
576 moc.note("No relevant classes found. No output generated.");
577 else
578 moc.generate(out.get(), jsonOutput.get());
579 }
580
581 out.reset();
582
583 if (parser.isSet(depFileOption)) {
584 // 4. write a Make-style dependency file (can also be consumed by Ninja).
585 QString depOutputFileName;
586 QString depRuleName = output;
587
588 if (parser.isSet(depFileRuleNameOption))
589 depRuleName = parser.value(depFileRuleNameOption);
590
591 if (parser.isSet(depFilePathOption)) {
592 depOutputFileName = parser.value(depFilePathOption);
593 } else if (outputToFile) {
594 depOutputFileName = output + ".d"_L1;
595 } else {
596 fprintf(stderr, "moc: Writing to stdout, but no depfile path specified.\n");
597 }
598
599 File depFileHandle = openFileForWriting(depOutputFileName);
600 if (!depFileHandle) {
601 const auto fopen_errno = errno;
602 fprintf(stderr, "moc: Cannot create dep output file '%s'. Error: %s\n",
603 QFile::encodeName(depOutputFileName).constData(),
604 strerror(fopen_errno));
605 }
606
607 if (depFileHandle) {
608 // First line is the path to the generated file.
609 fprintf(depFileHandle.get(), "%s: ",
610 escapeAndEncodeDependencyPath(depRuleName).constData());
611
612 QByteArrayList dependencies;
613
614 // If there's an input file, it's the first dependency.
615 if (!filename.isEmpty()) {
616 dependencies.append(escapeAndEncodeDependencyPath(filename).constData());
617 }
618
619 // Additional passed-in includes are dependencies (like moc_predefs.h).
620 for (const QString &includeName : validIncludesFiles) {
621 dependencies.append(escapeAndEncodeDependencyPath(includeName).constData());
622 }
623
624 // Plugin metadata json files discovered via Q_PLUGIN_METADATA macros are also
625 // dependencies.
626 for (const QString &pluginMetadataFile : moc.parsedPluginMetadataFiles) {
627 dependencies.append(escapeAndEncodeDependencyPath(pluginMetadataFile).constData());
628 }
629
630 // All pre-processed includes are dependnecies.
631 // Sort the entries for easier human consumption.
632 auto includeList = pp.preprocessedIncludes.values();
633 std::sort(includeList.begin(), includeList.end());
634
635 for (QByteArray &includeName : includeList) {
636 dependencies.append(escapeDependencyPath(includeName));
637 }
638
639 // Join dependencies, output them, and output a final new line.
640 const auto dependenciesJoined = dependencies.join(QByteArrayLiteral(" \\\n "));
641 fprintf(depFileHandle.get(), "%s\n", dependenciesJoined.constData());
642 }
643 }
644
645 return 0;
646}
647
649
650int main(int _argc, char **_argv)
651{
652 return QT_PREPEND_NAMESPACE(runMoc)(_argc, _argv);
653}
Definition moc.h:208
static Symbols tokenize(const QByteArray &input, int lineNum=1, TokenizeMode mode=TokenizeCpp)
\inmodule QtCore
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
qsizetype length() const noexcept
Same as size().
Definition qbytearray.h:499
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
QByteArray mid(qsizetype index, qsizetype len=-1) const &
The QCommandLineOption class defines a possible command-line option. \inmodule QtCore.
The QCommandLineParser class provides a means for handling the command line options.
QString value(const QString &name) const
Returns the option value found for the given option name optionName, or an empty string if not found.
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax=QString())
Defines an additional argument to the application, for the benefit of the help text.
QStringList positionalArguments() const
Returns a list of positional arguments.
void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode)
Sets the parsing mode to singleDashWordOptionMode.
QStringList values(const QString &name) const
Returns a list of option values found for the given option name optionName, or an empty list if not f...
void setApplicationDescription(const QString &description)
Sets the application description shown by helpText().
bool addOption(const QCommandLineOption &commandLineOption)
Adds the option option to look for while parsing.
Q_NORETURN void showHelp(int exitCode=0)
Displays the help information, and exits the application.
bool isSet(const QString &name) const
Checks whether the option name was passed to the application.
void process(const QStringList &arguments)
Processes the command line arguments.
QCommandLineOption addVersionOption()
Adds the {-v} / {–version} option, which displays the version string of the application.
QCommandLineOption addHelpOption()
Adds help options to the command-line parser.
\inmodule QtCore
static void setApplicationVersion(const QString &version)
static QStringList arguments()
static QDir current()
Returns the application's current directory.
Definition qdir.h:219
static QChar separator()
Returns the native directory separator: "/" under Unix and "\\" under Windows.
Definition qdir.h:209
static constexpr QChar listSeparator() noexcept
Definition qdir.h:200
\inmodule QtCore
Definition qfile.h:93
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString left(qsizetype n) const &
Definition qstring.h:363
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:296
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5949
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QByteArray toLocal8Bit() const &
Definition qstring.h:638
int collectJson(const QStringList &jsonFiles, const QString &outputFile, bool skipStdIn)
StringType escapeDependencyPath(const StringType &path)
static QByteArray escapeAndEncodeDependencyPath(const QString &path)
int main()
[0]
QList< QVariant > arguments
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
@ mocOutputRevision
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define Q_UNLIKELY(x)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError * error
static const char includeList[]
static QString moc(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLuint64 GLenum void * handle
GLuint64 key
GLfloat GLfloat f
GLuint name
GLenum array
GLuint in
GLsizei const GLchar *const * path
GLfloat GLfloat p
[1]
static void split(QT_FT_Vector *b)
SSL_CTX int void * arg
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
static QByteArray combinePath(const QString &infile, const QString &outfile)
Definition main.cpp:40
static bool hasNext(const Symbols &symbols, int i)
Definition main.cpp:78
int runMoc(int argc, char **argv)
Definition main.cpp:170
static auto openFileForWriting(const QString &name)
Definition main.cpp:62
static QStringList argumentsFromCommandLineAndFile(const QStringList &arguments, bool &hasOptionFiles)
Definition main.cpp:138
QByteArray composePreprocessorOutput(const Symbols &symbols)
Definition main.cpp:85
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
ptrdiff_t qsizetype
Definition qtypes.h:165
QT_BEGIN_NAMESPACE typedef uchar * output
QFile file
[0]
QTextStream out(stdout)
[7]
QStringList files
[8]
QApplication app(argc, argv)
[0]
QDBusArgument argument
Symbols symbols
bool isFunction
Token token
Definition symbols.h:59
int lineNum
Definition symbols.h:58
QByteArray lexem() const
Definition symbols.h:60
@ PP_NEWLINE
Definition token.h:224
@ PP_STRING_LITERAL
Definition token.h:238
@ PP_IDENTIFIER
Definition token.h:216
@ PP_WHITESPACE
Definition token.h:240
@ PP_NOTOKEN
Definition token.h:225