Просмотр исходного кода

install: Add EXCLUDE_FROM_ALL option (#14921)

Let us take an example of a project that has some tests in a component
that need to be installed into a dedicated test package.  The user
expectation is that the result could be achieved by typing the
following:

    make
    make tests
    make install
    DESTDIR=/testpkgs make install-tests

However this results in test components in the default installation as
well as the testpkg.

Add an EXCLUDE_FROM_ALL option to the install() command to tell it that
the installation rule should not be included unless its component is
explicitly specified for installation.
Nick Lewis 10 лет назад
Родитель
Сommit
18ce97c4a2

+ 15 - 8
Help/command/install.rst

@@ -45,11 +45,15 @@ signatures that specify them.  The common options are:
   is associated, such as "runtime" or "development".  During
   component-specific installation only install rules associated with
   the given component name will be executed.  During a full installation
-  all components are installed.  If ``COMPONENT`` is not provided a
-  default component "Unspecified" is created.  The default component
-  name may be controlled with the
+  all components are installed unless marked with ``EXCLUDE_FROM_ALL``.
+  If ``COMPONENT`` is not provided a default component "Unspecified" is
+  created.  The default component name may be controlled with the
   :variable:`CMAKE_INSTALL_DEFAULT_COMPONENT_NAME` variable.
 
+``EXCLUDE_FROM_ALL``
+  Specify that the file is excluded from a full installation and only
+  installed as part of a component-specific installation
+
 ``RENAME``
   Specify a name for an installed file that may be different from the
   original file.  Renaming is allowed only when a single file is
@@ -76,7 +80,8 @@ Installing Targets
            [PERMISSIONS permissions...]
            [CONFIGURATIONS [Debug|Release|...]]
            [COMPONENT <component>]
-           [OPTIONAL] [NAMELINK_ONLY|NAMELINK_SKIP]
+           [OPTIONAL] [EXCLUDE_FROM_ALL]
+           [NAMELINK_ONLY|NAMELINK_SKIP]
           ] [...])
 
 The ``TARGETS`` form specifies rules for installing targets from a
@@ -172,7 +177,7 @@ Installing Files
           [PERMISSIONS permissions...]
           [CONFIGURATIONS [Debug|Release|...]]
           [COMPONENT <component>]
-          [RENAME <name>] [OPTIONAL])
+          [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL])
 
 The ``FILES`` form specifies rules for installing files for a project.
 File names given as relative paths are interpreted with respect to the
@@ -206,7 +211,8 @@ Installing Directories
           [DIRECTORY_PERMISSIONS permissions...]
           [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]
           [CONFIGURATIONS [Debug|Release|...]]
-          [COMPONENT <component>] [FILES_MATCHING]
+          [COMPONENT <component>] [EXCLUDE_FROM_ALL]
+          [FILES_MATCHING]
           [[PATTERN <pattern> | REGEX <regex>]
            [EXCLUDE] [PERMISSIONS permissions...]] [...])
 
@@ -282,7 +288,7 @@ Custom Installation Logic
 ::
 
   install([[SCRIPT <file>] [CODE <code>]]
-          [COMPONENT <component>] [...])
+          [COMPONENT <component>] [EXCLUDE_FROM_ALL] [...])
 
 The ``SCRIPT`` form will invoke the given CMake script files during
 installation.  If the script file name is a relative path it will be
@@ -307,7 +313,8 @@ Installing Exports
           [PERMISSIONS permissions...]
           [CONFIGURATIONS [Debug|Release|...]]
           [EXPORT_LINK_INTERFACE_LIBRARIES]
-          [COMPONENT <component>])
+          [COMPONENT <component>]
+          [EXCLUDE_FROM_ALL])
 
 The ``EXPORT`` form generates and installs a CMake file containing code to
 import targets from the installation tree into another project.

+ 27 - 4
Source/cmInstallCommand.cxx

@@ -33,6 +33,7 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target,
                         impLib, args.GetPermissions().c_str(),
                         args.GetConfigurations(), args.GetComponent().c_str(),
                         message,
+                        args.GetExcludeFromAll(),
                         args.GetOptional() || forceOpt);
 }
 
