1
0
Эх сурвалжийг харах

install: Implement new install(CODE|SCRIPT) option ALL_COMPONENTS

In a per-component installation the generated installation scripts
are invoked once for each component.

Per default custom installation script code added by install(CODE|SCRIPT)
only runs for one specific component in this context.

The new ALL_COMPONENTS option allows custom script code to be run once
for each component being installed.
Nils Gladitz 4 жил өмнө
parent
commit
99ff75455e

+ 7 - 1
Help/command/install.rst

@@ -619,7 +619,7 @@ Custom Installation Logic
 .. code-block:: cmake
 
   install([[SCRIPT <file>] [CODE <code>]]
-          [COMPONENT <component>] [EXCLUDE_FROM_ALL] [...])
+          [COMPONENT <component>] [EXCLUDE_FROM_ALL] [ALL_COMPONENTS] [...])
 
 The ``SCRIPT`` form will invoke the given CMake script files during
 installation.  If the script file name is a relative path it will be
@@ -634,6 +634,12 @@ example, the code
 
 will print a message during installation.
 
+The option ``ALL_COMPONENTS``
+  .. versionadded:: 3.21
+
+  Run the custom installation script code for every component of a
+  component-specific installation.
+
 .. versionadded:: 3.14
   ``<file>`` or ``<code>`` may use "generator expressions" with the syntax
   ``$<...>`` (in the case of ``<file>``, this refers to their use in the file

+ 5 - 0
Help/manual/cmake-file-api.7.rst

@@ -751,6 +751,11 @@ with members:
     Optional member that is present with boolean value ``true`` when
     :command:`install` is called with the ``EXCLUDE_FROM_ALL`` option.
 
+  ``isForAllComponents``
+    Optional member that is present with boolean value ``true`` when
+    :command:`install(SCRIPT|CODE)` is called with the
+    ``ALL_COMPONENTS`` option.
+
   ``isOptional``
     Optional member that is present with boolean value ``true`` when
     :command:`install` is called with the ``OPTIONAL`` option.

+ 7 - 0
Help/release/dev/install-script-all-components.rst

@@ -0,0 +1,7 @@
+install-script-all-components
+-----------------------------
+
+* The :command:`install(SCRIPT|CODE)` command
+  supports a new option ``ALL_COMPONENTS`` which allows
+  the corresponding code to run for every component of
+  a per component installation.

+ 5 - 0
Source/cmFileAPICodemodel.cxx

@@ -1016,6 +1016,11 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
   if (gen->GetExcludeFromAll()) {
     installer["isExcludeFromAll"] = true;
   }
+
+  if (gen->GetAllComponentsFlag()) {
+    installer["isForAllComponents"] = true;
+  }
+
   this->AddBacktrace(installer, gen->GetBacktrace());
 
   return installer;

+ 10 - 2
Source/cmInstallCommand.cxx

@@ -161,6 +161,7 @@ bool HandleScriptMode(std::vector<std::string> const& args,
   bool doing_script = false;
   bool doing_code = false;
   bool exclude_from_all = false;
+  bool all_components = false;
 
   // Scan the args once for COMPONENT. Only allow one.
   //
@@ -172,6 +173,8 @@ bool HandleScriptMode(std::vector<std::string> const& args,
     }
     if (args[i] == "EXCLUDE_FROM_ALL") {
       exclude_from_all = true;
+    } else if (args[i] == "ALL_COMPONENTS") {
+      all_components = true;
     }
   }
 
@@ -182,6 +185,11 @@ bool HandleScriptMode(std::vector<std::string> const& args,
     return false;
   }
 
+  if (all_components && componentCount == 1) {
+    status.SetError("ALL_COMPONENTS and COMPONENT are mutually exclusive");
+    return false;
+  }
+
   // Scan the args again, this time adding install generators each time we
   // encounter a SCRIPT or CODE arg:
   //
@@ -208,14 +216,14 @@ bool HandleScriptMode(std::vector<std::string> const& args,
       }
       helper.Makefile->AddInstallGenerator(
         cm::make_unique<cmInstallScriptGenerator>(
-          script, false, component, exclude_from_all,
+          script, false, component, exclude_from_all, all_components,
           helper.Makefile->GetBacktrace()));
     } else if (doing_code) {
       doing_code = false;
       std::string const& code = arg;
       helper.Makefile->AddInstallGenerator(
         cm::make_unique<cmInstallScriptGenerator>(
-          code, true, component, exclude_from_all,
+          code, true, component, exclude_from_all, all_components,
           helper.Makefile->GetBacktrace()));
     }
   }

