From c71ac889ba6565c2a2aa31a403e3ab999abb5570 Mon Sep 17 00:00:00 2001 From: Justin Goshi Date: Mon, 23 Sep 2019 11:21:07 -0700 Subject: cmSourceFile: Add backtraces for a few source properties Adding backtrace support for INCLUDE_DIRECTORIES, COMPILE_OPTIONS, and COMPILE_DEFINITIONS. --- Source/cmSourceFile.cxx | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- Source/cmSourceFile.h | 22 ++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index bd68d04..2a345eb 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -6,6 +6,7 @@ #include #include "cmGlobalGenerator.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmProperty.h" @@ -28,6 +29,11 @@ std::string const& cmSourceFile::GetExtension() const const std::string cmSourceFile::propLANGUAGE = "LANGUAGE"; const std::string cmSourceFile::propLOCATION = "LOCATION"; const std::string cmSourceFile::propGENERATED = "GENERATED"; +const std::string cmSourceFile::propCOMPILE_DEFINITIONS = + "COMPILE_DEFINITIONS"; +const std::string cmSourceFile::propCOMPILE_OPTIONS = "COMPILE_OPTIONS"; +const std::string cmSourceFile::propINCLUDE_DIRECTORIES = + "INCLUDE_DIRECTORIES"; void cmSourceFile::SetObjectLibrary(std::string const& objlib) { @@ -226,7 +232,27 @@ bool cmSourceFile::Matches(cmSourceFileLocation const& loc) void cmSourceFile::SetProperty(const std::string& prop, const char* value) { - this->Properties.SetProperty(prop, value); + if (prop == propINCLUDE_DIRECTORIES) { + this->IncludeDirectories.clear(); + if (value) { + cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); + this->IncludeDirectories.emplace_back(value, lfbt); + } + } else if (prop == propCOMPILE_OPTIONS) { + this->CompileOptions.clear(); + if (value) { + cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); + this->CompileOptions.emplace_back(value, lfbt); + } + } else if (prop == propCOMPILE_DEFINITIONS) { + this->CompileDefinitions.clear(); + if (value) { + cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); + this->CompileDefinitions.emplace_back(value, lfbt); + } + } else { + this->Properties.SetProperty(prop, value); + } // Update IsGenerated flag if (prop == propGENERATED) { @@ -237,7 +263,24 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value) void cmSourceFile::AppendProperty(const std::string& prop, const char* value, bool asString) { - this->Properties.AppendProperty(prop, value, asString); + if (prop == propINCLUDE_DIRECTORIES) { + if (value && *value) { + cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); + this->IncludeDirectories.emplace_back(value, lfbt); + } + } else if (prop == propCOMPILE_OPTIONS) { + if (value && *value) { + cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); + this->CompileOptions.emplace_back(value, lfbt); + } + } else if (prop == propCOMPILE_DEFINITIONS) { + if (value && *value) { + cmListFileBacktrace lfbt = this->Location.GetMakefile()->GetBacktrace(); + this->CompileDefinitions.emplace_back(value, lfbt); + } + } else { + this->Properties.AppendProperty(prop, value, asString); + } // Update IsGenerated flag if (prop == propGENERATED) { @@ -287,6 +330,37 @@ const char* cmSourceFile::GetProperty(const std::string& prop) const return this->FullPath.c_str(); } + // Check for the properties with backtraces. + if (prop == propINCLUDE_DIRECTORIES) { + if (this->IncludeDirectories.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(this->IncludeDirectories, ";"); + return output.c_str(); + } + + if (prop == propCOMPILE_OPTIONS) { + if (this->CompileOptions.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(this->CompileOptions, ";"); + return output.c_str(); + } + + if (prop == propCOMPILE_DEFINITIONS) { + if (this->CompileDefinitions.empty()) { + return nullptr; + } + + static std::string output; + output = cmJoin(this->CompileDefinitions, ";"); + return output.c_str(); + } + const char* retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { cmMakefile const* mf = this->Location.GetMakefile(); diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 3b18fdb..6ef4167 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCustomCommand.h" +#include "cmListFileCache.h" #include "cmPropertyMap.h" #include "cmSourceFileLocation.h" #include "cmSourceFileLocationKind.h" @@ -57,6 +58,21 @@ public: /// @return Equivalent to GetPropertyAsBool("GENERATED") bool GetIsGenerated() const { return this->IsGenerated; } + const std::vector>& GetCompileOptions() const + { + return this->CompileOptions; + } + + const std::vector>& GetCompileDefinitions() const + { + return this->CompileDefinitions; + } + + const std::vector>& GetIncludeDirectories() const + { + return this->IncludeDirectories; + } + /** * Resolves the full path to the file. Attempts to locate the file on disk * and finalizes its location. @@ -116,6 +132,9 @@ private: std::string FullPath; std::string ObjectLibrary; std::vector Depends; + std::vector> CompileOptions; + std::vector> CompileDefinitions; + std::vector> IncludeDirectories; bool FindFullPathFailed = false; bool IsGenerated = false; @@ -126,6 +145,9 @@ private: static const std::string propLANGUAGE; static const std::string propLOCATION; static const std::string propGENERATED; + static const std::string propCOMPILE_DEFINITIONS; + static const std::string propCOMPILE_OPTIONS; + static const std::string propINCLUDE_DIRECTORIES; }; // TODO: Factor out into platform information modules. -- cgit v0.12 From 8b84c046faa9d6e52b99855a955bd7b6f48e9a8b Mon Sep 17 00:00:00 2001 From: Justin Goshi Date: Tue, 24 Sep 2019 12:19:49 -0700 Subject: fileapi: add some source property backtraces Support backtraces for COMPILE_DEFINITIONS, COMPILE_OPTIONS, and INCLUDE_DIRECTORIES source properties. --- Source/cmFileAPICodemodel.cxx | 66 ++++++++++++++-------- Tests/RunCMake/FileAPI/codemodel-v2-check.py | 65 +++++++++++++++++++-- .../RunCMake/FileAPIExternalSource/CMakeLists.txt | 1 + 3 files changed, 106 insertions(+), 26 deletions(-) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 96ea071..fbdb975 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -858,47 +858,69 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) fd.Flags.emplace_back(std::move(flags), JBTIndex()); } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); - if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) { - std::string flags; - lg->AppendCompileOptions( - flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); - fd.Flags.emplace_back(std::move(flags), JBTIndex()); + for (BT tmpOpt : sf->GetCompileOptions()) { + tmpOpt.Value = genexInterpreter.Evaluate(tmpOpt.Value, COMPILE_OPTIONS); + // After generator evaluation we need to use the AppendCompileOptions + // method so we handle situations where backtrace entries have lists + // and properly escape flags. + std::string tmp; + lg->AppendCompileOptions(tmp, tmpOpt.Value); + BT opt(tmp, tmpOpt.Backtrace); + fd.Flags.emplace_back(this->ToJBT(opt)); } // Add include directories from source file properties. { - std::vector includes; const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); - if (const char* cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) { - const std::string& evaluatedIncludes = - genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES); - lg->AppendIncludeDirectories(includes, evaluatedIncludes, *sf); - - for (std::string const& include : includes) { - bool const isSystemInclude = this->GT->IsSystemIncludeDirectory( - include, this->Config, fd.Language); - fd.Includes.emplace_back(include, isSystemInclude); + for (BT tmpInclude : sf->GetIncludeDirectories()) { + tmpInclude.Value = + genexInterpreter.Evaluate(tmpInclude.Value, INCLUDE_DIRECTORIES); + + // After generator evaluation we need to use the AppendIncludeDirectories + // method so we handle situations where backtrace entries have lists. + std::vector tmp; + lg->AppendIncludeDirectories(tmp, tmpInclude.Value, *sf); + for (std::string& i : tmp) { + bool const isSystemInclude = + this->GT->IsSystemIncludeDirectory(i, this->Config, fd.Language); + BT include(i, tmpInclude.Backtrace); + fd.Includes.emplace_back(this->ToJBT(include), isSystemInclude); } } } const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); - std::set fileDefines; - if (const char* defs = sf->GetProperty(COMPILE_DEFINITIONS)) { - lg->AppendDefines(fileDefines, - genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS)); + std::set> fileDefines; + for (BT tmpDef : sf->GetCompileDefinitions()) { + tmpDef.Value = + genexInterpreter.Evaluate(tmpDef.Value, COMPILE_DEFINITIONS); + + // After generator evaluation we need to use the AppendDefines method + // so we handle situations where backtrace entries have lists. + std::set tmp; + lg->AppendDefines(tmp, tmpDef.Value); + for (const std::string& i : tmp) { + BT def(i, tmpDef.Backtrace); + fileDefines.insert(def); + } } + std::set configFileDefines; const std::string defPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config); if (const char* config_defs = sf->GetProperty(defPropName)) { lg->AppendDefines( - fileDefines, + configFileDefines, genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS)); } - fd.Defines.reserve(fileDefines.size()); - for (std::string const& d : fileDefines) { + fd.Defines.reserve(fileDefines.size() + configFileDefines.size()); + + for (BT const& def : fileDefines) { + fd.Defines.emplace_back(this->ToJBT(def)); + } + + for (std::string const& d : configFileDefines) { fd.Defines.emplace_back(d, JBTIndex()); } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 52934f2..66c559d 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -4838,7 +4838,20 @@ def gen_check_targets(c, g, inSource): { "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild$", "isSystem": None, - "backtrace": None, + "backtrace": [ + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": 10, + "command": "set_property", + "hasParent": True, + }, + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], }, { "path": "^.*/Tests/RunCMake/FileAPIExternalSource$", @@ -4862,11 +4875,37 @@ def gen_check_targets(c, g, inSource): "defines": [ { "define": "EMPTY_C=1", - "backtrace": None, + "backtrace": [ + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": 9, + "command": "set_property", + "hasParent": True, + }, + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], }, { "define": "SRC_DUMMY", - "backtrace": None, + "backtrace": [ + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": 9, + "command": "set_property", + "hasParent": True, + }, + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], }, { "define": "GENERATED_EXE=1", @@ -4903,7 +4942,25 @@ def gen_check_targets(c, g, inSource): ], }, ], - "compileCommandFragments": None, + "compileCommandFragments": [ + { + "fragment" : "SRC_COMPILE_OPTIONS_DUMMY", + "backtrace": [ + { + "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": 13, + "command": "set_source_files_properties", + "hasParent": True, + }, + { + "file" : "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + } + ], }, { "language": "CXX", diff --git a/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt b/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt index f5670a7..b3ca660 100644 --- a/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt +++ b/Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt @@ -10,3 +10,4 @@ set_property(SOURCE empty.c PROPERTY COMPILE_DEFINITIONS EMPTY_C=1 SRC_DUMMY) set_property(SOURCE empty.c PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}") target_include_directories(generated_exe SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_compile_definitions(generated_exe PRIVATE GENERATED_EXE=1 -DTGT_DUMMY) +set_source_files_properties(empty.c PROPERTIES COMPILE_OPTIONS SRC_COMPILE_OPTIONS_DUMMY) -- cgit v0.12