Bladeren bron

Merge topic 'standard-link-directories'

20e9b59d5e Linking: Add CMAKE_LANG_STANDARD_LINK_DIRECTORIES

Acked-by: Kitware Robot <[email protected]>
Tested-by: buildbot <[email protected]>
Merge-request: !9707
Brad King 1 jaar geleden
bovenliggende
commit
e25f95c4cc

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -654,6 +654,7 @@ Variables for Languages
    /variable/CMAKE_LANG_STANDARD_INCLUDE_DIRECTORIES
    /variable/CMAKE_LANG_STANDARD_LATEST
    /variable/CMAKE_LANG_STANDARD_LIBRARIES
+   /variable/CMAKE_LANG_STANDARD_LINK_DIRECTORIES
    /variable/CMAKE_LANG_STANDARD_REQUIRED
    /variable/CMAKE_OBJC_EXTENSIONS
    /variable/CMAKE_OBJC_STANDARD

+ 6 - 0
Help/release/dev/standard-link-directories.rst

@@ -0,0 +1,6 @@
+standard-link-directories
+-------------------------
+
+* The :variable:`CMAKE_<LANG>_STANDARD_LINK_DIRECTORIES` variable was added.
+  Toolchain files can set this variable to control which link library directory
+  paths are always passed to the compiler for the specified language.

+ 14 - 0
Help/variable/CMAKE_LANG_STANDARD_LINK_DIRECTORIES.rst

@@ -0,0 +1,14 @@
+CMAKE_<LANG>_STANDARD_LINK_DIRECTORIES
+--------------------------------------
+
+.. versionadded:: 3.31
+
+Link directories specified for every executable and library linked
+for language ``<LANG>``.  This is meant for specification of system
+link directories needed by the language for the current platform.
+
+This variable should not be set by project code.  It is meant to be set by
+CMake's platform information modules for the current toolchain, or by a
+toolchain file when used with :variable:`CMAKE_TOOLCHAIN_FILE`.
+
+See also :variable:`CMAKE_<LANG>_STANDARD_LIBRARIES`.

+ 10 - 1
Source/cmGlobalXCodeGenerator.cxx

@@ -3994,7 +3994,6 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
     {
       BuildObjectListOrString libSearchPaths(this, true);
 
-      std::string linkDirs;
       for (auto const& libDir : cli->GetDirectories()) {
         if (!libDir.empty() && libDir != "/usr/lib"_s) {
           cmPolicies::PolicyStatus cmp0142 =
@@ -4012,6 +4011,16 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
       for (auto& libDir : linkSearchPaths) {
         libSearchPaths.Add(this->XCodeEscapePath(libDir));
       }
+
+      // Add toolchain specified language link directories
+      std::string const& linkDirsString =
+        this->Makefiles.front()->GetSafeDefinition(cmStrCat(
+          "CMAKE_", cli->GetLinkLanguage(), "_STANDARD_LINK_DIRECTORIES"));
+
+      for (const auto& libDir : cmList(linkDirsString)) {
+        libSearchPaths.Add(this->XCodeEscapePath(libDir));
+      }
+
       if (!libSearchPaths.IsEmpty()) {
         this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
                                           libSearchPaths.CreateList(),

+ 12 - 3
Source/cmLinkLineComputer.cxx

@@ -9,6 +9,7 @@
 
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
+#include "cmList.h"
 #include "cmListFileCache.h"
 #include "cmOutputConverter.h"
 #include "cmStateTypes.h"
@@ -112,18 +113,20 @@ std::string cmLinkLineComputer::ConvertToOutputForExisting(
 
 std::string cmLinkLineComputer::ComputeLinkPath(
   cmComputeLinkInformation& cli, std::string const& libPathFlag,
-  std::string const& libPathTerminator)
+  std::string const& libPathTerminator, std::string const& stdLinkDirString)
 {
   std::string linkPath;
   std::vector<BT<std::string>> linkPathList;
-  this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, linkPathList);
+  this->ComputeLinkPath(cli, libPathFlag, libPathTerminator, stdLinkDirString,
+                        linkPathList);
   cli.AppendValues(linkPath, linkPathList);
   return linkPath;
 }
 
 void cmLinkLineComputer::ComputeLinkPath(
   cmComputeLinkInformation& cli, std::string const& libPathFlag,
-  std::string const& libPathTerminator, std::vector<BT<std::string>>& linkPath)
+  std::string const& libPathTerminator, std::string const& stdLinkDirString,
+  std::vector<BT<std::string>>& linkPath)
 {
   if (cli.GetLinkLanguage() == "Swift") {
     std::string linkPathNoBT;
@@ -160,6 +163,12 @@ void cmLinkLineComputer::ComputeLinkPath(
                             libPathTerminator, " ");
     linkPath.emplace_back(libDir);
   }
+
+  for (auto& linkDir : cmList(stdLinkDirString)) {
+    linkPath.emplace_back(cmStrCat(' ', libPathFlag,
+                                   this->ConvertToOutputForExisting(linkDir),
+                                   libPathTerminator, ' '));
+  }
 }
 
 std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)

+ 3 - 1
Source/cmLinkLineComputer.h

@@ -36,11 +36,13 @@ public:
 
   std::string ComputeLinkPath(cmComputeLinkInformation& cli,
                               std::string const& libPathFlag,
-                              std::string const& libPathTerminator);
+                              std::string const& libPathTerminator,
+                              std::string const& stdLinkDirString);
 
   void ComputeLinkPath(cmComputeLinkInformation& cli,
                        std::string const& libPathFlag,
                        std::string const& libPathTerminator,
+                       std::string const& stdLinkDirString,
                        std::vector<BT<std::string>>& linkPath);
 
   std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,