+ 1 - 1
Source/cmInstallDirectoryGenerator.cxx

@@ -18,7 +18,7 @@ cmInstallDirectoryGenerator::cmInstallDirectoryGenerator(
   MessageLevel message, bool exclude_from_all, std::string literal_args,
   bool optional, cmListFileBacktrace backtrace)
   : cmInstallGenerator(dest, configurations, component, message,
-                       exclude_from_all, std::move(backtrace))
+                       exclude_from_all, false, std::move(backtrace))
   , LocalGenerator(nullptr)
   , Directories(dirs)
   , FilePermissions(std::move(file_permissions))

+ 1 - 1
Source/cmInstallExportGenerator.cxx

@@ -26,7 +26,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   std::string filename, std::string name_space, bool exportOld, bool android,
   cmListFileBacktrace backtrace)
   : cmInstallGenerator(destination, configurations, component, message,
-                       exclude_from_all, std::move(backtrace))
+                       exclude_from_all, false, std::move(backtrace))
   , ExportSet(exportSet)
   , FilePermissions(std::move(file_permissions))
   , FileName(std::move(filename))

+ 1 - 1
Source/cmInstallFilesGenerator.cxx

@@ -17,7 +17,7 @@ cmInstallFilesGenerator::cmInstallFilesGenerator(
   MessageLevel message, bool exclude_from_all, std::string rename,
   bool optional, cmListFileBacktrace backtrace)
   : cmInstallGenerator(dest, configurations, component, message,
-                       exclude_from_all, std::move(backtrace))
+                       exclude_from_all, false, std::move(backtrace))
   , LocalGenerator(nullptr)
   , Files(files)
   , FilePermissions(std::move(file_permissions))

+ 12 - 6
Source/cmInstallGenerator.cxx

@@ -11,12 +11,13 @@
 cmInstallGenerator::cmInstallGenerator(
   std::string destination, std::vector<std::string> const& configurations,
   std::string component, MessageLevel message, bool exclude_from_all,
-  cmListFileBacktrace backtrace)
+  bool all_components, cmListFileBacktrace backtrace)
   : cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
   , Destination(std::move(destination))
   , Component(std::move(component))
   , Message(message)
   , ExcludeFromAll(exclude_from_all)
+  , AllComponents(all_components)
   , Backtrace(std::move(backtrace))
 {
 }
@@ -160,15 +161,20 @@ void cmInstallGenerator::GenerateScript(std::ostream& os)
   Indent indent;
 
   // Begin this block of installation.
-  std::string component_test =
-    this->CreateComponentTest(this->Component, this->ExcludeFromAll);
-  os << indent << "if(" << component_test << ")\n";
+  if (!this->AllComponents) {
+    std::string component_test =
+      this->CreateComponentTest(this->Component, this->ExcludeFromAll);
+    os << indent << "if(" << component_test << ")\n";
+  }
 
   // Generate the script possibly with per-configuration code.
-  this->GenerateScriptConfigs(os, indent.Next());
+  this->GenerateScriptConfigs(os,
+                              this->AllComponents ? indent : indent.Next());
 
   // End this block of installation.
-  os << indent << "endif()\n\n";
+  if (!this->AllComponents) {
+    os << indent << "endif()\n\n";
+  }
 }
 
 bool cmInstallGenerator::InstallsForConfig(const std::string& config)

+ 4 - 1
Source/cmInstallGenerator.h

@@ -33,7 +33,8 @@ public:
   cmInstallGenerator(std::string destination,
                      std::vector<std::string> const& configurations,
                      std::string component, MessageLevel message,
-                     bool exclude_from_all, cmListFileBacktrace backtrace);
+                     bool exclude_from_all, bool all_components,
+                     cmListFileBacktrace backtrace);
   ~cmInstallGenerator() override;
 
   cmInstallGenerator(cmInstallGenerator const&) = delete;
@@ -65,6 +66,7 @@ public:
   std::string const& GetComponent() const { return this->Component; }
 
   bool GetExcludeFromAll() const { return this->ExcludeFromAll; }
+  bool GetAllComponentsFlag() const { return this->AllComponents; }
 
   cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
 
@@ -79,5 +81,6 @@ protected:
   std::string const Component;
   MessageLevel const Message;
   bool const ExcludeFromAll;
