diff options
author | Vito Gamberini <vito.gamberini@kitware.com> | 2024-08-07 18:17:18 (GMT) |
---|---|---|
committer | Vito Gamberini <vito.gamberini@kitware.com> | 2024-08-28 19:54:43 (GMT) |
commit | 20e9b59d5e215768956ec131e80e540ed60d2487 (patch) | |
tree | a2fd3c4d6adedfe1309526701b240f91955e4cc7 | |
parent | 041a482079baf690f1bf8e9cdc8a7a1922016267 (diff) | |
download | CMake-20e9b59d5e215768956ec131e80e540ed60d2487.zip CMake-20e9b59d5e215768956ec131e80e540ed60d2487.tar.gz CMake-20e9b59d5e215768956ec131e80e540ed60d2487.tar.bz2 |
Linking: Add CMAKE_LANG_STANDARD_LINK_DIRECTORIES
Closes: #18222
20 files changed, 120 insertions, 10 deletions
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 1d6331e..48d4a5c 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/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 diff --git a/Help/release/dev/standard-link-directories.rst b/Help/release/dev/standard-link-directories.rst new file mode 100644 index 0000000..5c4f287 --- /dev/null +++ b/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. diff --git a/Help/variable/CMAKE_LANG_STANDARD_LINK_DIRECTORIES.rst b/Help/variable/CMAKE_LANG_STANDARD_LINK_DIRECTORIES.rst new file mode 100644 index 0000000..15aec23 --- /dev/null +++ b/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`. diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index aa948a5..7fa21d0 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/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(), diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index a29e33f..e823337 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/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) diff --git a/Source/cmLinkLineComputer.h b/Source/cmLinkLineComputer.h index afd3944..63cbeb2 100644 --- a/Source/cmLinkLineComputer.h +++ b/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, diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 601f4b3..2dc8351 100644 --- a/Source/cmLocalGenerator.cxx +++ b/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); } diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 8577cc4..bf32ce5 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/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, diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index bb05226..7c395d6 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/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, diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 54bab9f..0a40645 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -4465,14 +4465,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); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 112e530..383c80f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -491,6 +491,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}) diff --git a/Tests/RunCMake/StandardLinkDirectories/CMakeLists.txt b/Tests/RunCMake/StandardLinkDirectories/CMakeLists.txt new file mode 100644 index 0000000..ccf88ee --- /dev/null +++ b/Tests/RunCMake/StandardLinkDirectories/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.30) +project(${RunCMake_TEST} LANGUAGES C) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/StandardLinkDirectories/RunCMakeTest.cmake b/Tests/RunCMake/StandardLinkDirectories/RunCMakeTest.cmake new file mode 100644 index 0000000..6760ffc --- /dev/null +++ b/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() diff --git a/Tests/RunCMake/StandardLinkDirectories/TestApp.cmake b/Tests/RunCMake/StandardLinkDirectories/TestApp.cmake new file mode 100644 index 0000000..53a9c9a --- /dev/null +++ b/Tests/RunCMake/StandardLinkDirectories/TestApp.cmake @@ -0,0 +1 @@ +add_subdirectory(TestApp) diff --git a/Tests/RunCMake/StandardLinkDirectories/TestApp/CMakeLists.txt b/Tests/RunCMake/StandardLinkDirectories/TestApp/CMakeLists.txt new file mode 100644 index 0000000..92dd52f --- /dev/null +++ b/Tests/RunCMake/StandardLinkDirectories/TestApp/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(TestApp TestApp.c) +target_link_libraries(TestApp PRIVATE SLD) diff --git a/Tests/RunCMake/StandardLinkDirectories/TestApp/TestApp.c b/Tests/RunCMake/StandardLinkDirectories/TestApp/TestApp.c new file mode 100644 index 0000000..66630d8 --- /dev/null +++ b/Tests/RunCMake/StandardLinkDirectories/TestApp/TestApp.c @@ -0,0 +1,6 @@ +int TestSymbol(void); + +int main(void) +{ + return TestSymbol(); +} diff --git a/Tests/RunCMake/StandardLinkDirectories/TestAppBad-result.txt b/Tests/RunCMake/StandardLinkDirectories/TestAppBad-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/StandardLinkDirectories/TestAppBad-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/StandardLinkDirectories/TestLib.cmake b/Tests/RunCMake/StandardLinkDirectories/TestLib.cmake new file mode 100644 index 0000000..aa8a6c3 --- /dev/null +++ b/Tests/RunCMake/StandardLinkDirectories/TestLib.cmake @@ -0,0 +1 @@ +add_subdirectory(TestLib) diff --git a/Tests/RunCMake/StandardLinkDirectories/TestLib/CMakeLists.txt b/Tests/RunCMake/StandardLinkDirectories/TestLib/CMakeLists.txt new file mode 100644 index 0000000..bf41631 --- /dev/null +++ b/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>) diff --git a/Tests/RunCMake/StandardLinkDirectories/TestLib/TestLib.c b/Tests/RunCMake/StandardLinkDirectories/TestLib/TestLib.c new file mode 100644 index 0000000..e5d2b1c --- /dev/null +++ b/Tests/RunCMake/StandardLinkDirectories/TestLib/TestLib.c @@ -0,0 +1,4 @@ +int TestSymbol(void) +{ + return 0; +} |