Ver Fonte

Ninja Multi-Config: Make cross-config building opt-in

Many users will want to use the Ninja Multi-Config generator like a
traditional Visual Studio-style multi-config generator, which doesn't
mix configurations - custom commands are built using target executables
of the same configuration the command is for. We do not want to force
these people to generate an N*N build matrix when they only need N*1,
especially if they have lots of targets. Add a new variable,
CMAKE_NINJA_CROSS_CONFIG_ENABLE, to opt-in to the cross-config build
matrix.
Kyle Edwards há 5 anos atrás
pai
commit
e8032e202e
22 ficheiros alterados com 148 adições e 12 exclusões
  1. 10 3
      Help/generator/Ninja Multi-Config.rst
  2. 1 0
      Help/manual/cmake-variables.7.rst
  3. 6 0
      Help/variable/CMAKE_NINJA_CROSS_CONFIG_ENABLE.rst
  4. 11 2
      Source/cmGlobalNinjaGenerator.cxx
  5. 2 0
      Source/cmGlobalNinjaGenerator.h
  6. 12 2
      Source/cmNinjaNormalTargetGenerator.cxx
  7. 26 5
      Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
  8. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-result.txt
  9. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-stderr.txt
  10. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-result.txt
  11. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-stderr.txt
  12. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-result.txt
  13. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-stderr.txt
  14. 31 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-build-check.cmake
  15. 32 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-ninja-check.cmake
  16. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-result.txt
  17. 3 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-stderr.txt
  18. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-result.txt
  19. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-stderr.txt
  20. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-result.txt
  21. 3 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-stderr.txt
  22. 1 0
      Tests/RunCMake/NinjaMultiConfig/SimpleNoCross.cmake

+ 10 - 3
Help/generator/Ninja Multi-Config.rst

@@ -19,9 +19,10 @@ the desired ``build-<Config>.ninja`` file with ``ninja -f``. Running
 ``build-<Config>.ninja`` as the ``-f`` file and ``<target>`` as the build
 target.
 
-Executables and libraries of any configuration can be built regardless of which
+If :variable:`CMAKE_NINJA_CROSS_CONFIG_ENABLE` is turned on, executables and
+libraries of any configuration can be built regardless of which
 ``build-<Config>.ninja`` file is used, simply by specifying
-``<target>:<Config>`` as the Ninja target. You can also specify
+``<target>:<OtherConfig>`` as the Ninja target. You can also specify
 ``<target>:all`` to build a target in all configurations. Each
 ``build-<Config>.ninja`` file will additionally have ``<target>`` targets which
 are aliases for ``<target>:<Config>``. However, custom commands and custom
@@ -30,6 +31,11 @@ targets will always use the configuration specified in
 Ninja for the same file to be output with different commands in the same build
 graph.
 
+If :variable:`CMAKE_NINJA_CROSS_CONFIG_ENABLE` is not enabled, you can still
+build any target in ``build-<Config>.ninja`` by specifying
+``<target>:<Config>`` or ``<target>``, but not ``<target>:<OtherConfig>`` or
+``<target>:all``.
+
 Consider the following example:
 
 .. code-block:: cmake
@@ -54,7 +60,8 @@ This would build the ``Debug`` configuration of ``generator``, which would be
 used to generate ``generated.c``, which would be used to build the ``Debug``
 configuration of ``generated``.
 
-But if you run the following instead:
+But if :variable:`CMAKE_NINJA_CROSS_CONFIG_ENABLE` is enabled, and you run the
+following instead:
 
 .. code-block:: shell
 

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

@@ -423,6 +423,7 @@ Variables that Control the Build
    /variable/CMAKE_MODULE_LINKER_FLAGS_INIT
    /variable/CMAKE_MSVCIDE_RUN_PATH
    /variable/CMAKE_MSVC_RUNTIME_LIBRARY
+   /variable/CMAKE_NINJA_CROSS_CONFIG_ENABLE
    /variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX
    /variable/CMAKE_NO_BUILTIN_CHRPATH
    /variable/CMAKE_NO_SYSTEM_FROM_IMPORTED

+ 6 - 0
Help/variable/CMAKE_NINJA_CROSS_CONFIG_ENABLE.rst

