summaryrefslogtreecommitdiffstats
path: root/Source/cmcmd.cxx
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2020-10-18 14:11:27 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2020-11-29 14:25:42 (GMT)
commit2c71d051facad13b0a42a57066be2489d5fff6ea (patch)
treed07f850f8abc74d9df34ad885681c08d36c14472 /Source/cmcmd.cxx
parentafd0f6785dc1220a07743d31699fcd9097cca46a (diff)
downloadCMake-2c71d051facad13b0a42a57066be2489d5fff6ea.zip
CMake-2c71d051facad13b0a42a57066be2489d5fff6ea.tar.gz
CMake-2c71d051facad13b0a42a57066be2489d5fff6ea.tar.bz2
Makefiles Generators: use compiler for dependencies generation
Each source compilation generates a dependencies file. These dependencies files are consolidated in one file per target. This consolidation is done as part of command 'cmake -E cmake_depends` launched before evaluation of makefile dependency graph. The consolidation uses the same approach as `CMake` dependencies management. Fixes: #21321
Diffstat (limited to 'Source/cmcmd.cxx')
-rw-r--r--Source/cmcmd.cxx183
1 files changed, 155 insertions, 28 deletions
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 81374a1..b8464f2 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -33,6 +33,13 @@
# include "bindexplib.h"
#endif
+#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
+# include <algorithm>
+
+# include "cmCMakePath.h"
+# include "cmProcessTools.h"
+#endif
+
#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__)
# include "cmVisualStudioWCEPlatformParser.h"
#endif
@@ -66,6 +73,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd);
+namespace {
void CMakeCommandUsage(const char* program)
{
std::ostringstream errorStream;
@@ -144,8 +152,7 @@ void CMakeCommandUsage(const char* program)
cmSystemTools::Error(errorStream.str());
}
-static bool cmTarFilesFrom(std::string const& file,
- std::vector<std::string>& files)
+bool cmTarFilesFrom(std::string const& file, std::vector<std::string>& files)
{
if (cmSystemTools::FileIsDirectory(file)) {
std::ostringstream e;
@@ -180,7 +187,7 @@ static bool cmTarFilesFrom(std::string const& file,
return true;
}
-static void cmCatFile(const std::string& fileToAppend)
+void cmCatFile(const std::string& fileToAppend)
{
#ifdef _WIN32
_setmode(fileno(stdout), _O_BINARY);
@@ -190,7 +197,7 @@ static void cmCatFile(const std::string& fileToAppend)
std::cout << source.rdbuf();
}
-static bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
+bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
{
if (cmSystemTools::FileIsSymlink(dir)) {
if (!cmSystemTools::RemoveFile(dir)) {
@@ -208,9 +215,123 @@ static bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
return true;
}
-static int HandleIWYU(const std::string& runCmd,
- const std::string& /* sourceFile */,
- const std::vector<std::string>& orig_cmd)
+#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
+class CLIncludeParser : public cmProcessTools::LineParser
+{
+public:
+ CLIncludeParser(cm::string_view includePrefix, cmsys::ofstream& depFile,
+ std::ostream& output)
+ : IncludePrefix(includePrefix)
+ , DepFile(depFile)
+ , Output(output)
+ {
+ }
+
+private:
+ bool ProcessLine() override
+ {
+ if (cmHasPrefix(this->Line, this->IncludePrefix)) {
+ this->DepFile << cmCMakePath(
+ cmTrimWhitespace(this->Line.c_str() +
+ this->IncludePrefix.size()))
+ .GenericString()
+ << std::endl;
+ } else {
+ this->Output << this->Line << std::endl << std::flush;
+ }
+
+ return true;
+ }
+
+ cm::string_view IncludePrefix;
+ cmsys::ofstream& DepFile;
+ std::ostream& Output;
+};
+
+class CLOutputLogger : public cmProcessTools::OutputLogger
+{
+public:
+ CLOutputLogger(std::ostream& log)
+ : cmProcessTools::OutputLogger(log)
+ {
+ }
+
+ bool ProcessLine() override
+ {
+ *this->Log << std::flush;
+ return true;
+ }
+};
+
+int CLCompileAndDependencies(const std::vector<std::string>& args)
+{
+ std::string depFile;
+ std::string currentBinaryDir;
+ std::string filterPrefix;
+ std::vector<std::string> command;
+ for (auto it = args.cbegin() + 2; it != args.cend(); it++) {
+ if (cmHasLiteralPrefix(*it, "--dep-file=")) {
+ depFile = it->substr(11);
+ } else if (cmHasLiteralPrefix(*it, "--working-dir=")) {
+ currentBinaryDir = it->substr(14);
+ } else if (cmHasLiteralPrefix(*it, "--filter-prefix=")) {
+ filterPrefix = it->substr(16);
+ } else if (*it == "--") {
+ command.insert(command.begin(), ++it, args.cend());
+ break;
+ } else {
+ return 1;
+ }
+ }
+
+ std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp(
+ cmsysProcess_New(), cmsysProcess_Delete);
+ std::vector<const char*> argv(command.size() + 1);
+ std::transform(command.begin(), command.end(), argv.begin(),
+ [](std::string const& s) { return s.c_str(); });
+ argv.back() = nullptr;
+ cmsysProcess_SetCommand(cp.get(), argv.data());
+ cmsysProcess_SetWorkingDirectory(cp.get(), currentBinaryDir.c_str());
+
+ cmsys::ofstream fout(depFile.c_str());
+ if (!fout) {
+ return 3;
+ }
+
+ CLIncludeParser includeParser(filterPrefix, fout, std::cout);
+ CLOutputLogger errLogger(std::cerr);
+
+ // Start the process.
+ cmProcessTools::RunProcess(cp.get(), &includeParser, &errLogger);
+
+ int status = 0;
+ // handle status of process
+ switch (cmsysProcess_GetState(cp.get())) {
+ case cmsysProcess_State_Exited:
+ status = cmsysProcess_GetExitValue(cp.get());
+ break;
+ case cmsysProcess_State_Exception:
+ status = 1;
+ break;
+ case cmsysProcess_State_Error:
+ status = 2;
+ break;
+ default:
+ break;
+ }
+
+ if (status != 0) {
+ // remove the dependencies file because potentially invalid
+ fout.close();
+ cmSystemTools::RemoveFile(depFile);
+ }
+
+ return status;
+}
+#endif
+
+int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */,
+ const std::vector<std::string>& orig_cmd)
{
// Construct the iwyu command line by taking what was given
// and adding all the arguments we give to the compiler.
@@ -235,8 +356,8 @@ static int HandleIWYU(const std::string& runCmd,
return 0;
}
-static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
- const std::vector<std::string>& orig_cmd)
+int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
{
// Construct the clang-tidy command line by taking what was given
// and adding our compiler command line. The clang-tidy tool will
@@ -265,9 +386,8 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
return ret;
}
-static int HandleLWYU(const std::string& runCmd,
- const std::string& /* sourceFile */,
- const std::vector<std::string>&)
+int HandleLWYU(const std::string& runCmd, const std::string& /* sourceFile */,
+ const std::vector<std::string>&)
{
// Construct the ldd -r -u (link what you use lwyu) command line
// ldd -u -r lwuy target
@@ -298,9 +418,8 @@ static int HandleLWYU(const std::string& runCmd,
return 0;
}
-static int HandleCppLint(const std::string& runCmd,
- const std::string& sourceFile,
- const std::vector<std::string>&)
+int HandleCppLint(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>&)
{
// Construct the cpplint command line.
std::vector<std::string> cpplint_cmd = cmExpandedList(runCmd, true);
@@ -326,9 +445,8 @@ static int HandleCppLint(const std::string& runCmd,
return 0;
}
-static int HandleCppCheck(const std::string& runCmd,
- const std::string& sourceFile,
- const std::vector<std::string>& orig_cmd)
+int HandleCppCheck(const std::string& runCmd, const std::string& sourceFile,
+ const std::vector<std::string>& orig_cmd)
{
// Construct the cpplint command line.
std::vector<std::string> cppcheck_cmd = cmExpandedList(runCmd, true);
@@ -391,7 +509,7 @@ struct CoCompiler
bool NoOriginalCommand;
};
-static const std::array<CoCompiler, 5> CoCompilers = {
+const std::array<CoCompiler, 5> CoCompilers = {
{ // Table of options and handlers.
{ "--cppcheck=", HandleCppCheck, false },
{ "--cpplint=", HandleCppLint, false },
@@ -405,6 +523,7 @@ struct CoCompileJob
std::string Command;
CoCompileHandler Handler;
};
+}
// called when args[0] == "__run_co_compile"
int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args)
@@ -586,7 +705,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
} else if (args[2] == "--ignore-eol") {
filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]);
} else {
- ::CMakeCommandUsage(args[0].c_str());
+ CMakeCommandUsage(args[0].c_str());
return 2;
}
@@ -621,8 +740,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
}
if (outValid) {
- // The def file already exists and all input files are older than the
- // existing def file.
+ // The def file already exists and all input files are older than
+ // the existing def file.
return 0;
}
}
@@ -1162,6 +1281,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
return 1;
}
+#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
+ // Internal CMake compiler dependencies filtering
+ if (args[1] == "cmake_cl_compile_depends") {
+ return CLCompileAndDependencies(args);
+ }
+#endif
+
// Internal CMake link script support.
if (args[1] == "cmake_link_script" && args.size() >= 3) {
return cmcmd::ExecuteLinkScript(args);
@@ -1412,7 +1538,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
}
}
- ::CMakeCommandUsage(args[0].c_str());
+ CMakeCommandUsage(args[0].c_str());
return 1;
}
@@ -1779,8 +1905,8 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
skipNextArg = false;
continue;
}
- // We use ++ as seperator between the preprocessing step definition and the
- // rc compilation step becase we need to prepend a -- to seperate the
+ // We use ++ as seperator between the preprocessing step definition and
+ // the rc compilation step becase we need to prepend a -- to seperate the
// source file properly from other options when using clang-cl for
// preprocessing.
if (arg == "++") {
@@ -1830,7 +1956,8 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
return 1;
}
// Since we might have skipped the last argument to llvm-rc
- // we need to make sure the llvm-rc source file is present in the commandline
+ // we need to make sure the llvm-rc source file is present in the
+ // commandline
if (resource_compile.back() != intermediate_file) {
resource_compile.push_back(intermediate_file);
}
@@ -2123,8 +2250,8 @@ int cmVSLink::LinkIncremental()
// http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
// 1. Compiler compiles the application and generates the *.obj files.
- // 2. An empty manifest file is generated if this is a clean build and if
- // not the previous one is reused.
+ // 2. An empty manifest file is generated if this is a clean build and
+ // if not the previous one is reused.
// 3. The resource compiler (rc.exe) compiles the *.manifest file to a
// *.res file.
// 4. Linker generates the binary (EXE or DLL) with the /incremental