浏览代码

sourceFile properties: add property COMPILE_OPTIONS

Add the support of per-source property COMPILE_OPTIONS,
including generator expressions support.

Related: #17507
Marc Chevrier 8 年之前
父节点
当前提交
78b1c2e09e

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -370,6 +370,7 @@ 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

+ 16 - 0
Help/prop_sf/COMPILE_OPTIONS.rst

@@ -0,0 +1,16 @@
+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.
+
+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.

+ 4 - 0
Help/release/dev/sourceFile-new-properties.rst

@@ -0,0 +1,4 @@
+sourceFile-new-properties
+-------------------------
+
+* The source files learn new property :prop_sf:`COMPILE_OPTIONS`.

+ 9 - 2
Source/cmExtraSublimeTextGenerator.cxx

@@ -361,13 +361,20 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
   }
 
   // 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;
 }
 

+ 5 - 0
Source/cmGlobalXCodeGenerator.cxx

@@ -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);

+ 6 - 0
Source/cmLocalVisualStudio7Generator.cxx

@@ -1494,6 +1494,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"))) {

+ 10 - 0
Source/cmMakefileTargetGenerator.cxx

@@ -445,6 +445,16 @@ 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 language-specific defines.
   std::set<std::string> defines;
 

+ 11 - 4
Source/cmNinjaTargetGenerator.cxx

@@ -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;
 }
 

+ 5 - 0
Source/cmServerProtocol.cxx

@@ -708,6 +708,11 @@ 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;

+ 20 - 1
Source/cmVisualStudio10TargetGenerator.cxx

@@ -2036,6 +2036,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
   }
   std::string flags;
   bool configDependentFlags = false;
+  std::string options;
+  bool configDependentOptions = false;
   std::string defines;
   bool configDependentDefines = false;
   if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
@@ -2043,6 +2045,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
       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;
@@ -2099,7 +2106,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() ||
+        compileAs || noWinRT) {
       (*this->BuildFileStream) << firstString;
       firstString = ""; // only do firstString once
       hasFlags = true;
@@ -2137,6 +2145,17 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
       } else {
         clOptions.Parse(flags.c_str());
       }
+      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("AdditionalIncludeDirectories")) {
         clOptions.AppendFlag("AdditionalIncludeDirectories",
                              "%(AdditionalIncludeDirectories)");

+ 27 - 11
Tests/GeneratorExpression/CMakeLists.txt

@@ -260,17 +260,33 @@ 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>")
-
-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_defs srcgenex_defs.c)
-set_property(SOURCE srcgenex_defs.c PROPERTY COMPILE_DEFINITIONS 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>>)
+## 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_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 "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c"
+             PROPERTY COMPILE_DEFINITIONS 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>>)
 
 #-----------------------------------------------------------------------------
 # Cover test properties with generator expressions.

+ 1 - 1
Tests/GeneratorExpression/srcgenex_defs.c → Tests/GeneratorExpression/srcgenex.c.in

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

+ 0 - 12
Tests/GeneratorExpression/srcgenex_defs_COMPILE_LANGUAGE.c

@@ -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();
-}

+ 0 - 12
Tests/GeneratorExpression/srcgenex_flags.c

@@ -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();
-}

+ 0 - 12
Tests/GeneratorExpression/srcgenex_flags_COMPILE_LANGUAGE.c

@@ -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();
-}