@@ -48,7 +49,8 @@ static cmInstallFilesGenerator* CreateInstallFilesGenerator(
                         programs, args.GetPermissions().c_str(),
                         args.GetConfigurations(), args.GetComponent().c_str(),
                         message,
-                        args.GetRename().c_str(), args.GetOptional());
+                        args.GetExcludeFromAll(), args.GetRename().c_str(),
+                        args.GetOptional());
 }
 
 
@@ -117,6 +119,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
   int componentCount = 0;
   bool doing_script = false;
   bool doing_code = false;
+  bool exclude_from_all = false;
 
   // Scan the args once for COMPONENT. Only allow one.
   //
@@ -128,6 +131,10 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
         ++i;
         component = args[i];
         }
+    if(args[i] == "EXCLUDE_FROM_ALL")
+      {
+      exclude_from_all = true;
+      }
     }
 
   if(componentCount>1)
@@ -175,7 +182,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
         }
       this->Makefile->AddInstallGenerator(
         new cmInstallScriptGenerator(script.c_str(), false,
-                                     component.c_str()));
+                                     component.c_str(), exclude_from_all));
       }
     else if(doing_code)
       {
@@ -183,7 +190,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
       std::string code = args[i];
       this->Makefile->AddInstallGenerator(
         new cmInstallScriptGenerator(code.c_str(), true,
-                                     component.c_str()));
+                                     component.c_str(), exclude_from_all));
       }
     }
 
@@ -949,6 +956,7 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
   Doing doing = DoingDirs;
   bool in_match_mode = false;
   bool optional = false;
+  bool exclude_from_all = false;
   bool message_never = false;
   std::vector<std::string> dirs;
   const char* destination = 0;
@@ -1130,6 +1138,19 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
       // Switch to setting the component property.
       doing = DoingComponent;
       }
+    else if(args[i] == "EXCLUDE_FROM_ALL")
+      {
+      if(in_match_mode)
+        {
+        std::ostringstream e;
+        e << args[0] << " does not allow \""
+          << args[i] << "\" after PATTERN or REGEX.";
+        this->SetError(e.str().c_str());
+        return false;
+        }
+      exclude_from_all = true;
+      doing = DoingNone;
+      }
     else if(doing == DoingDirs)
       {
       // Convert this directory to a full path.
@@ -1273,6 +1294,7 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
                                     configurations,
                                     component.c_str(),
                                     message,
+                                    exclude_from_all,
                                     literal_args.c_str(),
                                     optional));
 
@@ -1401,7 +1423,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
       exportSet,
       ica.GetDestination().c_str(),
       ica.GetPermissions().c_str(), ica.GetConfigurations(),
-      ica.GetComponent().c_str(), message, fname.c_str(),
+      ica.GetComponent().c_str(), message,
+      ica.GetExcludeFromAll(), fname.c_str(),
       name_space.GetCString(), exportOld.IsEnabled());
   this->Makefile->AddInstallGenerator(exportGenerator);
 

+ 22 - 8
Source/cmInstallCommandArguments.cxx

@@ -27,14 +27,15 @@ cmInstallCommandArguments::cmInstallCommandArguments(
                                            const std::string& defaultComponent)
 :Parser()
 ,ArgumentGroup()
-,Destination   (&Parser, "DESTINATION"   , &ArgumentGroup)
-,Component     (&Parser, "COMPONENT"     , &ArgumentGroup)
-,Rename        (&Parser, "RENAME"        , &ArgumentGroup)
-,Permissions   (&Parser, "PERMISSIONS"   , &ArgumentGroup)
-,Configurations(&Parser, "CONFIGURATIONS", &ArgumentGroup)
-,Optional      (&Parser, "OPTIONAL"      , &ArgumentGroup)
-,NamelinkOnly  (&Parser, "NAMELINK_ONLY" , &ArgumentGroup)
-,NamelinkSkip  (&Parser, "NAMELINK_SKIP" , &ArgumentGroup)
+,Destination   (&Parser, "DESTINATION"     , &ArgumentGroup)
+,Component     (&Parser, "COMPONENT"       , &ArgumentGroup)
+,ExcludeFromAll(&Parser, "EXCLUDE_FROM_ALL", &ArgumentGroup)
+,Rename        (&Parser, "RENAME"          , &ArgumentGroup)
+,Permissions   (&Parser, "PERMISSIONS"     , &ArgumentGroup)
+,Configurations(&Parser, "CONFIGURATIONS"  , &ArgumentGroup)
+,Optional      (&Parser, "OPTIONAL"        , &ArgumentGroup)
+,NamelinkOnly  (&Parser, "NAMELINK_ONLY"   , &ArgumentGroup)
+,NamelinkSkip  (&Parser, "NAMELINK_SKIP"   , &ArgumentGroup)
 ,GenericArguments(0)
 ,DefaultComponentName(defaultComponent)
 {
@@ -110,6 +111,19 @@ bool cmInstallCommandArguments::GetOptional() const
   return false;
 }
 
