mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-16 11:21:41 -05:00
file: Add GET_RUNTIME_DEPENDENCIES mode
Co-Authored-by: Bryon Bean <bryon.bean@kitware.com>
This commit is contained in:
@@ -13,6 +13,7 @@ Synopsis
|
||||
file(`STRINGS`_ <filename> <out-var> [...])
|
||||
file(`\<HASH\> <HASH_>`_ <filename> <out-var>)
|
||||
file(`TIMESTAMP`_ <filename> <out-var> [...])
|
||||
file(`GET_RUNTIME_DEPENDENCIES`_ [...])
|
||||
|
||||
`Writing`_
|
||||
file({`WRITE`_ | `APPEND`_} <filename> <content>...)
|
||||
@@ -130,6 +131,273 @@ timestamp variable will be set to the empty string ("").
|
||||
See the :command:`string(TIMESTAMP)` command for documentation of
|
||||
the ``<format>`` and ``UTC`` options.
|
||||
|
||||
.. _GET_RUNTIME_DEPENDENCIES:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
[RESOLVED_DEPENDENCIES_VAR <deps_var>]
|
||||
[UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>]
|
||||
[CONFLICTING_DEPENDENICES_PREFIX <conflicting_deps_prefix>]
|
||||
[EXECUTABLES [<executable_files>...]]
|
||||
[LIBRARIES [<library_files>...]]
|
||||
[MODULES [<module_files>...]]
|
||||
[DIRECTORIES [<directories>...]]
|
||||
[BUNDLE_EXECUTABLE <bundle_executable_file>]
|
||||
[PRE_INCLUDE_REGEXES [<regexes>...]]
|
||||
[PRE_EXCLUDE_REGEXES [<regexes>...]]
|
||||
[POST_INCLUDE_REGEXES [<regexes>...]]
|
||||
[POST_EXCLUDE_REGEXES [<regexes>...]]
|
||||
)
|
||||
|
||||
Recursively get the list of libraries depended on by the given files.
|
||||
|
||||
Please note that this sub-command is not intended to be used in project mode.
|
||||
Instead, use it in an :command:`install(CODE)` or :command:`install(SCRIPT)`
|
||||
block. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
# ...
|
||||
)
|
||||
]])
|
||||
|
||||
The arguments are as follows:
|
||||
|
||||
``RESOLVED_DEPENDENCIES_VAR <deps_var>``
|
||||
Name of the variable in which to store the list of resolved dependencies.
|
||||
|
||||
``UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>``
|
||||
Name of the variable in which to store the list of unresolved dependencies.
|
||||
If this variable is not specified, and there are any unresolved dependencies,
|
||||
an error is issued.
|
||||
|
||||
``CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>``
|
||||
Variable prefix in which to store conflicting dependency information.
|
||||
Dependencies are conflicting if two files with the same name are found in
|
||||
two different directories. The list of filenames that conflict are stored in
|
||||
``<conflicting_deps_prefix>_FILENAMES``. For each filename, the list of paths
|
||||
that were found for that filename are stored in
|
||||
``<conflicting_deps_prefix>_<filename>``.
|
||||
|
||||
``EXECUTABLES <executable_files>``
|
||||
List of executable files to read for dependencies. These are executables that
|
||||
are typically created with :command:`add_executable`, but they do not have to
|
||||
be created by CMake. On Apple platforms, the paths to these files determine
|
||||
the value of ``@executable_path`` when recursively resolving the libraries.
|
||||
Specifying ``STATIC`` libraries, ``MODULE`` s, or ``SHARED`` libraries here
|
||||
will result in undefined behavior.
|
||||
|
||||
``LIBRARIES <library_files>``
|
||||
List of library files to read for dependencies. These are libraries that are
|
||||
typically created with :command:`add_library(SHARED)`, but they do not have
|
||||
to be created by CMake. Specifying ``STATIC`` libraries, ``MODULE`` s, or
|
||||
executables here will result in undefined behavior.
|
||||
|
||||
``MODULES <module_files>``
|
||||
List of loadable module files to read for dependencies. These are modules
|
||||
that are typically created with :command:`add_library(MODULE)`, but they do
|
||||
not have to be created by CMake. They are typically used by calling
|
||||
``dlopen()`` at runtime rather than linked at link time with ``ld -l``.
|
||||
Specifying ``STATIC`` libraries, ``SHARED`` libraries, or executables here
|
||||
will result in undefined behavior.
|
||||
|
||||
``DIRECTORIES <directories>``
|
||||
List of additional directories to search for dependencies. On Linux
|
||||
platforms, these directories are searched if the dependency is not found in
|
||||
any of the other usual paths. If it is found in such a directory, a warning
|
||||
is issued, because it means that the file is incomplete (it does not list all
|
||||
of the directories that contain its dependencies.) On Windows platforms,
|
||||
these directories are searched if the dependency is not found in any of the
|
||||
other search paths, but no warning is issued, because searching other paths
|
||||
is a normal part of Windows dependency resolution. On Apple platforms, this
|
||||
argument has no effect.
|
||||
|
||||
``BUNDLE_EXECTUBLE <bundle_executable_file>``
|
||||
Executable to treat as the "bundle executable" when resolving libraries. On
|
||||
Apple platforms, this argument determines the value of ``@executable_path``
|
||||
when recursively resolving libraries for ``LIBRARIES`` and ``MODULES`` files.
|
||||
It has no effect on ``EXECUTABLES`` files. On other platforms, it has no
|
||||
effect. This is typically (but not always) one of the executables in the
|
||||
``EXECUTABLES`` argument which designates the "main" executable of the
|
||||
package.
|
||||
|
||||
The following arguments specify filters for including or excluding libraries to
|
||||
be resolved. See below for a full description of how they work.
|
||||
|
||||
``PRE_INCLUDE_REGEXES <regexes>``
|
||||
List of pre-include regexes through which to filter the names of
|
||||
not-yet-resolved dependencies.
|
||||
|
||||
``PRE_EXCLUDE_REGEXES <regexes>``
|
||||
List of pre-exclude regexes through which to filter the names of
|
||||
not-yet-resolved dependencies.
|
||||
|
||||
``POST_INCLUDE_REGEXES <regexes>``
|
||||
List of post-include regexes through which to filter the names of resolved
|
||||
dependencies.
|
||||
|
||||
``POST_EXCLUDE_REGEXES <regexes>``
|
||||
List of post-exclude regexes through which to filter the names of resolved
|
||||
dependencies.
|
||||
|
||||
These arguments can be used to blacklist unwanted system libraries when
|
||||
resolving the dependencies, or to whitelist libraries from a specific
|
||||
directory. The filtering works as follows:
|
||||
|
||||
1. If the not-yet-resolved dependency matches any of the
|
||||
``PRE_INCLUDE_REGEXES``, steps 2 and 3 are skipped, and the dependency
|
||||
resolution proceeds to step 4.
|
||||
2. If the not-yet-resolved dependency matches any of the
|
||||
``PRE_EXCLUDE_REGEXES``, dependency resolution stops for that dependency.
|
||||
3. Otherwise, dependency resolution proceeds.
|
||||
4. ``file(GET_RUNTIME_DEPENDENCIES)`` searches for the dependency according to
|
||||
the linking rules of the platform (see below).
|
||||
5. If the dependency is found, and its full path matches one of the
|
||||
``POST_INCLUDE_REGEXES``, the full path is added to the resolved
|
||||
dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves
|
||||
that library's own dependencies. Otherwise, resolution proceeds to step 6.
|
||||
6. If the dependency is found, but its full path matches one of the
|
||||
``POST_EXCLUDE_REGEXES``, it is not added to the resolved dependencies, and
|
||||
dependency resolution stops for that dependency.
|
||||
7. If the dependency is found, and its full path does not match either
|
||||
``POST_INCLUDE_REGEXES`` or ``POST_EXCLUDE_REGEXES``, the full path is added
|
||||
to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)``
|
||||
recursively resolves that library's own dependencies.
|
||||
|
||||
Different platforms have different rules for how dependencies are resolved.
|
||||
These specifics are described here.
|
||||
|
||||
On Linux platforms, library resolution works as follows:
|
||||
|
||||
1. If the depending file does not have any ``RUNPATH`` entries, and the library
|
||||
exists in one of the depending file's ``RPATH`` entries, or its parents', in
|
||||
that order, the dependency is resolved to that file.
|
||||
2. Otherwise, if the depending file has any ``RUNPATH`` entries, and the
|
||||
library exists in one of those entries, the dependency is resolved to that
|
||||
file.
|
||||
3. Otherwise, if the library exists in one of the directories listed by
|
||||
``ldconfig``, the dependency is resolved to that file.
|
||||
4. Otherwise, if the library exists in one of the ``DIRECTORIES`` entries, the
|
||||
dependency is resolved to that file. In this case, a warning is issued,
|
||||
because finding a file in one of the ``DIRECTORIES`` means that the
|
||||
depending file is not complete (it does not list all the directories from
|
||||
which it pulls dependencies.)
|
||||
5. Otherwise, the dependency is unresolved.
|
||||
|
||||
On Windows platforms, library resolution works as follows:
|
||||
|
||||
1. The dependent DLL name is converted to lowercase. Windows DLL names are
|
||||
case-insensitive, and some linkers mangle the case of the DLL dependency
|
||||
names. However, this makes it more difficult for ``PRE_INCLUDE_REGEXES``,
|
||||
``PRE_EXCLUDE_REGEXES``, ``POST_INCLUDE_REGEXES``, and
|
||||
``POST_EXCLUDE_REGEXES`` to properly filter DLL names - every regex would
|
||||
have to check for both uppercase and lowercase letters. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
# ...
|
||||
PRE_INCLUDE_REGEXES "^[Mm][Yy][Ll][Ii][Bb][Rr][Aa][Rr][Yy]\\.[Dd][Ll][Ll]$"
|
||||
)
|
||||
|
||||
Converting the DLL name to lowercase allows the regexes to only match
|
||||
lowercase names, thus simplifying the regex. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
# ...
|
||||
PRE_INCLUDE_REGEXES "^mylibrary\\.dll$"
|
||||
)
|
||||
|
||||
This regex will match ``mylibrary.dll`` regardless of how it is cased,
|
||||
either on disk or in the depending file. (For example, it will match
|
||||
``mylibrary.dll``, ``MyLibrary.dll``, and ``MYLIBRARY.DLL``.)
|
||||
|
||||
Please note that the directory portion of any resolved DLLs retains its
|
||||
casing and is not converted to lowercase. Only the filename portion is
|
||||
converted.
|
||||
|
||||
2. (**Not yet implemented**) If the depending file is a Windows Store app, and
|
||||
the dependency is listed as a dependency in the application's package
|
||||
manifest, the dependency is resolved to that file.
|
||||
3. Otherwise, if the library exists in the same directory as the depending
|
||||
file, the dependency is resolved to that file.
|
||||
4. Otherwise, if the library exists in either the operating system's
|
||||
``system32`` directory or the ``Windows`` directory, in that order, the
|
||||
dependency is resolved to that file.
|
||||
5. Otherwise, if the library exists in one of the directories specified by
|
||||
``DIRECTORIES``, in the order they are listed, the dependency is resolved to
|
||||
that file. (In this case, a warning is not issued, because searching other
|
||||
directories is a normal part of Windows library resolution.)
|
||||
6. Otherwise, the dependency is unresolved.
|
||||
|
||||
On Apple platforms, library resolution works as follows:
|
||||
|
||||
1. If the dependency starts with ``@executable_path/``, and an ``EXECUTABLES``
|
||||
argument is in the process of being resolved, and replacing
|
||||
``@executable_path/`` with the directory of the executable yields an
|
||||
existing file, the dependency is resolved to that file.
|
||||
2. Otherwise, if the dependency starts with ``@executable_path/``, and there is
|
||||
a ``BUNDLE_EXECUTABLE`` argument, and replacing ``@executable_path/`` with
|
||||
the directory of the bundle executable yields an existing file, the
|
||||
dependency is resolved to that file.
|
||||
3. Otherwise, if the dependency starts with ``@loader_path/``, and replacing
|
||||
``@loader_path/`` with the directory of the depending file yields an
|
||||
existing file, the dependency is resolved to that file.
|
||||
4. Otherwise, if the dependency starts with ``@rpath/``, and replacing
|
||||
``@rpath/`` with one of the ``RPATH`` entries of the depending file yields
|
||||
an existing file, the dependency is resolved to that file. (Note that
|
||||
``RPATH`` entries that start with ``@executable_path/`` or ``@loader_path/``
|
||||
also have these items replaced with the appropriate path.)
|
||||
5. Otherwise, if the dependency is an absolute file that exists, the dependency
|
||||
is resolved to that file.
|
||||
6. Otherwise, the dependency is unresolved.
|
||||
|
||||
This function accepts several variables that determine which tool is used for
|
||||
dependency resolution:
|
||||
|
||||
.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM
|
||||
|
||||
Determines which operating system and executable format the files are built
|
||||
for. This could be one of several values:
|
||||
|
||||
* ``linux+elf``
|
||||
* ``windows+pe``
|
||||
* ``macos+macho``
|
||||
|
||||
If this variable is not specified, it is determined automatically by system
|
||||
introspection.
|
||||
|
||||
.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL
|
||||
|
||||
Determines the tool to use for dependency resolution. It could be one of
|
||||
several values, depending on the value of
|
||||
:variable:`CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`:
|
||||
|
||||
================================================= =============================================
|
||||
``CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`` ``CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL``
|
||||
================================================= =============================================
|
||||
``linux+elf`` ``objdump``
|
||||
``windows+pe`` ``dumpbin``
|
||||
``windows+pe`` ``objdump``
|
||||
``macos+macho`` ``otool``
|
||||
================================================= =============================================
|
||||
|
||||
If this variable is not specified, it is determined automatically by system
|
||||
introspection.
|
||||
|
||||
.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND
|
||||
|
||||
Determines the path to the tool to use for dependency resolution. This is the
|
||||
actual path to ``objdump``, ``dumpbin``, or ``otool``.
|
||||
|
||||
If this variable is not specified, it is determined automatically by system
|
||||
introspection.
|
||||
|
||||
Writing
|
||||
^^^^^^^
|
||||
|
||||
|
||||
7
Help/release/dev/get-runtime-dependencies.rst
Normal file
7
Help/release/dev/get-runtime-dependencies.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
get-runtime-dependencies
|
||||
------------------------
|
||||
|
||||
* The :command:`file` command learned a new sub-command,
|
||||
``GET_RUNTIME_DEPENDENCIES``, which allows you to recursively get the list of
|
||||
libraries linked by an executable or library. This sub-command is intended as
|
||||
a replacement for :module:`GetPrerequisites`.
|
||||
@@ -146,6 +146,28 @@ set(SRCS
|
||||
cmArgumentParser.cxx
|
||||
cmArgumentParser.h
|
||||
cmBase32.cxx
|
||||
cmBinUtilsLinker.cxx
|
||||
cmBinUtilsLinker.h
|
||||
cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
|
||||
cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
|
||||
cmBinUtilsLinuxELFLinker.cxx
|
||||
cmBinUtilsLinuxELFLinker.h
|
||||
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
|
||||
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
|
||||
cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
|
||||
cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
|
||||
cmBinUtilsMacOSMachOLinker.cxx
|
||||
cmBinUtilsMacOSMachOLinker.h
|
||||
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
|
||||
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
|
||||
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
|
||||
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h
|
||||
cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
|
||||
cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
|
||||
cmBinUtilsWindowsPELinker.cxx
|
||||
cmBinUtilsWindowsPELinker.h
|
||||
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
|
||||
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h
|
||||
cmCacheManager.cxx
|
||||
cmCacheManager.h
|
||||
cmCLocaleEnvironmentScope.h
|
||||
@@ -295,6 +317,10 @@ set(SRCS
|
||||
cmInstallTargetGenerator.cxx
|
||||
cmInstallDirectoryGenerator.h
|
||||
cmInstallDirectoryGenerator.cxx
|
||||
cmLDConfigLDConfigTool.cxx
|
||||
cmLDConfigLDConfigTool.h
|
||||
cmLDConfigTool.cxx
|
||||
cmLDConfigTool.h
|
||||
cmLinkedTree.h
|
||||
cmLinkItem.cxx
|
||||
cmLinkItem.h
|
||||
@@ -360,6 +386,8 @@ set(SRCS
|
||||
cmQtAutoRcc.h
|
||||
cmRST.cxx
|
||||
cmRST.h
|
||||
cmRuntimeDependencyArchive.cxx
|
||||
cmRuntimeDependencyArchive.h
|
||||
cmScriptGenerator.h
|
||||
cmScriptGenerator.cxx
|
||||
cmSourceFile.cxx
|
||||
|
||||
15
Source/cmBinUtilsLinker.cxx
Normal file
15
Source/cmBinUtilsLinker.cxx
Normal file
@@ -0,0 +1,15 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsLinker.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
|
||||
cmBinUtilsLinker::cmBinUtilsLinker(cmRuntimeDependencyArchive* archive)
|
||||
: Archive(archive)
|
||||
{
|
||||
}
|
||||
|
||||
void cmBinUtilsLinker::SetError(const std::string& e)
|
||||
{
|
||||
this->Archive->SetError(e);
|
||||
}
|
||||
30
Source/cmBinUtilsLinker.h
Normal file
30
Source/cmBinUtilsLinker.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsLinker_h
|
||||
#define cmBinUtilsLinker_h
|
||||
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsLinker
|
||||
{
|
||||
public:
|
||||
cmBinUtilsLinker(cmRuntimeDependencyArchive* archive);
|
||||
virtual ~cmBinUtilsLinker() = default;
|
||||
|
||||
virtual bool Prepare() { return true; }
|
||||
|
||||
virtual bool ScanDependencies(std::string const& file,
|
||||
cmStateEnums::TargetType type) = 0;
|
||||
|
||||
protected:
|
||||
cmRuntimeDependencyArchive* Archive;
|
||||
|
||||
void SetError(const std::string& e);
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsLinker_h
|
||||
18
Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
Normal file
18
Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
|
||||
cmBinUtilsLinuxELFGetRuntimeDependenciesTool::
|
||||
cmBinUtilsLinuxELFGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: Archive(archive)
|
||||
{
|
||||
}
|
||||
|
||||
void cmBinUtilsLinuxELFGetRuntimeDependenciesTool::SetError(
|
||||
const std::string& error)
|
||||
{
|
||||
this->Archive->SetError(error);
|
||||
}
|
||||
30
Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
Normal file
30
Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
|
||||
#define cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsLinuxELFGetRuntimeDependenciesTool
|
||||
{
|
||||
public:
|
||||
cmBinUtilsLinuxELFGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive);
|
||||
virtual ~cmBinUtilsLinuxELFGetRuntimeDependenciesTool() = default;
|
||||
|
||||
virtual bool GetFileInfo(std::string const& file,
|
||||
std::vector<std::string>& needed,
|
||||
std::vector<std::string>& rpaths,
|
||||
std::vector<std::string>& runpaths) = 0;
|
||||
|
||||
protected:
|
||||
cmRuntimeDependencyArchive* Archive;
|
||||
|
||||
void SetError(const std::string& e);
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h
|
||||
177
Source/cmBinUtilsLinuxELFLinker.cxx
Normal file
177
Source/cmBinUtilsLinuxELFLinker.cxx
Normal file
@@ -0,0 +1,177 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsLinuxELFLinker.h"
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
|
||||
#include "cmLDConfigLDConfigTool.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
static std::string ReplaceOrigin(const std::string& rpath,
|
||||
const std::string& origin)
|
||||
{
|
||||
static const cmsys::RegularExpression originRegex(
|
||||
"(\\$ORIGIN)([^a-zA-Z0-9_]|$)");
|
||||
static const cmsys::RegularExpression originCurlyRegex("\\${ORIGIN}");
|
||||
|
||||
cmsys::RegularExpressionMatch match;
|
||||
if (originRegex.find(rpath.c_str(), match)) {
|
||||
std::string begin = rpath.substr(0, match.start(1));
|
||||
std::string end = rpath.substr(match.end(1));
|
||||
return begin + origin + end;
|
||||
}
|
||||
if (originCurlyRegex.find(rpath.c_str(), match)) {
|
||||
std::string begin = rpath.substr(0, match.start());
|
||||
std::string end = rpath.substr(match.end());
|
||||
return begin + origin + end;
|
||||
}
|
||||
return rpath;
|
||||
}
|
||||
|
||||
cmBinUtilsLinuxELFLinker::cmBinUtilsLinuxELFLinker(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmBinUtilsLinker(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBinUtilsLinuxELFLinker::Prepare()
|
||||
{
|
||||
std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
|
||||
if (tool.empty()) {
|
||||
tool = "objdump";
|
||||
}
|
||||
if (tool == "objdump") {
|
||||
this->Tool =
|
||||
cm::make_unique<cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool>(
|
||||
this->Archive);
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string ldConfigTool =
|
||||
this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_TOOL");
|
||||
if (ldConfigTool.empty()) {
|
||||
ldConfigTool = "ldconfig";
|
||||
}
|
||||
if (ldConfigTool == "ldconfig") {
|
||||
this->LDConfigTool =
|
||||
cm::make_unique<cmLDConfigLDConfigTool>(this->Archive);
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "Invalid value for CMAKE_LDCONFIG_TOOL: " << ldConfigTool;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsLinuxELFLinker::ScanDependencies(
|
||||
std::string const& file, cmStateEnums::TargetType /* unused */)
|
||||
{
|
||||
std::vector<std::string> parentRpaths;
|
||||
return this->ScanDependencies(file, parentRpaths);
|
||||
}
|
||||
|
||||
bool cmBinUtilsLinuxELFLinker::ScanDependencies(
|
||||
std::string const& file, std::vector<std::string> const& parentRpaths)
|
||||
{
|
||||
std::string origin = cmSystemTools::GetFilenamePath(file);
|
||||
std::vector<std::string> needed;
|
||||
std::vector<std::string> rpaths;
|
||||
std::vector<std::string> runpaths;
|
||||
if (!this->Tool->GetFileInfo(file, needed, rpaths, runpaths)) {
|
||||
return false;
|
||||
}
|
||||
for (auto& runpath : runpaths) {
|
||||
runpath = ReplaceOrigin(runpath, origin);
|
||||
}
|
||||
for (auto& rpath : rpaths) {
|
||||
rpath = ReplaceOrigin(rpath, origin);
|
||||
}
|
||||
|
||||
std::vector<std::string> searchPaths;
|
||||
if (!runpaths.empty()) {
|
||||
searchPaths = runpaths;
|
||||
} else {
|
||||
searchPaths = rpaths;
|
||||
searchPaths.insert(searchPaths.end(), parentRpaths.begin(),
|
||||
parentRpaths.end());
|
||||
}
|
||||
|
||||
std::vector<std::string> ldConfigPaths;
|
||||
if (!this->LDConfigTool->GetLDConfigPaths(ldConfigPaths)) {
|
||||
return false;
|
||||
}
|
||||
searchPaths.insert(searchPaths.end(), ldConfigPaths.begin(),
|
||||
ldConfigPaths.end());
|
||||
|
||||
for (auto const& dep : needed) {
|
||||
if (!this->Archive->IsPreExcluded(dep)) {
|
||||
std::string path;
|
||||
bool resolved = false;
|
||||
if (dep.find('/') != std::string::npos) {
|
||||
this->SetError("Paths to dependencies are not supported");
|
||||
return false;
|
||||
}
|
||||
if (!this->ResolveDependency(dep, searchPaths, path, resolved)) {
|
||||
return false;
|
||||
}
|
||||
if (resolved) {
|
||||
if (!this->Archive->IsPostExcluded(path)) {
|
||||
bool unique;
|
||||
this->Archive->AddResolvedPath(dep, path, unique);
|
||||
if (unique && !this->ScanDependencies(path, rpaths)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->Archive->AddUnresolvedPath(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsLinuxELFLinker::ResolveDependency(
|
||||
std::string const& name, std::vector<std::string> const& searchPaths,
|
||||
std::string& path, bool& resolved)
|
||||
{
|
||||
for (auto const& searchPath : searchPaths) {
|
||||
path = searchPath + '/' + name;
|
||||
if (cmSystemTools::PathExists(path)) {
|
||||
resolved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& searchPath : this->Archive->GetSearchDirectories()) {
|
||||
path = searchPath + '/' + name;
|
||||
if (cmSystemTools::PathExists(path)) {
|
||||
std::ostringstream warning;
|
||||
warning << "Dependency " << name << " found in search directory:\n "
|
||||
<< searchPath
|
||||
<< "\nSee file(GET_RUNTIME_DEPENDENCIES) documentation for "
|
||||
<< "more information.";
|
||||
this->Archive->GetMakefile()->IssueMessage(MessageType::WARNING,
|
||||
warning.str());
|
||||
resolved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
resolved = false;
|
||||
return true;
|
||||
}
|
||||
44
Source/cmBinUtilsLinuxELFLinker.h
Normal file
44
Source/cmBinUtilsLinuxELFLinker.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsLinuxELFLinker_h
|
||||
#define cmBinUtilsLinuxELFLinker_h
|
||||
|
||||
#include "cmBinUtilsLinker.h"
|
||||
#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
|
||||
#include "cmLDConfigTool.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
#include <memory> // IWYU pragma: keep
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsLinuxELFLinker : public cmBinUtilsLinker
|
||||
{
|
||||
public:
|
||||
cmBinUtilsLinuxELFLinker(cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool Prepare() override;
|
||||
|
||||
bool ScanDependencies(std::string const& file,
|
||||
cmStateEnums::TargetType type) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cmBinUtilsLinuxELFGetRuntimeDependenciesTool> Tool;
|
||||
std::unique_ptr<cmLDConfigTool> LDConfigTool;
|
||||
bool HaveLDConfigPaths = false;
|
||||
std::vector<std::string> LDConfigPaths;
|
||||
|
||||
bool ScanDependencies(std::string const& file,
|
||||
std::vector<std::string> const& parentRpaths);
|
||||
|
||||
bool ResolveDependency(std::string const& name,
|
||||
std::vector<std::string> const& searchPaths,
|
||||
std::string& path, bool& resolved);
|
||||
|
||||
bool GetLDConfigPaths();
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsLinuxELFLinker_h
|
||||
@@ -0,0 +1,84 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::
|
||||
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmBinUtilsLinuxELFGetRuntimeDependenciesTool(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::GetFileInfo(
|
||||
std::string const& file, std::vector<std::string>& needed,
|
||||
std::vector<std::string>& rpaths, std::vector<std::string>& runpaths)
|
||||
{
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
|
||||
|
||||
std::vector<std::string> command;
|
||||
if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) {
|
||||
this->SetError("Could not find objdump");
|
||||
return false;
|
||||
}
|
||||
command.emplace_back("-p");
|
||||
command.push_back(file);
|
||||
builder.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start objdump process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
static const cmsys::RegularExpression neededRegex("^ *NEEDED *([^\n]*)$");
|
||||
static const cmsys::RegularExpression rpathRegex("^ *RPATH *([^\n]*)$");
|
||||
static const cmsys::RegularExpression runpathRegex("^ *RUNPATH *([^\n]*)$");
|
||||
while (std::getline(*process.OutputStream(), line)) {
|
||||
cmsys::RegularExpressionMatch match;
|
||||
if (neededRegex.find(line.c_str(), match)) {
|
||||
needed.push_back(match.match(1));
|
||||
} else if (rpathRegex.find(line.c_str(), match)) {
|
||||
std::vector<std::string> rpathSplit =
|
||||
cmSystemTools::SplitString(match.match(1), ':');
|
||||
rpaths.reserve(rpaths.size() + rpathSplit.size());
|
||||
for (auto const& rpath : rpathSplit) {
|
||||
rpaths.push_back(rpath);
|
||||
}
|
||||
} else if (runpathRegex.find(line.c_str(), match)) {
|
||||
std::vector<std::string> runpathSplit =
|
||||
cmSystemTools::SplitString(match.match(1), ':');
|
||||
runpaths.reserve(runpaths.size() + runpathSplit.size());
|
||||
for (auto const& runpath : runpathSplit) {
|
||||
runpaths.push_back(runpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!process.Wait()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to wait on objdump process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run objdump on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
26
Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
Normal file
26
Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h
|
||||
#define cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h
|
||||
|
||||
#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool
|
||||
: public cmBinUtilsLinuxELFGetRuntimeDependenciesTool
|
||||
{
|
||||
public:
|
||||
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool GetFileInfo(std::string const& file, std::vector<std::string>& needed,
|
||||
std::vector<std::string>& rpaths,
|
||||
std::vector<std::string>& runpaths) override;
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool_h
|
||||
19
Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
Normal file
19
Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx
Normal file
@@ -0,0 +1,19 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
|
||||
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
|
||||
cmBinUtilsMacOSMachOGetRuntimeDependenciesTool::
|
||||
cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: Archive(archive)
|
||||
{
|
||||
}
|
||||
|
||||
void cmBinUtilsMacOSMachOGetRuntimeDependenciesTool::SetError(
|
||||
const std::string& error)
|
||||
{
|
||||
this->Archive->SetError(error);
|
||||
}
|
||||
29
Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
Normal file
29
Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
|
||||
#define cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsMacOSMachOGetRuntimeDependenciesTool
|
||||
{
|
||||
public:
|
||||
cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive);
|
||||
virtual ~cmBinUtilsMacOSMachOGetRuntimeDependenciesTool() = default;
|
||||
|
||||
virtual bool GetFileInfo(std::string const& file,
|
||||
std::vector<std::string>& libs,
|
||||
std::vector<std::string>& rpaths) = 0;
|
||||
|
||||
protected:
|
||||
cmRuntimeDependencyArchive* Archive;
|
||||
|
||||
void SetError(const std::string& error);
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h
|
||||
228
Source/cmBinUtilsMacOSMachOLinker.cxx
Normal file
228
Source/cmBinUtilsMacOSMachOLinker.cxx
Normal file
@@ -0,0 +1,228 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsMacOSMachOLinker.h"
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
cmBinUtilsMacOSMachOLinker::cmBinUtilsMacOSMachOLinker(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmBinUtilsLinker(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::Prepare()
|
||||
{
|
||||
std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
|
||||
if (tool.empty()) {
|
||||
tool = "otool";
|
||||
}
|
||||
if (tool == "otool") {
|
||||
this->Tool =
|
||||
cm::make_unique<cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool>(
|
||||
this->Archive);
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
|
||||
std::string const& file, cmStateEnums::TargetType type)
|
||||
{
|
||||
std::string executableFile;
|
||||
if (type == cmStateEnums::EXECUTABLE) {
|
||||
executableFile = file;
|
||||
} else {
|
||||
executableFile = this->Archive->GetBundleExecutable();
|
||||
}
|
||||
std::string executablePath;
|
||||
if (!executableFile.empty()) {
|
||||
executablePath = cmSystemTools::GetFilenamePath(executableFile);
|
||||
}
|
||||
return this->ScanDependencies(file, executablePath);
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
|
||||
std::string const& file, std::string const& executablePath)
|
||||
{
|
||||
std::vector<std::string> libs, rpaths;
|
||||
if (!this->Tool->GetFileInfo(file, libs, rpaths)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string loaderPath = cmSystemTools::GetFilenamePath(file);
|
||||
return this->GetFileDependencies(libs, executablePath, loaderPath, rpaths);
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::GetFileDependencies(
|
||||
std::vector<std::string> const& names, std::string const& executablePath,
|
||||
std::string const& loaderPath, std::vector<std::string> const& rpaths)
|
||||
{
|
||||
for (std::string const& name : names) {
|
||||
if (!this->Archive->IsPreExcluded(name)) {
|
||||
std::string path;
|
||||
bool resolved;
|
||||
if (!this->ResolveDependency(name, executablePath, loaderPath, rpaths,
|
||||
path, resolved)) {
|
||||
return false;
|
||||
}
|
||||
if (resolved) {
|
||||
if (!this->Archive->IsPostExcluded(path)) {
|
||||
auto filename = cmSystemTools::GetFilenameName(path);
|
||||
bool unique;
|
||||
this->Archive->AddResolvedPath(filename, path, unique);
|
||||
if (unique && !this->ScanDependencies(path, executablePath)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->Archive->AddUnresolvedPath(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::ResolveDependency(
|
||||
std::string const& name, std::string const& executablePath,
|
||||
std::string const& loaderPath, std::vector<std::string> const& rpaths,
|
||||
std::string& path, bool& resolved)
|
||||
{
|
||||
resolved = false;
|
||||
if (cmHasLiteralPrefix(name, "@rpath/")) {
|
||||
if (!this->ResolveRPathDependency(name, executablePath, loaderPath, rpaths,
|
||||
path, resolved)) {
|
||||
return false;
|
||||
}
|
||||
} else if (cmHasLiteralPrefix(name, "@loader_path/")) {
|
||||
if (!this->ResolveLoaderPathDependency(name, loaderPath, path, resolved)) {
|
||||
return false;
|
||||
}
|
||||
} else if (cmHasLiteralPrefix(name, "@executable_path/")) {
|
||||
if (!this->ResolveExecutablePathDependency(name, executablePath, path,
|
||||
resolved)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
resolved = true;
|
||||
path = name;
|
||||
}
|
||||
|
||||
if (resolved && !cmSystemTools::FileIsFullPath(path)) {
|
||||
this->SetError("Resolved path is not absolute");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::ResolveExecutablePathDependency(
|
||||
std::string const& name, std::string const& executablePath,
|
||||
std::string& path, bool& resolved)
|
||||
{
|
||||
if (executablePath.empty()) {
|
||||
resolved = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 16 is == "@executable_path".length()
|
||||
path = name;
|
||||
path.replace(0, 16, executablePath);
|
||||
|
||||
if (!cmSystemTools::PathExists(path)) {
|
||||
resolved = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
resolved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::ResolveLoaderPathDependency(
|
||||
std::string const& name, std::string const& loaderPath, std::string& path,
|
||||
bool& resolved)
|
||||
{
|
||||
if (loaderPath.empty()) {
|
||||
resolved = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 12 is "@loader_path".length();
|
||||
path = name;
|
||||
path.replace(0, 12, loaderPath);
|
||||
|
||||
if (!cmSystemTools::PathExists(path)) {
|
||||
resolved = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
resolved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOLinker::ResolveRPathDependency(
|
||||
std::string const& name, std::string const& executablePath,
|
||||
std::string const& loaderPath, std::vector<std::string> const& rpaths,
|
||||
std::string& path, bool& resolved)
|
||||
{
|
||||
for (std::string const& rpath : rpaths) {
|
||||
std::string searchFile = name;
|
||||
searchFile.replace(0, 6, rpath);
|
||||
if (cmHasLiteralPrefix(searchFile, "@loader_path/")) {
|
||||
if (!this->ResolveLoaderPathDependency(searchFile, loaderPath, path,
|
||||
resolved)) {
|
||||
return false;
|
||||
}
|
||||
if (resolved) {
|
||||
return true;
|
||||
}
|
||||
} else if (cmHasLiteralPrefix(searchFile, "@executable_path/")) {
|
||||
if (!this->ResolveExecutablePathDependency(searchFile, executablePath,
|
||||
path, resolved)) {
|
||||
return false;
|
||||
}
|
||||
if (resolved) {
|
||||
return true;
|
||||
}
|
||||
} else if (cmSystemTools::PathExists(searchFile)) {
|
||||
/*
|
||||
* paraphrasing @ben.boeckel:
|
||||
* if /b/libB.dylib is supposed to be used,
|
||||
* /a/libbB.dylib will be found first if it exists. CMake tries to
|
||||
* sort rpath directories to avoid this, but sometimes there is no
|
||||
* right answer.
|
||||
*
|
||||
* I believe it is possible to resolve this using otools -l
|
||||
* then checking the LC_LOAD_DYLIB command whose name is
|
||||
* equal to the value of search_file, UNLESS the build
|
||||
* specifically sets the RPath to paths that will match
|
||||
* duplicate libs; at this point can we just point to
|
||||
* user error, or is there a reason why the advantages
|
||||
* to this scenario outweigh its disadvantages?
|
||||
*
|
||||
* Also priority seems to be the order as passed in when compiled
|
||||
* so as long as this method's resolution guarantees priority
|
||||
* in that manner further checking should not be necessary?
|
||||
*/
|
||||
path = searchFile;
|
||||
resolved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
resolved = false;
|
||||
return true;
|
||||
}
|
||||
59
Source/cmBinUtilsMacOSMachOLinker.h
Normal file
59
Source/cmBinUtilsMacOSMachOLinker.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsMacOSMachOLinker_h
|
||||
#define cmBinUtilsMacOSMachOLinker_h
|
||||
|
||||
#include "cmBinUtilsLinker.h"
|
||||
#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
#include <memory> // IWYU pragma: keep
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsMacOSMachOLinker : public cmBinUtilsLinker
|
||||
{
|
||||
public:
|
||||
cmBinUtilsMacOSMachOLinker(cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool Prepare() override;
|
||||
|
||||
bool ScanDependencies(std::string const& file,
|
||||
cmStateEnums::TargetType type) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool;
|
||||
|
||||
bool ScanDependencies(std::string const& file,
|
||||
std::string const& executablePath);
|
||||
|
||||
bool GetFileDependencies(std::vector<std::string> const& names,
|
||||
std::string const& executablePath,
|
||||
std::string const& loaderPath,
|
||||
std::vector<std::string> const& rpaths);
|
||||
|
||||
bool ResolveDependency(std::string const& name,
|
||||
std::string const& executablePath,
|
||||
std::string const& loaderPath,
|
||||
std::vector<std::string> const& rpaths,
|
||||
std::string& path, bool& resolved);
|
||||
|
||||
bool ResolveExecutablePathDependency(std::string const& name,
|
||||
std::string const& executablePath,
|
||||
std::string& path, bool& resolved);
|
||||
|
||||
bool ResolveLoaderPathDependency(std::string const& name,
|
||||
std::string const& loaderPath,
|
||||
std::string& path, bool& resolved);
|
||||
|
||||
bool ResolveRPathDependency(std::string const& name,
|
||||
std::string const& executablePath,
|
||||
std::string const& loaderPath,
|
||||
std::vector<std::string> const& rpaths,
|
||||
std::string& path, bool& resolved);
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsMacOSMachOLinker_h
|
||||
100
Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
Normal file
100
Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
Normal file
@@ -0,0 +1,100 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h"
|
||||
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::
|
||||
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
|
||||
std::string const& file, std::vector<std::string>& libs,
|
||||
std::vector<std::string>& rpaths)
|
||||
{
|
||||
std::vector<std::string> command;
|
||||
if (!this->Archive->GetGetRuntimeDependenciesCommand("otool", command)) {
|
||||
this->SetError("Could not find otool");
|
||||
return false;
|
||||
}
|
||||
command.emplace_back("-l");
|
||||
command.emplace_back(file);
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start otool process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
static const cmsys::RegularExpression rpathRegex("^ *cmd LC_RPATH$");
|
||||
static const cmsys::RegularExpression loadDylibRegex(
|
||||
"^ *cmd LC_LOAD_DYLIB$");
|
||||
static const cmsys::RegularExpression pathRegex(
|
||||
"^ *path (.*) \\(offset [0-9]+\\)$");
|
||||
static const cmsys::RegularExpression nameRegex(
|
||||
"^ *name (.*) \\(offset [0-9]+\\)$");
|
||||
while (std::getline(*process.OutputStream(), line)) {
|
||||
cmsys::RegularExpressionMatch cmdMatch;
|
||||
if (rpathRegex.find(line.c_str(), cmdMatch)) {
|
||||
if (!std::getline(*process.OutputStream(), line) ||
|
||||
!std::getline(*process.OutputStream(), line)) {
|
||||
this->SetError("Invalid output from otool");
|
||||
return false;
|
||||
}
|
||||
|
||||
cmsys::RegularExpressionMatch pathMatch;
|
||||
if (pathRegex.find(line.c_str(), pathMatch)) {
|
||||
rpaths.push_back(pathMatch.match(1));
|
||||
} else {
|
||||
this->SetError("Invalid output from otool");
|
||||
return false;
|
||||
}
|
||||
} else if (loadDylibRegex.find(line.c_str(), cmdMatch)) {
|
||||
if (!std::getline(*process.OutputStream(), line) ||
|
||||
!std::getline(*process.OutputStream(), line)) {
|
||||
this->SetError("Invalid output from otool");
|
||||
return false;
|
||||
}
|
||||
|
||||
cmsys::RegularExpressionMatch nameMatch;
|
||||
if (nameRegex.find(line.c_str(), nameMatch)) {
|
||||
libs.push_back(nameMatch.match(1));
|
||||
} else {
|
||||
this->SetError("Invalid output from otool");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!process.Wait()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to wait on otool process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run otool on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
25
Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
Normal file
25
Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
|
||||
#define cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
|
||||
|
||||
#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool
|
||||
: public cmBinUtilsMacOSMachOGetRuntimeDependenciesTool
|
||||
{
|
||||
public:
|
||||
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool GetFileInfo(std::string const& file, std::vector<std::string>& libs,
|
||||
std::vector<std::string>& rpaths) override;
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h
|
||||
@@ -0,0 +1,67 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::
|
||||
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::GetFileInfo(
|
||||
const std::string& file, std::vector<std::string>& needed)
|
||||
{
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
|
||||
|
||||
std::vector<std::string> command;
|
||||
if (!this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
|
||||
this->SetError("Could not find dumpbin");
|
||||
return false;
|
||||
}
|
||||
command.emplace_back("/dependents");
|
||||
command.push_back(file);
|
||||
builder.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start dumpbin process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
static const cmsys::RegularExpression regex(
|
||||
"^ ([^\n]*\\.[Dd][Ll][Ll])\r$");
|
||||
while (std::getline(*process.OutputStream(), line)) {
|
||||
cmsys::RegularExpressionMatch match;
|
||||
if (regex.find(line.c_str(), match)) {
|
||||
needed.push_back(match.match(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (!process.Wait()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to wait on dumpbin process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run dumpbin on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
|
||||
#define cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
|
||||
|
||||
#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool
|
||||
: public cmBinUtilsWindowsPEGetRuntimeDependenciesTool
|
||||
{
|
||||
public:
|
||||
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool GetFileInfo(const std::string& file,
|
||||
std::vector<std::string>& needed) override;
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h
|
||||
18
Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
Normal file
18
Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
|
||||
cmBinUtilsWindowsPEGetRuntimeDependenciesTool::
|
||||
cmBinUtilsWindowsPEGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: Archive(archive)
|
||||
{
|
||||
}
|
||||
|
||||
void cmBinUtilsWindowsPEGetRuntimeDependenciesTool::SetError(
|
||||
const std::string& error)
|
||||
{
|
||||
this->Archive->SetError(error);
|
||||
}
|
||||
28
Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
Normal file
28
Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
|
||||
#define cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsWindowsPEGetRuntimeDependenciesTool
|
||||
{
|
||||
public:
|
||||
cmBinUtilsWindowsPEGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive);
|
||||
virtual ~cmBinUtilsWindowsPEGetRuntimeDependenciesTool() = default;
|
||||
|
||||
virtual bool GetFileInfo(const std::string& file,
|
||||
std::vector<std::string>& needed) = 0;
|
||||
|
||||
protected:
|
||||
cmRuntimeDependencyArchive* Archive;
|
||||
|
||||
void SetError(const std::string& error);
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h
|
||||
121
Source/cmBinUtilsWindowsPELinker.cxx
Normal file
121
Source/cmBinUtilsWindowsPELinker.cxx
Normal file
@@ -0,0 +1,121 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsWindowsPELinker.h"
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
|
||||
#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmBinUtilsLinker(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBinUtilsWindowsPELinker::Prepare()
|
||||
{
|
||||
std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
|
||||
if (tool.empty()) {
|
||||
std::vector<std::string> command;
|
||||
if (this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
|
||||
tool = "dumpbin";
|
||||
} else {
|
||||
tool = "objdump";
|
||||
}
|
||||
}
|
||||
if (tool == "dumpbin") {
|
||||
this->Tool =
|
||||
cm::make_unique<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool>(
|
||||
this->Archive);
|
||||
} else if (tool == "objdump") {
|
||||
this->Tool =
|
||||
cm::make_unique<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool>(
|
||||
this->Archive);
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsWindowsPELinker::ScanDependencies(
|
||||
std::string const& file, cmStateEnums::TargetType /* unused */)
|
||||
{
|
||||
std::vector<std::string> needed;
|
||||
if (!this->Tool->GetFileInfo(file, needed)) {
|
||||
return false;
|
||||
}
|
||||
for (auto& n : needed) {
|
||||
n = cmSystemTools::LowerCase(n);
|
||||
}
|
||||
std::string origin = cmSystemTools::GetFilenamePath(file);
|
||||
|
||||
for (auto const& lib : needed) {
|
||||
if (!this->Archive->IsPreExcluded(lib)) {
|
||||
std::string path;
|
||||
bool resolved = false;
|
||||
if (!this->ResolveDependency(lib, origin, path, resolved)) {
|
||||
return false;
|
||||
}
|
||||
if (resolved) {
|
||||
if (!this->Archive->IsPostExcluded(path)) {
|
||||
bool unique;
|
||||
this->Archive->AddResolvedPath(lib, path, unique);
|
||||
if (unique &&
|
||||
!this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->Archive->AddUnresolvedPath(lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string const& name,
|
||||
std::string const& origin,
|
||||
std::string& path,
|
||||
bool& resolved)
|
||||
{
|
||||
auto dirs = this->Archive->GetSearchDirectories();
|
||||
|
||||
#ifdef _WIN32
|
||||
char buf[MAX_PATH];
|
||||
unsigned int len;
|
||||
if ((len = GetWindowsDirectoryA(buf, MAX_PATH)) > 0) {
|
||||
dirs.insert(dirs.begin(), std::string(buf, len));
|
||||
}
|
||||
if ((len = GetSystemDirectoryA(buf, MAX_PATH)) > 0) {
|
||||
dirs.insert(dirs.begin(), std::string(buf, len));
|
||||
}
|
||||
#endif
|
||||
|
||||
dirs.insert(dirs.begin(), origin);
|
||||
|
||||
for (auto const& searchPath : dirs) {
|
||||
path = searchPath + '/' + name;
|
||||
if (cmSystemTools::PathExists(path)) {
|
||||
resolved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
resolved = false;
|
||||
return true;
|
||||
}
|
||||
33
Source/cmBinUtilsWindowsPELinker.h
Normal file
33
Source/cmBinUtilsWindowsPELinker.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsWindowsPELinker_h
|
||||
#define cmBinUtilsWindowsPELinker_h
|
||||
|
||||
#include "cmBinUtilsLinker.h"
|
||||
#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
|
||||
#include "cmStateTypes.h"
|
||||
|
||||
#include <memory> // IWYU pragma: keep
|
||||
#include <string>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsWindowsPELinker : public cmBinUtilsLinker
|
||||
{
|
||||
public:
|
||||
cmBinUtilsWindowsPELinker(cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool Prepare() override;
|
||||
|
||||
bool ScanDependencies(std::string const& file,
|
||||
cmStateEnums::TargetType type) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cmBinUtilsWindowsPEGetRuntimeDependenciesTool> Tool;
|
||||
|
||||
bool ResolveDependency(std::string const& name, std::string const& origin,
|
||||
std::string& path, bool& resolved);
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsWindowsPELinker_h
|
||||
@@ -0,0 +1,67 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::
|
||||
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo(
|
||||
const std::string& file, std::vector<std::string>& needed)
|
||||
{
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT);
|
||||
|
||||
std::vector<std::string> command;
|
||||
if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) {
|
||||
this->SetError("Could not find objdump");
|
||||
return false;
|
||||
}
|
||||
command.emplace_back("-p");
|
||||
command.push_back(file);
|
||||
builder.AddCommand(command);
|
||||
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to start objdump process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
static const cmsys::RegularExpression regex(
|
||||
"^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])\r$");
|
||||
while (std::getline(*process.OutputStream(), line)) {
|
||||
cmsys::RegularExpressionMatch match;
|
||||
if (regex.find(line.c_str(), match)) {
|
||||
needed.push_back(match.match(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (!process.Wait()) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to wait on objdump process for:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
std::ostringstream e;
|
||||
e << "Failed to run objdump on:\n " << file;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
|
||||
#define cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
|
||||
|
||||
#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool
|
||||
: public cmBinUtilsWindowsPEGetRuntimeDependenciesTool
|
||||
{
|
||||
public:
|
||||
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool(
|
||||
cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool GetFileInfo(const std::string& file,
|
||||
std::vector<std::string>& needed) override;
|
||||
};
|
||||
|
||||
#endif // cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h
|
||||
@@ -12,7 +12,9 @@
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include <ctype.h>
|
||||
#include <map>
|
||||
#include <memory> // IWYU pragma: keep
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -34,6 +36,8 @@
|
||||
#include "cmMessageType.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmRange.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmState.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTimestamp.h"
|
||||
#include "cm_sys_stat.h"
|
||||
@@ -184,6 +188,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
|
||||
if (subCommand == "CREATE_LINK") {
|
||||
return this->HandleCreateLinkCommand(args);
|
||||
}
|
||||
if (subCommand == "GET_RUNTIME_DEPENDENCIES") {
|
||||
return this->HandleGetRuntimeDependenciesCommand(args);
|
||||
}
|
||||
|
||||
std::string e = "does not recognize sub-command " + subCommand;
|
||||
this->SetError(e);
|
||||
@@ -2690,3 +2697,171 @@ bool cmFileCommand::HandleCreateLinkCommand(
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmFileCommand::HandleGetRuntimeDependenciesCommand(
|
||||
std::vector<std::string> const& args)
|
||||
{
|
||||
static const std::set<std::string> supportedPlatforms = { "Windows", "Linux",
|
||||
"Darwin" };
|
||||
std::string platform =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
|
||||
if (!supportedPlatforms.count(platform)) {
|
||||
std::ostringstream e;
|
||||
e << "GET_RUNTIME_DEPENDENCIES is not supported on system \"" << platform
|
||||
<< "\"";
|
||||
this->SetError(e.str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->Makefile->GetState()->GetMode() == cmState::Project) {
|
||||
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING,
|
||||
"You have used file(GET_RUNTIME_DEPENDENCIES)"
|
||||
" in project mode. This is probably not what "
|
||||
"you intended to do. Instead, please consider"
|
||||
" using it in an install(CODE) or "
|
||||
"install(SCRIPT) command. For example:"
|
||||
"\n install(CODE [["
|
||||
"\n file(GET_RUNTIME_DEPENDENCIES"
|
||||
"\n # ..."
|
||||
"\n )"
|
||||
"\n ]])");
|
||||
}
|
||||
|
||||
struct Arguments
|
||||
{
|
||||
std::string ResolvedDependenciesVar;
|
||||
std::string UnresolvedDependenciesVar;
|
||||
std::string ConflictingDependenciesPrefix;
|
||||
std::string BundleExecutable;
|
||||
std::vector<std::string> Executables;
|
||||
std::vector<std::string> Libraries;
|
||||
std::vector<std::string> Directories;
|
||||
std::vector<std::string> Modules;
|
||||
std::vector<std::string> PreIncludeRegexes;
|
||||
std::vector<std::string> PreExcludeRegexes;
|
||||
std::vector<std::string> PostIncludeRegexes;
|
||||
std::vector<std::string> PostExcludeRegexes;
|
||||
};
|
||||
|
||||
static auto const parser =
|
||||
cmArgumentParser<Arguments>{}
|
||||
.Bind("RESOLVED_DEPENDENCIES_VAR"_s, &Arguments::ResolvedDependenciesVar)
|
||||
.Bind("UNRESOLVED_DEPENDENCIES_VAR"_s,
|
||||
&Arguments::UnresolvedDependenciesVar)
|
||||
.Bind("CONFLICTING_DEPENDENCIES_PREFIX"_s,
|
||||
&Arguments::ConflictingDependenciesPrefix)
|
||||
.Bind("BUNDLE_EXECUTABLE"_s, &Arguments::BundleExecutable)
|
||||
.Bind("EXECUTABLES"_s, &Arguments::Executables)
|
||||
.Bind("LIBRARIES"_s, &Arguments::Libraries)
|
||||
.Bind("MODULES"_s, &Arguments::Modules)
|
||||
.Bind("DIRECTORIES"_s, &Arguments::Directories)
|
||||
.Bind("PRE_INCLUDE_REGEXES"_s, &Arguments::PreIncludeRegexes)
|
||||
.Bind("PRE_EXCLUDE_REGEXES"_s, &Arguments::PreExcludeRegexes)
|
||||
.Bind("POST_INCLUDE_REGEXES"_s, &Arguments::PostIncludeRegexes)
|
||||
.Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes);
|
||||
|
||||
std::vector<std::string> unrecognizedArguments;
|
||||
std::vector<std::string> keywordsMissingValues;
|
||||
auto parsedArgs =
|
||||
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
|
||||
&keywordsMissingValues);
|
||||
auto argIt = unrecognizedArguments.begin();
|
||||
if (argIt != unrecognizedArguments.end()) {
|
||||
std::ostringstream e;
|
||||
e << "Unrecognized argument: \"" << *argIt << "\"";
|
||||
this->SetError(e.str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
argIt = keywordsMissingValues.begin();
|
||||
if (argIt != keywordsMissingValues.end()) {
|
||||
std::ostringstream e;
|
||||
e << "Keyword missing value: " << *argIt;
|
||||
this->SetError(e.str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
|
||||
cmRuntimeDependencyArchive archive(
|
||||
this, parsedArgs.Directories, parsedArgs.BundleExecutable,
|
||||
parsedArgs.PreIncludeRegexes, parsedArgs.PreExcludeRegexes,
|
||||
parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes);
|
||||
if (!archive.Prepare()) {
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!archive.GetRuntimeDependencies(
|
||||
parsedArgs.Executables, parsedArgs.Libraries, parsedArgs.Modules)) {
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> deps, unresolvedDeps, conflictingDeps;
|
||||
for (auto const& val : archive.GetResolvedPaths()) {
|
||||
bool unique = true;
|
||||
auto it = val.second.begin();
|
||||
assert(it != val.second.end());
|
||||
auto const& firstPath = *it;
|
||||
while (++it != val.second.end()) {
|
||||
if (!cmSystemTools::SameFile(firstPath, *it)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unique) {
|
||||
deps.push_back(firstPath);
|
||||
} else if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
|
||||
conflictingDeps.push_back(val.first);
|
||||
std::vector<std::string> paths;
|
||||
paths.insert(paths.begin(), val.second.begin(), val.second.end());
|
||||
std::string varName =
|
||||
parsedArgs.ConflictingDependenciesPrefix + "_" + val.first;
|
||||
std::string pathsStr = cmJoin(paths, ";");
|
||||
this->Makefile->AddDefinition(varName, pathsStr.c_str());
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "Multiple conflicting paths found for " << val.first << ":";
|
||||
for (auto const& path : val.second) {
|
||||
e << "\n " << path;
|
||||
}
|
||||
this->SetError(e.str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!archive.GetUnresolvedPaths().empty()) {
|
||||
if (!parsedArgs.UnresolvedDependenciesVar.empty()) {
|
||||
unresolvedDeps.insert(unresolvedDeps.begin(),
|
||||
archive.GetUnresolvedPaths().begin(),
|
||||
archive.GetUnresolvedPaths().end());
|
||||
} else {
|
||||
auto it = archive.GetUnresolvedPaths().begin();
|
||||
assert(it != archive.GetUnresolvedPaths().end());
|
||||
std::ostringstream e;
|
||||
e << "Could not resolve file " << *it;
|
||||
this->SetError(e.str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parsedArgs.ResolvedDependenciesVar.empty()) {
|
||||
std::string val = cmJoin(deps, ";");
|
||||
this->Makefile->AddDefinition(parsedArgs.ResolvedDependenciesVar,
|
||||
val.c_str());
|
||||
}
|
||||
if (!parsedArgs.UnresolvedDependenciesVar.empty()) {
|
||||
std::string val = cmJoin(unresolvedDeps, ";");
|
||||
this->Makefile->AddDefinition(parsedArgs.UnresolvedDependenciesVar,
|
||||
val.c_str());
|
||||
}
|
||||
if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
|
||||
std::string val = cmJoin(conflictingDeps, ";");
|
||||
this->Makefile->AddDefinition(
|
||||
parsedArgs.ConflictingDependenciesPrefix + "_FILENAMES", val.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ protected:
|
||||
bool HandleSizeCommand(std::vector<std::string> const& args);
|
||||
bool HandleReadSymlinkCommand(std::vector<std::string> const& args);
|
||||
bool HandleCreateLinkCommand(std::vector<std::string> const& args);
|
||||
bool HandleGetRuntimeDependenciesCommand(
|
||||
std::vector<std::string> const& args);
|
||||
|
||||
private:
|
||||
void AddEvaluationFile(const std::string& inputName,
|
||||
|
||||
70
Source/cmLDConfigLDConfigTool.cxx
Normal file
70
Source/cmLDConfigLDConfigTool.cxx
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmLDConfigLDConfigTool.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmUVProcessChain.h"
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include <istream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
cmLDConfigLDConfigTool::cmLDConfigLDConfigTool(
|
||||
cmRuntimeDependencyArchive* archive)
|
||||
: cmLDConfigTool(archive)
|
||||
{
|
||||
}
|
||||
|
||||
bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths)
|
||||
{
|
||||
std::string ldConfigPath =
|
||||
this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_COMMAND");
|
||||
if (ldConfigPath.empty()) {
|
||||
ldConfigPath = cmSystemTools::FindProgram(
|
||||
"ldconfig", { "/sbin", "/usr/sbin", "/usr/local/sbin" });
|
||||
if (ldConfigPath.empty()) {
|
||||
this->Archive->SetError("Could not find ldconfig");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> ldConfigCommand;
|
||||
cmSystemTools::ExpandListArgument(ldConfigPath, ldConfigCommand);
|
||||
ldConfigCommand.emplace_back("-v");
|
||||
ldConfigCommand.emplace_back("-N"); // Don't rebuild the cache.
|
||||
ldConfigCommand.emplace_back("-X"); // Don't update links.
|
||||
|
||||
cmUVProcessChainBuilder builder;
|
||||
builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT)
|
||||
.AddCommand(ldConfigCommand);
|
||||
auto process = builder.Start();
|
||||
if (!process.Valid()) {
|
||||
this->Archive->SetError("Failed to start ldconfig process");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
static const cmsys::RegularExpression regex("^([^\t:]*):");
|
||||
while (std::getline(*process.OutputStream(), line)) {
|
||||
cmsys::RegularExpressionMatch match;
|
||||
if (regex.find(line.c_str(), match)) {
|
||||
paths.push_back(match.match(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (!process.Wait()) {
|
||||
this->Archive->SetError("Failed to wait on ldconfig process");
|
||||
return false;
|
||||
}
|
||||
auto status = process.GetStatus();
|
||||
if (!status[0] || status[0]->ExitStatus != 0) {
|
||||
this->Archive->SetError("Failed to run ldconfig");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
22
Source/cmLDConfigLDConfigTool.h
Normal file
22
Source/cmLDConfigLDConfigTool.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmLDConfigLDConfigTool_h
|
||||
#define cmLDConfigLDConfigTool_h
|
||||
|
||||
#include "cmLDConfigTool.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmLDConfigLDConfigTool : public cmLDConfigTool
|
||||
{
|
||||
public:
|
||||
cmLDConfigLDConfigTool(cmRuntimeDependencyArchive* archive);
|
||||
|
||||
bool GetLDConfigPaths(std::vector<std::string>& paths) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
9
Source/cmLDConfigTool.cxx
Normal file
9
Source/cmLDConfigTool.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmLDConfigTool.h"
|
||||
|
||||
cmLDConfigTool::cmLDConfigTool(cmRuntimeDependencyArchive* archive)
|
||||
: Archive(archive)
|
||||
{
|
||||
}
|
||||
24
Source/cmLDConfigTool.h
Normal file
24
Source/cmLDConfigTool.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmLDConfigTool_h
|
||||
#define cmLDConfigTool_h
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmRuntimeDependencyArchive;
|
||||
|
||||
class cmLDConfigTool
|
||||
{
|
||||
public:
|
||||
cmLDConfigTool(cmRuntimeDependencyArchive* archive);
|
||||
virtual ~cmLDConfigTool() = default;
|
||||
|
||||
virtual bool GetLDConfigPaths(std::vector<std::string>& paths) = 0;
|
||||
|
||||
protected:
|
||||
cmRuntimeDependencyArchive* Archive;
|
||||
};
|
||||
|
||||
#endif
|
||||
378
Source/cmRuntimeDependencyArchive.cxx
Normal file
378
Source/cmRuntimeDependencyArchive.cxx
Normal file
@@ -0,0 +1,378 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
|
||||
#include "cmAlgorithms.h"
|
||||
#include "cmBinUtilsLinuxELFLinker.h"
|
||||
#include "cmBinUtilsMacOSMachOLinker.h"
|
||||
#include "cmBinUtilsWindowsPELinker.h"
|
||||
#include "cmCommand.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include "cmGlobalGenerator.h"
|
||||
# ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
# include "cmGlobalVisualStudioVersionedGenerator.h"
|
||||
# endif
|
||||
# include "cmVSSetupHelper.h"
|
||||
# include "cmsys/Glob.hxx"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#if defined(_WIN32)
|
||||
static void AddVisualStudioPath(std::vector<std::string>& paths,
|
||||
const std::string& prefix,
|
||||
unsigned int version, cmGlobalGenerator* gg)
|
||||
{
|
||||
// If generating for the VS IDE, use the same instance.
|
||||
std::string vsloc;
|
||||
bool found = false;
|
||||
# ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
if (gg->GetName().find(prefix) == 0) {
|
||||
cmGlobalVisualStudioVersionedGenerator* vsgen =
|
||||
static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
|
||||
if (vsgen->GetVSInstance(vsloc)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
// Otherwise, find a VS instance ourselves.
|
||||
if (!found) {
|
||||
cmVSSetupAPIHelper vsSetupAPIHelper(version);
|
||||
if (vsSetupAPIHelper.GetVSInstanceInfo(vsloc)) {
|
||||
cmSystemTools::ConvertToUnixSlashes(vsloc);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
cmsys::Glob glob;
|
||||
glob.SetListDirs(true);
|
||||
glob.FindFiles(vsloc + "/VC/Tools/MSVC/*");
|
||||
for (auto const& vcdir : glob.GetFiles()) {
|
||||
paths.push_back(vcdir + "/bin/Hostx64/x64");
|
||||
paths.push_back(vcdir + "/bin/Hostx86/x64");
|
||||
paths.push_back(vcdir + "/bin/Hostx64/x86");
|
||||
paths.push_back(vcdir + "/bin/Hostx86/x86");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AddRegistryPath(std::vector<std::string>& paths,
|
||||
const std::string& path, cmMakefile* mf)
|
||||
{
|
||||
// We should view the registry as the target application would view
|
||||
// it.
|
||||
cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32;
|
||||
cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64;
|
||||
if (mf->PlatformIs64Bit()) {
|
||||
view = cmSystemTools::KeyWOW64_64;
|
||||
other_view = cmSystemTools::KeyWOW64_32;
|
||||
}
|
||||
|
||||
// Expand using the view of the target application.
|
||||
std::string expanded = path;
|
||||
cmSystemTools::ExpandRegistryValues(expanded, view);
|
||||
cmSystemTools::GlobDirs(expanded, paths);
|
||||
|
||||
// Executables can be either 32-bit or 64-bit, so expand using the
|
||||
// alternative view.
|
||||
expanded = path;
|
||||
cmSystemTools::ExpandRegistryValues(expanded, other_view);
|
||||
cmSystemTools::GlobDirs(expanded, paths);
|
||||
}
|
||||
|
||||
static void AddEnvPath(std::vector<std::string>& paths, const std::string& var,
|
||||
const std::string& suffix)
|
||||
{
|
||||
std::string value;
|
||||
if (cmSystemTools::GetEnv(var, value)) {
|
||||
paths.push_back(value + suffix);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static cmsys::RegularExpression TransformCompile(const std::string& str)
|
||||
{
|
||||
return cmsys::RegularExpression(str);
|
||||
}
|
||||
|
||||
cmRuntimeDependencyArchive::cmRuntimeDependencyArchive(
|
||||
cmCommand* command, std::vector<std::string> searchDirectories,
|
||||
std::string bundleExecutable,
|
||||
const std::vector<std::string>& preIncludeRegexes,
|
||||
const std::vector<std::string>& preExcludeRegexes,
|
||||
const std::vector<std::string>& postIncludeRegexes,
|
||||
const std::vector<std::string>& postExcludeRegexes)
|
||||
: Command(command)
|
||||
, SearchDirectories(std::move(searchDirectories))
|
||||
, BundleExecutable(std::move(bundleExecutable))
|
||||
, PreIncludeRegexes(preIncludeRegexes.size())
|
||||
, PreExcludeRegexes(preExcludeRegexes.size())
|
||||
, PostIncludeRegexes(postIncludeRegexes.size())
|
||||
, PostExcludeRegexes(postExcludeRegexes.size())
|
||||
{
|
||||
std::transform(preIncludeRegexes.begin(), preIncludeRegexes.end(),
|
||||
this->PreIncludeRegexes.begin(), TransformCompile);
|
||||
std::transform(preExcludeRegexes.begin(), preExcludeRegexes.end(),
|
||||
this->PreExcludeRegexes.begin(), TransformCompile);
|
||||
std::transform(postIncludeRegexes.begin(), postIncludeRegexes.end(),
|
||||
this->PostIncludeRegexes.begin(), TransformCompile);
|
||||
std::transform(postExcludeRegexes.begin(), postExcludeRegexes.end(),
|
||||
this->PostExcludeRegexes.begin(), TransformCompile);
|
||||
}
|
||||
|
||||
bool cmRuntimeDependencyArchive::Prepare()
|
||||
{
|
||||
std::string platform = this->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM");
|
||||
if (platform.empty()) {
|
||||
std::string systemName =
|
||||
this->GetMakefile()->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
|
||||
if (systemName == "Windows") {
|
||||
platform = "windows+pe";
|
||||
} else if (systemName == "Darwin") {
|
||||
platform = "macos+macho";
|
||||
} else if (systemName == "Linux") {
|
||||
platform = "linux+elf";
|
||||
}
|
||||
}
|
||||
if (platform == "linux+elf") {
|
||||
this->Linker = cm::make_unique<cmBinUtilsLinuxELFLinker>(this);
|
||||
} else if (platform == "windows+pe") {
|
||||
this->Linker = cm::make_unique<cmBinUtilsWindowsPELinker>(this);
|
||||
} else if (platform == "macos+macho") {
|
||||
this->Linker = cm::make_unique<cmBinUtilsMacOSMachOLinker>(this);
|
||||
} else {
|
||||
std::ostringstream e;
|
||||
e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM: "
|
||||
<< platform;
|
||||
this->SetError(e.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->Linker->Prepare();
|
||||
}
|
||||
|
||||
bool cmRuntimeDependencyArchive::GetRuntimeDependencies(
|
||||
const std::vector<std::string>& executables,
|
||||
const std::vector<std::string>& libraries,
|
||||
const std::vector<std::string>& modules)
|
||||
{
|
||||
for (auto const& exe : executables) {
|
||||
if (!this->Linker->ScanDependencies(exe, cmStateEnums::EXECUTABLE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto const& lib : libraries) {
|
||||
if (!this->Linker->ScanDependencies(lib, cmStateEnums::SHARED_LIBRARY)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto const& mod : modules) {
|
||||
if (!this->Linker->ScanDependencies(mod, cmStateEnums::MODULE_LIBRARY)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmRuntimeDependencyArchive::SetError(const std::string& e)
|
||||
{
|
||||
this->Command->SetError(e);
|
||||
}
|
||||
|
||||
std::string cmRuntimeDependencyArchive::GetBundleExecutable()
|
||||
{
|
||||
return this->BundleExecutable;
|
||||
}
|
||||
|
||||
const std::vector<std::string>&
|
||||
cmRuntimeDependencyArchive::GetSearchDirectories()
|
||||
{
|
||||
return this->SearchDirectories;
|
||||
}
|
||||
|
||||
std::string cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool()
|
||||
{
|
||||
return this->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL");
|
||||
}
|
||||
|
||||
bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
|
||||
const std::string& search, std::vector<std::string>& command)
|
||||
{
|
||||
// First see if it was supplied by the user
|
||||
std::string toolCommand = this->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND");
|
||||
if (!toolCommand.empty()) {
|
||||
cmSystemTools::ExpandListArgument(toolCommand, command);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now go searching for it
|
||||
std::vector<std::string> paths;
|
||||
#ifdef _WIN32
|
||||
cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator();
|
||||
|
||||
// Add newer Visual Studio paths
|
||||
AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg);
|
||||
AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg);
|
||||
|
||||
// Add older Visual Studio paths
|
||||
AddRegistryPath(
|
||||
paths,
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0;InstallDir]/"
|
||||
"../../VC/bin",
|
||||
this->GetMakefile());
|
||||
AddEnvPath(paths, "VS140COMNTOOLS", "/../../VC/bin");
|
||||
paths.push_back(
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin");
|
||||
AddRegistryPath(
|
||||
paths,
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0;InstallDir]/"
|
||||
"../../VC/bin",
|
||||
this->GetMakefile());
|
||||
AddEnvPath(paths, "VS120COMNTOOLS", "/../../VC/bin");
|
||||
paths.push_back(
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin");
|
||||
AddRegistryPath(
|
||||
paths,
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0;InstallDir]/"
|
||||
"../../VC/bin",
|
||||
this->GetMakefile());
|
||||
AddEnvPath(paths, "VS110COMNTOOLS", "/../../VC/bin");
|
||||
paths.push_back(
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin");
|
||||
AddRegistryPath(
|
||||
paths,
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0;InstallDir]/"
|
||||
"../../VC/bin",
|
||||
this->GetMakefile());
|
||||
AddEnvPath(paths, "VS100COMNTOOLS", "/../../VC/bin");
|
||||
paths.push_back(
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin");
|
||||
AddRegistryPath(
|
||||
paths,
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]/"
|
||||
"../../VC/bin",
|
||||
this->GetMakefile());
|
||||
AddEnvPath(paths, "VS90COMNTOOLS", "/../../VC/bin");
|
||||
paths.push_back("C:/Program Files/Microsoft Visual Studio 9.0/VC/bin");
|
||||
paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin");
|
||||
AddRegistryPath(
|
||||
paths,
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]/"
|
||||
"../../VC/bin",
|
||||
this->GetMakefile());
|
||||
AddEnvPath(paths, "VS80COMNTOOLS", "/../../VC/bin");
|
||||
paths.push_back("C:/Program Files/Microsoft Visual Studio 8/VC/BIN");
|
||||
paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN");
|
||||
AddRegistryPath(
|
||||
paths,
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1;InstallDir]/"
|
||||
"../../VC7/bin",
|
||||
this->GetMakefile());
|
||||
AddEnvPath(paths, "VS71COMNTOOLS", "/../../VC7/bin");
|
||||
paths.push_back(
|
||||
"C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN");
|
||||
paths.push_back(
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN");
|
||||
#endif
|
||||
|
||||
std::string program = cmSystemTools::FindProgram(search, paths);
|
||||
if (!program.empty()) {
|
||||
command = { program };
|
||||
return true;
|
||||
}
|
||||
|
||||
// Couldn't find it
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name)
|
||||
{
|
||||
cmsys::RegularExpressionMatch match;
|
||||
|
||||
for (auto const& regex : this->PreIncludeRegexes) {
|
||||
if (regex.find(name.c_str(), match)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& regex : this->PreExcludeRegexes) {
|
||||
if (regex.find(name.c_str(), match)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name)
|
||||
{
|
||||
cmsys::RegularExpressionMatch match;
|
||||
|
||||
for (auto const& regex : this->PostIncludeRegexes) {
|
||||
if (regex.find(name.c_str(), match)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& regex : this->PostExcludeRegexes) {
|
||||
if (regex.find(name.c_str(), match)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name,
|
||||
const std::string& path,
|
||||
bool& unique)
|
||||
{
|
||||
auto it =
|
||||
this->ResolvedPaths
|
||||
.insert(std::pair<std::string, std::set<std::string>>{ name, {} })
|
||||
.first;
|
||||
unique = true;
|
||||
for (auto const& other : it->second) {
|
||||
if (cmSystemTools::SameFile(path, other)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
it->second.insert(path);
|
||||
}
|
||||
|
||||
void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name)
|
||||
{
|
||||
this->UnresolvedPaths.insert(name);
|
||||
}
|
||||
|
||||
cmMakefile* cmRuntimeDependencyArchive::GetMakefile()
|
||||
{
|
||||
return this->Command->GetMakefile();
|
||||
}
|
||||
|
||||
const std::map<std::string, std::set<std::string>>&
|
||||
cmRuntimeDependencyArchive::GetResolvedPaths()
|
||||
{
|
||||
return this->ResolvedPaths;
|
||||
}
|
||||
|
||||
const std::set<std::string>& cmRuntimeDependencyArchive::GetUnresolvedPaths()
|
||||
{
|
||||
return this->UnresolvedPaths;
|
||||
}
|
||||
70
Source/cmRuntimeDependencyArchive.h
Normal file
70
Source/cmRuntimeDependencyArchive.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#ifndef cmRuntimeDependencyArchive_h
|
||||
#define cmRuntimeDependencyArchive_h
|
||||
|
||||
#include "cmBinUtilsLinker.h"
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include <map>
|
||||
#include <memory> // IWYU pragma: keep
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class cmCommand;
|
||||
class cmMakefile;
|
||||
|
||||
class cmRuntimeDependencyArchive
|
||||
{
|
||||
public:
|
||||
explicit cmRuntimeDependencyArchive(
|
||||
cmCommand* command, std::vector<std::string> searchDirectories,
|
||||
std::string bundleExecutable,
|
||||
const std::vector<std::string>& preIncludeRegexes,
|
||||
const std::vector<std::string>& preExcludeRegexes,
|
||||
const std::vector<std::string>& postIncludeRegexes,
|
||||
const std::vector<std::string>& postExcludeRegexes);
|
||||
bool Prepare();
|
||||
bool GetRuntimeDependencies(const std::vector<std::string>& executables,
|
||||
const std::vector<std::string>& libraries,
|
||||
const std::vector<std::string>& modules);
|
||||
|
||||
void SetError(const std::string& e);
|
||||
|
||||
std::string GetBundleExecutable();
|
||||
const std::vector<std::string>& GetSearchDirectories();
|
||||
std::string GetGetRuntimeDependenciesTool();
|
||||
bool GetGetRuntimeDependenciesCommand(const std::string& search,
|
||||
std::vector<std::string>& command);
|
||||
bool IsPreExcluded(const std::string& name);
|
||||
bool IsPostExcluded(const std::string& name);
|
||||
|
||||
void AddResolvedPath(const std::string& name, const std::string& path,
|
||||
bool& unique);
|
||||
void AddUnresolvedPath(const std::string& name);
|
||||
|
||||
cmMakefile* GetMakefile();
|
||||
const std::map<std::string, std::set<std::string>>& GetResolvedPaths();
|
||||
const std::set<std::string>& GetUnresolvedPaths();
|
||||
|
||||
private:
|
||||
cmCommand* Command;
|
||||
std::unique_ptr<cmBinUtilsLinker> Linker;
|
||||
|
||||
std::string GetRuntimeDependenciesTool;
|
||||
std::vector<std::string> GetRuntimeDependenciesCommand;
|
||||
|
||||
std::vector<std::string> SearchDirectories;
|
||||
std::string BundleExecutable;
|
||||
std::vector<cmsys::RegularExpression> PreIncludeRegexes;
|
||||
std::vector<cmsys::RegularExpression> PreExcludeRegexes;
|
||||
std::vector<cmsys::RegularExpression> PostIncludeRegexes;
|
||||
std::vector<cmsys::RegularExpression> PostExcludeRegexes;
|
||||
std::map<std::string, std::set<std::string>> ResolvedPaths;
|
||||
std::set<std::string> UnresolvedPaths;
|
||||
};
|
||||
|
||||
#endif // cmRuntimeDependencyArchive_h
|
||||
@@ -408,7 +408,7 @@ else()
|
||||
set(NO_NAMELINK 0)
|
||||
endif()
|
||||
|
||||
add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN})
|
||||
add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
|
||||
add_RunCMake_test(CPackCommandLine)
|
||||
add_RunCMake_test(CPackConfig)
|
||||
add_RunCMake_test(CPackInstallProperties)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
if(RunCMake_TEST MATCHES "^file-GET_RUNTIME_DEPENDENCIES")
|
||||
cmake_policy(SET CMP0087 NEW)
|
||||
endif()
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
|
||||
@@ -139,6 +139,36 @@ run_install_test(FILES-PERMISSIONS)
|
||||
run_install_test(TARGETS-RPATH)
|
||||
run_install_test(InstallRequiredSystemLibraries)
|
||||
|
||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-unresolved)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-conflict)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-notfile)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-project)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2)
|
||||
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-unresolved)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-conflict)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-notfile)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-project)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2)
|
||||
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||
if(NOT CMAKE_C_COMPILER_ID MATCHES "^XL")
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux)
|
||||
endif()
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-unresolved)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-conflict)
|
||||
run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-notfile)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-project)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1)
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2)
|
||||
else()
|
||||
run_cmake(file-GET_RUNTIME_DEPENDENCIES-unsupported)
|
||||
endif()
|
||||
|
||||
set(run_install_test_components 1)
|
||||
run_install_test(FILES-EXCLUDE_FROM_ALL)
|
||||
run_install_test(TARGETS-EXCLUDE_FROM_ALL)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,18 @@
|
||||
^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-badargs1\.cmake:[0-9]+ \(file\):
|
||||
You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\. This is
|
||||
probably not what you intended to do\. Instead, please consider using it in
|
||||
an install\(CODE\) or install\(SCRIPT\) command\. For example:
|
||||
|
||||
install\(CODE \[\[
|
||||
file\(GET_RUNTIME_DEPENDENCIES
|
||||
# \.\.\.
|
||||
\)
|
||||
]]\)
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-dev to suppress it\.
|
||||
|
||||
CMake Error at file-GET_RUNTIME_DEPENDENCIES-badargs1\.cmake:[0-9]+ \(file\):
|
||||
file Unrecognized argument: "invalid"
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -0,0 +1,2 @@
|
||||
file(GET_RUNTIME_DEPENDENCIES invalid)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,18 @@
|
||||
^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-badargs2\.cmake:[0-9]+ \(file\):
|
||||
You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\. This is
|
||||
probably not what you intended to do\. Instead, please consider using it in
|
||||
an install\(CODE\) or install\(SCRIPT\) command\. For example:
|
||||
|
||||
install\(CODE \[\[
|
||||
file\(GET_RUNTIME_DEPENDENCIES
|
||||
# \.\.\.
|
||||
\)
|
||||
]]\)
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-dev to suppress it\.
|
||||
|
||||
CMake Error at file-GET_RUNTIME_DEPENDENCIES-badargs2\.cmake:[0-9]+ \(file\):
|
||||
file Keyword missing value: BUNDLE_EXECUTABLE
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -0,0 +1,2 @@
|
||||
file(GET_RUNTIME_DEPENDENCIES BUNDLE_EXECUTABLE)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
@@ -0,0 +1,44 @@
|
||||
function(check_contents filename contents_regex)
|
||||
if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
|
||||
file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
|
||||
if(NOT contents MATCHES "${contents_regex}")
|
||||
string(APPEND RunCMake_TEST_FAILED "File contents:
|
||||
${contents}
|
||||
do not match what we expected:
|
||||
${contents_regex}
|
||||
in file:
|
||||
${CMAKE_INSTALL_PREFIX}/${filename}\n")
|
||||
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
|
||||
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(_check
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/libtest_rpath\.so]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/libtest_runpath\.so]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath/librpath\.so]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_parent/librpath_parent\.so]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search/librpath_search\.so]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath/librunpath\.so]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search/librunpath_search\.so]]
|
||||
)
|
||||
check_contents(deps/deps1.txt "^${_check}$")
|
||||
check_contents(deps/deps2.txt "^${_check}$")
|
||||
check_contents(deps/deps3.txt "^${_check}$")
|
||||
set(_check
|
||||
[[librpath_unresolved\.so]]
|
||||
[[librunpath_parent_unresolved\.so]]
|
||||
[[librunpath_unresolved\.so]]
|
||||
)
|
||||
check_contents(deps/udeps1.txt "^${_check}$")
|
||||
check_contents(deps/udeps2.txt "^${_check}$")
|
||||
check_contents(deps/udeps3.txt "^${_check}$")
|
||||
set(_check
|
||||
"^libconflict\\.so:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/conflict/libconflict\\.so;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/conflict2/libconflict\\.so\n$"
|
||||
)
|
||||
check_contents(deps/cdeps1.txt "${_check}")
|
||||
check_contents(deps/cdeps2.txt "${_check}")
|
||||
check_contents(deps/cdeps3.txt "${_check}")
|
||||
@@ -0,0 +1,119 @@
|
||||
^CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librpath_search_postexcluded\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librpath_search\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librunpath_search_postexcluded\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librunpath_search\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librpath_search_postexcluded\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librpath_search\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librunpath_search_postexcluded\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librunpath_search\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librpath_search_postexcluded\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librpath_search\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librunpath_search_postexcluded\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)
|
||||
|
||||
*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
Dependency librunpath_search\.so found in search directory:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search
|
||||
|
||||
See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\.
|
||||
Call Stack \(most recent call first\):
|
||||
cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)$
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,7 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Multiple conflicting paths found for librpath\.so:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-build/root-all/lib/rpath1/librpath\.so
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-build/root-all/lib/rpath2/librpath\.so$
|
||||
@@ -0,0 +1,54 @@
|
||||
enable_language(C)
|
||||
|
||||
set(test1_names rpath)
|
||||
set(test2_names rpath)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/rpath.c" "void rpath(void) {}\n")
|
||||
add_library(rpath SHARED "${CMAKE_BINARY_DIR}/rpath.c")
|
||||
install(TARGETS rpath DESTINATION lib/rpath1)
|
||||
install(TARGETS rpath DESTINATION lib/rpath2)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test1.c")
|
||||
add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c")
|
||||
foreach(name ${test1_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "void test1(void)\n{\n")
|
||||
foreach(name ${test1_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n")
|
||||
|
||||
target_link_libraries(test1 PRIVATE ${test1_names})
|
||||
set_property(TARGET test1 PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath1"
|
||||
)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test2.c")
|
||||
add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c")
|
||||
foreach(name ${test2_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "void test2(void)\n{\n")
|
||||
foreach(name ${test2_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n")
|
||||
|
||||
target_link_libraries(test2 PRIVATE ${test2_names})
|
||||
set_property(TARGET test2 PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath2"
|
||||
)
|
||||
|
||||
install(TARGETS test1 test2 DESTINATION lib)
|
||||
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test1>"
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test2>"
|
||||
PRE_INCLUDE_REGEXES "^librpath\\.so$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Failed to run objdump on:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-build/root-all/bin/\.\./lib/libtest\.so$
|
||||
@@ -0,0 +1,29 @@
|
||||
enable_language(C)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
]])
|
||||
|
||||
add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c")
|
||||
add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
|
||||
target_link_libraries(exe PRIVATE test)
|
||||
set_property(TARGET exe PROPERTY INSTALL_RPATH "\\\${ORIGIN}/../lib")
|
||||
|
||||
install(TARGETS exe DESTINATION bin)
|
||||
|
||||
install(CODE [[
|
||||
file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>")
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
EXECUTABLES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
|
||||
PRE_INCLUDE_REGEXES "^libtest\\.so$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Could not resolve file libunresolved\.so$
|
||||
@@ -0,0 +1,18 @@
|
||||
enable_language(C)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "extern void unresolved(void);\nvoid testlib(void)\n{\n unresolved();\n}\n")
|
||||
add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "void unresolved(void) {}\n")
|
||||
add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c")
|
||||
target_link_libraries(testlib PRIVATE unresolved)
|
||||
install(TARGETS testlib DESTINATION lib)
|
||||
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
PRE_INCLUDE_REGEXES "^libunresolved\\.so$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
168
Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake
Normal file
168
Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake
Normal file
@@ -0,0 +1,168 @@
|
||||
enable_language(C)
|
||||
|
||||
set(test_rpath_names
|
||||
preexcluded
|
||||
rpath_postexcluded
|
||||
rpath
|
||||
rpath_parent_postexcluded
|
||||
rpath_parent
|
||||
rpath_origin_postexcluded
|
||||
rpath_origin
|
||||
rpath_search_postexcluded
|
||||
rpath_search
|
||||
rpath_unresolved
|
||||
conflict
|
||||
)
|
||||
set(test_runpath_names
|
||||
runpath_postexcluded
|
||||
runpath
|
||||
runpath_origin_postexcluded
|
||||
runpath_origin
|
||||
runpath_parent_unresolved
|
||||
runpath_search_postexcluded
|
||||
runpath_search
|
||||
runpath_unresolved
|
||||
)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test_rpath.c")
|
||||
add_library(test_rpath SHARED "${CMAKE_BINARY_DIR}/test_rpath.c")
|
||||
foreach(name ${test_rpath_names})
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n")
|
||||
add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
|
||||
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "void test_rpath(void)\n{\n")
|
||||
foreach(name ${test_rpath_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "}\n")
|
||||
|
||||
install(TARGETS rpath_postexcluded DESTINATION lib/rpath_postexcluded)
|
||||
install(TARGETS rpath DESTINATION lib/rpath)
|
||||
install(TARGETS rpath_origin_postexcluded DESTINATION lib/rpath_origin_postexcluded)
|
||||
install(TARGETS rpath_origin DESTINATION lib/rpath_origin)
|
||||
install(TARGETS rpath_parent_postexcluded DESTINATION lib/rpath_parent_postexcluded)
|
||||
install(TARGETS rpath rpath_origin rpath_parent DESTINATION lib/rpath_parent)
|
||||
install(TARGETS rpath_search_postexcluded DESTINATION lib/rpath_search_postexcluded)
|
||||
install(TARGETS rpath rpath_origin rpath_parent rpath_search DESTINATION lib/rpath_search)
|
||||
install(TARGETS conflict DESTINATION lib/conflict)
|
||||
|
||||
target_link_libraries(test_rpath PRIVATE ${test_rpath_names})
|
||||
set_property(TARGET test_rpath PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath_postexcluded"
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath"
|
||||
"\\\$ORIGIN/rpath_origin_postexcluded"
|
||||
"\\\${ORIGIN}/rpath_origin" # This must be double-escaped because of issue #19225.
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/conflict"
|
||||
)
|
||||
target_link_options(test_rpath PRIVATE -Wl,--disable-new-dtags)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test_runpath.c")
|
||||
add_library(test_runpath SHARED "${CMAKE_BINARY_DIR}/test_runpath.c")
|
||||
foreach(name ${test_runpath_names} rpath conflict)
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n")
|
||||
if(NOT name MATCHES "^(rpath|conflict)$")
|
||||
add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
|
||||
endif()
|
||||
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "void test_runpath(void)\n{\n")
|
||||
foreach(name ${test_runpath_names} rpath conflict)
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "}\n")
|
||||
|
||||
install(TARGETS runpath_postexcluded DESTINATION lib/runpath_postexcluded)
|
||||
install(TARGETS runpath DESTINATION lib/runpath)
|
||||
install(TARGETS runpath_origin_postexcluded DESTINATION lib/runpath_origin_postexcluded)
|
||||
install(TARGETS runpath_origin DESTINATION lib/runpath_origin)
|
||||
install(TARGETS runpath_parent_unresolved DESTINATION lib/runpath_parent_unresolved)
|
||||
install(TARGETS runpath_search_postexcluded DESTINATION lib/runpath_search_postexcluded)
|
||||
install(TARGETS runpath runpath_origin runpath_search DESTINATION lib/runpath_search)
|
||||
install(TARGETS conflict DESTINATION lib/conflict2)
|
||||
|
||||
target_link_libraries(test_runpath PRIVATE ${test_runpath_names} rpath conflict)
|
||||
set_property(TARGET test_runpath PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/runpath/../rpath" # Ensure that files that don't conflict are treated correctly
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/runpath_postexcluded"
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/runpath"
|
||||
"\\\${ORIGIN}/runpath_origin_postexcluded" # This must be double-escaped because of issue #19225.
|
||||
"\\\$ORIGIN/runpath_origin"
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/conflict2"
|
||||
)
|
||||
target_link_options(test_runpath PRIVATE -Wl,--enable-new-dtags)
|
||||
|
||||
set_property(TARGET test_rpath ${test_rpath_names} test_runpath ${test_runpath_names} PROPERTY LIBRARY_OUTPUT_DIRECTORY lib)
|
||||
install(TARGETS test_rpath test_runpath DESTINATION lib)
|
||||
|
||||
add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c)
|
||||
add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c)
|
||||
add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c)
|
||||
target_link_libraries(topexe PRIVATE test_rpath test_runpath)
|
||||
target_link_libraries(toplib PRIVATE test_rpath test_runpath)
|
||||
target_link_libraries(topmod PRIVATE test_rpath test_runpath)
|
||||
set_property(TARGET topexe toplib topmod PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib"
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath_parent_postexcluded"
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath_parent"
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/runpath_parent_unresolved"
|
||||
)
|
||||
target_link_options(topexe PRIVATE -Wl,--disable-new-dtags)
|
||||
target_link_options(toplib PRIVATE -Wl,--disable-new-dtags)
|
||||
target_link_options(topmod PRIVATE -Wl,--disable-new-dtags)
|
||||
|
||||
install(TARGETS topexe toplib RUNTIME DESTINATION bin LIBRARY DESTINATION lib)
|
||||
install(TARGETS topmod LIBRARY DESTINATION lib/modules)
|
||||
|
||||
install(CODE [[
|
||||
function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile)
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
RESOLVED_DEPENDENCIES_VAR deps
|
||||
UNRESOLVED_DEPENDENCIES_VAR udeps
|
||||
CONFLICTING_DEPENDENCIES_PREFIX cdeps
|
||||
PRE_INCLUDE_REGEXES
|
||||
"^lib(test_rpath|rpath_postexcluded|rpath|rpath_parent_postexcluded|rpath_parent|rpath_origin_postexcluded|rpath_origin|rpath_search_postexcluded|rpath_search|rpath_unresolved|test_runpath|runpath_postexcluded|runpath|runpath_origin_postexcluded|runpath_origin|runpath_parent_unresolved|runpath_search_postexcluded|runpath_search|runpath_unresolved|conflict)\\.so$"
|
||||
"^libc\\.so"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
POST_INCLUDE_REGEXES "^.*/(libtest_rpath|rpath/librpath|rpath_parent/librpath_parent|rpath_search/librpath_search|libtest_runpath|runpath/librunpath|runpath_origin_postexcluded|runpath_origin|runpath_search/librunpath_search|conflict2?/libconflict)\\.so$"
|
||||
POST_EXCLUDE_REGEXES ".*"
|
||||
DIRECTORIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/rpath_search_postexcluded"
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/rpath_search"
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/runpath_search_postexcluded"
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/runpath_search"
|
||||
${ARGN}
|
||||
)
|
||||
list(SORT deps)
|
||||
list(SORT udeps)
|
||||
list(SORT cdeps_FILENAMES)
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}")
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}")
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "")
|
||||
foreach(cdep IN LISTS cdeps_FILENAMES)
|
||||
set(cdep_values ${cdeps_${cdep}})
|
||||
list(SORT cdep_values)
|
||||
file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps1.txt udeps1.txt cdeps1.txt
|
||||
EXECUTABLES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topexe>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps2.txt udeps2.txt cdeps2.txt
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:toplib>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps3.txt udeps3.txt cdeps3.txt
|
||||
MODULES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/modules/$<TARGET_FILE_NAME:topmod>"
|
||||
)
|
||||
]])
|
||||
@@ -0,0 +1,9 @@
|
||||
extern void test_rpath(void);
|
||||
extern void test_runpath(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_rpath();
|
||||
test_runpath();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
extern void test_rpath(void);
|
||||
extern void test_runpath(void);
|
||||
|
||||
void toplib(void)
|
||||
{
|
||||
test_rpath();
|
||||
test_runpath();
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
function(check_contents filename contents_regex)
|
||||
if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
|
||||
file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
|
||||
if(NOT contents MATCHES "${contents_regex}")
|
||||
string(APPEND RunCMake_TEST_FAILED "File contents:
|
||||
${contents}
|
||||
do not match what we expected:
|
||||
${contents_regex}
|
||||
in file:
|
||||
${CMAKE_INSTALL_PREFIX}/${filename}\n")
|
||||
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
|
||||
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(_check
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/executable_path/libexecutable_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/rpath_executable_path/librpath_executable_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
|
||||
[[/usr/lib/libSystem\.B\.dylib]]
|
||||
)
|
||||
check_contents(deps/deps1.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
|
||||
[[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_executable_path_bundle\.dylib]]
|
||||
[[@rpath/librpath_loader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_unresolved\.dylib]]
|
||||
)
|
||||
check_contents(deps/udeps1.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
|
||||
[[/usr/lib/libSystem\.B\.dylib]]
|
||||
)
|
||||
check_contents(deps/deps2.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
|
||||
[[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
|
||||
[[@executable_path/../lib/executable_path_postexcluded/libexecutable_path_postexcluded\.dylib]]
|
||||
[[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_executable_path\.dylib]]
|
||||
[[@rpath/librpath_executable_path_bundle\.dylib]]
|
||||
[[@rpath/librpath_executable_path_postexcluded\.dylib]]
|
||||
[[@rpath/librpath_loader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_unresolved\.dylib]]
|
||||
)
|
||||
check_contents(deps/udeps2.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
|
||||
[[/usr/lib/libSystem\.B\.dylib]]
|
||||
)
|
||||
check_contents(deps/deps3.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
|
||||
[[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
|
||||
[[@executable_path/../lib/executable_path_postexcluded/libexecutable_path_postexcluded\.dylib]]
|
||||
[[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_executable_path\.dylib]]
|
||||
[[@rpath/librpath_executable_path_bundle\.dylib]]
|
||||
[[@rpath/librpath_executable_path_postexcluded\.dylib]]
|
||||
[[@rpath/librpath_loader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_unresolved\.dylib]]
|
||||
)
|
||||
check_contents(deps/udeps3.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/executable_path/libexecutable_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/rpath_executable_path/librpath_executable_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
|
||||
[[/usr/lib/libSystem\.B\.dylib]]
|
||||
)
|
||||
check_contents(deps/deps4.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
|
||||
[[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_executable_path_bundle\.dylib]]
|
||||
[[@rpath/librpath_loader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_unresolved\.dylib]]
|
||||
)
|
||||
check_contents(deps/udeps4.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/bundle_executable/bin/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
|
||||
[[/usr/lib/libSystem\.B\.dylib]]
|
||||
)
|
||||
check_contents(deps/deps5.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
|
||||
[[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_executable_path\.dylib]]
|
||||
[[@rpath/librpath_executable_path_bundle\.dylib]]
|
||||
[[@rpath/librpath_loader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_unresolved\.dylib]]
|
||||
)
|
||||
check_contents(deps/udeps5.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/bundle_executable/bin/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]]
|
||||
[[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]]
|
||||
[[/usr/lib/libSystem\.B\.dylib]]
|
||||
)
|
||||
check_contents(deps/deps6.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
[[@executable_path/../lib/executable_path/libexecutable_path\.dylib]]
|
||||
[[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_executable_path\.dylib]]
|
||||
[[@rpath/librpath_executable_path_bundle\.dylib]]
|
||||
[[@rpath/librpath_loader_path_unresolved\.dylib]]
|
||||
[[@rpath/librpath_unresolved\.dylib]]
|
||||
)
|
||||
check_contents(deps/udeps6.txt "^${_check}$")
|
||||
|
||||
set(_check
|
||||
"^libconflict\\.dylib:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/conflict/libconflict\\.dylib;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/conflict2/libconflict\\.dylib\n$"
|
||||
)
|
||||
check_contents(deps/cdeps1.txt "${_check}")
|
||||
check_contents(deps/cdeps2.txt "${_check}")
|
||||
check_contents(deps/cdeps3.txt "${_check}")
|
||||
check_contents(deps/cdeps4.txt "${_check}")
|
||||
check_contents(deps/cdeps5.txt "${_check}")
|
||||
check_contents(deps/cdeps6.txt "${_check}")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,7 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Multiple conflicting paths found for librpath\.dylib:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-build/root-all/lib/rpath1/librpath\.dylib
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-build/root-all/lib/rpath2/librpath\.dylib$
|
||||
@@ -0,0 +1,55 @@
|
||||
enable_language(C)
|
||||
|
||||
set(test1_names rpath)
|
||||
set(test2_names rpath)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/rpath.c" "void rpath(void) {}\n")
|
||||
add_library(rpath SHARED "${CMAKE_BINARY_DIR}/rpath.c")
|
||||
set_property(TARGET rpath PROPERTY INSTALL_NAME_DIR @rpath)
|
||||
install(TARGETS rpath DESTINATION lib/rpath1)
|
||||
install(TARGETS rpath DESTINATION lib/rpath2)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test1.c")
|
||||
add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c")
|
||||
foreach(name ${test1_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "void test1(void)\n{\n")
|
||||
foreach(name ${test1_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n")
|
||||
|
||||
target_link_libraries(test1 PRIVATE ${test1_names})
|
||||
set_property(TARGET test1 PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath1"
|
||||
)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test2.c")
|
||||
add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c")
|
||||
foreach(name ${test2_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "void test2(void)\n{\n")
|
||||
foreach(name ${test2_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n")
|
||||
|
||||
target_link_libraries(test2 PRIVATE ${test2_names})
|
||||
set_property(TARGET test2 PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/lib/rpath2"
|
||||
)
|
||||
|
||||
install(TARGETS test1 test2 DESTINATION lib)
|
||||
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test1>"
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test2>"
|
||||
PRE_INCLUDE_REGEXES "^@rpath/librpath\\.dylib$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Failed to run otool on:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-build/root-all/bin/\.\./lib/libtest\.dylib$
|
||||
@@ -0,0 +1,30 @@
|
||||
enable_language(C)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
]])
|
||||
|
||||
add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c")
|
||||
set_property(TARGET test PROPERTY INSTALL_NAME_DIR @rpath)
|
||||
add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
|
||||
target_link_libraries(exe PRIVATE test)
|
||||
set_property(TARGET exe PROPERTY INSTALL_RPATH "@loader_path/../lib")
|
||||
|
||||
install(TARGETS exe DESTINATION bin)
|
||||
|
||||
install(CODE [[
|
||||
file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>")
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
EXECUTABLES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
|
||||
PRE_INCLUDE_REGEXES "^@rpath/libtest\\.dylib$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Could not resolve file @rpath/libunresolved\.dylib$
|
||||
@@ -0,0 +1,18 @@
|
||||
enable_language(C)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "extern void unresolved(void);\nvoid testlib(void)\n{\n unresolved();\n}\n")
|
||||
add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "void unresolved(void) {}\n")
|
||||
add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c")
|
||||
target_link_libraries(testlib PRIVATE unresolved)
|
||||
install(TARGETS testlib DESTINATION lib)
|
||||
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
PRE_INCLUDE_REGEXES "^@rpath/libunresolved\\.dylib$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
216
Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake
Normal file
216
Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake
Normal file
@@ -0,0 +1,216 @@
|
||||
enable_language(C)
|
||||
|
||||
set(testlib_names
|
||||
preexcluded
|
||||
executable_path
|
||||
executable_path_bundle
|
||||
executable_path_postexcluded
|
||||
loader_path
|
||||
loader_path_unresolved
|
||||
loader_path_postexcluded
|
||||
rpath
|
||||
rpath_unresolved
|
||||
rpath_postexcluded
|
||||
rpath_executable_path
|
||||
rpath_executable_path_bundle
|
||||
rpath_executable_path_postexcluded
|
||||
rpath_loader_path
|
||||
rpath_loader_path_unresolved
|
||||
rpath_loader_path_postexcluded
|
||||
normal
|
||||
normal_unresolved
|
||||
normal_postexcluded
|
||||
conflict
|
||||
)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/testlib.c")
|
||||
add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
|
||||
foreach(name ${testlib_names})
|
||||
if(name STREQUAL "normal")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/normal.c" "extern void rpath(void);\nvoid normal(void)\n{\n rpath();\n}\n")
|
||||
else()
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n")
|
||||
endif()
|
||||
add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
|
||||
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "void testlib(void)\n{\n")
|
||||
foreach(name ${testlib_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "}\n")
|
||||
set_property(TARGET ${testlib_names} PROPERTY BUILD_WITH_INSTALL_NAME_DIR 1)
|
||||
target_link_libraries(normal PRIVATE rpath)
|
||||
set_property(TARGET normal PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/executable/lib/normal/../rpath"
|
||||
)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/testlib_conflict.c" "extern void conflict(void);\nvoid testlib_conflict(void)\n{\n conflict();\n}\n")
|
||||
add_library(testlib_conflict SHARED "${CMAKE_BINARY_DIR}/testlib_conflict.c")
|
||||
target_link_libraries(testlib_conflict PRIVATE conflict)
|
||||
|
||||
set_property(TARGET testlib PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath"
|
||||
"${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath_unresolved"
|
||||
"${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath_postexcluded"
|
||||
"${CMAKE_BINARY_DIR}/root-all/executable/lib/conflict"
|
||||
@executable_path/../lib/rpath_executable_path
|
||||
@executable_path/../lib/rpath_executable_path_unresolved
|
||||
@executable_path/../lib/rpath_executable_path_postexcluded
|
||||
@loader_path/rpath_loader_path
|
||||
@loader_path/rpath_loader_path_unresolved
|
||||
@loader_path/rpath_loader_path_postexcluded
|
||||
)
|
||||
set_property(TARGET testlib_conflict PROPERTY INSTALL_RPATH
|
||||
"${CMAKE_BINARY_DIR}/root-all/executable/lib/conflict2"
|
||||
)
|
||||
|
||||
foreach(t
|
||||
executable_path
|
||||
executable_path_postexcluded
|
||||
loader_path
|
||||
loader_path_postexcluded
|
||||
rpath
|
||||
rpath_postexcluded
|
||||
rpath_executable_path
|
||||
rpath_executable_path_postexcluded
|
||||
rpath_loader_path
|
||||
rpath_loader_path_postexcluded
|
||||
conflict
|
||||
)
|
||||
install(TARGETS ${t} DESTINATION executable/lib/${t})
|
||||
endforeach()
|
||||
install(TARGETS conflict DESTINATION executable/lib/conflict2)
|
||||
|
||||
foreach(t
|
||||
executable_path_bundle
|
||||
executable_path_postexcluded
|
||||
loader_path_postexcluded
|
||||
rpath_postexcluded
|
||||
rpath_executable_path_bundle
|
||||
rpath_executable_path_postexcluded
|
||||
rpath_loader_path_postexcluded
|
||||
)
|
||||
install(TARGETS ${t} DESTINATION bundle_executable/lib/${t})
|
||||
endforeach()
|
||||
|
||||
foreach(t executable_path executable_path_bundle executable_path_postexcluded)
|
||||
set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @executable_path/../lib/${t})
|
||||
endforeach()
|
||||
|
||||
foreach(t loader_path loader_path_unresolved loader_path_postexcluded)
|
||||
set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @loader_path/${t})
|
||||
endforeach()
|
||||
|
||||
foreach(t
|
||||
rpath
|
||||
rpath_unresolved
|
||||
rpath_postexcluded
|
||||
rpath_executable_path
|
||||
rpath_executable_path_bundle
|
||||
rpath_executable_path_postexcluded
|
||||
rpath_loader_path
|
||||
rpath_loader_path_unresolved
|
||||
rpath_loader_path_postexcluded
|
||||
conflict
|
||||
)
|
||||
set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @rpath)
|
||||
endforeach()
|
||||
|
||||
foreach(t normal normal_unresolved normal_postexcluded)
|
||||
set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR "${CMAKE_BINARY_DIR}/root-all/executable/lib/${t}")
|
||||
if(NOT t STREQUAL "normal_unresolved")
|
||||
install(TARGETS ${t} DESTINATION executable/lib/${t})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
target_link_libraries(testlib PRIVATE ${testlib_names})
|
||||
|
||||
add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c)
|
||||
add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c)
|
||||
add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c)
|
||||
target_link_libraries(topexe PRIVATE testlib)
|
||||
target_link_libraries(toplib PRIVATE testlib)
|
||||
target_link_libraries(topmod PRIVATE testlib)
|
||||
|
||||
set_property(TARGET topexe toplib topmod PROPERTY INSTALL_RPATH "${CMAKE_BINARY_DIR}/root-all/executable/lib")
|
||||
|
||||
install(TARGETS topexe toplib topmod testlib testlib_conflict RUNTIME DESTINATION executable/bin LIBRARY DESTINATION executable/lib)
|
||||
install(TARGETS topexe toplib topmod testlib testlib_conflict RUNTIME DESTINATION bundle_executable/bin LIBRARY DESTINATION bundle_executable/lib)
|
||||
|
||||
install(CODE [[
|
||||
function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile)
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
RESOLVED_DEPENDENCIES_VAR deps
|
||||
UNRESOLVED_DEPENDENCIES_VAR udeps
|
||||
CONFLICTING_DEPENDENCIES_PREFIX cdeps
|
||||
PRE_INCLUDE_REGEXES "^.*/lib(testlib|executable_path|executable_path_bundle|executable_path_postexcluded|loader_path|loader_path_unresolved|loader_path_postexcluded|rpath|rpath_unresolved|rpath_postexcluded|rpath_executable_path|rpath_executable_path_bundle|rpath_executable_path_postexcluded|rpath_loader_path|rpath_loader_path_unresolved|rpath_loader_path_postexcluded|normal|normal_unresolved|normal_postexcluded|conflict|System\\.B)\\.dylib$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
POST_INCLUDE_REGEXES "^.*/lib(testlib|executable_path|executable_path_bundle|loader_path|rpath|rpath_executable_path|rpath_executable_path_bundle|rpath_loader_path|normal|conflict|System\\.B)\\.dylib$"
|
||||
POST_EXCLUDE_REGEXES ".*"
|
||||
${ARGN}
|
||||
)
|
||||
list(SORT deps)
|
||||
list(SORT udeps)
|
||||
list(SORT cdeps_FILENAMES)
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}")
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}")
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "")
|
||||
foreach(cdep IN LISTS cdeps_FILENAMES)
|
||||
set(cdep_values ${cdeps_${cdep}})
|
||||
list(SORT cdep_values)
|
||||
file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps1.txt udeps1.txt cdeps1.txt
|
||||
EXECUTABLES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/bin/$<TARGET_FILE_NAME:topexe>"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps2.txt udeps2.txt cdeps2.txt
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:toplib>"
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps3.txt udeps3.txt cdeps3.txt
|
||||
MODULES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:topmod>"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps4.txt udeps4.txt cdeps4.txt
|
||||
EXECUTABLES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/bin/$<TARGET_FILE_NAME:topexe>"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
BUNDLE_EXECUTABLE
|
||||
"${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps5.txt udeps5.txt cdeps5.txt
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:toplib>"
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
BUNDLE_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps6.txt udeps6.txt cdeps6.txt
|
||||
MODULES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:topmod>"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
BUNDLE_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>"
|
||||
)
|
||||
]])
|
||||
@@ -0,0 +1,7 @@
|
||||
extern void testlib(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
testlib();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
extern void testlib(void);
|
||||
|
||||
void toplib(void)
|
||||
{
|
||||
testlib();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-project\.cmake:[0-9]+ \(file\):
|
||||
You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\. This is
|
||||
probably not what you intended to do\. Instead, please consider using it in
|
||||
an install\(CODE\) or install\(SCRIPT\) command\. For example:
|
||||
|
||||
install\(CODE \[\[
|
||||
file\(GET_RUNTIME_DEPENDENCIES
|
||||
# \.\.\.
|
||||
\)
|
||||
]]\)
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-dev to suppress it\.$
|
||||
@@ -0,0 +1 @@
|
||||
file(GET_RUNTIME_DEPENDENCIES RESOLVED_DEPENDENCIES_VAR deps)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
^CMake Error at file-GET_RUNTIME_DEPENDENCIES-unsupported\.cmake:[0-9]+ \(file\):
|
||||
file GET_RUNTIME_DEPENDENCIES is not supported on system "[^
|
||||
]+"
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
@@ -0,0 +1,2 @@
|
||||
file(GET_RUNTIME_DEPENDENCIES RESOLVED_DEPENDENCIES_VAR deps)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
@@ -0,0 +1,38 @@
|
||||
function(check_contents filename contents_regex)
|
||||
if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}")
|
||||
file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents)
|
||||
if(NOT contents MATCHES "${contents_regex}")
|
||||
string(APPEND RunCMake_TEST_FAILED "File contents:
|
||||
${contents}
|
||||
do not match what we expected:
|
||||
${contents_regex}
|
||||
in file:
|
||||
${CMAKE_INSTALL_PREFIX}/${filename}\n")
|
||||
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist")
|
||||
set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(_check
|
||||
[=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\.conflict/\.\./(lib)?libdir\.dll]=]
|
||||
[=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\.search/(lib)?search\.dll]=]
|
||||
[=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/(lib)?testlib\.dll]=]
|
||||
)
|
||||
check_contents(deps/deps1.txt "^${_check}$")
|
||||
check_contents(deps/deps2.txt "^${_check}$")
|
||||
check_contents(deps/deps3.txt "^${_check}$")
|
||||
set(_check
|
||||
[=[(lib)?unresolved\.dll]=]
|
||||
)
|
||||
check_contents(deps/udeps1.txt "^${_check}$")
|
||||
check_contents(deps/udeps2.txt "^${_check}$")
|
||||
check_contents(deps/udeps3.txt "^${_check}$")
|
||||
set(_check
|
||||
"^(lib)?conflict\\.dll:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\\.conflict/(lib)?conflict\\.dll;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/(lib)?conflict\\.dll\n$"
|
||||
)
|
||||
check_contents(deps/cdeps1.txt "${_check}")
|
||||
check_contents(deps/cdeps2.txt "${_check}")
|
||||
check_contents(deps/cdeps3.txt "${_check}")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,7 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Multiple conflicting paths found for (lib)?path\.dll:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-build/root-all/lib/test1/(lib)?path\.dll
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-build/root-all/lib/test2/(lib)?path\.dll$
|
||||
@@ -0,0 +1,47 @@
|
||||
enable_language(C)
|
||||
|
||||
set(test1_names path)
|
||||
set(test2_names path)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/path.c" "__declspec(dllexport) void path(void) {}\n")
|
||||
add_library(path SHARED "${CMAKE_BINARY_DIR}/path.c")
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test1.c")
|
||||
add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c")
|
||||
foreach(name ${test1_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "__declspec(dllimport) extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "__declspec(dllexport) void test1(void)\n{\n")
|
||||
foreach(name ${test1_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n")
|
||||
|
||||
target_link_libraries(test1 PRIVATE ${test1_names})
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/test2.c")
|
||||
add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c")
|
||||
foreach(name ${test2_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "__declspec(dllimport) extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "__declspec(dllexport) void test2(void)\n{\n")
|
||||
foreach(name ${test2_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n")
|
||||
|
||||
target_link_libraries(test2 PRIVATE ${test2_names})
|
||||
|
||||
install(TARGETS test1 path DESTINATION lib/test1)
|
||||
install(TARGETS test2 path DESTINATION lib/test2)
|
||||
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/test1/$<TARGET_FILE_NAME:test1>"
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/test2/$<TARGET_FILE_NAME:test2>"
|
||||
PRE_INCLUDE_REGEXES "^(lib)?path\\.dll$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Failed to run (dumpbin|objdump) on:
|
||||
|
||||
[^
|
||||
]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-build/root-all/bin/(lib)?test\.dll$
|
||||
@@ -0,0 +1,28 @@
|
||||
enable_language(C)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/test.c" "__declspec(dllexport) void test(void) {}\n")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[__declspec(dllimport) extern void test(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
]])
|
||||
|
||||
add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c")
|
||||
add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
|
||||
target_link_libraries(exe PRIVATE test)
|
||||
|
||||
install(TARGETS exe DESTINATION bin)
|
||||
|
||||
install(CODE [[
|
||||
file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:test>")
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
EXECUTABLES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>"
|
||||
PRE_INCLUDE_REGEXES "^(lib)?test\\.dll$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,2 @@
|
||||
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
|
||||
file Could not resolve file (lib)?unresolved\.dll$
|
||||
@@ -0,0 +1,18 @@
|
||||
enable_language(C)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllimport) extern void unresolved(void);\n__declspec(dllexport) void testlib(void)\n{\n unresolved();\n}\n")
|
||||
add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "__declspec(dllexport) void unresolved(void) {}\n")
|
||||
add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c")
|
||||
target_link_libraries(testlib PRIVATE unresolved)
|
||||
install(TARGETS testlib DESTINATION lib)
|
||||
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
PRE_INCLUDE_REGEXES "^(lib)?unresolved\\.dll$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>"
|
||||
)
|
||||
message(FATAL_ERROR "This message should not be displayed")
|
||||
]])
|
||||
@@ -0,0 +1,114 @@
|
||||
enable_language(C)
|
||||
|
||||
set(testlib_names
|
||||
preexcluded
|
||||
libdir_postexcluded
|
||||
libdir
|
||||
search_postexcluded
|
||||
search
|
||||
unresolved
|
||||
conflict
|
||||
)
|
||||
|
||||
file(REMOVE "${CMAKE_BINARY_DIR}/testlib.c")
|
||||
add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c")
|
||||
foreach(name ${testlib_names})
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "__declspec(dllexport) void ${name}(void) {}\n")
|
||||
add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c")
|
||||
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllimport) extern void ${name}(void);\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllexport) void testlib(void)\n{\n")
|
||||
foreach(name ${testlib_names})
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" " ${name}();\n")
|
||||
endforeach()
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "}\n")
|
||||
|
||||
target_link_libraries(testlib PRIVATE ${testlib_names})
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/testlib_conflict.c" "__declspec(dllimport) extern void conflict(void);\n__declspec(dllexport) void testlib_conflict(void)\n{\n conflict();\n}\n")
|
||||
add_library(testlib_conflict SHARED "${CMAKE_BINARY_DIR}/testlib_conflict.c")
|
||||
target_link_libraries(testlib_conflict PRIVATE conflict)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/testlib_noconflict.c" "__declspec(dllimport) extern void libdir(void);\n__declspec(dllexport) void testlib_noconflict(void)\n{\n libdir();\n}\n")
|
||||
add_library(testlib_noconflict SHARED "${CMAKE_BINARY_DIR}/testlib_noconflict.c")
|
||||
target_link_libraries(testlib_noconflict PRIVATE libdir)
|
||||
|
||||
install(TARGETS testlib libdir_postexcluded libdir conflict testlib_noconflict DESTINATION bin)
|
||||
install(TARGETS libdir search_postexcluded search DESTINATION bin/.search) # Prefixing with "." ensures it is the first item after list(SORT)
|
||||
install(TARGETS testlib_conflict conflict DESTINATION bin/.conflict)
|
||||
|
||||
add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c)
|
||||
add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c)
|
||||
add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c)
|
||||
target_link_libraries(topexe PRIVATE testlib)
|
||||
target_link_libraries(toplib PRIVATE testlib)
|
||||
target_link_libraries(topmod PRIVATE testlib)
|
||||
|
||||
install(TARGETS topexe toplib topmod DESTINATION bin)
|
||||
|
||||
install(CODE [[
|
||||
function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile)
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
RESOLVED_DEPENDENCIES_VAR deps
|
||||
UNRESOLVED_DEPENDENCIES_VAR udeps
|
||||
CONFLICTING_DEPENDENCIES_PREFIX cdeps
|
||||
PRE_INCLUDE_REGEXES
|
||||
"^(lib)?testlib\\.dll$"
|
||||
"^(lib)?libdir_postexcluded\\.dll$"
|
||||
"^(lib)?libdir\\.dll$"
|
||||
"^(lib)?search_postexcluded\\.dll$"
|
||||
"^(lib)?search\\.dll$"
|
||||
"^(lib)?unresolved\\.dll$"
|
||||
"^(lib)?conflict\\.dll$"
|
||||
"^kernel32\\.dll$"
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
POST_INCLUDE_REGEXES
|
||||
"^.*/(lib)?testlib\\.dll$"
|
||||
"^.*/(lib)?libdir\\.dll$"
|
||||
"^.*/(lib)?search\\.dll$"
|
||||
"^.*/(lib)?conflict\\.dll$"
|
||||
POST_EXCLUDE_REGEXES ".*"
|
||||
DIRECTORIES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/.search"
|
||||
${ARGN}
|
||||
)
|
||||
list(SORT deps)
|
||||
list(SORT udeps)
|
||||
list(SORT cdeps_FILENAMES)
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}")
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}")
|
||||
file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "")
|
||||
foreach(cdep IN LISTS cdeps_FILENAMES)
|
||||
set(cdep_values ${cdeps_${cdep}})
|
||||
list(SORT cdep_values)
|
||||
file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps1.txt udeps1.txt cdeps1.txt
|
||||
EXECUTABLES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topexe>"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps2.txt udeps2.txt cdeps2.txt
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:toplib>"
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>"
|
||||
)
|
||||
|
||||
exec_get_runtime_dependencies(
|
||||
deps3.txt udeps3.txt cdeps3.txt
|
||||
MODULES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topmod>"
|
||||
LIBRARIES
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>"
|
||||
"${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>"
|
||||
)
|
||||
]])
|
||||
@@ -0,0 +1,7 @@
|
||||
__declspec(dllimport) extern void testlib(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
testlib();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
__declspec(dllimport) extern void testlib(void);
|
||||
|
||||
__declspec(dllexport) void toplib(void)
|
||||
{
|
||||
testlib();
|
||||
}
|
||||
20
bootstrap
20
bootstrap
@@ -261,6 +261,17 @@ CMAKE_CXX_SOURCES="\
|
||||
cmAddSubDirectoryCommand \
|
||||
cmAddTestCommand \
|
||||
cmArgumentParser \
|
||||
cmBinUtilsLinker \
|
||||
cmBinUtilsLinuxELFGetRuntimeDependenciesTool \
|
||||
cmBinUtilsLinuxELFLinker \
|
||||
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool \
|
||||
cmBinUtilsMacOSMachOGetRuntimeDependenciesTool \
|
||||
cmBinUtilsMacOSMachOLinker \
|
||||
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool \
|
||||
cmBinUtilsWindowsPEGetRuntimeDependenciesTool \
|
||||
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool \
|
||||
cmBinUtilsWindowsPELinker \
|
||||
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool \
|
||||
cmBreakCommand \
|
||||
cmBuildCommand \
|
||||
cmCMakeMinimumRequired \
|
||||
@@ -357,6 +368,8 @@ CMAKE_CXX_SOURCES="\
|
||||
cmInstallTargetGenerator \
|
||||
cmInstallTargetsCommand \
|
||||
cmInstalledFile \
|
||||
cmLDConfigLDConfigTool \
|
||||
cmLDConfigTool \
|
||||
cmLinkDirectoriesCommand \
|
||||
cmLinkItem \
|
||||
cmLinkLineComputer \
|
||||
@@ -394,6 +407,7 @@ CMAKE_CXX_SOURCES="\
|
||||
cmPropertyMap \
|
||||
cmReturnCommand \
|
||||
cmRulePlaceholderExpander \
|
||||
cmRuntimeDependencyArchive \
|
||||
cmScriptGenerator \
|
||||
cmSearchPath \
|
||||
cmSeparateArgumentsCommand \
|
||||
@@ -443,7 +457,9 @@ CMAKE_CXX_SOURCES="\
|
||||
if ${cmake_system_mingw}; then
|
||||
CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES}\
|
||||
cmGlobalMSYSMakefileGenerator \
|
||||
cmGlobalMinGWMakefileGenerator"
|
||||
cmGlobalMinGWMakefileGenerator \
|
||||
cmVSSetupHelper \
|
||||
"
|
||||
fi
|
||||
|
||||
LexerParser_CXX_SOURCES="\
|
||||
@@ -1370,7 +1386,7 @@ libs=""
|
||||
uv_c_flags=""
|
||||
if ${cmake_system_mingw}; then
|
||||
uv_c_flags="${uv_c_flags} -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600"
|
||||
libs="${libs} -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv"
|
||||
libs="${libs} -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -lole32 -loleaut32"
|
||||
else
|
||||
uv_c_flags="${uv_c_flags} -DCMAKE_BOOTSTRAP"
|
||||
case "${cmake_system}" in
|
||||
|
||||
Reference in New Issue
Block a user