+ 5 - 1
Source/cmLocalGenerator.cxx

@@ -1897,6 +1897,10 @@ void cmLocalGenerator::OutputLinkLibraries(
       this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
   }
 
+  // Add standard link directories for this language
+  std::string stdLinkDirString = this->Makefile->GetSafeDefinition(
+    cmStrCat("CMAKE_", cli.GetLinkLanguage(), "_STANDARD_LINK_DIRECTORIES"));
+
   // Add standard libraries for this language.
   std::string stdLibString = this->Makefile->GetSafeDefinition(
     cmStrCat("CMAKE_", cli.GetLinkLanguage(), "_STANDARD_LIBRARIES"));
@@ -1907,7 +1911,7 @@ void cmLocalGenerator::OutputLinkLibraries(
 
   frameworkPath = linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag);
   linkLineComputer->ComputeLinkPath(cli, libPathFlag, libPathTerminator,
-                                    linkPath);
+                                    stdLinkDirString, linkPath);
   linkLineComputer->ComputeLinkLibraries(cli, stdLibString, linkLibraries);
 }
 

+ 17 - 3
Source/cmLocalVisualStudio7Generator.cxx

@@ -1123,7 +1123,10 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       this->WriteTargetVersionAttribute(fout, target);
       linkOptions.OutputFlagMap(fout, 4);
       fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
-      this->OutputLibraryDirectories(fout, cli.GetDirectories());
+      std::string const& linkDirsString = this->Makefile->GetSafeDefinition(
+        cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LINK_DIRECTORIES"));
+      this->OutputLibraryDirectories(fout, cmList(linkDirsString),
+                                     cli.GetDirectories());
       fout << "\"\n";
       temp =
         cmStrCat(target->GetPDBDirectory(configName), '/', targetNames.PDB);
@@ -1206,7 +1209,10 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       this->WriteTargetVersionAttribute(fout, target);
       linkOptions.OutputFlagMap(fout, 4);
       fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
-      this->OutputLibraryDirectories(fout, cli.GetDirectories());
+      std::string const& linkDirsString = this->Makefile->GetSafeDefinition(
+        cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LINK_DIRECTORIES"));
+      this->OutputLibraryDirectories(fout, cmList(linkDirsString),
+                                     cli.GetDirectories());
       fout << "\"\n";
       std::string path = this->ConvertToXMLOutputPathSingle(
         target->GetPDBDirectory(configName));
@@ -1356,9 +1362,11 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
 }
 
 void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
-  std::ostream& fout, std::vector<std::string> const& dirs)
+  std::ostream& fout, std::vector<std::string> const& stdlink,
+  std::vector<std::string> const& dirs)
 {
   const char* comma = "";
+
   for (std::string dir : dirs) {
     // Remove any trailing slash and skip empty paths.
     if (dir.back() == '/') {
@@ -1384,6 +1392,12 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
          << ',' << this->ConvertToXMLOutputPath(dir);
     comma = ",";
   }
+
+  // No special processing on toolchain-defined standard link directory paths
+  for (const auto& dir : stdlink) {
+    fout << comma << this->ConvertToXMLOutputPath(dir);
+    comma = ",";
+  }
 }
 
 void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,

+ 1 - 0
Source/cmLocalVisualStudio7Generator.h

@@ -125,6 +125,7 @@ private:
                                     std::string const& config,
                                     cmGeneratorTarget* target);
   void OutputLibraryDirectories(std::ostream& fout,
+                                std::vector<std::string> const& stdlink,
                                 std::vector<std::string> const& dirs);
   void WriteProjectSCC(std::ostream& fout, cmGeneratorTarget* target);
   void WriteProjectStart(std::ostream& fout, const std::string& libName,

+ 8 - 1
Source/cmVisualStudio10TargetGenerator.cxx

@@ -4457,14 +4457,21 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
     this->AddTargetsFileAndConfigPair(ti, config);
   }
 