+bool cmInstallCommandArguments::GetExcludeFromAll() const
+{
+  if (this->ExcludeFromAll.IsEnabled())
+    {
+    return true;
+    }
+  if (this->GenericArguments!=0)
+    {
+    return this->GenericArguments->GetExcludeFromAll();
+    }
+  return false;
+}
+
 bool cmInstallCommandArguments::GetNamelinkOnly() const
 {
   if (this->NamelinkOnly.IsEnabled())

+ 2 - 0
Source/cmInstallCommandArguments.h

@@ -30,6 +30,7 @@ class cmInstallCommandArguments
 
     const std::string& GetDestination() const;
     const std::string& GetComponent() const;
+    bool GetExcludeFromAll() const;
     const std::string& GetRename() const;
     const std::string& GetPermissions() const;
     const std::vector<std::string>& GetConfigurations() const;
@@ -48,6 +49,7 @@ class cmInstallCommandArguments
     cmInstallCommandArguments(); // disabled
     cmCAString Destination;
     cmCAString Component;
+    cmCAEnabler ExcludeFromAll;
     cmCAString Rename;
     cmCAStringVector Permissions;
     cmCAStringVector Configurations;

+ 3 - 1
Source/cmInstallDirectoryGenerator.cxx

@@ -23,9 +23,11 @@ cmInstallDirectoryGenerator
                               std::vector<std::string> const& configurations,
                               const char* component,
                               MessageLevel message,
+                              bool exclude_from_all,
                               const char* literal_args,
                               bool optional):
-  cmInstallGenerator(dest, configurations, component, message),
+  cmInstallGenerator(dest, configurations, component, message,
+                     exclude_from_all),
   LocalGenerator(0),
   Directories(dirs),
   FilePermissions(file_permissions), DirPermissions(dir_permissions),

+ 1 - 0
Source/cmInstallDirectoryGenerator.h

@@ -27,6 +27,7 @@ public:
                               std::vector<std::string> const& configurations,
                               const char* component,
                               MessageLevel message,
+                              bool exclude_from_all,
                               const char* literal_args,
                               bool optional = false);
   virtual ~cmInstallDirectoryGenerator();

+ 3 - 1
Source/cmInstallExportGenerator.cxx

@@ -33,9 +33,11 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   std::vector<std::string> const& configurations,
   const char* component,
   MessageLevel message,
+  bool exclude_from_all,
   const char* filename, const char* name_space,
   bool exportOld)
-  :cmInstallGenerator(destination, configurations, component, message)
+  :cmInstallGenerator(destination, configurations, component, message,
+                      exclude_from_all)
   ,ExportSet(exportSet)
   ,FilePermissions(file_permissions)
   ,FileName(filename)

+ 1 - 0
Source/cmInstallExportGenerator.h

@@ -31,6 +31,7 @@ public:
                            const std::vector<std::string>& configurations,
                            const char* component,
                            MessageLevel message,
+                           bool exclude_from_all,
                            const char* filename, const char* name_space,
                            bool exportOld);
   ~cmInstallExportGenerator();

+ 3 - 1
Source/cmInstallFilesCommand.cxx

@@ -122,6 +122,7 @@ void cmInstallFilesCommand::CreateInstallGenerator() const
   // Use a file install generator.
   const char* no_permissions = "";
   const char* no_rename = "";