+  bool const AllComponents;
   cmListFileBacktrace const Backtrace;
 };

+ 3 - 2
Source/cmInstallScriptGenerator.cxx

@@ -14,9 +14,10 @@
 
 cmInstallScriptGenerator::cmInstallScriptGenerator(
   std::string script, bool code, std::string const& component,
-  bool exclude_from_all, cmListFileBacktrace backtrace)
+  bool exclude_from_all, bool all_components, cmListFileBacktrace backtrace)
   : cmInstallGenerator("", std::vector<std::string>(), component,
-                       MessageDefault, exclude_from_all, std::move(backtrace))
+                       MessageDefault, exclude_from_all, all_components,
+                       std::move(backtrace))
   , Script(std::move(script))
   , Code(code)
   , AllowGenex(false)

+ 1 - 1
Source/cmInstallScriptGenerator.h

@@ -21,7 +21,7 @@ class cmInstallScriptGenerator : public cmInstallGenerator
 public:
   cmInstallScriptGenerator(
     std::string script, bool code, std::string const& component,
-    bool exclude_from_all,
+    bool exclude_from_all, bool all_components,
     cmListFileBacktrace backtrace = cmListFileBacktrace());
   ~cmInstallScriptGenerator() override;
 

+ 1 - 1
Source/cmInstallSubdirectoryGenerator.cxx

@@ -17,7 +17,7 @@ cmInstallSubdirectoryGenerator::cmInstallSubdirectoryGenerator(
   cmMakefile* makefile, std::string binaryDirectory, bool excludeFromAll,
   cmListFileBacktrace backtrace)
   : cmInstallGenerator("", std::vector<std::string>(), "", MessageDefault,
-                       excludeFromAll, std::move(backtrace))
+                       excludeFromAll, false, std::move(backtrace))
   , Makefile(makefile)
   , BinaryDirectory(std::move(binaryDirectory))
 {

+ 1 - 1
Source/cmInstallTargetGenerator.cxx

@@ -46,7 +46,7 @@ cmInstallTargetGenerator::cmInstallTargetGenerator(
   std::string const& component, MessageLevel message, bool exclude_from_all,
   bool optional, cmListFileBacktrace backtrace)
   : cmInstallGenerator(dest, configurations, component, message,
-                       exclude_from_all, std::move(backtrace))
+                       exclude_from_all, false, std::move(backtrace))
   , TargetName(std::move(targetName))
   , Target(nullptr)
   , FilePermissions(std::move(file_permissions))

+ 2 - 2
Source/cmLocalGenerator.cxx

@@ -3317,7 +3317,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
 
     // Include the user-specified pre-install script for this target.
     if (cmProp preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) {
-      cmInstallScriptGenerator g(*preinstall, false, "", false);
+      cmInstallScriptGenerator g(*preinstall, false, "", false, false);
       g.Generate(os, config, configurationTypes);
     }
 
@@ -3370,7 +3370,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
 
     // Include the user-specified post-install script for this target.
     if (cmProp postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) {
-      cmInstallScriptGenerator g(*postinstall, false, "", false);
+      cmInstallScriptGenerator g(*postinstall, false, "", false, false);
       g.Generate(os, config, configurationTypes);
     }
   }

+ 4 - 0
Tests/RunCMake/FileAPI/codemodel-v2-check.py

@@ -136,6 +136,10 @@ def check_directory(c):
                 expected_keys.append("isExcludeFromAll")
                 assert is_bool(a["isExcludeFromAll"], e["isExcludeFromAll"])
 
+            if e["isForAllComponents"] is not None:
+                expected_keys.append("isForAllComponents")
+                assert is_bool(a["isForAllComponents"], e["isForAllComponents"])
+
             if e["isOptional"] is not None:
                 expected_keys.append("isOptional")
                 assert is_bool(a["isOptional"], e["isOptional"])

+ 2 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json

@@ -20,6 +20,7 @@
                 "^.*/Tests/RunCMake/FileAPIExternalSource/\\.$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": null,
             "targetIndex": null,
@@ -51,6 +52,7 @@
                 "^.*/Tests/RunCMake/FileAPIExternalSource$"
             ],
             "isExcludeFromAll": true,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": null,
             "targetIndex": null,

+ 2 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/directories/object.json

@@ -23,6 +23,7 @@
                 "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?c_object_exe(\\.exe)?$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^c_object_exe::@5ed5358f70faf8d8af7a$",
             "targetIndex": "c_object_exe",
