NMake is a Make-like builder that comes with Microsoft Visual Studio.
Jom (https://wiki.qt.io/Jom) is an NMake-compatible build tool.
Dependency files for NMake/Jom need to use double-quotes to wrap
filespecs containing special characters, instead of the backslash
escapes that GNU Make wants.
Adds the -MV option, which specifies to use double-quotes as needed
instead of backslash escapes when writing the dependency file.
Differential Revision: http://reviews.llvm.org/D9260
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@235903
91177308-0d34-0410-b5e6-
96231b3b80d8
translated from debug annotations. That translation can be lossy,
which results in some remarks having no location information.
+Other Options
+-------------
+Clang options that that don't fit neatly into other categories.
+
+.. option:: -MV
+
+ When emitting a dependency file, use formatting conventions appropriate
+ for NMake or Jom. Ignored unless another option causes Clang to emit a
+ dependency file.
+
+When Clang emits a dependency file (e.g., you supplied the -M option)
+most filenames can be written to the file without any special formatting.
+Different Make tools will treat different sets of characters as "special"
+and use different conventions for telling the Make tool that the character
+is actually part of the filename. Normally Clang uses backslash to "escape"
+a special character, which is the convention used by GNU Make. The -MV
+option tells Clang to put double-quotes around the entire filename, which
+is the convention used by NMake and Jom.
+
Language and Target-Independent Features
========================================
HelpText<"Specify name of main file output to quote in depfile">;
def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Specify name of main file output in depfile">;
+def MV : Flag<["-"], "MV">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Use NMake/Jom format for the depfile">;
def Mach : Flag<["-"], "Mach">;
def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>;
def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>;
namespace clang {
+/// DependencyOutputFormat - Format for the compiler dependency file.
+enum class DependencyOutputFormat { Make, NMake };
+
/// DependencyOutputOptions - Options for controlling the compiler dependency
/// file generation.
class DependencyOutputOptions {
unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
-
+
+ /// The format for the dependency file.
+ DependencyOutputFormat OutputFormat;
+
/// The file to write dependency output to.
std::string OutputFile;
AddMissingHeaderDeps = 0;
PrintShowIncludes = 0;
IncludeModuleFiles = 0;
+ OutputFormat = DependencyOutputFormat::Make;
}
};
}
Args.AddLastArg(CmdArgs, options::OPT_MP);
+ Args.AddLastArg(CmdArgs, options::OPT_MV);
// Convert all -MQ <target> args to -MT <quoted target>
for (arg_iterator it = Args.filtered_begin(options::OPT_MT,
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
Opts.ModuleDependencyOutputDir =
Args.getLastArgValue(OPT_module_dependency_dir);
+ if (Args.hasArg(OPT_MV))
+ Opts.OutputFormat = DependencyOutputFormat::NMake;
}
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
bool AddMissingHeaderDeps;
bool SeenMissingHeader;
bool IncludeModuleFiles;
+ DependencyOutputFormat OutputFormat;
+
private:
bool FileMatchesDepCriteria(const char *Filename,
SrcMgr::CharacteristicKind FileType);
PhonyTarget(Opts.UsePhonyTargets),
AddMissingHeaderDeps(Opts.AddMissingHeaderDeps),
SeenMissingHeader(false),
- IncludeModuleFiles(Opts.IncludeModuleFiles) {}
+ IncludeModuleFiles(Opts.IncludeModuleFiles),
+ OutputFormat(Opts.OutputFormat) {}
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
}
/// PrintFilename - GCC escapes spaces, # and $, but apparently not ' or " or
-/// other scary characters.
-static void PrintFilename(raw_ostream &OS, StringRef Filename) {
+/// other scary characters. NMake/Jom has a different set of scary characters,
+/// but wraps filespecs in double-quotes to avoid misinterpreting them;
+/// https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx for NMake info,
+/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+/// for Windows file-naming info.
+static void PrintFilename(raw_ostream &OS, StringRef Filename,
+ DependencyOutputFormat OutputFormat) {
+ if (OutputFormat == DependencyOutputFormat::NMake) {
+ // Add quotes if needed. These are the characters listed as "special" to
+ // NMake, that are legal in a Windows filespec, and that could cause
+ // misinterpretation of the dependency string.
+ if (Filename.find_first_of(" #${}^!") != StringRef::npos)
+ OS << '\"' << Filename << '\"';
+ else
+ OS << Filename;
+ return;
+ }
for (unsigned i = 0, e = Filename.size(); i != e; ++i) {
if (Filename[i] == ' ' || Filename[i] == '#')
OS << '\\';
Columns = 2;
}
OS << ' ';
- PrintFilename(OS, *I);
+ PrintFilename(OS, *I, OutputFormat);
Columns += N + 1;
}
OS << '\n';
for (std::vector<std::string>::iterator I = Files.begin() + 1,
E = Files.end(); I != E; ++I) {
OS << '\n';
- PrintFilename(OS, *I);
+ PrintFilename(OS, *I, OutputFormat);
OS << ":\n";
}
}
// RUN: echo > '%t.dir/ .h'
// RUN: echo > '%t.dir/$$.h'
// RUN: echo > '%t.dir/##.h'
+// RUN: echo > '%t.dir/normal.h'
// RUN: cd %t.dir
// RUN: %clang -MD -MF - %s -fsyntax-only -I. | FileCheck -strict-whitespace %s
+// RUN: %clang -MD -MF - -MV %s -fsyntax-only -I. | FileCheck -strict-whitespace %s --check-prefix=QUOTE
// CHECK: \ \ \ \ .h
// CHECK: $$$$.h
// CHECK: \#\#.h
+// QUOTE: " .h"
+// QUOTE: "$$.h"
+// QUOTE: "##.h"
+// QUOTE-NOT: "
+// QUOTE: normal.h
+// QUOTE-NOT: "
#include " .h"
#include "$$.h"
#include "##.h"
+#include "normal.h"