Merge topic 'ninja-directory-targets'

02789894 Ninja: Add `$subdir/{test,install,package}` targets
a88c99f1 Ninja: Simplify computation of GLOBAL_TARGET outputs
This commit is contained in:
Brad King 2016-08-10 11:15:55 -04:00 committed by CMake Topic Stage
commit e01c576338
10 changed files with 61 additions and 29 deletions

View File

@ -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.

View File

@ -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`.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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")
]])

View File

@ -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")
]])