Explorar o código

Merge topic 'ninja-directory-targets'

02789894 Ninja: Add `$subdir/{test,install,package}` targets
a88c99f1 Ninja: Simplify computation of GLOBAL_TARGET outputs
Brad King %!s(int64=9) %!d(string=hai) anos
pai
achega
e01c576338

+ 14 - 3
Help/generator/Ninja.rst

@@ -7,6 +7,17 @@ A build.ninja file is generated into the build tree.  Recent versions
 of the ninja program can build the project through the "all" target.
 An "install" target is also provided.
 
-For each subdirectory ``sub/dir`` of the project an additional target
-named ``sub/dir/all`` is generated that depends on all targets required
-by that subdirectory.
+For each subdirectory ``sub/dir`` of the project, additional targets
+are generated:
+
+``sub/dir/all``
+  Depends on all targets required by the subdirectory.
+
+``sub/dir/install``
+  Runs the install step in the subdirectory, if any.
+
+``sub/dir/test``
+  Runs the test step in the subdirectory, if any.
+
+``sub/dir/package``
+  Runs the package step in the subdirectory, if any.

+ 8 - 0
Help/release/dev/ninja-directory-targets.rst

@@ -0,0 +1,8 @@
+ninja-directory-targets
+-----------------------
+
+* The :generator:`Ninja` generator learned to produce phony targets
+  of the form ``sub/dir/{test,install,package}`` to drive the build
+  of a subdirectory installation, test or packaging target.
+  This is equivalent to ``cd sub/dir; make {test,install,package}``
+  with :ref:`Makefile Generators`.

+ 9 - 9
Source/cmGlobalNinjaGenerator.cxx

@@ -867,6 +867,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
       break;
     }
     case cmState::OBJECT_LIBRARY:
+    case cmState::GLOBAL_TARGET:
     case cmState::UTILITY: {
       std::string path =
         target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
@@ -875,12 +876,6 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
       break;
     }
 
-    case cmState::GLOBAL_TARGET:
-      // Always use the target in HOME instead of an unused duplicate in a
-      // subdirectory.
-      outputs.push_back(this->NinjaOutputPath(target->GetName()));
-      break;
-
     default:
       return;
   }
@@ -890,10 +885,15 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
   cmGeneratorTarget const* target, cmNinjaDeps& outputs)
 {
   if (target->GetType() == cmState::GLOBAL_TARGET) {
-    // Global targets only depend on other utilities, which may not appear in
-    // the TargetDepends set (e.g. "all").
+    // These depend only on other CMake-provided targets, e.g. "all".
     std::set<std::string> const& utils = target->GetUtilities();
-    std::copy(utils.begin(), utils.end(), std::back_inserter(outputs));
+    for (std::set<std::string>::const_iterator i = utils.begin();
+         i != utils.end(); ++i) {
+      std::string d =
+        target->GetLocalGenerator()->GetCurrentBinaryDirectory() +
+        std::string("/") + *i;
+      outputs.push_back(this->ConvertToNinjaPath(d));
+    }
   } else {
     cmNinjaDeps outs;
     cmTargetDependSet const& targetDeps = this->GetTargetDirectDepends(target);

+ 1 - 12
Source/cmNinjaTargetGenerator.cxx

@@ -38,19 +38,8 @@ cmNinjaTargetGenerator* cmNinjaTargetGenerator::New(cmGeneratorTarget* target)
       return new cmNinjaNormalTargetGenerator(target);
 
     case cmState::UTILITY:
+    case cmState::GLOBAL_TARGET:
       return new cmNinjaUtilityTargetGenerator(target);
-      ;
-
-    case cmState::GLOBAL_TARGET: {
-      // We only want to process global targets that live in the home
-      // (i.e. top-level) directory.  CMake creates copies of these targets
-      // in every directory, which we don't need.
-      if (strcmp(target->GetLocalGenerator()->GetCurrentSourceDirectory(),
-                 target->GetLocalGenerator()->GetSourceDirectory()) == 0) {
-        return new cmNinjaUtilityTargetGenerator(target);
-      }
-      // else fallthrough
-    }
 
     default:
       return CM_NULLPTR;

+ 12 - 5
Source/cmNinjaUtilityTargetGenerator.cxx

@@ -31,10 +31,12 @@ cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator()
 
 void cmNinjaUtilityTargetGenerator::Generate()
 {
-  std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
+  std::string utilCommandName =
+    this->GetLocalGenerator()->GetCurrentBinaryDirectory();
+  utilCommandName += cmake::GetCMakeFilesDirectory();
+  utilCommandName += "/";
   utilCommandName += this->GetTargetName() + ".util";
-  utilCommandName =
-    this->GetGlobalGenerator()->NinjaOutputPath(utilCommandName);
+  utilCommandName = this->ConvertToNinjaPath(utilCommandName);
 
   std::vector<std::string> commands;
   cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName);
@@ -144,6 +146,11 @@ void cmNinjaUtilityTargetGenerator::Generate()
       cmNinjaDeps(1, utilCommandName));
   }
 
-  this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
-                                             this->GetGeneratorTarget());
+  // Add an alias for the logical target name regardless of what directory
+  // contains it.  Skip this for GLOBAL_TARGET because they are meant to
+  // be per-directory and have one at the top-level anyway.
+  if (this->GetGeneratorTarget()->GetType() != cmState::GLOBAL_TARGET) {
+    this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
+                                               this->GetGeneratorTarget());
+  }
 }

+ 6 - 0
Tests/RunCMake/Ninja/RunCMakeTest.cmake

@@ -41,10 +41,16 @@ function(run_SubDir)
   run_cmake(SubDir)
   if(WIN32)
     set(SubDir_all [[SubDir\all]])
+    set(SubDir_test [[SubDir\test]])
+    set(SubDir_install [[SubDir\install]])
   else()
     set(SubDir_all [[SubDir/all]])
+    set(SubDir_test [[SubDir/test]])
+    set(SubDir_install [[SubDir/install]])
   endif()
   run_cmake_command(SubDir-build ${CMAKE_COMMAND} --build . --target ${SubDir_all})
+  run_cmake_command(SubDir-test ${CMAKE_COMMAND} --build . --target ${SubDir_test})
+  run_cmake_command(SubDir-install ${CMAKE_COMMAND} --build . --target ${SubDir_install})
 endfunction()
 run_SubDir()
 

+ 1 - 0
Tests/RunCMake/Ninja/SubDir-install-stdout.txt

@@ -0,0 +1 @@
+-- Installing SubDir

+ 1 - 0
Tests/RunCMake/Ninja/SubDir-test-stdout.txt

@@ -0,0 +1 @@
+1/1 Test #1: SubDirTest

+ 5 - 0
Tests/RunCMake/Ninja/SubDir.cmake

@@ -1,2 +1,7 @@
+include(CTest)
 add_subdirectory(SubDir)
 add_custom_target(TopFail ALL COMMAND does_not_exist)
+add_test(NAME TopTest COMMAND ${CMAKE_COMMAND} -E echo "Running TopTest")
+install(CODE [[
+  message(FATAL_ERROR "Installing Top")
+]])

+ 4 - 0
Tests/RunCMake/Ninja/SubDir/CMakeLists.txt

@@ -1,2 +1,6 @@
 add_custom_target(SubFail COMMAND does_not_exist)
 add_custom_target(InAll ALL COMMAND ${CMAKE_COMMAND} -E echo "Building InAll")
+add_test(NAME SubDirTest COMMAND ${CMAKE_COMMAND} -E echo "Running SubDirTest")
+install(CODE [[
+  message(STATUS "Installing SubDir")
+]])