Merge topic 'sourceFile-new-properties'

04483111 sourceFile properties: add property INCLUDE_DIRECTORIES
3073bd1f VisualStudio generators: refactoring
78b1c2e0 sourceFile properties: add property COMPILE_OPTIONS
3f935e69 LocalGenerator: refactoring

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1596
This commit is contained in:
Brad King 2018-01-25 13:33:23 +00:00 committed by Kitware Robot
commit 76f5a87cf1
51 changed files with 719 additions and 229 deletions

View File

@ -370,10 +370,12 @@ Properties on Source Files
/prop_sf/AUTORCC_OPTIONS
/prop_sf/COMPILE_DEFINITIONS
/prop_sf/COMPILE_FLAGS
/prop_sf/COMPILE_OPTIONS
/prop_sf/EXTERNAL_OBJECT
/prop_sf/Fortran_FORMAT
/prop_sf/GENERATED
/prop_sf/HEADER_FILE_ONLY
/prop_sf/INCLUDE_DIRECTORIES
/prop_sf/KEEP_EXTENSION
/prop_sf/LABELS
/prop_sf/LANGUAGE

View File

@ -0,0 +1,17 @@
COMPILE_OPTIONS
---------------
List of additional options to pass to the compiler.
This property holds a :ref:`;-list <CMake Language Lists>` of options
and will be added to the list of compile flags when this
source file builds. Use :prop_sf:`COMPILE_DEFINITIONS` to pass
additional preprocessor definitions and :prop_sf:`INCLUDE_DIRECTORIES` to pass
additional include directories.
Contents of ``COMPILE_OPTIONS`` may use "generator expressions" with the
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
for available expressions. However, :generator:`Xcode`
does not support per-config per-source settings, so expressions
that depend on the build configuration are not allowed with that
generator.

View File

@ -0,0 +1,18 @@
INCLUDE_DIRECTORIES
-------------------
List of preprocessor include file search directories.
This property holds a :ref:`;-list <CMake Language Lists>` of paths
and will be added to the list of include directories when this
source file builds. These directories will take precedence over directories
defined at target level except for :generator:`Xcode` generator due to technical
limitations.
Relative paths should not be added to this property directly.
Contents of ``INCLUDE_DIRECTORIES`` may use "generator expressions" with
the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
for available expressions. However, :generator:`Xcode` does not support
per-config per-source settings, so expressions that depend on the build
configuration are not allowed with that generator.

View File

@ -0,0 +1,10 @@
src-new-properties-COMPILE_OPTIONS-and-INCLUDE_DIRECTORIES
----------------------------------------------------------
* Source file learns new properties:
* A :prop_sf:`COMPILE_OPTIONS` source file property was added to manage list
of options to pass to the compiler.
* An :prop_sf:`INCLUDE_DIRECTORIES` source file property was added to specify
list of preprocessor include file search directories.

View File

@ -257,6 +257,8 @@ void cmExtraSublimeTextGenerator::AppendTarget(
std::string flagsString =
this->ComputeFlagsForObject(sourceFile, lg, target);
std::string definesString = this->ComputeDefines(sourceFile, lg, target);
std::string includesString =
this->ComputeIncludes(sourceFile, lg, target);
flags.clear();
cmsys::RegularExpression flagRegex;
// Regular expression to extract compiler flags from a string
@ -264,7 +266,8 @@ void cmExtraSublimeTextGenerator::AppendTarget(
const char* regexString =
"(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
flagRegex.compile(regexString);
std::string workString = flagsString + " " + definesString;
std::string workString =
flagsString + " " + definesString + " " + includesString;
while (flagRegex.find(workString)) {
std::string::size_type start = flagRegex.start();
if (workString[start] == ' ') {
@ -351,23 +354,21 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
lg->GetTargetCompileFlags(gtgt, config, language, flags);
// Add include directory flags.
{
std::vector<std::string> includes;
lg->GetIncludeDirectories(includes, gtgt, language, config);
std::string includeFlags = lg->GetIncludeFlags(includes, gtgt, language,
true); // full include paths
lg->AppendFlags(flags, includeFlags);
}
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config,
gtgt->GetName(), language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
cmGeneratorExpressionInterpreter genexInterpreter(
lg, gtgt, config, gtgt->GetName(), language);
lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = source->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
return flags;
}
@ -410,6 +411,34 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
return definesString;
}
std::string cmExtraSublimeTextGenerator::ComputeIncludes(
cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* target)
{
std::vector<std::string> includes;
cmMakefile* makefile = lg->GetMakefile();
const std::string& language = source->GetLanguage();
const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
cmGeneratorExpressionInterpreter genexInterpreter(
lg, target, config, target->GetName(), language);
// Add include directories for this source file
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
lg->AppendIncludeDirectories(
includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES),
*source);
}
// Add include directory flags.
lg->GetIncludeDirectories(includes, target, language, config);
std::string includesString =
lg->GetIncludeFlags(includes, target, language, true, false, config);
return includesString;
}
bool cmExtraSublimeTextGenerator::Open(const std::string& bindir,
const std::string& projectName,
bool dryRun)

View File

@ -65,6 +65,9 @@ private:
std::string ComputeDefines(cmSourceFile* source, cmLocalGenerator* lg,
cmGeneratorTarget* gtgt);
std::string ComputeIncludes(cmSourceFile* source, cmLocalGenerator* lg,
cmGeneratorTarget* gtgt);
bool Open(const std::string& bindir, const std::string& projectName,
bool dryRun) override;

View File