@@ -54,6 +55,7 @@
                 "^object/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_object_exe(\\.exe)?$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
             "targetIndex": "cxx_object_exe",

+ 54 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json

@@ -35,6 +35,7 @@
                 "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?cxx_exe(\\.exe)?$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^cxx_exe::@a56b12a3f5c0529fb296$",
             "targetIndex": "cxx_exe",
@@ -78,6 +79,7 @@
                 "^((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(lib|dll\\.a)$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
             "targetIndex": "c_shared_lib",
@@ -126,6 +128,7 @@
                 "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(so\\.1|1\\.dylib)$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
             "targetIndex": "c_shared_lib",
@@ -169,6 +172,7 @@
                 "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?cxx_shared_lib\\.(lib|dll\\.a)$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
             "targetIndex": "cxx_shared_lib",
@@ -213,6 +217,7 @@
                 "^cxx/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib|cyg|msys-)?cxx_shared_lib\\.(dll|so|dylib)$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
             "targetIndex": "cxx_shared_lib",
@@ -256,6 +261,7 @@
                 "^lib/((Debug|Release|MinSizeRel|RelWithDebInfo)/)?(lib)?c_shared_lib\\.(dll|so|dylib)$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": "^c_shared_lib::@6890427a1f51a3e7e1df$",
             "targetIndex": "c_shared_lib",
@@ -302,6 +308,7 @@
                 }
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": true,
             "targetId": null,
             "targetIndex": null,
@@ -346,6 +353,7 @@
                 "^empty\\.h$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": null,
             "targetIndex": null,
@@ -394,6 +402,7 @@
                 }
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": true,
             "targetId": null,
             "targetIndex": null,
@@ -445,6 +454,7 @@
                 }
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": null,
             "targetIndex": null,
@@ -488,6 +498,7 @@
                 "^CMakeFiles/Export/lib/cmake/foo/FooTargets\\.cmake$"
             ],
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": null,
             "targetIndex": null,
@@ -534,6 +545,7 @@
             "destination": null,
             "paths": null,
             "isExcludeFromAll": null,
+            "isForAllComponents": null,
             "isOptional": null,
             "targetId": null,
             "targetIndex": null,
@@ -568,6 +580,48 @@
                     "hasParent": false
                 }
             ]
+        },
+        {
+            "component": "Unspecified",
+            "type": "code",
+            "destination": null,
+            "paths": null,
+            "isExcludeFromAll": null,
+            "isForAllComponents": true,
+            "isOptional": null,
+            "targetId": null,
+            "targetIndex": null,
+            "targetIsImportLibrary": null,
+            "targetInstallNamelink": null,
+            "exportName": null,
+            "exportTargets": null,
+            "scriptFile": null,
+            "backtrace": [
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 54,
+                    "command": "install",
+                    "hasParent": true
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": null,
+                    "command": null,
+                    "hasParent": true
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": true
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": null,
+                    "command": null,
+                    "hasParent": false
+                }
+            ]
         }
     ]
 }

+ 1 - 0
Tests/RunCMake/FileAPI/codemodel-v2.cmake

@@ -51,3 +51,4 @@ install(DIRECTORY . dir cxx/ OPTIONAL DESTINATION dir1)
 install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}/cxx/" DESTINATION dir2)
 install(EXPORT FooTargets DESTINATION lib/cmake/foo)
 install(SCRIPT InstallScript.cmake)
+install(CODE "message(foo)" ALL_COMPONENTS)

+ 1 - 0
Tests/RunCMake/install/RunCMakeTest.cmake

@@ -179,3 +179,4 @@ run_install_test(FILES-EXCLUDE_FROM_ALL)
 run_install_test(TARGETS-EXCLUDE_FROM_ALL)
 run_install_test(TARGETS-NAMELINK_COMPONENT)
 run_install_test(SCRIPT-COMPONENT)
+run_install_test(SCRIPT-ALL_COMPONENTS)

+ 1 - 0
Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake

@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])

+ 1 - 0
Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake

@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])

+ 1 - 0
Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake

@@ -0,0 +1 @@
+check_installed([[^empty1.txt;empty2.txt$]])

+ 5 - 0
Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake

@@ -0,0 +1,5 @@
+install(
+  SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/install_script.cmake"
+  CODE "write_empty_file(empty2.txt)"
+  ALL_COMPONENTS
+  )