175 bool autoInclude =
true;
176 bool defaultInclude =
true;
179 pp.macros[
"Q_MOC_RUN"];
180 pp.macros[
"__cplusplus"];
183 Macro dummyVariadicFunctionMacro;
185 dummyVariadicFunctionMacro.isVariadic =
true;
187 pp.macros[
"__attribute__"] = dummyVariadicFunctionMacro;
188 pp.macros[
"__declspec"] = dummyVariadicFunctionMacro;
205 outputOption.setDescription(
QStringLiteral(
"Write output to file rather than stdout."));
211 includePathOption.setDescription(
QStringLiteral(
"Add dir to the include path for header files."));
217 macFrameworkOption.setDescription(
QStringLiteral(
"Add Mac framework to the include path for header files."));
223 preprocessOption.setDescription(
QStringLiteral(
"Preprocess only; do not generate meta object code."));
227 defineOption.setDescription(
QStringLiteral(
"Define macro, with optional definition."));
239 metadataOption.setDescription(
QStringLiteral(
"Add key/value pair to plugin meta data"));
245 compilerFlavorOption.setDescription(
QStringLiteral(
"Set the compiler flavor: either \"msvc\" or \"unix\"."));
250 noIncludeOption.setDescription(
QStringLiteral(
"Do not generate an #include statement."));
254 pathPrefixOption.setDescription(
QStringLiteral(
"Path prefix for included file."));
260 forceIncludeOption.setDescription(
QStringLiteral(
"Force #include <file> (overwrite default)."));
266 prependIncludeOption.setDescription(
QStringLiteral(
"Prepend #include <file> (preserve default include)."));
272 includeOption.setDescription(
QStringLiteral(
"Parse <file> as an #include before the main source(s)."));
277 noNotesWarningsCompatOption.setDescription(
QStringLiteral(
"Do not display notes (-nn) or warnings (-nw). Compatibility option."));
278 noNotesWarningsCompatOption.setValueName(
QStringLiteral(
"which"));
280 parser.
addOption(noNotesWarningsCompatOption);
283 noNotesOption.setDescription(
QStringLiteral(
"Do not display notes."));
287 noWarningsOption.setDescription(
QStringLiteral(
"Do not display warnings (implies --no-notes)."));
291 ignoreConflictsOption.setDescription(
QStringLiteral(
"Ignore all options that conflict with compilers, like -pthread conflicting with moc's -p option."));
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."));
299 debugIncludesOption.setDescription(
QStringLiteral(
"Display debug messages of each considered include path."));
303 collectOption.setDescription(
QStringLiteral(
"Instead of processing C++ code, collect previously generated JSON output into a single file."));
307 depFileOption.setDescription(
308 QStringLiteral(
"Output a Make-style dep file for build system consumption."));
312 depFilePathOption.setDescription(
QStringLiteral(
"Path where to write the dep file."));
317 depFileRuleNameOption.setDescription(
323 requireCompleTypesOption.setDescription(
QStringLiteral(
"Require complete types for better performance"));
324 parser.
addOption(requireCompleTypesOption);
333 bool hasOptionFiles =
false;
342 if (parser.
isSet(collectOption))
345 if (
files.size() > 1) {
348 }
else if (!
files.isEmpty()) {
349 filename =
files.first();
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;
359 if (parser.
isSet(requireCompleTypesOption))
360 moc.requireCompleteTypes =
true;
361 if (!ignoreConflictingOptions) {
362 if (parser.
isSet(forceIncludeOption)) {
363 moc.noInclude =
false;
365 const auto forceIncludes = parser.
values(forceIncludeOption);
366 for (
const QString &include : forceIncludes) {
368 defaultInclude =
false;
371 const auto prependIncludes = parser.
values(prependIncludeOption);
372 for (
const QString &include : prependIncludes)
374 if (parser.
isSet(pathPrefixOption))
378 const auto includePaths = parser.
values(includePathOption);
381 QString compilerFlavor = parser.
value(compilerFlavorOption);
382 if (compilerFlavor.isEmpty() || compilerFlavor ==
"unix"_L1) {
392 }
else if (compilerFlavor ==
"msvc"_L1) {
399 "'; valid values are: msvc, unix."_L1));
403 const auto macFrameworks = parser.
values(macFrameworkOption);
407 p.isFrameworkPath =
true;
410 const auto defines = parser.
values(defineOption);
419 if (
name.isEmpty()) {
420 error(
"Missing macro name");
425 macro.symbols.removeLast();
426 pp.macros.insert(
name, macro);
428 const auto undefines = parser.
values(undefineOption);
431 if (macro.isEmpty()) {
432 error(
"Missing macro name");
435 pp.macros.remove(macro);
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;
447 moc.noInclude = (ppos > spos && filename.
at(ppos + 1).toLower() != u
'h');
449 if (defaultInclude) {
450 if (
moc.includePath.isEmpty()) {
451 if (filename.
size()) {
465 fprintf(stderr,
"moc: cannot open standard input: %s\n",
qPrintable(
in.errorString()));
469 in.setFileName(filename);
477 const auto metadata = parser.
values(metadataOption);
478 for (
const QString &md : metadata) {
484 error(
"missing key or value for option '-M'");
485 }
else if (
key.indexOf(u
'.') != -1) {
488 error(
"A key cannot contain the letter '.' for option '-M'");
497 moc.includes = pp.includes;
500 fprintf(stderr,
"debug-includes: include search list:\n");
502 for (
auto &includePath : pp.includes) {
503 fprintf(stderr,
"debug-includes: '%s' framework: %d \n",
504 includePath.path.constData(),
505 includePath.isFrameworkPath);
507 fprintf(stderr,
"debug-includes: end of search list.\n");
511 const auto includeFiles = parser.
values(includeOption);
513 for (
const QString &includeName : includeFiles) {
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());
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);
527 fprintf(stderr,
"Warning: Cannot open %s included by moc file %s: %s\n",
529 moc.filename.isEmpty() ?
"<standard input>" :
moc.filename.constData(),
530 f.errorString().toLocal8Bit().constData());
534 moc.symbols += pp.preprocessed(
moc.filename, &
in);
536 if (!pp.preprocessOnly) {
545 bool outputToFile =
true;
550 const auto fopen_errno = errno;
551 fprintf(stderr,
"moc: Cannot create %s. Error: %s\n",
553 strerror(fopen_errno));
557 if (parser.
isSet(jsonOption)) {
561 const auto fopen_errno = errno;
562 fprintf(stderr,
"moc: Cannot create JSON output file %s. Error: %s\n",
564 strerror(fopen_errno));
569 outputToFile =
false;
572 if (pp.preprocessOnly) {
575 if (
moc.classList.isEmpty())
576 moc.note(
"No relevant classes found. No output generated.");
578 moc.generate(
out.get(), jsonOutput.get());
583 if (parser.
isSet(depFileOption)) {
588 if (parser.
isSet(depFileRuleNameOption))
589 depRuleName = parser.
value(depFileRuleNameOption);
591 if (parser.
isSet(depFilePathOption)) {
592 depOutputFileName = parser.
value(depFilePathOption);
593 }
else if (outputToFile) {
594 depOutputFileName =
output +
".d"_L1;
596 fprintf(stderr,
"moc: Writing to stdout, but no depfile path specified.\n");
600 if (!depFileHandle) {
601 const auto fopen_errno = errno;
602 fprintf(stderr,
"moc: Cannot create dep output file '%s'. Error: %s\n",
604 strerror(fopen_errno));
609 fprintf(depFileHandle.get(),
"%s: ",
620 for (
const QString &includeName : validIncludesFiles) {
626 for (
const QString &pluginMetadataFile :
moc.parsedPluginMetadataFiles) {
632 auto includeList = pp.preprocessedIncludes.values();
641 fprintf(depFileHandle.get(),
"%s\n", dependenciesJoined.constData());