@@ -0,0 +1,6 @@
+CMAKE_NINJA_CROSS_CONFIG_ENABLE
+-------------------------------
+
+If this variable is enabled, cross-configuration building is enabled in the
+:generator:`Ninja Multi-Config` generator. See the generator's description for
+more details.

+ 11 - 2
Source/cmGlobalNinjaGenerator.cxx

@@ -1274,7 +1274,7 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
     }
 
     // Add target for all configs
-    if (this->IsMultiConfig()) {
+    if (this->EnableCrossConfigBuild()) {
       build.ExplicitDeps.clear();
       for (auto const& config : configs) {
         build.ExplicitDeps.push_back(this->BuildAlias(
@@ -1710,6 +1710,9 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
           config));
       }
       for (auto const& fileConfig : configs) {
+        if (fileConfig != config && !this->EnableCrossConfigBuild()) {
+          continue;
+        }
         if (this->IsMultiConfig()) {
           build.Variables["FILE_ARG"] = cmStrCat(
             "-f ", cmGlobalNinjaMultiGenerator::GetNinjaFilename(fileConfig));
@@ -1718,7 +1721,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
       }
     }
 
-    if (this->IsMultiConfig()) {
+    if (this->EnableCrossConfigBuild()) {
       build.Outputs.front() = this->BuildAlias(
         this->NinjaOutputPath(this->GetCleanTargetName()), "all");
       build.ExplicitDeps.clear();
@@ -2192,6 +2195,12 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
   return true;
 }
 
+bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const
+{
+  return this->IsMultiConfig() &&
+    this->Makefiles.front()->IsOn("CMAKE_NINJA_CROSS_CONFIG_ENABLE");
+}
+
 int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
                              std::vector<std::string>::const_iterator argEnd)
 {

+ 2 - 0
Source/cmGlobalNinjaGenerator.h

@@ -395,6 +395,8 @@ public:
     return this->Configs[config].ByproductsForCleanTarget;
   }
 
+  bool EnableCrossConfigBuild() const;
+
 protected:
   void Generate() override;
 

+ 12 - 2
Source/cmNinjaNormalTargetGenerator.cxx

@@ -72,6 +72,10 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config)
   // Write the build statements
   bool firstForConfig = true;
   for (auto const& fileConfig : this->GetConfigNames()) {
+    if (fileConfig != config &&
+        !this->GetGlobalGenerator()->EnableCrossConfigBuild()) {
+      continue;
+    }
     this->WriteObjectBuildStatements(config, fileConfig, firstForConfig);
     firstForConfig = false;
   }
@@ -84,12 +88,18 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config)
     this->WriteDeviceLinkStatement(config);
     firstForConfig = true;
     for (auto const& fileConfig : this->GetConfigNames()) {
+      if (fileConfig != config &&
+          !this->GetGlobalGenerator()->EnableCrossConfigBuild()) {
+        continue;
+      }
       this->WriteLinkStatement(config, fileConfig, firstForConfig);
       firstForConfig = false;
     }
   }
-  this->GetGlobalGenerator()->AddTargetAlias(
-    this->GetTargetName(), this->GetGeneratorTarget(), "all");
+  if (this->GetGlobalGenerator()->EnableCrossConfigBuild()) {
+    this->GetGlobalGenerator()->AddTargetAlias(
+      this->GetTargetName(), this->GetGeneratorTarget(), "all");
+  }
 
   // Find ADDITIONAL_CLEAN_FILES
   this->AdditionalCleanFiles(config);

+ 26 - 5
Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake

@@ -76,8 +76,9 @@ endfunction()
 set(RunCMake_TEST_NO_CLEAN 1)
 
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Simple-build)
-set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo")
+set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE=RelWithDebInfo;-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON")
 run_cmake_configure(Simple)
+unset(RunCMake_TEST_OPTIONS)
 include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
 run_cmake_build(Simple debug-target Debug simpleexe)
 run_ninja(Simple debug-target build-Debug.ninja simplestatic)