+  bool no_exclude_from_all = false;
   std::string no_component = this->Makefile->GetSafeDefinition(
                                        "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
   std::vector<std::string> no_configurations;
@@ -131,7 +132,8 @@ void cmInstallFilesCommand::CreateInstallGenerator() const
     new cmInstallFilesGenerator(this->Files,
                                 destination.c_str(), false,
                                 no_permissions, no_configurations,
-                                no_component.c_str(), message, no_rename));
+                                no_component.c_str(), message,
+                                no_exclude_from_all, no_rename));
 }
 
 

+ 3 - 1
Source/cmInstallFilesGenerator.cxx

@@ -24,9 +24,11 @@ cmInstallFilesGenerator
                           std::vector<std::string> const& configurations,
                           const char* component,
                           MessageLevel message,
+                          bool exclude_from_all,
                           const char* rename,
                           bool optional):
-  cmInstallGenerator(dest, configurations, component, message),
+  cmInstallGenerator(dest, configurations, component, message,
+                     exclude_from_all),
   LocalGenerator(0),
   Files(files),
   FilePermissions(file_permissions),

+ 1 - 0
Source/cmInstallFilesGenerator.h

@@ -26,6 +26,7 @@ public:
                           std::vector<std::string> const& configurations,
                           const char* component,
                           MessageLevel message,
+                          bool exclude_from_all,
                           const char* rename,
                           bool optional = false);
   virtual ~cmInstallFilesGenerator();

+ 12 - 6
Source/cmInstallGenerator.cxx

@@ -19,11 +19,13 @@ cmInstallGenerator
 ::cmInstallGenerator(const char* destination,
                      std::vector<std::string> const& configurations,
                      const char* component,
-                     MessageLevel message):
+                     MessageLevel message,
+                     bool exclude_from_all):
   cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations),
   Destination(destination? destination:""),
   Component(component? component:""),
-  Message(message)
+  Message(message),
+  ExcludeFromAll(exclude_from_all)
 {
 }
 
@@ -146,12 +148,16 @@ void cmInstallGenerator
 
 //----------------------------------------------------------------------------
 std::string
-cmInstallGenerator::CreateComponentTest(const char* component)
+cmInstallGenerator::CreateComponentTest(const char* component,
+                                        bool exclude_from_all)
 {
-  std::string result = "NOT CMAKE_INSTALL_COMPONENT OR "
-    "\"${CMAKE_INSTALL_COMPONENT}\" STREQUAL \"";
+  std::string result = "\"${CMAKE_INSTALL_COMPONENT}\" STREQUAL \"";
   result += component;
   result += "\"";
+  if(!exclude_from_all)
+    {
+    result += " OR NOT CMAKE_INSTALL_COMPONENT";
+    }
   return result;
 }
 
@@ -163,7 +169,7 @@ void cmInstallGenerator::GenerateScript(std::ostream& os)
 
   // Begin this block of installation.
   std::string component_test =
-    this->CreateComponentTest(this->Component.c_str());
+    this->CreateComponentTest(this->Component.c_str(),this->ExcludeFromAll);
   os << indent << "if(" << component_test << ")\n";
 
   // Generate the script possibly with per-configuration code.

+ 5 - 2
Source/cmInstallGenerator.h

@@ -36,7 +36,8 @@ public:
   cmInstallGenerator(const char* destination,
                      std::vector<std::string> const& configurations,
                      const char* component,
-                     MessageLevel message);
+                     MessageLevel message,
+                     bool exclude_from_all);
   virtual ~cmInstallGenerator();
 
   void AddInstallRule(
@@ -67,12 +68,14 @@ public:
 protected:
   virtual void GenerateScript(std::ostream& os);
 
-  std::string CreateComponentTest(const char* component);
+  std::string CreateComponentTest(const char* component,
+                                  bool exclude_from_all);
 
   // Information shared by most generator types.
   std::string Destination;
   std::string Component;
   MessageLevel Message;
+  bool ExcludeFromAll;
 };
 
 #endif

+ 3 - 1
Source/cmInstallProgramsCommand.cxx