@ -743,6 +743,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) {
lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
@ -759,6 +764,16 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
flags += flagsBuild.GetString();
}
// Add per-source include directories.
std::vector<std::string> includes;
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
lg->AppendIncludeDirectories(
includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES),
*sf);
}
lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true));
cmXCodeObject* buildFile =
this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf);
@ -3521,7 +3536,7 @@ void cmGlobalXCodeGenerator::AppendDefines(
}
void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
std::string const& flag)
std::string const& flag) const
{
// Short-circuit for an empty flag.
if (flag.empty()) {

View File

@ -104,7 +104,7 @@ public:
bool ShouldStripResourcePath(cmMakefile*) const override;
bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
void AppendFlag(std::string& flags, std::string const& flag);
void AppendFlag(std::string& flags, std::string const& flag) const;
protected:
void AddExtraIDETargets() override;

View File

@ -13,6 +13,7 @@ cmIDEOptions::cmIDEOptions()
{
this->DoingDefine = false;
this->AllowDefine = true;
this->DoingInclude = false;
this->AllowSlash = false;
this->DoingFollowing = 0;
for (int i = 0; i < FlagTableCount; ++i) {
@ -33,6 +34,13 @@ void cmIDEOptions::HandleFlag(const char* flag)
return;
}
// If the last option was -I then this option is the include directory.
if (this->DoingInclude) {
this->DoingInclude = false;
this->Includes.push_back(flag);
return;
}
// If the last option expected a following value, this is it.
if (this->DoingFollowing) {
this->FlagMapUpdate(this->DoingFollowing, flag);
@ -53,6 +61,17 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
return;
}
// Look for include directory.
if (this->AllowInclude && flag[1] == 'I') {
if (flag[2] == '\0') {
// The next argument will have the include directory.
this->DoingInclude = true;
} else {
// Store this include directory.
this->Includes.push_back(flag + 2);
}
return;
}
// Look through the available flag tables.
bool flag_handled = false;
@ -155,6 +174,29 @@ std::vector<std::string> const& cmIDEOptions::GetDefines() const
return this->Defines;
}
void cmIDEOptions::AddInclude(const std::string& include)
{
this->Includes.push_back(include);
}
void cmIDEOptions::AddIncludes(const char* includes)
{
if (includes) {
// Expand the list of includes.
cmSystemTools::ExpandListArgument(includes, this->Includes);
}
}
void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
{
this->Includes.insert(this->Includes.end(), includes.begin(),
includes.end());
}
std::vector<std::string> const& cmIDEOptions::GetIncludes() const
{
return this->Includes;
}
void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value)
{
this->FlagMap[flag] = value;

View File

@ -20,12 +20,17 @@ public:
cmIDEOptions();
virtual ~cmIDEOptions();
// Store definitions and flags.
// Store definitions, includes and flags.
void AddDefine(const std::string& define);
void AddDefines(const char* defines);
void AddDefines(const std::vector<std::string>& defines);
std::vector<std::string> const& GetDefines() const;
void AddInclude(const std::string& includes);
void AddIncludes(const char* includes);
void AddIncludes(const std::vector<std::string>& includes);
std::vector<std::string> const& GetIncludes() const;
void AddFlag(std::string const& flag, std::string const& value);
void AddFlag(std::string const& flag, std::vector<std::string> const& value);
void AppendFlag(std::string const& flag, std::string const& value);
@ -76,8 +81,13 @@ protected:
// Preprocessor definitions.
std::vector<std::string> Defines;
// Include directories.
std::vector<std::string> Includes;
bool DoingDefine;
bool AllowDefine;
bool DoingInclude;
bool AllowInclude;
bool AllowSlash;
cmIDEFlagTable const* DoingFollowing;
enum

View File

@ -16,6 +16,7 @@
#include "cmMakefile.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
@ -37,6 +38,7 @@
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <unordered_set>
#include <utility>
#if defined(__HAIKU__)
@ -792,19 +794,14 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags,
if (const char* langFlagRegexStr =
this->Makefile->GetDefinition(langFlagRegexVar)) {
// Filter flags acceptable to this language.
cmsys::RegularExpression r(langFlagRegexStr);
std::vector<std::string> opts;
if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) {
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
}
target->GetCompileOptions(opts, config, lang);
for (std::string const& opt : opts) {
if (r.find(opt.c_str())) {
// (Re-)Escape this flag. COMPILE_FLAGS were already parsed
// as a command line above, and COMPILE_OPTIONS are escaped.
this->AppendFlagEscape(flags, opt);
}
}
// (Re-)Escape these flags. COMPILE_FLAGS were already parsed
// as a command line above, and COMPILE_OPTIONS are escaped.
this->AppendCompileOptions(flags, opts, langFlagRegexStr);
} else {
// Use all flags.
if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) {
@ -813,10 +810,8 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags,
}
std::vector<std::string> opts;
target->GetCompileOptions(opts, config, lang);
for (std::string const& opt : opts) {
// COMPILE_OPTIONS are escaped.
this->AppendFlagEscape(flags, opt);
}
// COMPILE_OPTIONS are escaped.
this->AppendCompileOptions(flags, opts);
}
for (auto const& it : target->GetMaxLanguageStandards()) {
@ -1876,7 +1871,7 @@ void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
}
void cmLocalGenerator::AppendFlags(std::string& flags,
const std::string& newFlags)
const std::string& newFlags) const
{
if (!newFlags.empty()) {
if (!flags.empty()) {
@ -1886,7 +1881,8 @@ void cmLocalGenerator::AppendFlags(std::string& flags,
}
}
void cmLocalGenerator::AppendFlags(std::string& flags, const char* newFlags)
void cmLocalGenerator::AppendFlags(std::string& flags,
const char* newFlags) const
{
if (newFlags && *newFlags) {
this->AppendFlags(flags, std::string(newFlags));
@ -1894,7 +1890,7 @@ void cmLocalGenerator::AppendFlags(std::string& flags, const char* newFlags)
}
void cmLocalGenerator::AppendFlagEscape(std::string& flags,
const std::string& rawFlag)
const std::string& rawFlag) const
{
this->AppendFlags(flags, this->EscapeForShell(rawFlag));
}
@ -1930,6 +1926,87 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
}
}
void cmLocalGenerator::AppendCompileOptions(std::string& options,
const char* options_list,
const char* regex) const
{
// Short-circuit if there are no options.
if (!options_list) {
return;
}
// Expand the list of options.
std::vector<std::string> options_vec;
cmSystemTools::ExpandListArgument(options_list, options_vec);
this->AppendCompileOptions(options, options_vec, regex);
}
void cmLocalGenerator::AppendCompileOptions(
std::string& options, const std::vector<std::string>& options_vec,
const char* regex) const
{
if (regex != nullptr) {
// Filter flags upon specified reges.
cmsys::RegularExpression r(regex);
for (std::string const& opt : options_vec) {
if (r.find(opt.c_str())) {
this->AppendFlagEscape(options, opt);
}
}
} else {
for (std::string const& opt : options_vec) {
this->AppendFlagEscape(options, opt);
}
}
}
void cmLocalGenerator::AppendIncludeDirectories(
std::vector<std::string>& includes, const char* includes_list,
const cmSourceFile& sourceFile) const
{
// Short-circuit if there are no includes.
if (!includes_list) {
return;
}
// Expand the list of includes.
std::vector<std::string> includes_vec;
cmSystemTools::ExpandListArgument(includes_list, includes_vec);
this->AppendIncludeDirectories(includes, includes_vec, sourceFile);
}
void cmLocalGenerator::AppendIncludeDirectories(
std::vector<std::string>& includes,
const std::vector<std::string>& includes_vec,
const cmSourceFile& sourceFile) const
{
std::unordered_set<std::string> uniqueIncludes;
for (const std::string& include : includes_vec) {
if (!cmSystemTools::FileIsFullPath(include.c_str())) {
std::ostringstream e;
e << "Found relative path while evaluating include directories of "
"\""
<< sourceFile.GetLocation().GetName() << "\":\n \"" << include
<< "\"\n";
this->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
std::string inc = include;
if (!cmSystemTools::IsOff(inc.c_str())) {
cmSystemTools::ConvertToUnixSlashes(inc);
}
if (uniqueIncludes.insert(inc).second) {
includes.push_back(inc);
}
}
}
void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
const char* defines_list) const
{

View File

@ -118,10 +118,11 @@ public:
cmGeneratorTarget const* target,
const std::string& lang);
///! Append flags to a string.
virtual void AppendFlags(std::string& flags, const std::string& newFlags);
virtual void AppendFlags(std::string& flags, const char* newFlags);
virtual void AppendFlags(std::string& flags,
const std::string& newFlags) const;
virtual void AppendFlags(std::string& flags, const char* newFlags) const;
virtual void AppendFlagEscape(std::string& flags,
const std::string& rawFlag);
const std::string& rawFlag) const;
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
@ -151,6 +152,23 @@ public:
const std::string& name) const;
cmGeneratorTarget* FindGeneratorTargetToUse(const std::string& name) const;
/**
* Process a list of include directories
*/
void AppendIncludeDirectories(std::vector<std::string>& includes,
const char* includes_list,
const cmSourceFile& sourceFile) const;
void AppendIncludeDirectories(std::vector<std::string>& includes,
std::string const& includes_list,
const cmSourceFile& sourceFile) const
{
this->AppendIncludeDirectories(includes, includes_list.c_str(),
sourceFile);
}
void AppendIncludeDirectories(std::vector<std::string>& includes,
const std::vector<std::string>& includes_vec,
const cmSourceFile& sourceFile) const;
/**
* Encode a list of preprocessor definitions for the compiler
* command line.
@ -165,6 +183,22 @@ public:
void AppendDefines(std::set<std::string>& defines,
const std::vector<std::string>& defines_vec) const;
/**
* Encode a list of compile options for the compiler
* command line.
*/
void AppendCompileOptions(std::string& options, const char* options_list,
const char* regex = nullptr) const;
void AppendCompileOptions(std::string& options,
std::string const& options_list,
const char* regex = nullptr) const
{
this->AppendCompileOptions(options, options_list.c_str(), regex);
}
void AppendCompileOptions(std::string& options,
const std::vector<std::string>& options_vec,
const char* regex = nullptr) const;
/**
* Join a set of defines into a definesString with a space separator.
*/

