summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-08-05 19:55:32 (GMT)
committerBrad King <brad.king@kitware.com>2016-08-09 19:15:24 (GMT)
commit0278989405eea53ca7e5f1bfa6af9aea7a0b49c5 (patch)
treeb51f07947692aa3d95eef9299ee588061be83afc
parenta88c99f1bc301276a1780fec683d5061ca13f66f (diff)
downloadCMake-0278989405eea53ca7e5f1bfa6af9aea7a0b49c5.zip
CMake-0278989405eea53ca7e5f1bfa6af9aea7a0b49c5.tar.gz
CMake-0278989405eea53ca7e5f1bfa6af9aea7a0b49c5.tar.bz2
Ninja: Add `$subdir/{test,install,package}` targets
With the Makefile generator one can use `cd $subdir; make install` to build and install targets associated with a given subdirectory. This is not possible to do with the Ninja generator since there is only one `build.ninja` file at the top of the build tree. However, we can approximate it by allowing one to run `ninja $subdir/install` at the top of the tree to build the targets in the corresponding subdirectory and install them. This also makes sense for `test`, `package`, and other GLOBAL_TARGET targets. It was already done for `all` by commit v3.6.0-rc1~240^2~2 (Ninja: Add `$subdir/all` targets, 2016-03-11).
-rw-r--r--Help/generator/Ninja.rst17
-rw-r--r--Help/release/dev/ninja-directory-targets.rst8
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx11
-rw-r--r--Source/cmNinjaTargetGenerator.cxx13
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx17
-rw-r--r--Tests/RunCMake/Ninja/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/Ninja/SubDir-install-stdout.txt1
-rw-r--r--Tests/RunCMake/Ninja/SubDir-test-stdout.txt1
-rw-r--r--Tests/RunCMake/Ninja/SubDir.cmake5
-rw-r--r--Tests/RunCMake/Ninja/SubDir/CMakeLists.txt4
10 files changed, 60 insertions, 23 deletions
diff --git a/Help/generator/Ninja.rst b/Help/generator/Ninja.rst
index d94e5f6..ef0e28b 100644
--- a/Help/generator/Ninja.rst
+++ b/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.
diff --git a/Help/release/dev/ninja-directory-targets.rst b/Help/release/dev/ninja-directory-targets.rst
new file mode 100644
index 0000000..c4269d8
--- /dev/null
+++ b/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`.
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index afd43b8..3b8aaa6 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -885,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);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 1466f8a..9030e05 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/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;
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index c549646..96a17ff 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/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());
+ }
}
diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
index c73f852..622c327 100644
--- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake
+++ b/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()
diff --git a/Tests/RunCMake/Ninja/SubDir-install-stdout.txt b/Tests/RunCMake/Ninja/SubDir-install-stdout.txt
new file mode 100644
index 0000000..4261b0e
--- /dev/null
+++ b/Tests/RunCMake/Ninja/SubDir-install-stdout.txt
@@ -0,0 +1 @@
+-- Installing SubDir
diff --git a/Tests/RunCMake/Ninja/SubDir-test-stdout.txt b/Tests/RunCMake/Ninja/SubDir-test-stdout.txt
new file mode 100644
index 0000000..9c493ac
--- /dev/null
+++ b/Tests/RunCMake/Ninja/SubDir-test-stdout.txt
@@ -0,0 +1 @@
+1/1 Test #1: SubDirTest
diff --git a/Tests/RunCMake/Ninja/SubDir.cmake b/Tests/RunCMake/Ninja/SubDir.cmake
index 7224ec3..d227753 100644
--- a/Tests/RunCMake/Ninja/SubDir.cmake
+++ b/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")
+]])
diff --git a/Tests/RunCMake/Ninja/SubDir/CMakeLists.txt b/Tests/RunCMake/Ninja/SubDir/CMakeLists.txt
index 73ae431..456c1db 100644
--- a/Tests/RunCMake/Ninja/SubDir/CMakeLists.txt
+++ b/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")
+]])