-  std::vector<std::string> const& ldirs = cli.GetDirectories();
   std::vector<std::string> linkDirs;
+  std::vector<std::string> const& ldirs = cli.GetDirectories();
   for (std::string const& d : ldirs) {
     // first just full path
     linkDirs.push_back(d);
     // next path with configuration type Debug, Release, etc
     linkDirs.emplace_back(cmStrCat(d, "/$(Configuration)"));
   }
+
+  std::string const& linkDirsString = this->Makefile->GetSafeDefinition(
+    cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LINK_DIRECTORIES"));
+  for (const std::string& d : cmList(linkDirsString)) {
+    linkDirs.push_back(d);
+  }
+
   linkDirs.push_back("%(AdditionalLibraryDirectories)");
   linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs);
 

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -492,6 +492,7 @@ if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG)
     )
 endif()
 add_RunCMake_test(ScriptMode)
+add_RunCMake_test(StandardLinkDirectories)
 add_RunCMake_test(Swift -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
                         -DCMake_TEST_Swift=${CMake_TEST_Swift}
                         -DXCODE_VERSION=${XCODE_VERSION})

+ 3 - 0
Tests/RunCMake/StandardLinkDirectories/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.30)
+project(${RunCMake_TEST} LANGUAGES C)
+include(${RunCMake_TEST}.cmake)

+ 22 - 0
Tests/RunCMake/StandardLinkDirectories/RunCMakeTest.cmake

@@ -0,0 +1,22 @@
+include(RunCMake)
+
+# Link should succeed
+block()
+  set(libdir ${RunCMake_BINARY_DIR}/TestLib-build/TestLib/lib)
+  run_cmake(TestLib)
+  run_cmake_with_options(TestApp "-DCMAKE_C_STANDARD_LINK_DIRECTORIES=${libdir}")
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_OUTPUT_MERGE 1)
+  run_cmake_command(TestLib ${CMAKE_COMMAND} --build .)
+  run_cmake_command(TestAppGood ${CMAKE_COMMAND} --build ../TestApp-build)
+endblock()
+
+# Link should fail
+block()
+  run_cmake(TestLib)
+  run_cmake(TestApp)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_OUTPUT_MERGE 1)
+  run_cmake_command(TestLib ${CMAKE_COMMAND} --build .)
+  run_cmake_command(TestAppBad ${CMAKE_COMMAND} --build ../TestApp-build)
+endblock()

+ 1 - 0
Tests/RunCMake/StandardLinkDirectories/TestApp.cmake

@@ -0,0 +1 @@
+add_subdirectory(TestApp)

+ 2 - 0
Tests/RunCMake/StandardLinkDirectories/TestApp/CMakeLists.txt

@@ -0,0 +1,2 @@
+add_executable(TestApp TestApp.c)
+target_link_libraries(TestApp PRIVATE SLD)

+ 6 - 0
Tests/RunCMake/StandardLinkDirectories/TestApp/TestApp.c

@@ -0,0 +1,6 @@
+int TestSymbol(void);
+
+int main(void)
+{
+  return TestSymbol();
+}

+ 1 - 0
Tests/RunCMake/StandardLinkDirectories/TestAppBad-result.txt

@@ -0,0 +1 @@
+[^0]

+ 1 - 0
Tests/RunCMake/StandardLinkDirectories/TestLib.cmake

@@ -0,0 +1 @@
+add_subdirectory(TestLib)

+ 2 - 0
Tests/RunCMake/StandardLinkDirectories/TestLib/CMakeLists.txt

@@ -0,0 +1,2 @@
+add_library(SLD TestLib.c)
+set_target_properties(SLD PROPERTIES ARCHIVE_OUTPUT_DIRECTORY $<1:lib>)

+ 4 - 0
Tests/RunCMake/StandardLinkDirectories/TestLib/TestLib.c

@@ -0,0 +1,4 @@
+int TestSymbol(void)
+{
+  return 0;
+}