Commit dce58afd authored by Brad King's avatar Brad King

Merge branch 'backport-3.15-fix-EXCLUDE_FROM_ALL-subdir-all'

Resolve conflicts with changes since the 3.15 series:

* Convert `cmSystemTools::IsOn` => `cmIsOn`.
* Move one "EXCLUDE_FROM_ALL" target property logic fix to
  its new location in `cmMakefile::AddNewUtilityTarget`.
parents c88cf48b 013d7dd4
EXCLUDE_FROM_ALL
----------------
Exclude the directory from the all target of its parent.
Set this directory property to a true value on a subdirectory to exclude
its targets from the "all" target of its ancestors. If excluded, running
e.g. ``make`` in the parent directory will not build targets the
subdirectory by default. This does not affect the "all" target of the
subdirectory itself. Running e.g. ``make`` inside the subdirectory will
still build its targets.
A property on a directory that indicates if its targets are excluded
from the default build target. If it is not, then with a Makefile for
example typing make will cause the targets to be built. The same
concept applies to the default build of other generators.
Targets inherit the :prop_tgt:`EXCLUDE_FROM_ALL` property from the directory
that they are created in. When a directory is excluded, all of its targets will
have :prop_tgt:`EXCLUDE_FROM_ALL` set to ``TRUE``. After creating such a target
you can change its :prop_tgt:`EXCLUDE_FROM_ALL` property to ``FALSE``. This
will cause the target to be included in the default build target.
If the :prop_tgt:`EXCLUDE_FROM_ALL` target property is set on a target
then its value determines whether the target is included in the "all"
target of this directory and its ancestors.
EXCLUDE_FROM_ALL
----------------
Exclude the target from the all target.
Set this target property to a true (or false) value to exclude (or include)
the target from the "all" target of the containing directory and its
ancestors. If excluded, running e.g. ``make`` in the containing directory
or its ancestors will not build the target by default.
A property on a target that indicates if the target is excluded from
the default build target. If it is not, then with a Makefile for
example typing make will cause this target to be built. The same
concept applies to the default build of other generators.
If this target property is not set then the target will be included in
the "all" target of the containing directory. Furthermore, it will be
included in the "all" target of its ancestor directories unless the
:prop_dir:`EXCLUDE_FROM_ALL` directory property is set.
With ``EXCLUDE_FROM_ALL`` set to false or not set at all, the target
will be brought up to date as part of doing a ``make install`` or its
......@@ -16,6 +19,3 @@ target has undefined behavior. Note that such a target can still safely
be listed in an :command:`install(TARGETS)` command as long as the install
components the target belongs to are not part of the set of components
that anything tries to install.
This property is enabled by default for targets that are created in
directories that have :prop_dir:`EXCLUDE_FROM_ALL` set to ``TRUE``.
......@@ -428,3 +428,11 @@ Changes made since CMake 3.14.0 include the following.
policy :policy:`CMP0088` ``NEW`` behavior accidentally interpreted
a relative path to the ``.y`` input as relative to the build tree
directory instead of the source tree directory. This has been fixed.
3.14.7
------
* In CMake 3.14.0 through 3.14.6, the :prop_dir:`EXCLUDE_FROM_ALL`
directory property was regressed from pre-3.14 behavior and caused
targets within the directory to be excluded even from its own "all".
This has been fixed.
......@@ -376,3 +376,12 @@ Changes made since CMake 3.15.0 include the following.
* ``CrayPrgEnv`` compiler wrapper support has been updated for the 19.06
release of the Cray Programming Environment for which the default linking
mode on XC Cray systems is now dynamic instead of static.
3.15.4
------
* In CMake 3.15.0 through 3.15.3, the :prop_dir:`EXCLUDE_FROM_ALL`
directory property was regressed from pre-3.14 behavior and caused
targets within the directory to be excluded even from its own "all".
This has been fixed.
The bug also existed in 3.14.0 through 3.14.6 and is fixed in 3.14.7.
......@@ -2037,10 +2037,18 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
return this->IsExcluded(rootSnp, snp);
}
bool cmGlobalGenerator::IsExcluded(cmGeneratorTarget* target) const
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
cmGeneratorTarget* target) const
{
return target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
target->GetPropertyAsBool("EXCLUDE_FROM_ALL");
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
return true;
}
if (const char* exclude = target->GetProperty("EXCLUDE_FROM_ALL")) {
return cmIsOn(exclude);
}
// This target is included in its directory. Check whether the
// directory is excluded.
return this->IsExcluded(root, target->GetLocalGenerator());
}
void cmGlobalGenerator::GetEnabledLanguages(
......
......@@ -511,7 +511,7 @@ protected:
bool IsExcluded(cmStateSnapshot const& root,
cmStateSnapshot const& snp) const;
bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
bool IsExcluded(cmGeneratorTarget* target) const;
bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const;
virtual void InitializeProgressMarks() {}
struct GlobalTargetInfo
......
......@@ -302,9 +302,9 @@ public:
return LocalGenerators;
}
bool IsExcluded(cmGeneratorTarget* target)
bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target)
{
return cmGlobalGenerator::IsExcluded(target);
return cmGlobalGenerator::IsExcluded(root, target);
}
int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }
......
......@@ -230,6 +230,14 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
depends.push_back(this->EmptyRuleHackDepends);
}
// Write and empty all:
lg->WriteMakeRule(makefileStream, "The main recursive all target", "all",
depends, no_commands, true);
// Write an empty preinstall:
lg->WriteMakeRule(makefileStream, "The main recursive preinstall target",
"preinstall", depends, no_commands, true);
// Write out the "special" stuff
lg->WriteSpecialTargetsTop(makefileStream);
......@@ -460,18 +468,20 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
ruleFileStream << "\n\n";
}
if (!lg->IsRootMakefile()) {
// Write directory-level rules for "all".
this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
// Write directory-level rules for "preinstall".
this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
}
// Write directory-level rules for "clean".
{
std::vector<std::string> cmds;
lg->AppendDirectoryCleanCommand(cmds);
this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false, cmds);
}
// Write directory-level rules for "preinstall".
this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
......@@ -685,6 +695,15 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
localName, depends, commands, true);
// add the all/all dependency
if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
depends.clear();
depends.push_back(localName);
commands.clear();
lg->WriteMakeRule(ruleFileStream, "Include target in all.", "all",
depends, commands, true);
}
// Write the rule.
commands.clear();
......@@ -739,7 +758,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
"Pre-install relink rule for target.", localName,
depends, commands, true);
if (!this->IsExcluded(gtarget)) {
if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
depends.clear();
depends.push_back(localName);
commands.clear();
......
......@@ -214,7 +214,7 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
tgt->IsImported()) {
continue;
}
if (!this->IsExcluded(tgt)) {
if (!this->IsExcluded(gen[0], tgt)) {
allBuild->AddUtility(tgt->GetName());
}
}
......
......@@ -563,7 +563,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
cmObjectLibraryCommands::Accept);
}
if (!this->IsExcluded(target)) {
if (!this->IsExcluded(gens[0], target)) {
allbuild->AddUtility(target->GetName());
}
}
......
......@@ -89,7 +89,9 @@ void cmLocalNinjaGenerator::Generate()
if (tg) {
tg->Generate();
// Add the target to "all" if required.
if (!this->GetGlobalNinjaGenerator()->IsExcluded(target)) {
if (!this->GetGlobalNinjaGenerator()->IsExcluded(
this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0],
target)) {
this->GetGlobalNinjaGenerator()->AddDependencyToAll(target);
}
}
......
......@@ -1776,7 +1776,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot);
this->GetGlobalGenerator()->AddMakefile(subMf);
if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
if (excludeFromAll) {
subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
......@@ -2051,9 +2051,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
// over changes in CMakeLists.txt, making the information stale and
// hence useless.
target->ClearDependencyInformation(*this);
if (excludeFromAll ||
(type != cmStateEnums::INTERFACE_LIBRARY &&
this->GetPropertyAsBool("EXCLUDE_FROM_ALL"))) {
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
target->AddSources(srcs);
......@@ -2066,7 +2064,7 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
bool excludeFromAll)
{
cmTarget* target = this->AddNewTarget(cmStateEnums::EXECUTABLE, exeName);
if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
target->AddSources(srcs);
......@@ -2093,7 +2091,7 @@ cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
{
cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
target->SetIsGeneratorProvided(origin == cmCommandOrigin::Generator);
if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
return target;
......
......@@ -92,9 +92,12 @@ function(run_cmake test)
set(maybe_input_file "")
endif()
if(RunCMake_TEST_COMMAND)
if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY)
set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
endif()
execute_process(
COMMAND ${RunCMake_TEST_COMMAND}
WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}"
OUTPUT_VARIABLE actual_stdout
ERROR_VARIABLE ${actual_stderr_var}
RESULT_VARIABLE actual_result
......
......@@ -4,3 +4,11 @@ add_subdirectory(ExcludeFromAll EXCLUDE_FROM_ALL)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE foo)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
set(main_exe \"$<TARGET_FILE:main>\")
set(foo_lib \"$<TARGET_FILE:foo>\")
set(bar_lib \"$<TARGET_FILE:bar>\")
set(zot_lib \"$<TARGET_FILE:zot>\")
set(subinc_lib \"$<TARGET_FILE:subinc>\")
")
add_library(bar STATIC bar.cpp)
project(ExcludeFromAllSub NONE)
add_library(foo STATIC foo.cpp)
add_library(baz STATIC foo.cpp)
set_target_properties(baz PROPERTIES EXCLUDE_FROM_ALL OFF)
file(GENERATE
OUTPUT "${CMAKE_BINARY_DIR}/main.txt"
CONTENT "$<TARGET_FILE_NAME:main>")
add_library(bar STATIC EXCLUDE_FROM_ALL bar.cpp)
file(GENERATE
OUTPUT "${CMAKE_BINARY_DIR}/bar.txt"
CONTENT "$<TARGET_FILE_NAME:bar>")
file(GENERATE
OUTPUT "${CMAKE_BINARY_DIR}/baz.txt"
CONTENT "$<TARGET_FILE_NAME:baz>")
add_library(zot STATIC zot.cpp)
add_library(foo STATIC foo.cpp)
target_include_directories(foo PUBLIC .)
add_library(subinc STATIC subinc.cpp)
set_target_properties(subinc PROPERTIES EXCLUDE_FROM_ALL OFF)
if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
if(RunCMake_TEST_FAILED)
return()
endif()
foreach(file
"${foo_lib}"
"${subinc_lib}"
"${zot_lib}"
)
if(NOT EXISTS "${file}")
set(RunCMake_TEST_FAILED
"Artifact should exist but is missing:\n ${file}")
return()
endif()
endforeach()
foreach(file
"${main_exe}"
"${bar_lib}"
)
if(EXISTS "${file}")
set(RunCMake_TEST_FAILED
"Artifact should be missing but exists:\n ${file}")
return()
endif()
endforeach()
else()
set(RunCMake_TEST_FAILED "
'${RunCMake_TEST_BINARY_DIR}/check-debug.cmake' missing
")
endif()
# Use globbing to check if exes / libs were built because determining
# exactly where these files will live inside a CMake -P script is
# pretty challenging.
file(READ "${RunCMake_TEST_BINARY_DIR}/main.txt" main_exe)
file(READ "${RunCMake_TEST_BINARY_DIR}/bar.txt" bar_lib)
file(READ "${RunCMake_TEST_BINARY_DIR}/baz.txt" baz_lib)
set(found_main FALSE)
file(GLOB_RECURSE files
LIST_DIRECTORIES FALSE
RELATIVE "${RunCMake_TEST_BINARY_DIR}"
"${RunCMake_TEST_BINARY_DIR}/*")
foreach (file IN LISTS files)
if (file MATCHES "${main_exe}")
set(found_main TRUE)
if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
if(RunCMake_TEST_FAILED)
return()
endif()
endforeach()
if (NOT found_main)
set(RunCMake_TEST_FAILED "'main' missing from ${RunCMake_TEST_BINARY_DIR}")
endif()
set(found_bar FALSE)
set(found_baz FALSE)
file(GLOB_RECURSE files
LIST_DIRECTORIES FALSE
RELATIVE "${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll"
"${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll/*")
foreach (file IN LISTS files)
if (file MATCHES "${bar_lib}")
set(found_bar TRUE)
endif()
if (file MATCHES "${baz_lib}")
set(found_baz TRUE)
endif()
endforeach()
if (found_bar)
foreach(file
"${foo_lib}"
"${subinc_lib}"
"${main_exe}"
)
if(EXISTS "${file}")
# Remove for next step of test.
file(REMOVE "${file}")
else()
set(RunCMake_TEST_FAILED
"'bar' was not excluded from ${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll")
endif()
if (NOT found_baz)
"Artifact should exist but is missing:\n ${file}")
return()
endif()
endforeach()
foreach(file
"${zot_lib}"
"${bar_lib}"
)
if(EXISTS "${file}")
set(RunCMake_TEST_FAILED
"'baz' missing from ${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll")
"Artifact should be missing but exists:\n ${file}")
return()
endif()
endforeach()
else()
set(RunCMake_TEST_FAILED "
'${RunCMake_TEST_BINARY_DIR}/check-debug.cmake' missing
")
endif()
......@@ -27,14 +27,34 @@ run_cmake_install(CMP0082-OLD -DCMP0082_VALUE=OLD)
run_cmake_install(CMP0082-NEW -DCMP0082_VALUE=NEW)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExcludeFromAll-build)
set(RunCMake_TEST_NO_CLEAN 1)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
endif()
run_cmake(ExcludeFromAll)
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake-check-file ExcludeFromAll/check.cmake)
run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build .)
unset(RunCMake_TEST_BINARY_DIR)
run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build . --config Debug)
if(RunCMake_GENERATOR STREQUAL "Ninja")
if(WIN32)
set(slash [[\]])
else()
set(slash [[/]])
endif()
set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
run_cmake_command(ExcludeFromAll-build-sub ${CMAKE_COMMAND} --build . --target "ExcludeFromAll${slash}all")
elseif(RunCMake_GENERATOR MATCHES "Make")
set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_BINARY_DIR}/ExcludeFromAll-build/ExcludeFromAll)
run_cmake_command(ExcludeFromAll-build-sub "${RunCMake_MAKE_PROGRAM}")
elseif(RunCMake_GENERATOR MATCHES "^Visual Studio [1-9][0-9]")
set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
run_cmake_command(ExcludeFromAll-build-sub ${CMAKE_COMMAND} --build ExcludeFromAll --config Debug)
elseif(RunCMake_GENERATOR STREQUAL "Xcode")
set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_BINARY_DIR}/ExcludeFromAll-build/ExcludeFromAll)
run_cmake_command(ExcludeFromAll-build-sub xcodebuild -configuration Debug)
endif()
unset(RunCMake-check-file)
unset(RunCMake_TEST_NO_CLEAN)
unset(RunCMake_TEST_OPTIONS)
unset(RunCMake_TEST_BINARY_DIR)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment