Browse Source

Restore "all" target in subdirectories marked EXCLUDE_FROM_ALL

The "all" target in each directory is supposed to have targets from that
directory even if the directory itself is marked `EXCLUDE_FROM_ALL` in
its parent.  This was broken by commit dc6888573d (Pass EXCLUDE_FROM_ALL
from directory to targets, 2019-01-15, v3.14.0-rc1~83^2) which made the
participation of a target in "all" independent of context.  Revert much
of the logic change from that commit to restore the old behavior.  Then
re-implement the behavior intended by the commit to keep its test
working.  Extend the test to cover the old behavior too.

Fixes: #19753
Brad King 6 years ago
parent
commit
b3b1c7bf3a

+ 9 - 11
Help/prop_dir/EXCLUDE_FROM_ALL.rst

@@ -1,15 +1,13 @@
 EXCLUDE_FROM_ALL
 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.

+ 8 - 8
Help/prop_tgt/EXCLUDE_FROM_ALL.rst

@@ -1,12 +1,15 @@
 EXCLUDE_FROM_ALL
 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
 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
 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
 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
 components the target belongs to are not part of the set of components
 that anything tries to install.
 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``.

+ 11 - 3
Source/cmGlobalGenerator.cxx

@@ -2029,10 +2029,18 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
   return this->IsExcluded(rootSnp, snp);
   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 cmSystemTools::IsOn(exclude);
+  }
+  // This target is included in its directory.  Check whether the
+  // directory is excluded.
+  return this->IsExcluded(root, target->GetLocalGenerator());
 }
 }
 
 
 void cmGlobalGenerator::GetEnabledLanguages(
 void cmGlobalGenerator::GetEnabledLanguages(

+ 1 - 1
Source/cmGlobalGenerator.h

@@ -522,7 +522,7 @@ protected:
   bool IsExcluded(cmStateSnapshot const& root,
   bool IsExcluded(cmStateSnapshot const& root,
                   cmStateSnapshot const& snp) const;
                   cmStateSnapshot const& snp) const;
   bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
   bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
-  bool IsExcluded(cmGeneratorTarget* target) const;
+  bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const;
   virtual void InitializeProgressMarks() {}
   virtual void InitializeProgressMarks() {}
 
 
   struct GlobalTargetInfo
   struct GlobalTargetInfo

+ 2 - 2
Source/cmGlobalNinjaGenerator.h

@@ -329,9 +329,9 @@ public:
     return LocalGenerators;
     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]; }
   int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }

+ 2 - 2
Source/cmGlobalUnixMakefileGenerator3.cxx

@@ -713,7 +713,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
                         localName, depends, commands, true);
                         localName, depends, commands, true);
 
 
       // add the all/all dependency
       // add the all/all dependency
-      if (!this->IsExcluded(gtarget)) {
+      if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
         depends.clear();
         depends.clear();
         depends.push_back(localName);
         depends.push_back(localName);
         commands.clear();
         commands.clear();
@@ -777,7 +777,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
                           "Pre-install relink rule for target.", localName,
                           "Pre-install relink rule for target.", localName,
                           depends, commands, true);
                           depends, commands, true);
 
 
-        if (!this->IsExcluded(gtarget)) {
+        if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
           depends.clear();
           depends.clear();
           depends.push_back(localName);
           depends.push_back(localName);
           commands.clear();
           commands.clear();

+ 1 - 1
Source/cmGlobalVisualStudioGenerator.cxx

@@ -209,7 +209,7 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
               tgt->IsImported()) {
               tgt->IsImported()) {
             continue;
             continue;
           }
           }
-          if (!this->IsExcluded(tgt)) {
+          if (!this->IsExcluded(gen[0], tgt)) {
             allBuild->AddUtility(tgt->GetName());
             allBuild->AddUtility(tgt->GetName());
           }
           }
         }
         }

+ 1 - 1
Source/cmGlobalXCodeGenerator.cxx

@@ -567,7 +567,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
           false, "", false, cmMakefile::AcceptObjectLibraryCommands);
           false, "", false, cmMakefile::AcceptObjectLibraryCommands);
       }
       }
 
 
-      if (!this->IsExcluded(target)) {
+      if (!this->IsExcluded(gens[0], target)) {
         allbuild->AddUtility(target->GetName());
         allbuild->AddUtility(target->GetName());
       }
       }
     }
     }

+ 3 - 1
Source/cmLocalNinjaGenerator.cxx

@@ -88,7 +88,9 @@ void cmLocalNinjaGenerator::Generate()
     if (tg) {
     if (tg) {
       tg->Generate();
       tg->Generate();
       // Add the target to "all" if required.
       // 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);
         this->GetGlobalNinjaGenerator()->AddDependencyToAll(target);
       }
       }
       delete tg;
       delete tg;