@@ -85,6 +85,7 @@ void cmInstallProgramsCommand::FinalPass()
   // Use a file install generator.
   const char* no_permissions = "";
   const char* no_rename = "";
+  bool no_exclude_from_all = false;
   std::string no_component = this->Makefile->GetSafeDefinition(
                                        "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
   std::vector<std::string> no_configurations;
@@ -94,7 +95,8 @@ void cmInstallProgramsCommand::FinalPass()
     new cmInstallFilesGenerator(this->Files,
                                 destination.c_str(), true,
                                 no_permissions, no_configurations,
-                                no_component.c_str(), message, no_rename));
+                                no_component.c_str(), message,
+                                no_exclude_from_all, no_rename));
 }
 
 /**

+ 4 - 3
Source/cmInstallScriptGenerator.cxx

@@ -14,8 +14,9 @@
 //----------------------------------------------------------------------------
 cmInstallScriptGenerator
 ::cmInstallScriptGenerator(const char* script, bool code,
-                           const char* component) :
-  cmInstallGenerator(0, std::vector<std::string>(), component, MessageDefault),
+                           const char* component, bool exclude_from_all) :
+  cmInstallGenerator(0, std::vector<std::string>(), component, MessageDefault,
+                     exclude_from_all),
   Script(script), Code(code)
 {
 }
@@ -31,7 +32,7 @@ void cmInstallScriptGenerator::GenerateScript(std::ostream& os)
 {
   Indent indent;
   std::string component_test =
-    this->CreateComponentTest(this->Component.c_str());
+    this->CreateComponentTest(this->Component.c_str(), this->ExcludeFromAll);
   os << indent << "if(" << component_test << ")\n";
 
   if(this->Code)

+ 1 - 1
Source/cmInstallScriptGenerator.h

@@ -21,7 +21,7 @@ class cmInstallScriptGenerator: public cmInstallGenerator
 {
 public:
   cmInstallScriptGenerator(const char* script, bool code,
-    const char* component);
+    const char* component, bool exclude_from_all);
   virtual ~cmInstallScriptGenerator();
 
 protected:

+ 3 - 1
Source/cmInstallTargetGenerator.cxx

@@ -30,8 +30,10 @@ cmInstallTargetGenerator
                            std::vector<std::string> const& configurations,
                            const char* component,
                            MessageLevel message,
+                           bool exclude_from_all,
                            bool optional):
-  cmInstallGenerator(dest, configurations, component, message),
+  cmInstallGenerator(dest, configurations, component, message,
+                     exclude_from_all),
   TargetName(targetName),
   Target(0),
   FilePermissions(file_permissions),

+ 1 - 0
Source/cmInstallTargetGenerator.h

@@ -28,6 +28,7 @@ public:
     std::vector<std::string> const& configurations,
     const char* component,
     MessageLevel message,
+    bool exclude_from_all,
     bool optional
     );
   virtual ~cmInstallTargetGenerator();

+ 3 - 3
Source/cmLocalGenerator.cxx

@@ -2557,7 +2557,7 @@ public:
     cmInstallTargetGenerator(
       t, dest, implib, "", std::vector<std::string>(), "Unspecified",
       cmInstallGenerator::SelectMessageLevel(lg->GetMakefile()),
-      false)
+      false, false)
   {
     this->Compute(lg);
   }
@@ -2584,7 +2584,7 @@ cmLocalGenerator
     // Include the user-specified pre-install script for this target.
     if(const char* preinstall = (*l)->GetProperty("PRE_INSTALL_SCRIPT"))
       {
-      cmInstallScriptGenerator g(preinstall, false, 0);
+      cmInstallScriptGenerator g(preinstall, false, 0, false);
       g.Generate(os, config, configurationTypes);
       }
 
@@ -2645,7 +2645,7 @@ cmLocalGenerator
     // Include the user-specified post-install script for this target.
     if(const char* postinstall = (*l)->GetProperty("POST_INSTALL_SCRIPT"))
       {
-      cmInstallScriptGenerator g(postinstall, false, 0);
+      cmInstallScriptGenerator g(postinstall, false, 0, false);
       g.Generate(os, config, configurationTypes);
       }
     }