mirror of
https://github.com/reactos/CMake.git
synced 2024-11-29 06:20:23 +00:00
Merge topic 'target-COMPILE_OPTIONS'
24466f2
Add target_compile_options command.80ca9c4
Add COMPILE_OPTIONS target property.7cb2308
cmTarget: Rename LinkInterfaceIncludeDirectoriesEntries47f80d9
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.
This commit is contained in:
commit
e57b6a2521
@ -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);
|
||||
|
@ -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" \
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ struct cmGeneratorExpressionDAGChecker
|
||||
bool EvaluatingLinkLibraries();
|
||||
bool EvaluatingIncludeDirectories() const;
|
||||
bool EvaluatingCompileDefinitions() const;
|
||||
bool EvaluatingCompileOptions() const;
|
||||
|
||||
private:
|
||||
Result checkGraph() const;
|
||||
|
@ -246,6 +246,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
|
||||
{
|
||||
@ -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")
|
||||
|
@ -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))
|
||||
|
@ -1324,6 +1324,26 @@ std::string cmLocalGenerator::GetIncludeFlags(
|
||||
return flags;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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,
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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 =
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -286,6 +292,32 @@ void cmTarget::DefineProperties(cmake *cm)
|
||||
"Per-configuration preprocessor definitions on a target.",
|
||||
"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.",
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
@ -3116,6 +3182,159 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
|
||||
return includes;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
62
Source/cmTargetCompileOptionsCommand.cxx
Normal file
62
Source/cmTargetCompileOptionsCommand.cxx
Normal file
@ -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);
|
||||
}
|
90
Source/cmTargetCompileOptionsCommand.h
Normal file
90
Source/cmTargetCompileOptionsCommand.h
Normal file
@ -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
|
@ -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;
|
||||
|
35
Tests/CMakeCommands/target_compile_options/CMakeLists.txt
Normal file
35
Tests/CMakeCommands/target_compile_options/CMakeLists.txt
Normal file
@ -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()
|
18
Tests/CMakeCommands/target_compile_options/consumer.cpp
Normal file
18
Tests/CMakeCommands/target_compile_options/consumer.cpp
Normal file
@ -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; }
|
18
Tests/CMakeCommands/target_compile_options/main.cpp
Normal file
18
Tests/CMakeCommands/target_compile_options/main.cpp
Normal file
@ -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; }
|
@ -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"
|
||||
|
16
Tests/CompileOptions/CMakeLists.txt
Normal file
16
Tests/CompileOptions/CMakeLists.txt
Normal file
@ -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()
|
11
Tests/CompileOptions/main.cpp
Normal file
11
Tests/CompileOptions/main.cpp
Normal file
@ -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;
|
||||
}
|
5
Tests/CompileOptions/other.cpp
Normal file
5
Tests/CompileOptions/other.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
void foo(void)
|
||||
{
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user