@@ -103,8 +104,22 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1)
 file(TOUCH "${RunCMake_TEST_BINARY_DIR}/empty.cmake")
 run_ninja(Simple reconfigure-noconfig build.ninja simpleexe)
 
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SimpleNoCross-build)
+run_cmake_configure(SimpleNoCross)
+include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
+run_cmake_build(SimpleNoCross debug-target Debug simpleexe)
+run_ninja(SimpleNoCross debug-target build-Debug.ninja simplestatic:Debug)
+run_ninja(SimpleNoCross relwithdebinfo-in-release-graph-target build-Release.ninja simplestatic:RelWithDebInfo)
+run_cmake_build(SimpleNoCross relwithdebinfo-in-release-graph-all Release all:RelWithDebInfo)
+run_cmake_build(SimpleNoCross relwithdebinfo-in-release-graph-clean Release clean:RelWithDebInfo)
+run_ninja(SimpleNoCross all-target build-Debug.ninja simplestatic:all)
+run_ninja(SimpleNoCross all-all build-Debug.ninja all:all)
+run_cmake_build(SimpleNoCross all-clean Debug clean:all)
+
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandGenerator-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON")
 run_cmake_configure(CustomCommandGenerator)
+unset(RunCMake_TEST_OPTIONS)
 include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
 run_cmake_build(CustomCommandGenerator debug Debug generated)
 run_cmake_command(CustomCommandGenerator-debug-generated "${TARGET_FILE_generated_Debug}")
@@ -119,7 +134,9 @@ run_ninja(CustomCommandGenerator release-in-debug-graph build-Debug.ninja genera
 run_cmake_command(CustomCommandGenerator-release-in-debug-graph-generated "${TARGET_FILE_generated_Release}")
 
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandsAndTargets-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON")
 run_cmake_configure(CustomCommandsAndTargets)
+unset(RunCMake_TEST_OPTIONS)
 include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
 run_cmake_build(CustomCommandsAndTargets release-command Release SubdirCommand)
 #FIXME Get this working
@@ -133,9 +150,9 @@ run_cmake_build(CustomCommandsAndTargets debug-targetpostbuild Debug TopTargetPo
 run_ninja(CustomCommandsAndTargets release-targetpostbuild build-Release.ninja SubdirTargetPostBuild)
 
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PostfixAndLocation-build)
-set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release")
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON")
 run_cmake_configure(PostfixAndLocation)
-set(RunCMake_TEST_OPTIONS)
+unset(RunCMake_TEST_OPTIONS)
 include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
 run_cmake_build(PostfixAndLocation release-in-release-graph Release mylib:Release)
 run_cmake_build(PostfixAndLocation debug-in-release-graph Release mylib:Debug)
@@ -148,14 +165,16 @@ run_ninja(Clean release-notall build-Release.ninja exenotall)
 run_cmake_build(Clean release-clean Release clean)
 
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AdditionalCleanFiles-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON")
 run_cmake_configure(AdditionalCleanFiles)
+unset(RunCMake_TEST_OPTIONS)
 run_cmake_build(AdditionalCleanFiles release-clean Release clean)
 run_ninja(AdditionalCleanFiles all-clean build-Debug.ninja clean:all)
 
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Install-build)
-set(RunCMake_TEST_OPTIONS -DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_TEST_BINARY_DIR}/install;-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON")
 run_cmake_configure(Install)
-set(RunCMake_TEST_OPTIONS)
+unset(RunCMake_TEST_OPTIONS)
 include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
 run_cmake_build(Install release-install Release install)
 run_ninja(Install debug-in-release-graph-install build-Release.ninja install:Debug)
@@ -167,7 +186,9 @@ run_ninja(Install debug-in-release-graph-install build-Release.ninja install:Deb
 
 if(CMake_TEST_Qt5)
   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5-build)
+  set(RunCMake_TEST_OPTIONS "-DCMAKE_NINJA_CROSS_CONFIG_ENABLE=ON")
   run_cmake_configure(Qt5)
+  unset(RunCMake_TEST_OPTIONS)
   include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
   run_cmake_build(Qt5 debug-in-release-graph Release exe:Debug)
 endif()

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-all-ninja-stderr.txt

@@ -0,0 +1 @@
+^ninja: error: unknown target 'all:all'$

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-clean-build-stderr.txt

@@ -0,0 +1 @@
+^ninja: error: unknown target 'clean:all'$

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-all-target-ninja-stderr.txt

