summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2018-04-18 14:53:10 -0400
committerBrad King <brad.king@kitware.com>2018-05-03 08:08:37 -0400
commit0212d7c7629bb1a866da4f6c69b780c6d43f26f3 (patch)
treeea32f0aa311f23569ff0168c0446be4d831f93a2
parentcbb609072f00ee6aec3fdfb6e54ed2b3a747e840 (diff)
downloadcmake-0212d7c7629bb1a866da4f6c69b780c6d43f26f3.tar.gz
install: add NAMELINK_COMPONENT argument
For shared libraries, this allows you to specify separate components for the shared library and for the namelink. Suggested in https://cmake.org/pipermail/cmake-developers/2014-December/024032.html.
-rw-r--r--Help/command/install.rst59
-rw-r--r--Source/cmInstallCommand.cxx46
-rw-r--r--Source/cmInstallCommandArguments.cxx20
-rw-r--r--Source/cmInstallCommandArguments.h3
4 files changed, 113 insertions, 15 deletions
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 1037edf7e8..63ba210d3c 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -103,6 +103,7 @@ Installing Targets
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
+ [NAMELINK_COMPONENT <component>]
[OPTIONAL] [EXCLUDE_FROM_ALL]
[NAMELINK_ONLY|NAMELINK_SKIP]
] [...]
@@ -167,7 +168,7 @@ just a DLL or just an import library.)
In addition to the common options listed above, each target can accept
the following additional arguments:
-``NAMELINK_ONLY``
+``NAMELINK_COMPONENT``
On some platforms a versioned shared library has a symbolic link such
as::
@@ -175,13 +176,51 @@ the following additional arguments:
where ``lib<name>.so.1`` is the soname of the library and ``lib<name>.so``
is a "namelink" allowing linkers to find the library when given
- ``-l<name>``. The ``NAMELINK_ONLY`` option causes the installation of only
- the namelink when a library target is installed. On platforms where
- versioned shared libraries do not have namelinks or when a library is not
- versioned, the ``NAMELINK_ONLY`` option installs nothing. It is an error to
- use this parameter outside of a ``LIBRARY`` block. See the
- :prop_tgt:`VERSION` and :prop_tgt:`SOVERSION` target properties for details
- on creating versioned shared libraries.
+ ``-l<name>``. The ``NAMELINK_COMPONENT`` option is similar to the
+ ``COMPONENT`` option, but it changes the installation component of a shared
+ library namelink if one is generated. If not specified, this defaults to the
+ value of ``COMPONENT``. It is an error to use this parameter outside of a
+ ``LIBRARY`` block.
+
+ Consider the following example:
+
+ .. code-block:: cmake
+
+ install(TARGETS mylib
+ LIBRARY
+ DESTINATION lib
+ COMPONENT Libraries
+ NAMELINK_COMPONENT Development
+ PUBLIC_HEADER
+ DESTINATION include
+ COMPONENT Development
+ )
+
+ In this scenario, if you choose to install only the ``Development``
+ component, both the headers and namelink will be installed without the
+ library. (If you don't also install the ``Libraries`` component, the
+ namelink will be a dangling symlink, and projects that link to the library
+ will have build errors.) If you install only the ``Libraries`` component,
+ only the library will be installed, without the headers and namelink.
+
+ This option is typically used for package managers that have separate
+ runtime and development packages. For example, on Debian systems, the
+ library is expected to be in the runtime package, and the headers and
+ namelink are expected to be in the development package.
+
+ See the :prop_tgt:`VERSION` and :prop_tgt:`SOVERSION` target properties for
+ details on creating versioned shared libraries.
+
+``NAMELINK_ONLY``
+ This option causes the installation of only the namelink when a library
+ target is installed. On platforms where versioned shared libraries do not
+ have namelinks or when a library is not versioned, the ``NAMELINK_ONLY``
+ option installs nothing. It is an error to use this parameter outside of a
+ ``LIBRARY`` block.
+
+ When ``NAMELINK_ONLY`` is given, either ``NAMELINK_COMPONENT`` or
+ ``COMPONENT`` may be used to specify the installation component of the
+ namelink, but ``COMPONENT`` should generally be preferred.
``NAMELINK_SKIP``
Similar to ``NAMELINK_ONLY``, but it has the opposite effect: it causes the
@@ -192,6 +231,10 @@ the following additional arguments:
installs the library. It is an error to use this parameter outside of a
``LIBRARY`` block.
+ If ``NAMELINK_SKIP`` is specified, ``NAMELINK_COMPONENT`` has no effect. It
+ is not recommended to use ``NAMELINK_SKIP`` in conjunction with
+ ``NAMELINK_COMPONENT``.
+
The ``install(TARGETS)`` command can also accept the following options at the
top level:
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index b5291a16b6..b325b0c484 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -33,16 +33,17 @@ class cmExecutionStatus;
static cmInstallTargetGenerator* CreateInstallTargetGenerator(
cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
- bool forceOpt = false)
+ bool forceOpt = false, bool namelink = false)
{
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
target.SetHaveInstallRule(true);
+ const char* component = namelink ? args.GetNamelinkComponent().c_str()
+ : args.GetComponent().c_str();
return new cmInstallTargetGenerator(
target.GetName(), args.GetDestination().c_str(), impLib,
- args.GetPermissions().c_str(), args.GetConfigurations(),
- args.GetComponent().c_str(), message, args.GetExcludeFromAll(),
- args.GetOptional() || forceOpt);
+ args.GetPermissions().c_str(), args.GetConfigurations(), component,
+ message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt);
}
static cmInstallFilesGenerator* CreateInstallFilesGenerator(
@@ -313,6 +314,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
return false;
}
+ if (archiveArgs.HasNamelinkComponent() ||
+ runtimeArgs.HasNamelinkComponent() ||
+ objectArgs.HasNamelinkComponent() ||
+ frameworkArgs.HasNamelinkComponent() ||
+ bundleArgs.HasNamelinkComponent() ||
+ privateHeaderArgs.HasNamelinkComponent() ||
+ publicHeaderArgs.HasNamelinkComponent() ||
+ resourceArgs.HasNamelinkComponent()) {
+ this->SetError(
+ "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
+ "The NAMELINK_COMPONENT option may be specified only following "
+ "LIBRARY.");
+ return false;
+ }
if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) {
this->SetError("TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
"At most one of these two options may be specified.");
@@ -377,6 +392,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// any files of the given type.
bool installsArchive = false;
bool installsLibrary = false;
+ bool installsNamelink = false;
bool installsRuntime = false;
bool installsObject = false;
bool installsFramework = false;
@@ -391,6 +407,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmTarget& target = *ti;
cmInstallTargetGenerator* archiveGenerator = nullptr;
cmInstallTargetGenerator* libraryGenerator = nullptr;
+ cmInstallTargetGenerator* namelinkGenerator = nullptr;
cmInstallTargetGenerator* runtimeGenerator = nullptr;
cmInstallTargetGenerator* objectGenerator = nullptr;
cmInstallTargetGenerator* frameworkGenerator = nullptr;
@@ -453,9 +470,18 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
} else {
// The shared library uses the LIBRARY properties.
if (!libraryArgs.GetDestination().empty()) {
- libraryGenerator =
- CreateInstallTargetGenerator(target, libraryArgs, false);
- libraryGenerator->SetNamelinkMode(namelinkMode);
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
+ libraryGenerator =
+ CreateInstallTargetGenerator(target, libraryArgs, false);
+ libraryGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeSkip);
+ }
+ if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
+ namelinkGenerator = CreateInstallTargetGenerator(
+ target, libraryArgs, false, false, true);
+ namelinkGenerator->SetNamelinkMode(
+ cmInstallTargetGenerator::NamelinkModeOnly);
+ }
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
} else {
@@ -684,6 +710,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Keep track of whether we're installing anything in each category
installsArchive = installsArchive || archiveGenerator != nullptr;
installsLibrary = installsLibrary || libraryGenerator != nullptr;
+ installsNamelink = installsNamelink || namelinkGenerator != nullptr;
installsRuntime = installsRuntime || runtimeGenerator != nullptr;
installsObject = installsObject || objectGenerator != nullptr;
installsFramework = installsFramework || frameworkGenerator != nullptr;
@@ -696,6 +723,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->Makefile->AddInstallGenerator(archiveGenerator);
this->Makefile->AddInstallGenerator(libraryGenerator);
+ this->Makefile->AddInstallGenerator(namelinkGenerator);
this->Makefile->AddInstallGenerator(runtimeGenerator);
this->Makefile->AddInstallGenerator(objectGenerator);
this->Makefile->AddInstallGenerator(frameworkGenerator);
@@ -735,6 +763,10 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
libraryArgs.GetComponent().c_str());
}
+ if (installsNamelink) {
+ this->Makefile->GetGlobalGenerator()->AddInstallComponent(
+ libraryArgs.GetNamelinkComponent().c_str());
+ }
if (installsRuntime) {
this->Makefile->GetGlobalGenerator()->AddInstallComponent(
runtimeArgs.GetComponent().c_str());
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 7b79ab5c8d..2d6dc12956 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -21,6 +21,7 @@ cmInstallCommandArguments::cmInstallCommandArguments(
, ArgumentGroup()
, Destination(&Parser, "DESTINATION", &ArgumentGroup)
, Component(&Parser, "COMPONENT", &ArgumentGroup)
+ , NamelinkComponent(&Parser, "NAMELINK_COMPONENT", &ArgumentGroup)
, ExcludeFromAll(&Parser, "EXCLUDE_FROM_ALL", &ArgumentGroup)
, Rename(&Parser, "RENAME", &ArgumentGroup)
, Permissions(&Parser, "PERMISSIONS", &ArgumentGroup)
@@ -59,6 +60,14 @@ const std::string& cmInstallCommandArguments::GetComponent() const
return unspecifiedComponent;
}
+const std::string& cmInstallCommandArguments::GetNamelinkComponent() const
+{
+ if (!this->NamelinkComponent.GetString().empty()) {
+ return this->NamelinkComponent.GetString();
+ }
+ return this->GetComponent();
+}
+
const std::string& cmInstallCommandArguments::GetRename() const
{
if (!this->Rename.GetString().empty()) {
@@ -125,6 +134,17 @@ bool cmInstallCommandArguments::GetNamelinkSkip() const
return false;
}
+bool cmInstallCommandArguments::HasNamelinkComponent() const
+{
+ if (!this->NamelinkComponent.GetString().empty()) {
+ return true;
+ }
+ if (this->GenericArguments != nullptr) {
+ return this->GenericArguments->HasNamelinkComponent();
+ }
+ return false;
+}
+
const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
const
{
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index a576e72029..ee6e865975 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -26,6 +26,7 @@ public:
const std::string& GetDestination() const;
const std::string& GetComponent() const;
+ const std::string& GetNamelinkComponent() const;
bool GetExcludeFromAll() const;
const std::string& GetRename() const;
const std::string& GetPermissions() const;
@@ -33,6 +34,7 @@ public:
bool GetOptional() const;
bool GetNamelinkOnly() const;
bool GetNamelinkSkip() const;
+ bool HasNamelinkComponent() const;
// once HandleDirectoryMode() is also switched to using
// cmInstallCommandArguments then these two functions can become non-static
@@ -45,6 +47,7 @@ private:
cmInstallCommandArguments(); // disabled
cmCAString Destination;
cmCAString Component;
+ cmCAString NamelinkComponent;
cmCAEnabler ExcludeFromAll;
cmCAString Rename;
cmCAStringVector Permissions;