View File

@ -830,8 +830,8 @@ std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory(
return dir;
}
void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
const std::string& newFlags)
void cmLocalUnixMakefileGenerator3::AppendFlags(
std::string& flags, const std::string& newFlags) const
{
if (this->IsWatcomWMake() && !newFlags.empty()) {
std::string newf = newFlags;
@ -845,7 +845,7 @@ void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
}
void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
const char* newFlags)
const char* newFlags) const
{
this->cmLocalGenerator::AppendFlags(flags, newFlags);
}

View File

@ -88,8 +88,9 @@ public:
const std::string& tgt);
// append flags to a string
void AppendFlags(std::string& flags, const std::string& newFlags) override;
void AppendFlags(std::string& flags, const char* newFlags) override;
void AppendFlags(std::string& flags,
const std::string& newFlags) const override;
void AppendFlags(std::string& flags, const char* newFlags) const override;
// append an echo command
enum EchoColor

View File

@ -45,15 +45,6 @@ public:
extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
static void cmConvertToWindowsSlash(std::string& s)
{
std::string::size_type pos = 0;
while ((pos = s.find('/', pos)) != std::string::npos) {
s[pos] = '\\';
pos++;
}
}
cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(
cmGlobalGenerator* gg, cmMakefile* mf)
: cmLocalVisualStudioGenerator(gg, mf)
@ -704,11 +695,16 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
targetOptions.Parse(flags.c_str());
targetOptions.Parse(defineFlags.c_str());
targetOptions.ParseFinish();
std::vector<std::string> targetDefines;
if (!langForClCompile.empty()) {
std::vector<std::string> targetDefines;
target->GetCompileDefinitions(targetDefines, configName, langForClCompile);
targetOptions.AddDefines(targetDefines);
std::vector<std::string> targetIncludes;
this->GetIncludeDirectories(targetIncludes, target, langForClCompile,
configName);
targetOptions.AddIncludes(targetIncludes);
}
targetOptions.AddDefines(targetDefines);
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@ -795,27 +791,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
<< this->ConvertToXMLOutputPath(modDir.c_str())
<< "\\$(ConfigurationName)\"\n";
}
fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
std::vector<std::string> includes_cl;
if (!langForClCompile.empty()) {
this->GetIncludeDirectories(includes_cl, target, langForClCompile,
configName);
}
std::vector<std::string>::iterator i = includes_cl.begin();
for (; i != includes_cl.end(); ++i) {
// output the include path
std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
fout << ipath << ";";
// if this is fortran then output the include with
// a ConfigurationName on the end of it.
if (this->FortranProject) {
ipath = i->c_str();
ipath += "/$(ConfigurationName)";
ipath = this->ConvertToXMLOutputPath(ipath.c_str());
fout << ipath << ";";
}
}
fout << "\"\n";
targetOptions.OutputAdditionalIncludeDirectories(
fout, "\t\t\t\t", "\n",
this->FortranProject ? "Fortran" : langForClCompile);
targetOptions.OutputFlagMap(fout, "\t\t\t\t");
targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
langForClCompile);
@ -835,20 +813,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
fout <<
"\t\t\t<Tool\n"
"\t\t\t\tName=\"MASM\"\n"
"\t\t\t\tIncludePaths=\""
;
std::vector<std::string> includes_masm;
this->GetIncludeDirectories(includes_masm, target, "ASM_MASM",
configName);
/* clang-format on */
const char* sep = "";
for (i = includes_masm.begin(); i != includes_masm.end(); ++i) {
std::string inc = *i;
cmConvertToWindowsSlash(inc);
fout << sep << this->EscapeForXML(inc);
sep = ";";
}
fout << "\"\n";
targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t", "\n",
"ASM_MASM");
// Use same preprocessor definitions as VCCLCompilerTool.
targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
"ASM_MASM");
@ -868,16 +836,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
if (this->FortranProject) {
tool = "VFResourceCompilerTool";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
<< "\t\t\t\tAdditionalIncludeDirectories=\"";
std::vector<std::string> includes_rc;
this->GetIncludeDirectories(includes_rc, target, "RC", configName);
for (i = includes_rc.begin(); i != includes_rc.end(); ++i) {
std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
fout << ipath << ";";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
"RC");
// add the -D flags to the RC tool
fout << "\"";
targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
fout << "/>\n";
tool = "VCMIDLTool";
@ -885,14 +847,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
tool = "VFMIDLTool";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
std::vector<std::string> includes_midl;
this->GetIncludeDirectories(includes_midl, target, "MIDL", configName);
for (i = includes_midl.begin(); i != includes_midl.end(); ++i) {
std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
fout << ipath << ";";
}
fout << "\"\n";
targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
"MIDL");
fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n";
if (gg->GetPlatformName() == "x64") {
fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
@ -1440,6 +1396,7 @@ struct cmLVS7GFileConfig
std::string CompileDefs;
std::string CompileDefsConfig;
std::string AdditionalDeps;
std::string IncludeDirs;
bool ExcludedFromBuild;
};
@ -1494,6 +1451,12 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
fc.CompileFlags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
needfc = true;
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = sf.GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
fc.CompileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
needfc = true;
}
if (lg->FortranProject) {
switch (cmOutputConverter::GetFortranFormat(
sf.GetProperty("Fortran_FORMAT"))) {
@ -1522,6 +1485,12 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
needfc = true;
}
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) {
fc.IncludeDirs = genexInterpreter.Evaluate(cincs, INCLUDE_DIRECTORIES);
needfc = true;
}
// Check for extra object-file dependencies.
if (const char* deps = sf.GetProperty("OBJECT_DEPENDS")) {
std::vector<std::string> depends;
@ -1652,7 +1621,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
this->WriteCustomRule(fout, configs, source.c_str(), *command, fcinfo);
} else if (!fcinfo.FileConfigMap.empty()) {
const char* aCompilerTool = "VCCLCompilerTool";
const char* ppLang = "CXX";
std::string ppLang = "CXX";
if (this->FortranProject) {
aCompilerTool = "VFFortranCompilerTool";
}
@ -1699,7 +1668,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"" << aCompilerTool << "\"\n";
if (!fc.CompileFlags.empty() || !fc.CompileDefs.empty() ||
!fc.CompileDefsConfig.empty()) {
!fc.CompileDefsConfig.empty() || !fc.IncludeDirs.empty()) {
Options::Tool tool = Options::Compiler;
cmVS7FlagTable const* table =
cmLocalVisualStudio7GeneratorFlagTable;
@ -1711,7 +1680,14 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
fileOptions.Parse(fc.CompileFlags.c_str());
fileOptions.AddDefines(fc.CompileDefs.c_str());
fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
// validate source level include directories
std::vector<std::string> includes;
this->AppendIncludeDirectories(includes, fc.IncludeDirs, **sf);
fileOptions.AddIncludes(includes);
fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
fileOptions.OutputAdditionalIncludeDirectories(
fout, "\t\t\t\t\t", "\n",
ppLang == "CXX" && this->FortranProject ? "Fortran" : ppLang);
fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
ppLang);
}

