From 044831117955dfa33ed4e0c7799ea3f37258b149 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 21 Dec 2017 17:03:18 +0100 Subject: sourceFile properties: add property INCLUDE_DIRECTORIES --- Help/manual/cmake-properties.7.rst | 1 + Help/prop_sf/COMPILE_OPTIONS.rst | 3 +- Help/prop_sf/INCLUDE_DIRECTORIES.rst | 18 ++++++++ Help/release/dev/sourceFile-new-properties.rst | 4 -- ...ies-COMPILE_OPTIONS-and-INCLUDE_DIRECTORIES.rst | 10 +++++ Source/cmExtraSublimeTextGenerator.cxx | 42 ++++++++++++++----- Source/cmExtraSublimeTextGenerator.h | 3 ++ Source/cmGlobalXCodeGenerator.cxx | 10 +++++ Source/cmLocalGenerator.cxx | 48 ++++++++++++++++++++++ Source/cmLocalGenerator.h | 17 ++++++++ Source/cmLocalVisualStudio7Generator.cxx | 13 +++++- Source/cmMakefileTargetGenerator.cxx | 22 +++++++++- Source/cmNinjaTargetGenerator.cxx | 26 +++++++++++- Source/cmNinjaTargetGenerator.h | 3 ++ Source/cmServerProtocol.cxx | 19 ++++++++- Source/cmVisualStudio10TargetGenerator.cxx | 19 ++++++++- Tests/CMakeLists.txt | 3 ++ Tests/GeneratorExpression/CMakeLists.txt | 20 ++++++++- Tests/GeneratorExpression/srcgenex_includes.c.in | 12 ++++++ Tests/GeneratorExpression/srcgenex_includes.h.in | 7 ++++ Tests/RunCMake/CMakeLists.txt | 1 + Tests/RunCMake/SourceProperties/CMakeLists.txt | 3 ++ .../SourceProperties/RelativeIncludeDir-result.txt | 1 + .../SourceProperties/RelativeIncludeDir-stderr.txt | 4 ++ .../SourceProperties/RelativeIncludeDir.cmake | 4 ++ Tests/RunCMake/SourceProperties/RunCMakeTest.cmake | 3 ++ Tests/RunCMake/SourceProperties/empty.c | 5 +++ .../PerConfigPerSourceIncludeDirs-result.txt | 1 + .../PerConfigPerSourceIncludeDirs-stderr.txt | 8 ++++ .../PerConfigPerSourceIncludeDirs.cmake | 3 ++ .../PerConfigPerSourceOptions-result.txt | 1 + .../PerConfigPerSourceOptions-stderr.txt | 8 ++++ .../XcodeProject/PerConfigPerSourceOptions.cmake | 3 ++ Tests/RunCMake/XcodeProject/RunCMakeTest.cmake | 2 + Tests/SourceFileIncludeDirProperty/CMakeLists.txt | 15 +++++++ Tests/SourceFileIncludeDirProperty/main.c | 7 ++++ Tests/SourceFileIncludeDirProperty/source/header.h | 2 + Tests/SourceFileIncludeDirProperty/target/header.h | 2 + 38 files changed, 350 insertions(+), 23 deletions(-) create mode 100644 Help/prop_sf/INCLUDE_DIRECTORIES.rst delete mode 100644 Help/release/dev/sourceFile-new-properties.rst create mode 100644 Help/release/dev/src-new-properties-COMPILE_OPTIONS-and-INCLUDE_DIRECTORIES.rst create mode 100644 Tests/GeneratorExpression/srcgenex_includes.c.in create mode 100644 Tests/GeneratorExpression/srcgenex_includes.h.in create mode 100644 Tests/RunCMake/SourceProperties/CMakeLists.txt create mode 100644 Tests/RunCMake/SourceProperties/RelativeIncludeDir-result.txt create mode 100644 Tests/RunCMake/SourceProperties/RelativeIncludeDir-stderr.txt create mode 100644 Tests/RunCMake/SourceProperties/RelativeIncludeDir.cmake create mode 100644 Tests/RunCMake/SourceProperties/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/SourceProperties/empty.c create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-result.txt create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-stderr.txt create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs.cmake create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-result.txt create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-stderr.txt create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions.cmake create mode 100644 Tests/SourceFileIncludeDirProperty/CMakeLists.txt create mode 100644 Tests/SourceFileIncludeDirProperty/main.c create mode 100644 Tests/SourceFileIncludeDirProperty/source/header.h create mode 100644 Tests/SourceFileIncludeDirProperty/target/header.h diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 73db4b2..00a932f 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -375,6 +375,7 @@ Properties on Source Files /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 diff --git a/Help/prop_sf/COMPILE_OPTIONS.rst b/Help/prop_sf/COMPILE_OPTIONS.rst index 115ae99..157c0b0 100644 --- a/Help/prop_sf/COMPILE_OPTIONS.rst +++ b/Help/prop_sf/COMPILE_OPTIONS.rst @@ -6,7 +6,8 @@ List of additional options to pass to the compiler. This property holds a :ref:`;-list ` 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. +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 diff --git a/Help/prop_sf/INCLUDE_DIRECTORIES.rst b/Help/prop_sf/INCLUDE_DIRECTORIES.rst new file mode 100644 index 0000000..55780e5 --- /dev/null +++ b/Help/prop_sf/INCLUDE_DIRECTORIES.rst @@ -0,0 +1,18 @@ +INCLUDE_DIRECTORIES +------------------- + +List of preprocessor include file search directories. + +This property holds a :ref:`;-list ` 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. diff --git a/Help/release/dev/sourceFile-new-properties.rst b/Help/release/dev/sourceFile-new-properties.rst deleted file mode 100644 index 7db5332..0000000 --- a/Help/release/dev/sourceFile-new-properties.rst +++ /dev/null @@ -1,4 +0,0 @@ -sourceFile-new-properties -------------------------- - -* The source files learn new property :prop_sf:`COMPILE_OPTIONS`. diff --git a/Help/release/dev/src-new-properties-COMPILE_OPTIONS-and-INCLUDE_DIRECTORIES.rst b/Help/release/dev/src-new-properties-COMPILE_OPTIONS-and-INCLUDE_DIRECTORIES.rst new file mode 100644 index 0000000..d06c109 --- /dev/null +++ b/Help/release/dev/src-new-properties-COMPILE_OPTIONS-and-INCLUDE_DIRECTORIES.rst @@ -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. diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 7e998c7..a89c187 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -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,15 +354,6 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject( lg->GetTargetCompileFlags(gtgt, config, language, flags); - // Add include directory flags. - { - std::vector 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); @@ -417,6 +411,34 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( return definesString; } +std::string cmExtraSublimeTextGenerator::ComputeIncludes( + cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* target) + +{ + std::vector 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) diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h index 57ba1cf..bc158f6 100644 --- a/Source/cmExtraSublimeTextGenerator.h +++ b/Source/cmExtraSublimeTextGenerator.h @@ -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; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7813ec7..9db21d8 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -764,6 +764,16 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( flags += flagsBuild.GetString(); } + // Add per-source include directories. + std::vector 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); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index d918cf3..86b16f8 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -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 #include #include +#include #include #if defined(__HAIKU__) @@ -1959,6 +1961,52 @@ void cmLocalGenerator::AppendCompileOptions( } } +void cmLocalGenerator::AppendIncludeDirectories( + std::vector& 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 includes_vec; + cmSystemTools::ExpandListArgument(includes_list, includes_vec); + this->AppendIncludeDirectories(includes, includes_vec, sourceFile); +} + +void cmLocalGenerator::AppendIncludeDirectories( + std::vector& includes, + const std::vector& includes_vec, + const cmSourceFile& sourceFile) const +{ + std::unordered_set 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& defines, const char* defines_list) const { diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index b993967..a66fa6e 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -153,6 +153,23 @@ public: cmGeneratorTarget* FindGeneratorTargetToUse(const std::string& name) const; /** + * Process a list of include directories + */ + void AppendIncludeDirectories(std::vector& includes, + const char* includes_list, + const cmSourceFile& sourceFile) const; + void AppendIncludeDirectories(std::vector& includes, + std::string const& includes_list, + const cmSourceFile& sourceFile) const + { + this->AppendIncludeDirectories(includes, includes_list.c_str(), + sourceFile); + } + void AppendIncludeDirectories(std::vector& includes, + const std::vector& includes_vec, + const cmSourceFile& sourceFile) const; + + /** * Encode a list of preprocessor definitions for the compiler * command line. */ diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index f46c01a..996a649 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1396,6 +1396,7 @@ struct cmLVS7GFileConfig std::string CompileDefs; std::string CompileDefsConfig; std::string AdditionalDeps; + std::string IncludeDirs; bool ExcludedFromBuild; }; @@ -1484,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 depends; @@ -1661,7 +1668,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup( fout << "\t\t\t\t\t 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", diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index bee0168..1543536 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -455,10 +455,25 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( << "\n"; } + // Add include directories from source file properties. + std::vector 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 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 = @@ -575,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 diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 566924f..4f37882 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -211,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 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. @@ -825,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); diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 770a99d..4660a3a 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -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); diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index f91d296..c2dee8f 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -715,7 +715,24 @@ static Json::Value DumpSourceFilesList( } fileData.Flags = compileFlags; - fileData.IncludePathList = ld.IncludePathList; + // Add include directories from source file properties. + std::vector 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 defines; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index c3a77e2..fc165b6 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2024,6 +2024,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( 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; @@ -2039,6 +2041,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( 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); @@ -2091,7 +2098,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( // if we have flags or defines for this config then // use them if (!flags.empty() || !options.empty() || !configDefines.empty() || - compileAs || noWinRT) { + !includes.empty() || compileAs || noWinRT) { (*this->BuildFileStream) << firstString; firstString = ""; // only do firstString once hasFlags = true; @@ -2150,6 +2157,16 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } else { clOptions.AddDefines(configDefines.c_str()); } + std::vector 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, " "); diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index fb7313f..6a3960a 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -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) diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index bc47be7..19d12e5 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -283,10 +283,26 @@ set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options_COMPILE_LANGUA add_executable(srcgenex_defs "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c") set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c" - PROPERTY COMPILE_DEFINITIONS NAME=$) + PROPERTY COMPILE_DEFINITIONS UNUSED 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 $<$:NAME=$>) + PROPERTY COMPILE_DEFINITIONS $<$: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}" $<$:${CMAKE_CURRENT_BINARY_DIR}/sf_includes_COMPILE_LANGUAGE>) +endif() #----------------------------------------------------------------------------- # Cover test properties with generator expressions. diff --git a/Tests/GeneratorExpression/srcgenex_includes.c.in b/Tests/GeneratorExpression/srcgenex_includes.c.in new file mode 100644 index 0000000..b48d7df --- /dev/null +++ b/Tests/GeneratorExpression/srcgenex_includes.c.in @@ -0,0 +1,12 @@ + +#include "@TARGET_NAME@.h" + +int @TARGET_NAME@(void) +{ + return 0; +} + +int main(int argc, char* argv[]) +{ + return @TARGET_NAME@(); +} diff --git a/Tests/GeneratorExpression/srcgenex_includes.h.in b/Tests/GeneratorExpression/srcgenex_includes.h.in new file mode 100644 index 0000000..2259ca6 --- /dev/null +++ b/Tests/GeneratorExpression/srcgenex_includes.h.in @@ -0,0 +1,7 @@ + +#if !defined @TARGET_NAME@_H +#define @TARGET_NAME@_H + +int @TARGET_NAME@(void); + +#endif diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index e440b7f..d5bd297 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -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() diff --git a/Tests/RunCMake/SourceProperties/CMakeLists.txt b/Tests/RunCMake/SourceProperties/CMakeLists.txt new file mode 100644 index 0000000..a17c8cd --- /dev/null +++ b/Tests/RunCMake/SourceProperties/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} C) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/SourceProperties/RelativeIncludeDir-result.txt b/Tests/RunCMake/SourceProperties/RelativeIncludeDir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/SourceProperties/RelativeIncludeDir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/SourceProperties/RelativeIncludeDir-stderr.txt b/Tests/RunCMake/SourceProperties/RelativeIncludeDir-stderr.txt new file mode 100644 index 0000000..cf146c2 --- /dev/null +++ b/Tests/RunCMake/SourceProperties/RelativeIncludeDir-stderr.txt @@ -0,0 +1,4 @@ +CMake Error in CMakeLists.txt: + Found relative path while evaluating include directories of "empty.c": + + "relative" diff --git a/Tests/RunCMake/SourceProperties/RelativeIncludeDir.cmake b/Tests/RunCMake/SourceProperties/RelativeIncludeDir.cmake new file mode 100644 index 0000000..08dffa8 --- /dev/null +++ b/Tests/RunCMake/SourceProperties/RelativeIncludeDir.cmake @@ -0,0 +1,4 @@ + +set_property (SOURCE empty.c PROPERTY INCLUDE_DIRECTORIES "relative") + +add_library (somelib empty.c) diff --git a/Tests/RunCMake/SourceProperties/RunCMakeTest.cmake b/Tests/RunCMake/SourceProperties/RunCMakeTest.cmake new file mode 100644 index 0000000..0982153 --- /dev/null +++ b/Tests/RunCMake/SourceProperties/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(RelativeIncludeDir) diff --git a/Tests/RunCMake/SourceProperties/empty.c b/Tests/RunCMake/SourceProperties/empty.c new file mode 100644 index 0000000..a9ec102 --- /dev/null +++ b/Tests/RunCMake/SourceProperties/empty.c @@ -0,0 +1,5 @@ + +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-result.txt b/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-stderr.txt b/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-stderr.txt new file mode 100644 index 0000000..f9b8ee7 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs-stderr.txt @@ -0,0 +1,8 @@ +^CMake Error in CMakeLists.txt: + Xcode does not support per-config per-source INCLUDE_DIRECTORIES: + + \$<\$:MYDEBUG> + + specified for source: + + .*/Tests/RunCMake/XcodeProject/main.c$ diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs.cmake b/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs.cmake new file mode 100644 index 0000000..4476c39 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceIncludeDirs.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_executable(main main.c) +set_property(SOURCE main.c PROPERTY INCLUDE_DIRECTORIES "$<$:MYDEBUG>") diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-result.txt b/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-stderr.txt b/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-stderr.txt new file mode 100644 index 0000000..bfca020 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions-stderr.txt @@ -0,0 +1,8 @@ +^CMake Error in CMakeLists.txt: + Xcode does not support per-config per-source COMPILE_OPTIONS: + + \$<\$:-DMYDEBUG> + + specified for source: + + .*/Tests/RunCMake/XcodeProject/main.c$ diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions.cmake b/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions.cmake new file mode 100644 index 0000000..f8e8030 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceOptions.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_executable(main main.c) +set_property(SOURCE main.c PROPERTY COMPILE_OPTIONS $<$:-DMYDEBUG>) diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 1313cb5..64a07f0 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -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. diff --git a/Tests/SourceFileIncludeDirProperty/CMakeLists.txt b/Tests/SourceFileIncludeDirProperty/CMakeLists.txt new file mode 100644 index 0000000..786d5b6 --- /dev/null +++ b/Tests/SourceFileIncludeDirProperty/CMakeLists.txt @@ -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") diff --git a/Tests/SourceFileIncludeDirProperty/main.c b/Tests/SourceFileIncludeDirProperty/main.c new file mode 100644 index 0000000..36144ca --- /dev/null +++ b/Tests/SourceFileIncludeDirProperty/main.c @@ -0,0 +1,7 @@ + +#include "header.h" + +int main() +{ + return 0; +} diff --git a/Tests/SourceFileIncludeDirProperty/source/header.h b/Tests/SourceFileIncludeDirProperty/source/header.h new file mode 100644 index 0000000..0c6f241 --- /dev/null +++ b/Tests/SourceFileIncludeDirProperty/source/header.h @@ -0,0 +1,2 @@ + +/* used header file */ diff --git a/Tests/SourceFileIncludeDirProperty/target/header.h b/Tests/SourceFileIncludeDirProperty/target/header.h new file mode 100644 index 0000000..71c1521 --- /dev/null +++ b/Tests/SourceFileIncludeDirProperty/target/header.h @@ -0,0 +1,2 @@ + +#error "wrong header file" -- cgit v0.12