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.
This commit is contained in:
parent
cbb609072f
commit
0212d7c762
@ -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:
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user