View File

@ -31,10 +31,10 @@ std::string cmLocalXCodeGenerator::GetTargetDirectory(
}
void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags,
const std::string& rawFlag)
const std::string& rawFlag) const
{
cmGlobalXCodeGenerator* gg =
static_cast<cmGlobalXCodeGenerator*>(this->GlobalGenerator);
const cmGlobalXCodeGenerator* gg =
static_cast<const cmGlobalXCodeGenerator*>(this->GlobalGenerator);
gg->AppendFlag(flags, rawFlag);
}

View File

@ -31,7 +31,7 @@ public:
std::string GetTargetDirectory(
cmGeneratorTarget const* target) const override;
void AppendFlagEscape(std::string& flags,
const std::string& rawFlag) override;
const std::string& rawFlag) const override;
void Generate() override;
virtual void GenerateInstallRules();
void ComputeObjectFilenames(

View File

@ -445,10 +445,35 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
<< "\n";
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = source.GetProperty(COMPILE_OPTIONS)) {
const char* evaluatedOptions =
genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS);
this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions);
*this->FlagFileStream << "# Custom options: " << relativeObj
<< "_OPTIONS = " << evaluatedOptions << "\n"
<< "\n";
}
// Add include directories from source file properties.
std::vector<std::string> includes;
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
const char* evaluatedIncludes =
genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
this->LocalGenerator->AppendIncludeDirectories(includes, evaluatedIncludes,
source);
*this->FlagFileStream << "# Custom include directories: " << relativeObj
<< "_INCLUDE_DIRECTORIES = " << evaluatedIncludes
<< "\n"
<< "\n";
}
// Add language-specific defines.
std::set<std::string> defines;
// Add source-sepcific preprocessor definitions.
// Add source-specific preprocessor definitions.
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
if (const char* compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) {
const char* evaluatedDefs =
@ -565,7 +590,10 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
vars.Defines = definesString.c_str();
std::string const includesString = "$(" + lang + "_INCLUDES)";
std::string includesString = this->LocalGenerator->GetIncludeFlags(
includes, this->GeneratorTarget, lang, true, false, config);
this->LocalGenerator->AppendFlags(includesString,
"$(" + lang + "_INCLUDES)");
vars.Includes = includesString.c_str();
// At the moment, it is assumed that C, C++, Fortran, and CUDA have both

View File

@ -135,16 +135,23 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget,
this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(),
language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget,
this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(),
language);
this->LocalGenerator->AppendFlags(
flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = source->GetProperty(COMPILE_OPTIONS)) {
this->LocalGenerator->AppendCompileOptions(
flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
return flags;
}
@ -204,6 +211,30 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
return definesString;
}
std::string cmNinjaTargetGenerator::ComputeIncludes(
cmSourceFile const* source, const std::string& language)
{
std::vector<std::string> includes;
const std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget, config,
this->GeneratorTarget->GetName(), language);
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
this->LocalGenerator->AppendIncludeDirectories(
includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES),
*source);
}
std::string includesString = this->LocalGenerator->GetIncludeFlags(
includes, this->GeneratorTarget, language, true, false, config);
this->LocalGenerator->AppendFlags(includesString,
this->GetIncludes(language));
return includesString;
}
cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
{
// Static libraries never depend on other targets for linking.
@ -818,7 +849,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmNinjaVars vars;
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
vars["INCLUDES"] = this->GetIncludes(language);
vars["INCLUDES"] = this->ComputeIncludes(source, language);
if (!this->NeedDepTypeMSVC(language)) {
vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
objectFileName + ".d", cmOutputConverter::SHELL);

View File

@ -82,6 +82,9 @@ protected:
std::string ComputeDefines(cmSourceFile const* source,
const std::string& language);
std::string ComputeIncludes(cmSourceFile const* source,
const std::string& language);
std::string ConvertToNinjaPath(const std::string& path) const
{
return this->GetGlobalGenerator()->ConvertToNinjaPath(path);

View File

@ -708,9 +708,31 @@ static Json::Value DumpSourceFilesList(
lg->AppendFlags(compileFlags,
genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = file->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
compileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
fileData.Flags = compileFlags;
fileData.IncludePathList = ld.IncludePathList;
// Add include directories from source file properties.
std::vector<std::string> includes;
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
if (const char* cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) {
const char* evaluatedIncludes =
genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file);
for (const auto& include : includes) {
fileData.IncludePathList.push_back(std::make_pair(
include, target->IsSystemIncludeDirectory(include, config)));
}
}
fileData.IncludePathList.insert(fileData.IncludePathList.end(),
ld.IncludePathList.begin(),
ld.IncludePathList.end());
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
std::set<std::string> defines;

View File

@ -114,22 +114,6 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
{
for (OptionsMap::iterator i = this->ClOptions.begin();
i != this->ClOptions.end(); ++i) {
delete i->second;
}
for (OptionsMap::iterator i = this->LinkOptions.begin();
i != this->LinkOptions.end(); ++i) {
delete i->second;
}
for (OptionsMap::iterator i = this->CudaOptions.begin();
i != this->CudaOptions.end(); ++i) {
delete i->second;
}
for (OptionsMap::iterator i = this->CudaLinkOptions.begin();
i != this->CudaLinkOptions.end(); ++i) {
delete i->second;
}
if (!this->BuildFileStream) {
return;
}
@ -2036,18 +2020,32 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
std::string flags;
bool configDependentFlags = false;
std::string options;
bool configDependentOptions = false;
std::string defines;
bool configDependentDefines = false;
std::string includes;
bool configDependentIncludes = false;
if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
configDependentFlags =
cmGeneratorExpression::Find(cflags) != std::string::npos;
flags += cflags;
}
if (const char* coptions = sf.GetProperty("COMPILE_OPTIONS")) {
configDependentOptions =
cmGeneratorExpression::Find(coptions) != std::string::npos;
options += coptions;
}
if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
configDependentDefines =
cmGeneratorExpression::Find(cdefs) != std::string::npos;
defines += cdefs;
}
if (const char* cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) {
configDependentIncludes =
cmGeneratorExpression::Find(cincludes) != std::string::npos;
includes += cincludes;
}
std::string lang =
this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
@ -2099,7 +2097,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
// if we have flags or defines for this config then
// use them
if (!flags.empty() || !configDefines.empty() || compileAs || noWinRT) {
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
!includes.empty() || compileAs || noWinRT) {
(*this->BuildFileStream) << firstString;
firstString = ""; // only do firstString once
hasFlags = true;
@ -2137,9 +2136,16 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else {
clOptions.Parse(flags.c_str());
}
if (clOptions.HasFlag("AdditionalIncludeDirectories")) {
clOptions.AppendFlag("AdditionalIncludeDirectories",
"%(AdditionalIncludeDirectories)");
if (!options.empty()) {
std::string expandedOptions;
if (configDependentOptions) {
this->LocalGenerator->AppendCompileOptions(
expandedOptions,
genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
} else {
this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
}
clOptions.Parse(expandedOptions.c_str());
}
if (clOptions.HasFlag("DisableSpecificWarnings")) {
clOptions.AppendFlag("DisableSpecificWarnings",
@ -2151,9 +2157,21 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else {
clOptions.AddDefines(configDefines.c_str());
}
std::vector<std::string> includeList;
if (configDependentIncludes) {
this->LocalGenerator->AppendIncludeDirectories(
includeList,
genexInterpreter.Evaluate(includes, "INCLUDE_DIRECTORIES"), *source);
} else {
this->LocalGenerator->AppendIncludeDirectories(includeList, includes,
*source);
}
clOptions.AddIncludes(includeList);
clOptions.SetConfiguration(config.c_str());
clOptions.PrependInheritedString("AdditionalOptions");
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
" ", "\n", lang);
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", lang);
}
@ -2446,6 +2464,13 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
break;
}
clOptions.AddDefines(targetDefines);
// Get includes for this target
if (!this->LangForClCompile.empty()) {
clOptions.AddIncludes(
this->GetIncludes(configName, this->LangForClCompile));
}
if (this->MSTools) {
clOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@ -2497,7 +2522,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
}
}
this->ClOptions[configName] = pOptions.release();
this->ClOptions[configName] = std::move(pOptions);
return true;
}
@ -2510,14 +2535,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
}
this->WriteString("<ClCompile>\n", 2);
clOptions.PrependInheritedString("AdditionalOptions");
if (!this->LangForClCompile.empty()) {
std::vector<std::string> const includes =
this->GetIncludes(configName, this->LangForClCompile);
clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
}
clOptions.AppendFlag("AdditionalIncludeDirectories",
"%(AdditionalIncludeDirectories)");
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
clOptions.OutputAdditionalIncludeDirectories(
*this->BuildFileStream, " ", "\n", this->LangForClCompile);
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", this->LangForClCompile);
@ -2595,7 +2615,10 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
Options& clOptions = *(this->ClOptions[configName]);
rcOptions.AddDefines(clOptions.GetDefines());
this->RcOptions[configName] = pOptions.release();
// Get includes for this target
rcOptions.AddIncludes(this->GetIncludes(configName, "RC"));
this->RcOptions[configName] = std::move(pOptions);
return true;
}
@ -2610,11 +2633,8 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions(
Options& rcOptions = *(this->RcOptions[configName]);
rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", "RC");
std::vector<std::string> const includes =
this->GetIncludes(configName, "RC");
rcOptions.AppendFlag("AdditionalIncludeDirectories", includes);
rcOptions.AppendFlag("AdditionalIncludeDirectories",
"%(AdditionalIncludeDirectories)");
rcOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
" ", "\n", "RC");
rcOptions.PrependInheritedString("AdditionalOptions");
rcOptions.OutputFlagMap(*this->BuildFileStream, " ");
@ -2728,7 +2748,10 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
cudaOptions.AddDefine(exportMacro);
}
this->CudaOptions[configName] = pOptions.release();
// Get includes for this target
cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA"));
this->CudaOptions[configName] = std::move(pOptions);
return true;
}
@ -2741,10 +2764,8 @@ void cmVisualStudio10TargetGenerator::WriteCudaOptions(
this->WriteString("<CudaCompile>\n", 2);
Options& cudaOptions = *(this->CudaOptions[configName]);
std::vector<std::string> const includes =
this->GetIncludes(configName, "CUDA");
cudaOptions.AppendFlag("Include", includes);
cudaOptions.AppendFlag("Include", "%(Include)");
cudaOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
" ", "\n", "CUDA");
cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", "CUDA");
cudaOptions.PrependInheritedString("AdditionalOptions");
@ -2801,7 +2822,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
"-Wno-deprecated-gpu-targets");
}
this->CudaLinkOptions[configName] = pOptions.release();
this->CudaLinkOptions[configName] = std::move(pOptions);
return true;
}
@ -2852,7 +2873,11 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
masmOptions.Parse(flags.c_str());
this->MasmOptions[configName] = pOptions.release();
// Get includes for this target
masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM"));
this->MasmOptions[configName] = std::move(pOptions);
return true;
}
@ -2870,10 +2895,8 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions(
"\n", "ASM_MASM");
Options& masmOptions = *(this->MasmOptions[configName]);
std::vector<std::string> const includes =
this->GetIncludes(configName, "ASM_MASM");
masmOptions.AppendFlag("IncludePaths", includes);
masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
masmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
" ", "\n", "ASM_MASM");
masmOptions.PrependInheritedString("AdditionalOptions");
masmOptions.OutputFlagMap(*this->BuildFileStream, " ");
@ -2911,7 +2934,11 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
std::string(" ") +
std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
nasmOptions.Parse(flags.c_str());
this->NasmOptions[configName] = pOptions.release();
// Get includes for this target
nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM"));
this->NasmOptions[configName] = std::move(pOptions);
return true;
}
@ -2926,12 +2953,8 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions(
std::vector<std::string> includes =
this->GetIncludes(configName, "ASM_NASM");
Options& nasmOptions = *(this->NasmOptions[configName]);
for (size_t i = 0; i < includes.size(); i++) {
includes[i] += "\\";
}
nasmOptions.AppendFlag("IncludePaths", includes);
nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
nasmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
" ", "\n", "ASM_NASM");
nasmOptions.OutputFlagMap(*this->BuildFileStream, " ");
nasmOptions.PrependInheritedString("AdditionalOptions");
nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
@ -3357,7 +3380,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
}
}
this->LinkOptions[config] = pOptions.release();
this->LinkOptions[config] = std::move(pOptions);
return true;
}
@ -3523,7 +3546,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
if (this->ProjectType == csproj) {
return;
}
for (std::string const& i : this->Configurations) {
for (const auto& i : this->Configurations) {
this->WritePlatformConfigTag("ItemDefinitionGroup", i, 1);
*this->BuildFileStream << "\n";
// output cl compile flags <ClCompile></ClCompile>

View File

@ -7,6 +7,7 @@
#include <iosfwd>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
@ -24,6 +25,8 @@ class cmVisualStudioGeneratorOptions;
class cmVisualStudio10TargetGenerator
{
CM_DISABLE_COPY(cmVisualStudio10TargetGenerator)
public:
cmVisualStudio10TargetGenerator(cmGeneratorTarget* target,
cmGlobalVisualStudio10Generator* gg);
@ -169,7 +172,7 @@ private:
private:
typedef cmVisualStudioGeneratorOptions Options;
typedef std::map<std::string, Options*> OptionsMap;
typedef std::map<std::string, std::unique_ptr<Options>> OptionsMap;
OptionsMap ClOptions;
OptionsMap RcOptions;
OptionsMap CudaOptions;

View File

@ -29,23 +29,8 @@ static std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
cmLocalVisualStudioGenerator* lg, Tool tool,
cmVisualStudio10TargetGenerator* g)
: cmIDEOptions()
, LocalGenerator(lg)
, Version(lg->GetVersion())
, CurrentTool(tool)
, TargetGenerator(g)
: cmVisualStudioGeneratorOptions(lg, tool, nullptr, nullptr, g)
{
// Preprocessor definitions are not allowed for linker tools.
this->AllowDefine = (tool != Linker);
// Slash options are allowed for VS.
this->AllowSlash = true;
this->FortranRuntimeDebug = false;
this->FortranRuntimeDLL = false;
this->FortranRuntimeMT = false;
this->UnknownFlagField = "AdditionalOptions";
}
cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
@ -64,6 +49,9 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
// Preprocessor definitions are not allowed for linker tools.
this->AllowDefine = (tool != Linker);
// include directories are not allowed for linker tools.
this->AllowInclude = (tool != Linker);
// Slash options are allowed for VS.
this->AllowSlash = true;
@ -511,6 +499,69 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
}
}
void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
std::ostream& fout, const char* prefix, const char* suffix,
const std::string& lang)
{
if (this->Includes.empty()) {
return;
}
const char* tag = "AdditionalIncludeDirectories";
if (lang == "CUDA") {
tag = "Include";
} else if (lang == "ASM_MASM" || lang == "ASM_NASM") {
tag = "IncludePaths";
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
// if there are configuration specific flags, then
// use the configuration specific tag for PreprocessorDefinitions
if (!this->Configuration.empty()) {
fout << prefix;
this->TargetGenerator->WritePlatformConfigTag(
tag, this->Configuration.c_str(), 0, 0, 0, &fout);
} else {
fout << prefix << "<" << tag << ">";
}
} else {
fout << prefix << tag << "=\"";
}
const char* sep = "";
for (std::string include : this->Includes) {
// first convert all of the slashes
std::string::size_type pos = 0;
while ((pos = include.find('/', pos)) != std::string::npos) {
include[pos] = '\\';
pos++;
}
if (lang == "ASM_NASM") {
include += "\\";
}
// Escape this include for the IDE.
fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
: cmVisualStudioGeneratorOptionsEscapeForXML(include));
sep = ";";
if (lang == "Fortran") {
include += "/$(ConfigurationName)";
fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
: cmVisualStudioGeneratorOptionsEscapeForXML(include));
}
}
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
fout << sep << "%(" << tag << ")</" << tag << ">" << suffix;
} else {
fout << "\"" << suffix;
}
}
void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
const char* indent)
{

View File

@ -86,6 +86,10 @@ public:
void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix,
const char* suffix,
const std::string& lang);
void OutputAdditionalIncludeDirectories(std::ostream& fout,
const char* prefix,
const char* suffix,
const std::string& lang);
void OutputFlagMap(std::ostream& fout, const char* indent);
void SetConfiguration(const char* config);