@@ -0,0 +1 @@
+^ninja: error: unknown target 'simplestatic:all'$

+ 31 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-build-check.cmake

@@ -0,0 +1,31 @@
+check_files("${RunCMake_TEST_BINARY_DIR}"
+  INCLUDE
+    ${GENERATED_FILES}
+
+    ${TARGET_FILE_simpleexe_Debug}
+    ${TARGET_OBJECT_FILES_simpleexe_Debug}
+
+    ${TARGET_FILE_simpleshared_Debug}
+    ${TARGET_LINKER_FILE_simpleshared_Debug}
+    ${TARGET_OBJECT_FILES_simpleshared_Debug}
+
+    ${TARGET_OBJECT_FILES_simpleobj_Debug}
+
+  EXCLUDE
+    ${TARGET_OBJECT_FILES_simplestatic_Debug}
+
+    ${TARGET_OBJECT_FILES_simpleexe_Release}
+    ${TARGET_OBJECT_FILES_simpleshared_Release}
+    ${TARGET_OBJECT_FILES_simplestatic_Release}
+    ${TARGET_OBJECT_FILES_simpleobj_Release}
+
+    ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel}
+    ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel}
+    ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel}
+    ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel}
+
+    ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo}
+    ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo}
+    ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo}
+    ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo}
+  )

+ 32 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-debug-target-ninja-check.cmake

@@ -0,0 +1,32 @@
+check_files("${RunCMake_TEST_BINARY_DIR}"
+  INCLUDE
+    ${GENERATED_FILES}
+
+    ${TARGET_FILE_simpleexe_Debug}
+    ${TARGET_OBJECT_FILES_simpleexe_Debug}
+
+    ${TARGET_FILE_simpleshared_Debug}
+    ${TARGET_LINKER_FILE_simpleshared_Debug}
+    ${TARGET_OBJECT_FILES_simpleshared_Debug}
+
+    ${TARGET_FILE_simplestatic_Debug}
+    ${TARGET_OBJECT_FILES_simplestatic_Debug}
+
+    ${TARGET_OBJECT_FILES_simpleobj_Debug}
+
+  EXCLUDE
+    ${TARGET_OBJECT_FILES_simpleexe_Release}
+    ${TARGET_OBJECT_FILES_simpleshared_Release}
+    ${TARGET_OBJECT_FILES_simplestatic_Release}
+    ${TARGET_OBJECT_FILES_simpleobj_Release}
+
+    ${TARGET_OBJECT_FILES_simpleexe_MinSizeRel}
+    ${TARGET_OBJECT_FILES_simpleshared_MinSizeRel}
+    ${TARGET_OBJECT_FILES_simplestatic_MinSizeRel}
+    ${TARGET_OBJECT_FILES_simpleobj_MinSizeRel}
+
+    ${TARGET_OBJECT_FILES_simpleexe_RelWithDebInfo}
+    ${TARGET_OBJECT_FILES_simpleshared_RelWithDebInfo}
+    ${TARGET_OBJECT_FILES_simplestatic_RelWithDebInfo}
+    ${TARGET_OBJECT_FILES_simpleobj_RelWithDebInfo}
+  )

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-result.txt

@@ -0,0 +1 @@
+1

+ 3 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-all-build-stderr.txt

@@ -0,0 +1,3 @@
+^ninja: error: 'RelWithDebInfo/[^
+]*simplestatic[^
+]*', needed by 'all:RelWithDebInfo', missing and no known rule to make it$

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-clean-build-stderr.txt

@@ -0,0 +1 @@
+^ninja: error: unknown target 'clean:RelWithDebInfo'$

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-result.txt

@@ -0,0 +1 @@
+1

+ 3 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross-relwithdebinfo-in-release-graph-target-ninja-stderr.txt

@@ -0,0 +1,3 @@
+^ninja: error: 'RelWithDebInfo/[^
+]*simplestatic[^
+]*', needed by 'simplestatic:RelWithDebInfo', missing and no known rule to make it$

+ 1 - 0
Tests/RunCMake/NinjaMultiConfig/SimpleNoCross.cmake

@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_SOURCE_DIR}/Simple.cmake")