Merge topic 'Ninja-EXPORT_COMPILE_COMMANDS'
3545645
Exclude the CompileCommandOutput test on WIN32.fbaddf4
Escape the source file to be compiled if required.db839be
Make the CMAKE_EXPORT_COMPILE_COMMANDS option work with Ninja.8778357
Add newline to the output.2c04bc0
Move the EscapeJSON method to a sharable location.
This commit is contained in:
commit
7687d557dc
|
@ -60,6 +60,12 @@ IF(CMAKE_GENERATOR MATCHES "Makefiles")
|
|||
ENDIF(CMAKE_GENERATOR MATCHES "Unix Makefiles")
|
||||
ENDIF(CMAKE_GENERATOR MATCHES "Makefiles")
|
||||
|
||||
IF(CMAKE_GENERATOR MATCHES "Ninja")
|
||||
SET(CMAKE_EXPORT_COMPILE_COMMANDS OFF CACHE BOOL
|
||||
"Enable/Disable output of compile commands during generation."
|
||||
)
|
||||
MARK_AS_ADVANCED(CMAKE_EXPORT_COMPILE_COMMANDS)
|
||||
ENDIF(CMAKE_GENERATOR MATCHES "Ninja")
|
||||
|
||||
# GetDefaultWindowsPrefixBase
|
||||
#
|
||||
|
|
|
@ -2474,3 +2474,16 @@ void cmGlobalGenerator::WriteSummary(cmTarget* target)
|
|||
cmSystemTools::RemoveFile(file.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// static
|
||||
std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
|
||||
std::string result;
|
||||
for (std::string::size_type i = 0; i < s.size(); ++i) {
|
||||
if (s[i] == '"' || s[i] == '\\') {
|
||||
result += '\\';
|
||||
}
|
||||
result += s[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -280,6 +280,8 @@ public:
|
|||
/** Generate an <output>.rule file path for a given command output. */
|
||||
virtual std::string GenerateRuleFile(std::string const& output) const;
|
||||
|
||||
static std::string EscapeJSON(const std::string& s);
|
||||
|
||||
protected:
|
||||
typedef std::vector<cmLocalGenerator*> GeneratorVector;
|
||||
// for a project collect all its targets by following depend
|
||||
|
|
|
@ -341,6 +341,7 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator()
|
|||
: cmGlobalGenerator()
|
||||
, BuildFileStream(0)
|
||||
, RulesFileStream(0)
|
||||
, CompileCommandsStream(0)
|
||||
, Rules()
|
||||
, AllDependencies()
|
||||
{
|
||||
|
@ -390,6 +391,7 @@ void cmGlobalNinjaGenerator::Generate()
|
|||
this->BuildFileStream->setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
this->CloseCompileCommandsStream();
|
||||
this->CloseRulesFileStream();
|
||||
this->CloseBuildFileStream();
|
||||
}
|
||||
|
@ -623,6 +625,46 @@ void cmGlobalNinjaGenerator::CloseRulesFileStream()
|
|||
}
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::AddCXXCompileCommand(
|
||||
const std::string &commandLine,
|
||||
const std::string &sourceFile)
|
||||
{
|
||||
// Compute Ninja's build file path.
|
||||
std::string buildFileDir =
|
||||
this->GetCMakeInstance()->GetHomeOutputDirectory();
|
||||
if (!this->CompileCommandsStream)
|
||||
{
|
||||
std::string buildFilePath = buildFileDir + "/compile_commands.json";
|
||||
|
||||
// Get a stream where to generate things.
|
||||
this->CompileCommandsStream =
|
||||
new cmGeneratedFileStream(buildFilePath.c_str());
|
||||
*this->CompileCommandsStream << "[";
|
||||
} else {
|
||||
*this->CompileCommandsStream << "," << std::endl;
|
||||
}
|
||||
|
||||
*this->CompileCommandsStream << "\n{\n"
|
||||
<< " \"directory\": \""
|
||||
<< cmGlobalGenerator::EscapeJSON(buildFileDir) << "\",\n"
|
||||
<< " \"command\": \""
|
||||
<< cmGlobalGenerator::EscapeJSON(commandLine) << "\",\n"
|
||||
<< " \"file\": \""
|
||||
<< cmGlobalGenerator::EscapeJSON(sourceFile) << "\"\n"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::CloseCompileCommandsStream()
|
||||
{
|
||||
if (this->CompileCommandsStream)
|
||||
{
|
||||
*this->CompileCommandsStream << "\n]";
|
||||
delete this->CompileCommandsStream;
|
||||
this->CompileCommandsStream = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
|
||||
{
|
||||
os
|
||||
|
|
|
@ -213,6 +213,9 @@ public:
|
|||
cmGeneratedFileStream* GetRulesFileStream() const
|
||||
{ return this->RulesFileStream; }
|
||||
|
||||
void AddCXXCompileCommand(const std::string &commandLine,
|
||||
const std::string &sourceFile);
|
||||
|
||||
/**
|
||||
* Add a rule to the generated build system.
|
||||
* Call WriteRule() behind the scene but perform some check before like:
|
||||
|
@ -254,6 +257,8 @@ private:
|
|||
void OpenBuildFileStream();
|
||||
void CloseBuildFileStream();
|
||||
|
||||
void CloseCompileCommandsStream();
|
||||
|
||||
void OpenRulesFileStream();
|
||||
void CloseRulesFileStream();
|
||||
|
||||
|
@ -311,6 +316,7 @@ private:
|
|||
/// The file containing the rule statements. (The action attached to each
|
||||
/// edge of the compilation DAG).
|
||||
cmGeneratedFileStream* RulesFileStream;
|
||||
cmGeneratedFileStream* CompileCommandsStream;
|
||||
|
||||
/// The type used to store the set of rules added to the generated build
|
||||
/// system.
|
||||
|
|
|
@ -103,18 +103,6 @@ cmGlobalUnixMakefileGenerator3
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string EscapeJSON(const std::string& s) {
|
||||
std::string result;
|
||||
for (std::string::size_type i = 0; i < s.size(); ++i) {
|
||||
if (s[i] == '"' || s[i] == '\\') {
|
||||
result += '\\';
|
||||
}
|
||||
result += s[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void cmGlobalUnixMakefileGenerator3::Generate()
|
||||
{
|
||||
// first do superclass method
|
||||
|
@ -179,11 +167,14 @@ void cmGlobalUnixMakefileGenerator3::AddCXXCompileCommand(
|
|||
*this->CommandDatabase << "," << std::endl;
|
||||
}
|
||||
*this->CommandDatabase << "{" << std::endl
|
||||
<< " \"directory\": \"" << EscapeJSON(workingDirectory) << "\","
|
||||
<< " \"directory\": \""
|
||||
<< cmGlobalGenerator::EscapeJSON(workingDirectory) << "\","
|
||||
<< std::endl
|
||||
<< " \"command\": \"" << EscapeJSON(compileCommand) << "\","
|
||||
<< " \"command\": \"" <<
|
||||
cmGlobalGenerator::EscapeJSON(compileCommand) << "\","
|
||||
<< std::endl
|
||||
<< " \"file\": \"" << EscapeJSON(sourceFile) << "\""
|
||||
<< " \"file\": \"" <<
|
||||
cmGlobalGenerator::EscapeJSON(sourceFile) << "\""
|
||||
<< std::endl << "}";
|
||||
}
|
||||
|
||||
|
|
|
@ -487,6 +487,39 @@ cmNinjaTargetGenerator
|
|||
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
|
||||
this->GetTargetPDB().c_str(), cmLocalGenerator::SHELL);
|
||||
|
||||
if(this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS"))
|
||||
{
|
||||
cmLocalGenerator::RuleVariables compileObjectVars;
|
||||
std::string lang = language;
|
||||
compileObjectVars.Language = lang.c_str();
|
||||
std::string escapedSourceFileName =
|
||||
this->LocalGenerator->ConvertToOutputFormat(
|
||||
sourceFileName.c_str(), cmLocalGenerator::SHELL);
|
||||
compileObjectVars.Source = escapedSourceFileName.c_str();
|
||||
compileObjectVars.Object = objectFileName.c_str();
|
||||
compileObjectVars.Flags = vars["FLAGS"].c_str();
|
||||
compileObjectVars.Defines = vars["DEFINES"].c_str();
|
||||
|
||||
// Rule for compiling object file.
|
||||
std::string compileCmdVar = "CMAKE_";
|
||||
compileCmdVar += language;
|
||||
compileCmdVar += "_COMPILE_OBJECT";
|
||||
std::string compileCmd =
|
||||
this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str());
|
||||
std::vector<std::string> compileCmds;
|
||||
cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
|
||||
|
||||
for (std::vector<std::string>::iterator i = compileCmds.begin();
|
||||
i != compileCmds.end(); ++i)
|
||||
this->GetLocalGenerator()->ExpandRuleVariables(*i, compileObjectVars);
|
||||
|
||||
std::string cmdLine =
|
||||
this->GetLocalGenerator()->BuildCommandLine(compileCmds);
|
||||
|
||||
this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine,
|
||||
sourceFileName);
|
||||
}
|
||||
|
||||
cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
|
||||
comment,
|
||||
rule,
|
||||
|
|
|
@ -35,7 +35,7 @@ private:
|
|||
void ParseTranslationUnits()
|
||||
{
|
||||
this->TranslationUnits = TranslationUnitsType();
|
||||
ExpectOrDie('[', "at start of compile command file");
|
||||
ExpectOrDie('[', "at start of compile command file\n");
|
||||
do
|
||||
{
|
||||
ParseTranslationUnit();
|
||||
|
|
|
@ -47,7 +47,7 @@ CONFIGURE_FILE(${CMake_SOURCE_DIR}/Tests/EnforceConfig.cmake.in
|
|||
|
||||
# Testing
|
||||
IF(BUILD_TESTING)
|
||||
IF("${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
|
||||
IF("${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles" OR ("${CMAKE_TEST_GENERATOR}" MATCHES Ninja AND NOT WIN32))
|
||||
SET(TEST_CompileCommandOutput 1)
|
||||
ENDIF()
|
||||
|
||||
|
|
Loading…
Reference in New Issue