diff options
author | Brad King <brad.king@kitware.com> | 2013-06-03 13:57:44 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2013-06-03 13:57:44 (GMT) |
commit | e57b6a25211ea28b7b01aadfc3aaf1de79455bdb (patch) | |
tree | 3957355de7d91f18e663fc1ed13185bf31f35125 | |
parent | bcc29c56a599baa3e2d8bd1d56e3727911a1c7d7 (diff) | |
parent | 24466f22c0c0e3235f0a21bd2a298c39df50e2f3 (diff) | |
download | CMake-e57b6a25211ea28b7b01aadfc3aaf1de79455bdb.zip CMake-e57b6a25211ea28b7b01aadfc3aaf1de79455bdb.tar.gz CMake-e57b6a25211ea28b7b01aadfc3aaf1de79455bdb.tar.bz2 |
Merge topic 'target-COMPILE_OPTIONS'
24466f2 Add target_compile_options command.
80ca9c4 Add COMPILE_OPTIONS target property.
7cb2308 cmTarget: Rename LinkInterfaceIncludeDirectoriesEntries
47f80d9 cmTarget: Rename struct to be more re-usable.
1319a14 Add <LANG>_COMPILER_ID generator expressions.
3549676 Add cmLocalGenerator::GetCompileOptions.
f3ad863 VS6: Rename some variables to correspond to config values.
25 files changed, 752 insertions, 63 deletions
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 227b226..75f2ae8 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -29,6 +29,7 @@ #include "cmSourceGroupCommand.cxx" #include "cmSubdirDependsCommand.cxx" #include "cmTargetCompileDefinitionsCommand.cxx" +#include "cmTargetCompileOptionsCommand.cxx" #include "cmTargetIncludeDirectoriesCommand.cxx" #include "cmTargetPropCommandBase.cxx" #include "cmUseMangledMesaCommand.cxx" @@ -71,6 +72,7 @@ void GetPredefinedCommands(std::list<cmCommand*>& commands.push_back(new cmSubdirDependsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmTargetCompileDefinitionsCommand); + commands.push_back(new cmTargetCompileOptionsCommand); commands.push_back(new cmUseMangledMesaCommand); commands.push_back(new cmUtilitySourceCommand); commands.push_back(new cmVariableRequiresCommand); diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h index 656810d..a8b3847 100644 --- a/Source/cmDocumentGeneratorExpressions.h +++ b/Source/cmDocumentGeneratorExpressions.h @@ -40,6 +40,14 @@ "is exported using export(), or when the target is used by another " \ "target in the same buildsystem. Expands to the empty string " \ "otherwise.\n" \ + " $<C_COMPILER_ID> = The CMake-id of the C compiler " \ + "used.\n" \ + " $<C_COMPILER_ID:comp> = '1' if the CMake-id of the C " \ + "compiler matches comp, otherwise '0'.\n" \ + " $<CXX_COMPILER_ID> = The CMake-id of the CXX compiler " \ + "used.\n" \ + " $<CXX_COMPILER_ID:comp> = '1' if the CMake-id of the CXX " \ + "compiler matches comp, otherwise '0'.\n" \ " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \ " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \ " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \ diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 62e9194..29d86a6 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -429,7 +429,9 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source, lg->AppendFlags(flags, makefile->GetDefineFlags()); // Add target-specific flags. - if(target->GetProperty("COMPILE_FLAGS")) + std::string targetFlags; + lg->GetCompileOptions(targetFlags, target, config); + if (!targetFlags.empty()) { std::string langIncludeExpr = "CMAKE_"; langIncludeExpr += language; @@ -440,7 +442,7 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source, cmsys::RegularExpression r(regex); std::vector<std::string> args; cmSystemTools:: - ParseWindowsCommandLine(target->GetProperty("COMPILE_FLAGS"), args); + ParseWindowsCommandLine(targetFlags.c_str(), args); for(std::vector<std::string>::iterator i = args.begin(); i != args.end(); ++i) { @@ -452,7 +454,7 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source, } else { - lg->AppendFlags(flags, target->GetProperty("COMPILE_FLAGS")); + lg->AppendFlags(flags, targetFlags.c_str()); } } diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 5cb50b9..e5ffb0c 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -168,3 +168,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0 || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0); } + +//---------------------------------------------------------------------------- +bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const +{ + const char *prop = this->Property.c_str(); + return (strcmp(prop, "COMPILE_OPTIONS") == 0 + || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 ); +} diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 62a5cdf..8d9fd76 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -40,6 +40,7 @@ struct cmGeneratorExpressionDAGChecker bool EvaluatingLinkLibraries(); bool EvaluatingIncludeDirectories() const; bool EvaluatingCompileDefinitions() const; + bool EvaluatingCompileOptions() const; private: Result checkGraph() const; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index df52368..5e7d00d 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -247,6 +247,104 @@ static const struct SemicolonNode : public cmGeneratorExpressionNode } semicolonNode; //---------------------------------------------------------------------------- +struct CompilerIdNode : public cmGeneratorExpressionNode +{ + CompilerIdNode() {} + + virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; } + + std::string EvaluateWithLanguage(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *, + const std::string &lang) const + { + const char *compilerId = context->Makefile ? + context->Makefile->GetSafeDefinition(( + "CMAKE_" + lang + "_COMPILER_ID").c_str()) : ""; + if (parameters.size() == 0) + { + return compilerId ? compilerId : ""; + } + else + { + cmsys::RegularExpression compilerIdValidator; + compilerIdValidator.compile("^[A-Za-z0-9_]*$"); + if (!compilerIdValidator.find(parameters.begin()->c_str())) + { + reportError(context, content->GetOriginalExpression(), + "Expression syntax not recognized."); + return std::string(); + } + if (!compilerId) + { + return parameters.front().empty() ? "1" : "0"; + } + + if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) + { + return "1"; + } + return "0"; + } + } +}; + +//---------------------------------------------------------------------------- +static const struct CCompilerIdNode : public CompilerIdNode +{ + CCompilerIdNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (parameters.size() != 0 && parameters.size() != 1) + { + reportError(context, content->GetOriginalExpression(), + "$<C_COMPILER_ID> expression requires one or two parameters"); + return std::string(); + } + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<C_COMPILER_ID> may only be used with targets. It may not " + "be used with add_custom_command."); + } + return this->EvaluateWithLanguage(parameters, context, content, + dagChecker, "C"); + } +} cCompilerIdNode; + +//---------------------------------------------------------------------------- +static const struct CXXCompilerIdNode : public CompilerIdNode +{ + CXXCompilerIdNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (parameters.size() != 0 && parameters.size() != 1) + { + reportError(context, content->GetOriginalExpression(), + "$<CXX_COMPILER_ID> expression requires one or two parameters"); + return std::string(); + } + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<CXX_COMPILER_ID> may only be used with targets. It may not " + "be used with add_custom_command."); + } + return this->EvaluateWithLanguage(parameters, context, content, + dagChecker, "CXX"); + } +} cxxCompilerIdNode; + +//---------------------------------------------------------------------------- static const struct ConfigurationNode : public cmGeneratorExpressionNode { ConfigurationNode() {} @@ -397,6 +495,7 @@ static const struct JoinNode : public cmGeneratorExpressionNode static const char* targetPropertyTransitiveWhitelist[] = { "INTERFACE_INCLUDE_DIRECTORIES" , "INTERFACE_COMPILE_DEFINITIONS" + , "INTERFACE_COMPILE_OPTIONS" }; std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, @@ -604,7 +703,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode else { assert(dagCheckerParent->EvaluatingIncludeDirectories() - || dagCheckerParent->EvaluatingCompileDefinitions()); + || dagCheckerParent->EvaluatingCompileDefinitions() + || dagCheckerParent->EvaluatingCompileOptions()); } } @@ -623,6 +723,11 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; } + else if (propertyName == "INTERFACE_COMPILE_OPTIONS" + || propertyName == "COMPILE_OPTIONS") + { + interfacePropertyName = "INTERFACE_COMPILE_OPTIONS"; + } const char **transBegin = targetPropertyTransitiveWhitelist; const char **transEnd = targetPropertyTransitiveWhitelist @@ -1055,6 +1160,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &orNode; else if (identifier == "NOT") return ¬Node; + else if (identifier == "C_COMPILER_ID") + return &cCompilerIdNode; + else if (identifier == "CXX_COMPILER_ID") + return &cxxCompilerIdNode; else if (identifier == "CONFIGURATION") return &configurationNode; else if (identifier == "CONFIG") diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d782a06..2d76c82 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -681,9 +681,11 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, { // Add flags from target and source file properties. std::string flags; - if(cmtarget.GetProperty("COMPILE_FLAGS")) + std::string targetFlags; + lg->GetCompileOptions(targetFlags, &cmtarget, 0); // TODO: Config? + if(!targetFlags.empty()) { - lg->AppendFlags(flags, cmtarget.GetProperty("COMPILE_FLAGS")); + lg->AppendFlags(flags, targetFlags.c_str()); } const char* srcfmt = sf->GetProperty("Fortran_FORMAT"); switch(this->CurrentLocalGenerator->GetFortranFormat(srcfmt)) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index d346f16..57e25a1 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1325,6 +1325,26 @@ std::string cmLocalGenerator::GetIncludeFlags( } //---------------------------------------------------------------------------- +void cmLocalGenerator::GetCompileOptions(std::string& flags, + cmTarget* target, + const char *config) +{ + // Add target-specific flags. + if(const char *prop = target->GetProperty("COMPILE_FLAGS")) + { + this->AppendFlags(flags, prop); + } + + std::vector<std::string> opts; // TODO: Emitted. + target->GetCompileOptions(opts, config); + for(std::vector<std::string>::const_iterator li = opts.begin(); + li != opts.end(); ++li) + { + this->AppendFlags(flags, li->c_str()); + } +} + +//---------------------------------------------------------------------------- void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, cmGeneratorTarget* target, const char* lang, diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index a1c34f0..28c88e6 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -215,6 +215,9 @@ public: cmGeneratorTarget* target, const char* lang = "C", const char *config = 0, bool stripImplicitInclDirs = true); + void GetCompileOptions(std::string& flags, + cmTarget* target, + const char *config); /** Compute the language used to compile the given source file. */ const char* GetSourceFileLanguage(const cmSourceFile& source); diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index dc94476..4c78f7f 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -1639,9 +1639,9 @@ void cmLocalVisualStudio6Generator // store flags for each configuration std::string flags = " "; std::string flagsRelease = " "; - std::string flagsMinSize = " "; + std::string flagsMinSizeRel = " "; std::string flagsDebug = " "; - std::string flagsDebugRel = " "; + std::string flagsRelWithDebInfo = " "; if(target.GetType() >= cmTarget::EXECUTABLE && target.GetType() <= cmTarget::OBJECT_LIBRARY) { @@ -1664,16 +1664,16 @@ void cmLocalVisualStudio6Generator flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" "; flagVar = baseFlagVar + "_MINSIZEREL"; - flagsMinSize = this->Makefile->GetSafeDefinition(flagVar.c_str()); - flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" "; + flagsMinSizeRel = this->Makefile->GetSafeDefinition(flagVar.c_str()); + flagsMinSizeRel += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" "; flagVar = baseFlagVar + "_DEBUG"; flagsDebug = this->Makefile->GetSafeDefinition(flagVar.c_str()); flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" "; flagVar = baseFlagVar + "_RELWITHDEBINFO"; - flagsDebugRel = this->Makefile->GetSafeDefinition(flagVar.c_str()); - flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" "; + flagsRelWithDebInfo = this->Makefile->GetSafeDefinition(flagVar.c_str()); + flagsRelWithDebInfo += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" "; } // if _UNICODE and _SBCS are not found, then add -D_MBCS @@ -1686,12 +1686,31 @@ void cmLocalVisualStudio6Generator flags += " /D \"_MBCS\""; } + { + std::string targetFlags; + this->GetCompileOptions(targetFlags, &target, 0); // Add per-target flags. - if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS")) + if(!targetFlags.empty()) { flags += " "; flags += targetFlags; } + } +#define ADD_FLAGS(CONFIG) \ + { \ + std::string targetFlags; \ + this->GetCompileOptions(targetFlags, &target, #CONFIG); \ + if(!targetFlags.empty()) \ + { \ + flags ## CONFIG += " "; \ + flags ## CONFIG += targetFlags; \ + } \ + } + + ADD_FLAGS(Debug) + ADD_FLAGS(Release) + ADD_FLAGS(MinSizeRel) + ADD_FLAGS(RelWithDebInfo) // Add per-target and per-configuration preprocessor definitions. std::set<std::string> definesSet; @@ -1731,19 +1750,19 @@ void cmLocalVisualStudio6Generator flags += defines; flagsDebug += debugDefines; flagsRelease += releaseDefines; - flagsMinSize += minsizeDefines; - flagsDebugRel += debugrelDefines; + flagsMinSizeRel += minsizeDefines; + flagsRelWithDebInfo += debugrelDefines; // The template files have CXX FLAGS in them, that need to be replaced. // There are not separate CXX and C template files, so we use the same // variable names. The previous code sets up flags* variables to contain // the correct C or CXX flags cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL", - flagsMinSize.c_str()); + flagsMinSizeRel.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG", flagsDebug.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO", - flagsDebugRel.c_str()); + flagsRelWithDebInfo.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE", flagsRelease.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str()); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 58d28da..e7badf0 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -723,8 +723,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } } + std::string targetFlags; + this->GetCompileOptions(targetFlags, &target, configName); // Add the target-specific flags. - if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS")) + if(!targetFlags.empty()) { flags += " "; flags += targetFlags; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 6fc88d6..699a7fd 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -332,21 +332,25 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n"; } + std::string targetFlags; for(std::set<cmStdString>::const_iterator l = languages.begin(); l != languages.end(); ++l) { *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n"; *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) << "\n\n"; + std::string targetLangFlags; + this->LocalGenerator->GetCompileOptions(targetLangFlags, this->Target, + this->LocalGenerator->ConfigurationName.c_str()); + if (!targetFlags.empty() && targetFlags != targetLangFlags) + { + targetFlags += " " + targetLangFlags; + } } - // Add target-specific flags. - if(this->Target->GetProperty("COMPILE_FLAGS")) + if (!targetFlags.empty()) { - std::string flags; - this->LocalGenerator->AppendFlags - (flags, this->Target->GetProperty("COMPILE_FLAGS")); - *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n"; + *this->FlagFileStream << "# TARGET_FLAGS = " << targetFlags << "\n\n"; } } @@ -532,8 +536,13 @@ cmMakefileTargetGenerator langFlags += "_FLAGS)"; this->LocalGenerator->AppendFlags(flags, langFlags.c_str()); - // Add target-specific flags. - if(this->Target->GetProperty("COMPILE_FLAGS")) + std::string configUpper = + cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); + + std::string targetFlags; + this->LocalGenerator->GetCompileOptions(targetFlags, this->Target, + configUpper.c_str()); + if (!targetFlags.empty()) { std::string langIncludeExpr = "CMAKE_"; langIncludeExpr += lang; @@ -545,7 +554,7 @@ cmMakefileTargetGenerator cmsys::RegularExpression r(regex); std::vector<std::string> args; cmSystemTools::ParseWindowsCommandLine( - this->Target->GetProperty("COMPILE_FLAGS"), + targetFlags.c_str(), args); for(std::vector<std::string>::iterator i = args.begin(); i != args.end(); ++i) @@ -559,8 +568,7 @@ cmMakefileTargetGenerator } else { - this->LocalGenerator->AppendFlags - (flags, this->Target->GetProperty("COMPILE_FLAGS")); + this->LocalGenerator->AppendFlags(flags, targetFlags.c_str()); } } @@ -594,8 +602,6 @@ cmMakefileTargetGenerator << compile_defs << "\n" << "\n"; } - std::string configUpper = - cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName); std::string defPropName = "COMPILE_DEFINITIONS_"; defPropName += configUpper; if(const char* config_compile_defs = diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 532ee67..6f912b8 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -151,9 +151,9 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, this->GetConfigName()); // Add include directory flags. + const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); { std::vector<std::string> includes; - const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, language.c_str(), config); @@ -171,7 +171,9 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags()); // Add target-specific flags. - if(this->Target->GetProperty("COMPILE_FLAGS")) + std::string targetFlags; + this->LocalGenerator->GetCompileOptions(targetFlags, this->Target, config); + if(!targetFlags.empty()) { std::string langIncludeExpr = "CMAKE_"; langIncludeExpr += language; @@ -183,7 +185,7 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, cmsys::RegularExpression r(regex); std::vector<std::string> args; cmSystemTools::ParseWindowsCommandLine( - this->Target->GetProperty("COMPILE_FLAGS"), + targetFlags.c_str(), args); for(std::vector<std::string>::iterator i = args.begin(); i != args.end(); ++i) @@ -198,7 +200,7 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, else { this->LocalGenerator->AppendFlags - (flags, this->Target->GetProperty("COMPILE_FLAGS")); + (flags, targetFlags.c_str()); } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 5628971..f1d0ac3 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -130,31 +130,35 @@ public: typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType; SourceEntriesType SourceEntries; - struct IncludeDirectoriesEntry { - IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, + struct TargetPropertyEntry { + TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, const std::string &targetName = std::string()) : ge(cge), TargetName(targetName) {} const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge; - std::vector<std::string> CachedIncludes; + std::vector<std::string> CachedEntries; const std::string TargetName; }; - std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries; - std::vector<cmValueWithOrigin> LinkInterfaceIncludeDirectoriesEntries; + std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; + std::vector<TargetPropertyEntry*> CompileOptionsEntries; + std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries; - std::map<std::string, std::vector<IncludeDirectoriesEntry*> > + std::map<std::string, std::vector<TargetPropertyEntry*> > CachedLinkInterfaceIncludeDirectoriesEntries; + std::map<std::string, std::vector<TargetPropertyEntry*> > + CachedLinkInterfaceCompileOptionsEntries; std::map<std::string, std::string> CachedLinkInterfaceCompileDefinitions; std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone; std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone; + std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone; }; //---------------------------------------------------------------------------- void deleteAndClear( - std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries) + std::vector<cmTargetInternals::TargetPropertyEntry*> &entries) { - for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) @@ -167,10 +171,10 @@ void deleteAndClear( //---------------------------------------------------------------------------- void deleteAndClear( std::map<std::string, - std::vector<cmTargetInternals::IncludeDirectoriesEntry*> > &entries) + std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries) { for (std::map<std::string, - std::vector<cmTargetInternals::IncludeDirectoriesEntry*> >::iterator + std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator it = entries.begin(), end = entries.end(); it != end; ++it) { deleteAndClear(it->second); @@ -181,6 +185,7 @@ void deleteAndClear( cmTargetInternals::~cmTargetInternals() { deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries); + deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries); } //---------------------------------------------------------------------------- @@ -199,6 +204,7 @@ cmTarget::cmTarget() this->IsImportedTarget = false; this->BuildInterfaceIncludesAppended = false; this->DebugIncludesDone = false; + this->DebugCompileOptionsDone = false; } //---------------------------------------------------------------------------- @@ -287,6 +293,32 @@ void cmTarget::DefineProperties(cmake *cm) "This is the configuration-specific version of COMPILE_DEFINITIONS."); cm->DefineProperty + ("COMPILE_OPTIONS", cmProperty::TARGET, + "List of options to pass to the compiler.", + "This property specifies the list of options specified " + "so far for this property. " + "This property exists on targets only. " + "\n" + "The target property values are used by the generators to set " + "the options for the compiler.\n" + "Contents of COMPILE_OPTIONS may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS); + + cm->DefineProperty + ("INTERFACE_COMPILE_OPTIONS", cmProperty::TARGET, + "List of interface options to pass to the compiler.", + "Targets may populate this property to publish the compile options " + "required to compile against the headers for the target. Consuming " + "targets can add entries to their own COMPILE_OPTIONS property such " + "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_OPTIONS> to use the " + "compile options specified in the interface of 'foo'." + "\n" + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS); + + cm->DefineProperty ("DEFINE_SYMBOL", cmProperty::TARGET, "Define a symbol when compiling this target's sources.", "DEFINE_SYMBOL sets the name of the preprocessor symbol defined when " @@ -2751,7 +2783,18 @@ void cmTarget::SetProperty(const char* prop, const char* value) deleteAndClear(this->Internal->IncludeDirectoriesEntries); cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); this->Internal->IncludeDirectoriesEntries.push_back( - new cmTargetInternals::IncludeDirectoriesEntry(cge)); + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } + if(strcmp(prop,"COMPILE_OPTIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + deleteAndClear(this->Internal->CompileOptionsEntries); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); + this->Internal->CompileOptionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); return; } if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported()) @@ -2764,14 +2807,14 @@ void cmTarget::SetProperty(const char* prop, const char* value) } if (strcmp(prop, "LINK_LIBRARIES") == 0) { - this->Internal->LinkInterfaceIncludeDirectoriesEntries.clear(); + this->Internal->LinkInterfacePropertyEntries.clear(); if (cmGeneratorExpression::IsValidTargetName(value) || cmGeneratorExpression::Find(value) != std::string::npos) { cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); cmValueWithOrigin entry(value, lfbt); - this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry); + this->Internal->LinkInterfacePropertyEntries.push_back(entry); } // Fall through } @@ -2793,7 +2836,16 @@ void cmTarget::AppendProperty(const char* prop, const char* value, this->Makefile->GetBacktrace(lfbt); cmGeneratorExpression ge(lfbt); this->Internal->IncludeDirectoriesEntries.push_back( - new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value))); + new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); + return; + } + if(strcmp(prop,"COMPILE_OPTIONS") == 0) + { + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->CompileOptionsEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); return; } if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported()) @@ -2812,7 +2864,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value, cmListFileBacktrace lfbt; this->Makefile->GetBacktrace(lfbt); cmValueWithOrigin entry(value, lfbt); - this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry); + this->Internal->LinkInterfacePropertyEntries.push_back(entry); } // Fall through } @@ -2877,17 +2929,31 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry, { cmGeneratorExpression ge(entry.Backtrace); - std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::iterator position + std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position = before ? this->Internal->IncludeDirectoriesEntries.begin() : this->Internal->IncludeDirectoriesEntries.end(); this->Internal->IncludeDirectoriesEntries.insert(position, - new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value))); + new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); +} + +//---------------------------------------------------------------------------- +void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry, + bool before) +{ + cmGeneratorExpression ge(entry.Backtrace); + + std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position + = before ? this->Internal->CompileOptionsEntries.begin() + : this->Internal->CompileOptionsEntries.end(); + + this->Internal->CompileOptionsEntries.insert(position, + new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value))); } //---------------------------------------------------------------------------- static void processIncludeDirectories(cmTarget *tgt, - const std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries, + const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &includes, std::set<std::string> &uniqueIncludes, cmGeneratorExpressionDAGChecker *dagChecker, @@ -2895,12 +2961,12 @@ static void processIncludeDirectories(cmTarget *tgt, { cmMakefile *mf = tgt->GetMakefile(); - for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator it = entries.begin(), end = entries.end(); it != end; ++it) { bool testIsOff = true; bool cacheIncludes = false; - std::vector<std::string> entryIncludes = (*it)->CachedIncludes; + std::vector<std::string> entryIncludes = (*it)->CachedEntries; if(!entryIncludes.empty()) { testIsOff = false; @@ -3003,7 +3069,7 @@ static void processIncludeDirectories(cmTarget *tgt, } if (cacheIncludes) { - (*it)->CachedIncludes = entryIncludes; + (*it)->CachedEntries = entryIncludes; } if (!usedIncludes.empty()) { @@ -3059,8 +3125,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString]) { for (std::vector<cmValueWithOrigin>::const_iterator - it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(), - end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end(); + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); it != end; ++it) { { @@ -3089,7 +3155,7 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) this->Internal ->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back( - new cmTargetInternals::IncludeDirectoriesEntry(cge, + new cmTargetInternals::TargetPropertyEntry(cge, it->Value)); } } @@ -3117,6 +3183,159 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config) } //---------------------------------------------------------------------------- +static void processCompileOptions(cmTarget *tgt, + const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, + std::vector<std::string> &options, + std::set<std::string> &uniqueOptions, + cmGeneratorExpressionDAGChecker *dagChecker, + const char *config, bool debugOptions) +{ + cmMakefile *mf = tgt->GetMakefile(); + + for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator + it = entries.begin(), end = entries.end(); it != end; ++it) + { + bool cacheOptions = false; + std::vector<std::string> entryOptions = (*it)->CachedEntries; + if(entryOptions.empty()) + { + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + tgt, + dagChecker), + entryOptions); + if (mf->IsGeneratingBuildSystem() + && !(*it)->ge->GetHadContextSensitiveCondition()) + { + cacheOptions = true; + } + } + std::string usedOptions; + for(std::vector<std::string>::iterator + li = entryOptions.begin(); li != entryOptions.end(); ++li) + { + std::string opt = *li; + + if(uniqueOptions.insert(opt).second) + { + options.push_back(opt); + if (debugOptions) + { + usedOptions += " * " + opt + "\n"; + } + } + } + if (cacheOptions) + { + (*it)->CachedEntries = entryOptions; + } + if (!usedOptions.empty()) + { + mf->GetCMakeInstance()->IssueMessage(cmake::LOG, + std::string("Used compile options for target ") + + tgt->GetName() + ":\n" + + usedOptions, (*it)->ge->GetBacktrace()); + } + } +} + +//---------------------------------------------------------------------------- +void cmTarget::GetCompileOptions(std::vector<std::string> &result, + const char *config) +{ + std::set<std::string> uniqueOptions; + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "COMPILE_OPTIONS", 0, 0); + + std::vector<std::string> debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugOptions = !this->DebugCompileOptionsDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "COMPILE_OPTIONS") + != debugProperties.end(); + + if (this->Makefile->IsGeneratingBuildSystem()) + { + this->DebugCompileOptionsDone = true; + } + + processCompileOptions(this, + this->Internal->CompileOptionsEntries, + result, + uniqueOptions, + &dagChecker, + config, + debugOptions); + + std::string configString = config ? config : ""; + if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[configString]) + { + for (std::vector<cmValueWithOrigin>::const_iterator + it = this->Internal->LinkInterfacePropertyEntries.begin(), + end = this->Internal->LinkInterfacePropertyEntries.end(); + it != end; ++it) + { + { + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(it->Value); + std::string targetResult = cge->Evaluate(this->Makefile, config, + false, this, 0, 0); + if (!this->Makefile->FindTargetToUse(targetResult.c_str())) + { + continue; + } + } + std::string optionGenex = "$<TARGET_PROPERTY:" + + it->Value + ",INTERFACE_COMPILE_OPTIONS>"; + if (cmGeneratorExpression::Find(it->Value) != std::string::npos) + { + // Because it->Value is a generator expression, ensure that it + // evaluates to the non-empty string before being used in the + // TARGET_PROPERTY expression. + optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">"; + } + cmGeneratorExpression ge(it->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse( + optionGenex); + + this->Internal + ->CachedLinkInterfaceCompileOptionsEntries[configString].push_back( + new cmTargetInternals::TargetPropertyEntry(cge, + it->Value)); + } + } + + processCompileOptions(this, + this->Internal->CachedLinkInterfaceCompileOptionsEntries[configString], + result, + uniqueOptions, + &dagChecker, + config, + debugOptions); + + if (!this->Makefile->IsGeneratingBuildSystem()) + { + deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries); + } + else + { + this->Internal->CacheLinkInterfaceCompileOptionsDone[configString] = true; + } +} + +//---------------------------------------------------------------------------- std::string cmTarget::GetCompileDefinitions(const char *config) { const char *configProp = 0; @@ -3541,9 +3760,9 @@ const char *cmTarget::GetProperty(const char* prop, static std::string output; output = ""; std::string sep; - typedef cmTargetInternals::IncludeDirectoriesEntry - IncludeDirectoriesEntry; - for (std::vector<IncludeDirectoriesEntry*>::const_iterator + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for (std::vector<TargetPropertyEntry*>::const_iterator it = this->Internal->IncludeDirectoriesEntries.begin(), end = this->Internal->IncludeDirectoriesEntries.end(); it != end; ++it) @@ -3554,6 +3773,24 @@ const char *cmTarget::GetProperty(const char* prop, } return output.c_str(); } + if(strcmp(prop,"COMPILE_OPTIONS") == 0) + { + static std::string output; + output = ""; + std::string sep; + typedef cmTargetInternals::TargetPropertyEntry + TargetPropertyEntry; + for (std::vector<TargetPropertyEntry*>::const_iterator + it = this->Internal->CompileOptionsEntries.begin(), + end = this->Internal->CompileOptionsEntries.end(); + it != end; ++it) + { + output += sep; + output += (*it)->ge->GetInput(); + sep = ";"; + } + return output.c_str(); + } if (strcmp(prop,"IMPORTED") == 0) { @@ -6263,6 +6500,7 @@ cmTargetInternalPointer cmTargetInternalPointer::~cmTargetInternalPointer() { deleteAndClear(this->Pointer->IncludeDirectoriesEntries); + deleteAndClear(this->Pointer->CompileOptionsEntries); delete this->Pointer; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 0bcc2a8..3bc0ab2 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -511,9 +511,14 @@ public: std::vector<std::string> GetIncludeDirectories(const char *config); void InsertInclude(const cmValueWithOrigin &entry, bool before = false); + void InsertCompileOption(const cmValueWithOrigin &entry, + bool before = false); void AppendBuildInterfaceIncludes(); + void GetCompileOptions(std::vector<std::string> &result, + const char *config); + bool IsNullImpliedByLinkLibraries(const std::string &p); bool IsLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); @@ -643,6 +648,7 @@ private: bool IsApple; bool IsImportedTarget; bool DebugIncludesDone; + bool DebugCompileOptionsDone; mutable std::set<std::string> LinkImplicitNullProperties; bool BuildInterfaceIncludesAppended; diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx new file mode 100644 index 0000000..e80c845 --- /dev/null +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -0,0 +1,62 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmTargetCompileOptionsCommand.h" + +bool cmTargetCompileOptionsCommand +::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE); +} + +void cmTargetCompileOptionsCommand +::HandleImportedTarget(const std::string &tgt) +{ + cmOStringStream e; + e << "Cannot specify compile options for imported target \"" + << tgt << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +void cmTargetCompileOptionsCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify compile options for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +std::string cmTargetCompileOptionsCommand +::Join(const std::vector<std::string> &content) +{ + std::string defs; + std::string sep; + for(std::vector<std::string>::const_iterator it = content.begin(); + it != content.end(); ++it) + { + defs += sep + *it; + sep = ";"; + } + return defs; +} + +//---------------------------------------------------------------------------- +void cmTargetCompileOptionsCommand +::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, + bool) +{ + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmValueWithOrigin entry(this->Join(content), lfbt); + tgt->InsertCompileOption(entry); +} diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h new file mode 100644 index 0000000..87fa1a7 --- /dev/null +++ b/Source/cmTargetCompileOptionsCommand.h @@ -0,0 +1,90 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly <steveire@gmail.com> + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmTargetCompileOptionsCommand_h +#define cmTargetCompileOptionsCommand_h + +#include "cmTargetPropCommandBase.h" + +class cmTargetCompileOptionsCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetCompileOptionsCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector<std::string> const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual const char* GetName() const { return "target_compile_options";} + + /** + * Succinct documentation. + */ + virtual const char* GetTerseDocumentation() const + { + return + "Add compile options to a target."; + } + + /** + * More documentation. + */ + virtual const char* GetFullDocumentation() const + { + return + " target_compile_options(<target> [BEFORE] " + "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n" + " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n" + "Specify compile options to use when compiling a given target. " + "The named <target> must have been created by a command such as " + "add_executable or add_library and must not be an IMPORTED target. " + "If BEFORE is specified, the content will be prepended to the property " + "instead of being appended.\n" + "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " + "the scope of the following arguments. PRIVATE and PUBLIC items will " + "populate the COMPILE_OPTIONS property of <target>. PUBLIC and " + "INTERFACE items will populate the INTERFACE_COMPILE_OPTIONS " + "property of <target>. " + "The following arguments specify compile opitions. " + "Repeated calls for the same <target> append items in the order called." + "\n" + "Arguments to target_compile_options may use \"generator " + "expressions\" with the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + ; + } + + cmTypeMacro(cmTargetCompileOptionsCommand, cmTargetPropCommandBase); + +private: + virtual void HandleImportedTarget(const std::string &tgt); + virtual void HandleMissingTarget(const std::string &name); + + virtual void HandleDirectContent(cmTarget *tgt, + const std::vector<std::string> &content, + bool prepend); + virtual std::string Join(const std::vector<std::string> &content); +}; + +#endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index d0ab976..f8de3a8 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1270,8 +1270,12 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( flags += " /TP "; } } + + std::string targetFlags; + this->LocalGenerator->GetCompileOptions(targetFlags, this->Target, + configName.c_str()); // Add the target-specific flags. - if(const char* targetFlags = this->Target->GetProperty("COMPILE_FLAGS")) + if(!targetFlags.empty()) { flags += " "; flags += targetFlags; diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt new file mode 100644 index 0000000..06a48fb --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt @@ -0,0 +1,35 @@ + +cmake_minimum_required(VERSION 2.8) + +project(target_compile_options) + +add_executable(target_compile_options + "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp" +) +target_compile_options(target_compile_options + PRIVATE $<$<CXX_COMPILER_ID:GNU>:-DMY_PRIVATE_DEFINE> + PUBLIC $<$<CXX_COMPILER_ID:GNU>:-DMY_PUBLIC_DEFINE> + INTERFACE $<$<CXX_COMPILER_ID:GNU>:-DMY_INTERFACE_DEFINE> +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(target_compile_options + PRIVATE + "DO_GNU_TESTS" + ) +endif() + +add_executable(consumer + "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" +) + +target_compile_options(consumer + PRIVATE $<$<CXX_COMPILER_ID:GNU>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>> +) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(consumer + PRIVATE + "DO_GNU_TESTS" + ) +endif() diff --git a/Tests/CMakeCommands/target_compile_options/consumer.cpp b/Tests/CMakeCommands/target_compile_options/consumer.cpp new file mode 100644 index 0000000..1299606 --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/consumer.cpp @@ -0,0 +1,18 @@ + +#ifdef DO_GNU_TESTS + +# ifdef MY_PRIVATE_DEFINE +# error Unexpected MY_PRIVATE_DEFINE +# endif + +# ifndef MY_PUBLIC_DEFINE +# error Expected MY_PUBLIC_DEFINE +# endif + +# ifndef MY_INTERFACE_DEFINE +# error Expected MY_INTERFACE_DEFINE +# endif + +#endif + +int main() { return 0; } diff --git a/Tests/CMakeCommands/target_compile_options/main.cpp b/Tests/CMakeCommands/target_compile_options/main.cpp new file mode 100644 index 0000000..961c06d --- /dev/null +++ b/Tests/CMakeCommands/target_compile_options/main.cpp @@ -0,0 +1,18 @@ + +#ifdef DO_GNU_TESTS + +# ifndef MY_PRIVATE_DEFINE +# error Expected MY_PRIVATE_DEFINE +# endif + +# ifndef MY_PUBLIC_DEFINE +# error Expected MY_PUBLIC_DEFINE +# endif + +# ifdef MY_INTERFACE_DEFINE +# error Unexpected MY_INTERFACE_DEFINE +# endif + +#endif + +int main() { return 0; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index cd562c2..ee6c3e6 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -245,6 +245,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(PolicyScope PolicyScope) ADD_TEST_MACRO(EmptyLibrary EmptyLibrary) ADD_TEST_MACRO(CompileDefinitions CompileDefinitions) + ADD_TEST_MACRO(CompileOptions CompileOptions) ADD_TEST_MACRO(CompatibleInterface CompatibleInterface) set_tests_properties(EmptyLibrary PROPERTIES PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target:test") @@ -1990,6 +1991,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries) ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories) ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions) + ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options) configure_file( "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in" diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt new file mode 100644 index 0000000..6d8a96a --- /dev/null +++ b/Tests/CompileOptions/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8) + +project(CompileOptions) + +add_library(testlib other.cpp) + +add_executable(CompileOptions main.cpp) +set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE>") +target_link_libraries(CompileOptions testlib) + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_definitions(CompileOptions + PRIVATE + "DO_GNU_TESTS" + ) +endif() diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp new file mode 100644 index 0000000..0d39050 --- /dev/null +++ b/Tests/CompileOptions/main.cpp @@ -0,0 +1,11 @@ + +#ifdef DO_GNU_TESTS +# ifndef TEST_DEFINE +# error Expected TEST_DEFINE +# endif +#endif + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/Tests/CompileOptions/other.cpp b/Tests/CompileOptions/other.cpp new file mode 100644 index 0000000..0e34375 --- /dev/null +++ b/Tests/CompileOptions/other.cpp @@ -0,0 +1,5 @@ + +void foo(void) +{ + +} |