CMake target_link_directories 添加了额外意外的目录。如何移除它们?

huangapple go评论62阅读模式
英文:

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
	&quot;../MyProjectNameSharedComponents/glew/lib/x64&quot;
	&quot;../MyProjectNameSharedComponents/OpenImageIO/Windows/lib&quot;
#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.

&quot;$&lt;$&lt;CONFIG:Debug2022&gt;:&quot;
    &quot;$ENV{MAYA_X64_2022}/lib&quot;
&quot;&gt;&quot;

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.cxxcmVisualStudio10TargetGenerator::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()命令将其明确设置为OLDNEW。与许多策略不同,CMake版本3.27.0-rc3在未设置此策略时不会发出警告,而只是使用OLD行为。

查看cmGlobalXCodeGenerator.cxxcmGlobalXCodeGenerator::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&lt;std::string&gt; const&amp; ldirs = cli.GetDirectories();
  std::vector&lt;std::string&gt; linkDirs;
  for (std::string const&amp; d : ldirs) {
    // first just full path
    linkDirs.push_back(d);
    // next path with configuration type Debug, Release, etc
    linkDirs.push_back(d + &quot;/$(Configuration)&quot;);
  }

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&amp; libDir : cli-&gt;GetDirectories()) {
        if (!libDir.empty() &amp;&amp; libDir != &quot;/usr/lib&quot;) {
          cmPolicies::PolicyStatus cmp0142 =
            target-&gt;GetTarget()-&gt;GetPolicyStatusCMP0142();
          if (cmp0142 == cmPolicies::OLD || cmp0142 == cmPolicies::WARN) {
            libSearchPaths.Add(this-&gt;XCodeEscapePath(
              libDir + &quot;/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)&quot;));
          }
          libSearchPaths.Add(this-&gt;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.

huangapple
  • 本文由 发表于 2023年6月28日 23:49:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76574802.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定