View File

@ -390,6 +390,9 @@ if(BUILD_TESTING)
endif()
ADD_TEST_MACRO(SourcesProperty SourcesProperty)
ADD_TEST_MACRO(SourceFileProperty SourceFileProperty)
if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
ADD_TEST_MACRO(SourceFileIncludeDirProperty SourceFileIncludeDirProperty)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
set(runCxxDialectTest 1)

View File

@ -260,17 +260,49 @@ add_custom_target(check-part4 ALL
#-----------------------------------------------------------------------------
# Cover source file properties with generator expressions.
add_executable(srcgenex_flags srcgenex_flags.c)
set_property(SOURCE srcgenex_flags.c PROPERTY COMPILE_FLAGS "-DNAME=$<TARGET_PROPERTY:NAME>")
## generate various source files
foreach (item IN ITEMS flags flags_COMPILE_LANGUAGE
options options_COMPILE_LANGUAGE
defs defs_COMPILE_LANGUAGE)
set(TARGET_NAME srcgenex_${item})
configure_file(srcgenex.c.in ${TARGET_NAME}.c @ONLY)
endforeach()
add_executable(srcgenex_flags "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags.c"
PROPERTY COMPILE_FLAGS "-DNAME=$<TARGET_PROPERTY:NAME>")
add_executable(srcgenex_flags_COMPILE_LANGUAGE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags_COMPILE_LANGUAGE.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags_COMPILE_LANGUAGE.c"
PROPERTY COMPILE_FLAGS "$<$<COMPILE_LANGUAGE:C>:-DNAME=$<TARGET_PROPERTY:NAME>>")
add_executable(srcgenex_flags_COMPILE_LANGUAGE srcgenex_flags_COMPILE_LANGUAGE.c)
set_property(SOURCE srcgenex_flags_COMPILE_LANGUAGE.c PROPERTY COMPILE_FLAGS "$<$<COMPILE_LANGUAGE:C>:-DNAME=$<TARGET_PROPERTY:NAME>>")
add_executable(srcgenex_options "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options.c"
PROPERTY COMPILE_OPTIONS -DUNUSED -DNAME=$<TARGET_PROPERTY:NAME>)
add_executable(srcgenex_options_COMPILE_LANGUAGE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options_COMPILE_LANGUAGE.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options_COMPILE_LANGUAGE.c"
PROPERTY COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C>:-DNAME=$<TARGET_PROPERTY:NAME>>)
add_executable(srcgenex_defs srcgenex_defs.c)
set_property(SOURCE srcgenex_defs.c PROPERTY COMPILE_DEFINITIONS NAME=$<TARGET_PROPERTY:NAME>)
add_executable(srcgenex_defs "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c"
PROPERTY COMPILE_DEFINITIONS UNUSED NAME=$<TARGET_PROPERTY:NAME>)
add_executable(srcgenex_defs_COMPILE_LANGUAGE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs_COMPILE_LANGUAGE.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs_COMPILE_LANGUAGE.c"
PROPERTY COMPILE_DEFINITIONS $<$<COMPILE_LANGUAGE:C>:NAME=$<TARGET_PROPERTY:NAME>>)
add_executable(srcgenex_defs_COMPILE_LANGUAGE srcgenex_defs_COMPILE_LANGUAGE.c)
set_property(SOURCE srcgenex_defs_COMPILE_LANGUAGE.c PROPERTY COMPILE_DEFINITIONS $<$<COMPILE_LANGUAGE:C>:NAME=$<TARGET_PROPERTY:NAME>>)
foreach (item IN ITEMS basic COMPILE_LANGUAGE)
set(TARGET_NAME srcgenex_includes_${item})
configure_file(srcgenex_includes.h.in "sf_includes_${item}/${TARGET_NAME}.h" @ONLY)
configure_file(srcgenex_includes.c.in ${TARGET_NAME}.c @ONLY)
endforeach()
add_executable(srcgenex_includes_basic "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_includes_basic.c")
# first include directory is useless but ensure list aspect is tested
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_includes_basic.c"
PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/sf_includes_basic")
if (CMAKE_GENERATOR MATCHES "Makefiles|Ninja|Watcom WMake")
add_executable(srcgenex_includes_COMPILE_LANGUAGE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_includes_COMPILE_LANGUAGE.c")
# first include directory is useless but ensure list aspect is tested
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_includes_COMPILE_LANGUAGE.c"
PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}" $<$<COMPILE_LANGUAGE:C>:${CMAKE_CURRENT_BINARY_DIR}/sf_includes_COMPILE_LANGUAGE>)
endif()
#-----------------------------------------------------------------------------
# Cover test properties with generator expressions.

View File

@ -1,4 +1,4 @@
int srcgenex_defs(void)
int @TARGET_NAME@(void)
{
return 0;
}

View File

@ -1,12 +0,0 @@
int srcgenex_defs_COMPILE_LANGUAGE(void)
{
return 0;
}
int main(int argc, char* argv[])
{
#ifndef NAME
#error NAME not defined
#endif
return NAME();
}

View File

@ -1,12 +0,0 @@
int srcgenex_flags(void)
{
return 0;
}
int main(int argc, char* argv[])
{
#ifndef NAME
#error NAME not defined
#endif
return NAME();
}

View File

@ -1,12 +0,0 @@
int srcgenex_flags_COMPILE_LANGUAGE(void)
{
return 0;
}
int main(int argc, char* argv[])
{
#ifndef NAME
#error NAME not defined
#endif
return NAME();
}

View File

@ -0,0 +1,12 @@
#include "@TARGET_NAME@.h"
int @TARGET_NAME@(void)
{
return 0;
}
int main(int argc, char* argv[])
{
return @TARGET_NAME@();
}

View File

@ -0,0 +1,7 @@
#if !defined @TARGET_NAME@_H
#define @TARGET_NAME@_H
int @TARGET_NAME@(void);
#endif

View File

@ -176,6 +176,7 @@ add_RunCMake_test(CompileDefinitions)
add_RunCMake_test(CompileFeatures)
add_RunCMake_test(PolicyScope)
add_RunCMake_test(WriteCompilerDetectionHeader)
add_RunCMake_test(SourceProperties)
if(NOT WIN32)
add_RunCMake_test(PositionIndependentCode)
endif()

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} C)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error in CMakeLists.txt:
Found relative path while evaluating include directories of "empty.c":
"relative"

