1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

file(GET_RUNTIME_DEPENDENCIES): Add undocumented RPATH_PREFIX option

This commit is contained in:
Kyle Edwards
2021-04-23 11:19:11 -04:00
parent b613e09778
commit 2ef3ea394f
7 changed files with 72 additions and 12 deletions

View File

@@ -65,18 +65,18 @@ bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
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;
std::vector<std::string> rpaths;
if (!this->Tool->GetFileInfo(file, libs, rpaths)) {
return false;
}
return this->ScanDependencies(file, libs, rpaths, executablePath);
}
bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
std::string const& file, std::vector<std::string> const& libs,
std::vector<std::string> const& rpaths, std::string const& executablePath)
{
std::string loaderPath = cmSystemTools::GetFilenamePath(file);
return this->GetFileDependencies(libs, executablePath, loaderPath, rpaths);
}
@@ -98,8 +98,14 @@ bool cmBinUtilsMacOSMachOLinker::GetFileDependencies(
!IsMissingSystemDylib(path)) {
auto filename = cmSystemTools::GetFilenameName(path);
bool unique;
this->Archive->AddResolvedPath(filename, path, unique);
if (unique && !this->ScanDependencies(path, executablePath)) {
std::vector<std::string> libs;
std::vector<std::string> depRpaths;
if (!this->Tool->GetFileInfo(path, libs, depRpaths)) {
return false;
}
this->Archive->AddResolvedPath(filename, path, unique, depRpaths);
if (unique &&
!this->ScanDependencies(path, libs, depRpaths, executablePath)) {
return false;
}
}

View File

@@ -27,6 +27,8 @@ private:
std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool;
bool ScanDependencies(std::string const& file,
std::vector<std::string> const& libs,
std::vector<std::string> const& rpaths,
std::string const& executablePath);
bool GetFileDependencies(std::vector<std::string> const& names,

View File

@@ -3032,6 +3032,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
std::string ResolvedDependenciesVar;
std::string UnresolvedDependenciesVar;
std::string ConflictingDependenciesPrefix;
std::string RPathPrefix;
std::string BundleExecutable;
std::vector<std::string> Executables;
std::vector<std::string> Libraries;
@@ -3053,6 +3054,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
&Arguments::UnresolvedDependenciesVar)
.Bind("CONFLICTING_DEPENDENCIES_PREFIX"_s,
&Arguments::ConflictingDependenciesPrefix)
.Bind("RPATH_PREFIX"_s, &Arguments::RPathPrefix)
.Bind("BUNDLE_EXECUTABLE"_s, &Arguments::BundleExecutable)
.Bind("EXECUTABLES"_s, &Arguments::Executables)
.Bind("LIBRARIES"_s, &Arguments::Libraries)
@@ -3135,6 +3137,11 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
if (unique) {
deps.push_back(firstPath);
if (!parsedArgs.RPathPrefix.empty()) {
status.GetMakefile().AddDefinition(
parsedArgs.RPathPrefix + "_" + firstPath,
cmJoin(archive.GetRPaths().at(firstPath), ";"));
}
} else if (!parsedArgs.ConflictingDependenciesPrefix.empty()) {
conflictingDeps.push_back(val.first);
std::vector<std::string> paths;

View File

@@ -354,9 +354,9 @@ bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name) const
fileSearch(this->PostExcludeFiles)));
}
void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name,
const std::string& path,
bool& unique)
void cmRuntimeDependencyArchive::AddResolvedPath(
const std::string& name, const std::string& path, bool& unique,
std::vector<std::string> rpaths)
{
auto it = this->ResolvedPaths.emplace(name, std::set<std::string>{}).first;
unique = true;
@@ -367,6 +367,7 @@ void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name,
}
}
it->second.insert(path);
this->RPaths[path] = std::move(rpaths);
}
void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name)
@@ -390,3 +391,9 @@ const std::set<std::string>& cmRuntimeDependencyArchive::GetUnresolvedPaths()
{
return this->UnresolvedPaths;
}
const std::map<std::string, std::vector<std::string>>&
cmRuntimeDependencyArchive::GetRPaths() const
{
return this->RPaths;
}

View File

@@ -45,12 +45,13 @@ public:
bool IsPostExcluded(const std::string& name) const;
void AddResolvedPath(const std::string& name, const std::string& path,
bool& unique);
bool& unique, std::vector<std::string> rpaths = {});
void AddUnresolvedPath(const std::string& name);
cmMakefile* GetMakefile() const;
const std::map<std::string, std::set<std::string>>& GetResolvedPaths() const;
const std::set<std::string>& GetUnresolvedPaths() const;
const std::map<std::string, std::vector<std::string>>& GetRPaths() const;
private:
cmExecutionStatus& Status;
@@ -70,4 +71,5 @@ private:
std::vector<std::string> PostExcludeFilesStrict;
std::map<std::string, std::set<std::string>> ResolvedPaths;
std::set<std::string> UnresolvedPaths;
std::map<std::string, std::vector<std::string>> RPaths;
};

View File

@@ -36,6 +36,7 @@ endfunction()
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
if(NOT CMake_INSTALL_NAME_TOOL_BUG)
run_install_test(macos)
run_install_test(macos-rpath)
run_install_test(macos-unresolved)
run_install_test(macos-conflict)
run_install_test(macos-notfile)

View File

@@ -0,0 +1,35 @@
enable_language(C)
file(WRITE "${CMAKE_BINARY_DIR}/toplib.c" "extern void sublib1(void);\nextern void sublib2(void);\nvoid toplib(void)\n{\n sublib1();\n sublib2();\n}\n")
add_library(toplib SHARED "${CMAKE_BINARY_DIR}/toplib.c")
file(WRITE "${CMAKE_BINARY_DIR}/sublib1.c" "extern void sublib2(void);\nvoid sublib1(void)\n{\n sublib2();\n}\n")
add_library(sublib1 SHARED "${CMAKE_BINARY_DIR}/sublib1.c")
file(WRITE "${CMAKE_BINARY_DIR}/sublib2.c" "void sublib2(void)\n{\n}\n")
add_library(sublib2 SHARED "${CMAKE_BINARY_DIR}/sublib2.c")
target_link_libraries(toplib PRIVATE sublib1 sublib2)
target_link_libraries(sublib1 PRIVATE sublib2)
set_property(TARGET toplib PROPERTY INSTALL_RPATH "@loader_path/d1;@loader_path/d2")
set_property(TARGET sublib1 PROPERTY INSTALL_RPATH "@loader_path/;@loader_path/../d2")
install(TARGETS toplib DESTINATION lib)
install(TARGETS sublib1 DESTINATION lib/d1)
install(TARGETS sublib2 DESTINATION lib/d2)
install(CODE [[
file(GET_RUNTIME_DEPENDENCIES
LIBRARIES
"${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:toplib>"
RPATH_PREFIX _rpaths
)
set(_expected_rpath "(^|;)@loader_path/;@loader_path/\\.\\./d2$")
set(_actual_rpath "${_rpaths_${CMAKE_INSTALL_PREFIX}/lib/d1/$<TARGET_FILE_NAME:sublib1>}")
if(NOT _actual_rpath MATCHES "${_expected_rpath}")
message(FATAL_ERROR "Expected rpath:\n ${_expected_rpath}\nActual rpath:\n ${_actual_rpath}")
endif()
# Since RPATH_PREFIX is an undocumented option for install(), we don't really need the rpath
# for the top files anyway.
if(DEFINED "_rpaths_${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:toplib>")
message(FATAL_ERROR "rpath for top library should not be defined")
endif()
]])