+ 4 - 6
Source/cmMakefile.cxx

@@ -1151,7 +1151,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
   // Create a target instance for this utility.
   // Create a target instance for this utility.
   cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
   cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
   target->SetIsGeneratorProvided(origin == TargetOrigin::Generator);
   target->SetIsGeneratorProvided(origin == TargetOrigin::Generator);
-  if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+  if (excludeFromAll) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   }
   if (!comment) {
   if (!comment) {
@@ -1689,7 +1689,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
   cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot);
   cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot);
   this->GetGlobalGenerator()->AddMakefile(subMf);
   this->GetGlobalGenerator()->AddMakefile(subMf);
 
 
-  if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+  if (excludeFromAll) {
     subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
     subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   }
 
 
@@ -1985,9 +1985,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
   // over changes in CMakeLists.txt, making the information stale and
   // over changes in CMakeLists.txt, making the information stale and
   // hence useless.
   // hence useless.
   target->ClearDependencyInformation(*this);
   target->ClearDependencyInformation(*this);
-  if (excludeFromAll ||
-      (type != cmStateEnums::INTERFACE_LIBRARY &&
-       this->GetPropertyAsBool("EXCLUDE_FROM_ALL"))) {
+  if (excludeFromAll) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   }
   target->AddSources(srcs);
   target->AddSources(srcs);
@@ -2000,7 +1998,7 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
                                     bool excludeFromAll)
                                     bool excludeFromAll)
 {
 {
   cmTarget* target = this->AddNewTarget(cmStateEnums::EXECUTABLE, exeName);
   cmTarget* target = this->AddNewTarget(cmStateEnums::EXECUTABLE, exeName);
-  if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+  if (excludeFromAll) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   }
   target->AddSources(srcs);
   target->AddSources(srcs);

+ 1 - 0
Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt

@@ -0,0 +1 @@
+.*

+ 1 - 0
Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake

@@ -9,5 +9,6 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.c
 set(main_exe \"$<TARGET_FILE:main>\")
 set(main_exe \"$<TARGET_FILE:main>\")
 set(foo_lib \"$<TARGET_FILE:foo>\")
 set(foo_lib \"$<TARGET_FILE:foo>\")
 set(bar_lib \"$<TARGET_FILE:bar>\")
 set(bar_lib \"$<TARGET_FILE:bar>\")
+set(zot_lib \"$<TARGET_FILE:zot>\")
 set(subinc_lib \"$<TARGET_FILE:subinc>\")
 set(subinc_lib \"$<TARGET_FILE:subinc>\")
 ")
 ")

+ 5 - 1
Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt

@@ -1,4 +1,8 @@
-add_library(bar STATIC bar.cpp)
+project(ExcludeFromAllSub NONE)
+
+add_library(bar STATIC EXCLUDE_FROM_ALL bar.cpp)
+
+add_library(zot STATIC zot.cpp)
 
 
 add_library(foo STATIC foo.cpp)
 add_library(foo STATIC foo.cpp)
 target_include_directories(foo PUBLIC .)
 target_include_directories(foo PUBLIC .)

+ 32 - 0
Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake

@@ -0,0 +1,32 @@
+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()

+ 5 - 1
Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake

@@ -9,13 +9,17 @@ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
       "${subinc_lib}"
       "${subinc_lib}"
       "${main_exe}"
       "${main_exe}"
       )
       )
-    if(NOT EXISTS "${file}")
+    if(EXISTS "${file}")
+      # Remove for next step of test.
+      file(REMOVE "${file}")
+    else()
       set(RunCMake_TEST_FAILED
       set(RunCMake_TEST_FAILED
         "Artifact should exist but is missing:\n  ${file}")
         "Artifact should exist but is missing:\n  ${file}")
       return()
       return()
     endif()
     endif()
   endforeach()
   endforeach()
   foreach(file
   foreach(file
+      "${zot_lib}"
       "${bar_lib}"
       "${bar_lib}"
       )
       )
     if(EXISTS "${file}")
     if(EXISTS "${file}")

+ 4 - 0
Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp

@@ -0,0 +1,4 @@
+int zot()
+{
+  return 0;
+}

+ 20 - 0
Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake

@@ -34,6 +34,26 @@ run_cmake(ExcludeFromAll)
 set(RunCMake_TEST_NO_CLEAN 1)
 set(RunCMake_TEST_NO_CLEAN 1)
 set(RunCMake-check-file ExcludeFromAll/check.cmake)
 set(RunCMake-check-file ExcludeFromAll/check.cmake)
 run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build . --config Debug)
 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-check-file)
 unset(RunCMake_TEST_NO_CLEAN)
 unset(RunCMake_TEST_NO_CLEAN)
 unset(RunCMake_TEST_OPTIONS)
 unset(RunCMake_TEST_OPTIONS)