View File

@ -0,0 +1,4 @@
set_property (SOURCE empty.c PROPERTY INCLUDE_DIRECTORIES "relative")
add_library (somelib empty.c)

View File

@ -0,0 +1,3 @@
include(RunCMake)
run_cmake(RelativeIncludeDir)

View File

@ -0,0 +1,5 @@
int empty()
{
return 0;
}

View File

@ -0,0 +1,8 @@
^CMake Error in CMakeLists.txt:
Xcode does not support per-config per-source INCLUDE_DIRECTORIES:
\$<\$<CONFIG:Debug>:MYDEBUG>
specified for source:
.*/Tests/RunCMake/XcodeProject/main.c$

View File

@ -0,0 +1,3 @@
enable_language(C)
add_executable(main main.c)
set_property(SOURCE main.c PROPERTY INCLUDE_DIRECTORIES "$<$<CONFIG:Debug>:MYDEBUG>")

View File

@ -0,0 +1,8 @@
^CMake Error in CMakeLists.txt:
Xcode does not support per-config per-source COMPILE_OPTIONS:
\$<\$<CONFIG:Debug>:-DMYDEBUG>
specified for source:
.*/Tests/RunCMake/XcodeProject/main.c$

View File

@ -0,0 +1,3 @@
enable_language(C)
add_executable(main main.c)
set_property(SOURCE main.c PROPERTY COMPILE_OPTIONS $<$<CONFIG:Debug>:-DMYDEBUG>)

View File

@ -19,7 +19,9 @@ if (NOT XCODE_VERSION VERSION_LESS 6)
endif()
run_cmake(PerConfigPerSourceFlags)
run_cmake(PerConfigPerSourceOptions)
run_cmake(PerConfigPerSourceDefinitions)
run_cmake(PerConfigPerSourceIncludeDirs)
# Use a single build tree for a few tests without cleaning.

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.0)
project(SourceFileIncludeDirProperty C)
#
# Check that source level include directory take
# precedence over target one
add_executable(SourceFileIncludeDirProperty main.c)
set_property (TARGET SourceFileIncludeDirProperty
PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/target")
set_property (SOURCE main.c
PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/source")

View File

@ -0,0 +1,7 @@
#include "header.h"
int main()
{
return 0;
}

View File

@ -0,0 +1,2 @@
/* used header file */

View File

@ -0,0 +1,2 @@
#error "wrong header file"