英文:
CMake target_link_directories is adding extra unexpected directories. How can I remove them?
问题
请注意以下内容:
target_link_directories(${PROJECT_NAME} PUBLIC
"../MyProjectNameSharedComponents/glew/lib/x64"
"../MyProjectNameSharedComponents/OpenImageIO/Windows/lib"
#and etc.
这导致在“附加库目录”中的解决方案中出现以下行:
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/glew/lib/x64
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/glew/lib/x64/$(Configuration)
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/OpenImageIO/Windows/lib
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/OpenImageIO/Windows/lib/$(Configuration)
通过生成器表达式生成的行表现出类似的行为,例如:
"$<CONFIG:Debug2022>:"
"$ENV{MAYA_X64_2022}/lib"
">"
产生:
C:/Program Files/Autodesk/Maya2022/lib
C:/Program Files/Autodesk/Maya2022/lib/$(Configuration)
在macOS上,CMake将$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
添加到Xcode项目的LibrarySearchPath
行中,情况更糟糕。
这个"/$(Configuration)"
行是从哪里来的,如何去掉它?
英文:
Consider the following:
target_link_directories(${PROJECT_NAME} PUBLIC
"../MyProjectNameSharedComponents/glew/lib/x64"
"../MyProjectNameSharedComponents/OpenImageIO/Windows/lib"
#and etc.
This result in the following lines in the solution in Additional Library Directories:
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/glew/lib/x64
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/glew/lib/x64/$(Configuration)
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/OpenImageIO/Windows/lib
C:/Users/user/Documents/gpu-open/MyProjectName/MyProjectName.Src/../MyProjectNameSharedComponents/OpenImageIO/Windows/lib/$(Configuration)
Lines that are generated via generator expression show similar behavior, e.g.
"$<$<CONFIG:Debug2022>:"
"$ENV{MAYA_X64_2022}/lib"
">"
Produces:
C:/Program Files/Autodesk/Maya2022/lib
C:/Program Files/Autodesk/Maya2022/lib/$(Configuration)
And its even worse on macOS where CMake adds $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
to the LibrarySearchPath
lines of Xcode projects.
Where does this "/$(Configuration)" line come from, and how can I remove it?
答案1
得分: 1
在撰写本文时(CMake 3.27是最新版本),对于Visual Studio生成器,看起来这是硬编码在CMake源代码中的,没有任何禁用它的方法。
在cmVisualStudio10TargetGenerator.cxx的cmVisualStudio10TargetGenerator::ComputeLinkOptions
中:
std::vector<std::string> const& ldirs = cli.GetDirectories();
std::vector<std::string> linkDirs;
for (std::string const& d : ldirs) {
// first just full path
linkDirs.push_back(d);
// next path with configuration type Debug, Release, etc
linkDirs.push_back(d + "/$(Configuration)");
}
你可以要么构建你自己修改的CMake版本,要么请求维护者添加一个功能来切换这个行为。
对于Xcode生成器,看起来你可以通过更改policy CMP0142 (cmake_policy(SET CMP0142 NEW)
) 来禁用这个行为。引用文档:
自版本3.25起新添加。
Xcode生成器不会将每个库搜索路径附加到配置后缀。
在CMake 3.24及以下版本中,Xcode生成器在每个库搜索路径的条目之前附加了自身的副本,附加了
$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
。这是留下来的,早期版本的CMake中并没有很好地模拟每个配置目录。这种路径通常不存在,导致工具链发出警告。CMake 3.25及以上版本更倾向于不添加这样的库搜索路径。该策略提供了对可能无意依赖旧行为的项目的兼容性。该策略的
OLD
行为是将$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
附加到所有库搜索路径。NEW
行为是不修改库搜索路径。该策略是在CMake版本3.25中引入的。使用
cmake_policy()
命令将其明确设置为OLD
或NEW
。与许多策略不同,CMake版本3.27.0-rc3在未设置此策略时不会发出警告,而只是使用OLD
行为。
查看cmGlobalXCodeGenerator.cxx
的cmGlobalXCodeGenerator::AddDependAndLinkInformation
:
// add the library search paths
{
BuildObjectListOrString libSearchPaths(this, true);
std::string linkDirs;
for (auto const& libDir : cli->GetDirectories()) {
if (!libDir.empty() && libDir != "/usr/lib") {
cmPolicies::PolicyStatus cmp0142 =
target->GetTarget()->GetPolicyStatusCMP0142();
if (cmp0142 == cmPolicies::OLD || cmp0142 == cmPolicies::WARN) {
libSearchPaths.Add(this->XCodeEscapePath(
libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"));
}
libSearchPaths.Add(this->XCodeEscapePath(libDir));
}
}
}
你需要询问维护者为什么这些内容是这样的(至少从历史角度来看)。请查看https://discourse.cmake.org/。如果你提问了,请在此处留下一个链接指向Discourse页面。
英文:
At the time of this writing (when CMake 3.27 is the latest version), for the Visual Studio generator, it looks like this is hardcoded in the CMake source code without any way to disable it.
In cmVisualStudio10TargetGenerator.cxx's cmVisualStudio10TargetGenerator::ComputeLinkOptions
std::vector<std::string> const& ldirs = cli.GetDirectories();
std::vector<std::string> linkDirs;
for (std::string const& d : ldirs) {
// first just full path
linkDirs.push_back(d);
// next path with configuration type Debug, Release, etc
linkDirs.push_back(d + "/$(Configuration)");
}
You could either build your own modified version of CMake, or ask the maintainers to add a feature to toggle this behaviour.
For the Xcode generator, it looks like you can disable this by changing policy CMP0142 (cmake_policy(SET CMP0142 NEW)
). Quoting the docs:
> New in version 3.25.
>
> The Xcode generator does not append per-config suffixes to library search paths.
>
> In CMake 3.24 and below, the Xcode generator preceded each entry of a library search path with a copy of itself appended with $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
. This was left from very early versions of CMake in which per-config directories were not well modeled. Such paths often do not exist, resulting in warnings from the toolchain. CMake 3.25 and above prefer to not add such library search paths. This policy provides compatibility for projects that may have been accidentally relying on the old behavior.
>
> The OLD
behavior for this policy is to append $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
to all library search paths. The NEW
behavior is to not modify library search paths.
>
> This policy was introduced in CMake version 3.25. Use the cmake_policy()
command to set it to OLD
or NEW
explicitly. Unlike many policies, CMake version 3.27.0-rc3 does not warn when this policy is not set and simply uses OLD
behavior.
See cmGlobalXCodeGenerator.cxx
's cmGlobalXCodeGenerator::AddDependAndLinkInformation
:
// add the library search paths
{
BuildObjectListOrString libSearchPaths(this, true);
std::string linkDirs;
for (auto const& libDir : cli->GetDirectories()) {
if (!libDir.empty() && libDir != "/usr/lib") {
cmPolicies::PolicyStatus cmp0142 =
target->GetTarget()->GetPolicyStatusCMP0142();
if (cmp0142 == cmPolicies::OLD || cmp0142 == cmPolicies::WARN) {
libSearchPaths.Add(this->XCodeEscapePath(
libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"));
}
libSearchPaths.Add(this->XCodeEscapePath(libDir));
}
}
You'd need to ask the maintainers why exactly this stuff is the way it is (at least from a historical perspective). See https://discourse.cmake.org/. If you do ask, please comment here with a link to the Discourse page.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论