link_directories(): enhance capabilities

This commit is contained in:
Marc Chevrier 2018-09-19 14:12:35 +02:00 committed by Craig Scott
parent b5915744eb
commit f9717725f9
13 changed files with 120 additions and 10 deletions

View File

@ -5,7 +5,7 @@ Add directories in which the linker will look for libraries.
::
link_directories(directory1 [directory2 ...])
link_directories([AFTER|BEFORE] directory1 [directory2 ...])
Add the paths in which the linker should search for libraries.
Relative paths given to this command are interpreted as relative to
@ -16,6 +16,12 @@ property for the current ``CMakeLists.txt`` file, converting relative
paths to absolute as needed.
The command will apply only to targets created after it is called.
By default the directories specified are appended onto the current list of
directories. This default behavior can be changed by setting
:variable:`CMAKE_LINK_DIRECTORIES_BEFORE` to ``ON``. By using
``AFTER`` or ``BEFORE`` explicitly, you can select between appending and
prepending, independent of the default.
Arguments to ``link_directories`` may use "generator expressions" with
the syntax "$<...>". See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`

View File

@ -179,6 +179,7 @@ Variables that Change Behavior
/variable/CMAKE_INSTALL_PREFIX
/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
/variable/CMAKE_LIBRARY_PATH
/variable/CMAKE_LINK_DIRECTORIES_BEFORE
/variable/CMAKE_MFC_FLAG
/variable/CMAKE_MODULE_PATH
/variable/CMAKE_NOT_USING_CONFIG_FLAGS

View File

@ -0,0 +1,5 @@
link_directories-enhancements
-----------------------------
* :command:`link_directories` command gains capability to control directories
insertion position.

View File

@ -0,0 +1,9 @@
CMAKE_LINK_DIRECTORIES_BEFORE
-----------------------------
Whether to append or prepend directories by default in
:command:`link_directories`.
This variable affects the default behavior of the :command:`link_directories`
command. Setting this variable to ``ON`` is equivalent to using the ``BEFORE``
option in all uses of that command.

View File

@ -4,6 +4,7 @@
#include <sstream>
#include "cmAlgorithms.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
@ -20,13 +21,29 @@ bool cmLinkDirectoriesCommand::InitialPass(
return true;
}
for (std::string const& i : args) {
this->AddLinkDir(i);
bool before = this->Makefile->IsOn("CMAKE_LINK_DIRECTORIES_BEFORE");
auto i = args.cbegin();
if ((*i) == "BEFORE") {
before = true;
++i;
} else if ((*i) == "AFTER") {
before = false;
++i;
}
std::vector<std::string> directories;
for (; i != args.cend(); ++i) {
this->AddLinkDir(*i, directories);
}
this->Makefile->AddLinkDirectory(cmJoin(directories, ";"), before);
return true;
}
void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
void cmLinkDirectoriesCommand::AddLinkDir(
std::string const& dir, std::vector<std::string>& directories)
{
std::string unixPath = dir;
cmSystemTools::ConvertToUnixSlashes(unixPath);
@ -64,5 +81,5 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
unixPath = tmp;
}
}
this->Makefile->AddLinkDirectory(unixPath);
directories.push_back(unixPath);
}

View File

@ -36,7 +36,8 @@ public:
cmExecutionStatus& status) override;
private:
void AddLinkDir(std::string const& dir);
void AddLinkDir(std::string const& dir,
std::vector<std::string>& directories);
};
#endif

View File

@ -1248,9 +1248,16 @@ void cmMakefile::AddLinkOption(std::string const& option)
this->AppendProperty("LINK_OPTIONS", option.c_str());
}
void cmMakefile::AddLinkDirectory(std::string const& directory)
void cmMakefile::AddLinkDirectory(std::string const& directory, bool before)
{
this->AppendProperty("LINK_DIRECTORIES", directory.c_str());
cmListFileBacktrace lfbt = this->GetBacktrace();
if (before) {
this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory,
lfbt);
} else {
this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory,
lfbt);
}
}
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)

View File

@ -182,7 +182,7 @@ public:
void AddCompileDefinition(std::string const& definition);
void AddCompileOption(std::string const& option);
void AddLinkOption(std::string const& option);
void AddLinkDirectory(std::string const& directory);
void AddLinkDirectory(std::string const& directory, bool before = false);
/** Create a new imported target with the name and type given. */
cmTarget* AddImportedTarget(const std::string& name,

View File

@ -417,6 +417,33 @@ void cmStateDirectory::AppendLinkDirectoriesEntry(
this->DirectoryState->LinkDirectoriesBacktraces,
this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
}
void cmStateDirectory::PrependLinkDirectoriesEntry(
const std::string& vec, const cmListFileBacktrace& lfbt)
{
std::vector<std::string>::iterator entryEnd =
this->DirectoryState->LinkDirectories.begin() +
this->Snapshot_.Position->LinkDirectoriesPosition;
std::vector<std::string>::reverse_iterator rend =
this->DirectoryState->LinkDirectories.rend();
std::vector<std::string>::reverse_iterator rbegin =
cmMakeReverseIterator(entryEnd);
rbegin = std::find(rbegin, rend, cmPropertySentinal);
std::vector<std::string>::iterator entryIt = rbegin.base();
std::vector<std::string>::iterator entryBegin =
this->DirectoryState->LinkDirectories.begin();
std::vector<cmListFileBacktrace>::iterator btIt =
this->DirectoryState->LinkDirectoriesBacktraces.begin() +
std::distance(entryBegin, entryIt);
this->DirectoryState->LinkDirectories.insert(entryIt, vec);
this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt);
this->Snapshot_.Position->LinkDirectoriesPosition =
this->DirectoryState->LinkDirectories.size();
}
void cmStateDirectory::SetLinkDirectories(const std::string& vec,
const cmListFileBacktrace& lfbt)

View File

@ -62,6 +62,8 @@ public:
cmBacktraceRange GetLinkOptionsEntryBacktraces() const;
void AppendLinkOptionsEntry(std::string const& vec,
cmListFileBacktrace const& lfbt);
void PrependLinkDirectoriesEntry(std::string const& vec,
cmListFileBacktrace const& lfbt);
void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt);
void ClearLinkOptions();

View File

@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.12)
project(link_directories LANGUAGES C)
link_directories(/A)
link_directories(BEFORE /B)
set(CMAKE_LINK_DIRECTORIES_BEFORE ON)
link_directories(/C)
get_directory_property(result LINK_DIRECTORIES)
if (NOT result MATCHES "/C;/B;/A")
message(SEND_ERROR "link_directories not populated the LINK_DIRECTORIES directory property")
endif()
add_executable(link_directories EXCLUDE_FROM_ALL LinkDirectoriesExe.c)
get_target_property(result link_directories LINK_DIRECTORIES)
if (NOT result MATCHES "/C;/B;/A")
message(SEND_ERROR "link_directories not populated the LINK_DIRECTORIES target property")
endif()
add_library(imp UNKNOWN IMPORTED)
get_target_property(result imp LINK_DIRECTORIES)
if (result)
message(FATAL_ERROR "link_directories populated the LINK_DIRECTORIES target property")
endif()

View File

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

View File

@ -2823,7 +2823,6 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
ADD_TEST_MACRO(CMakeCommands.add_compile_definitions add_compile_definitions)
ADD_TEST_MACRO(CMakeCommands.add_compile_options add_compile_options)
ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries)
ADD_TEST_MACRO(CMakeCommands.target_link_directories)
ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories)
ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions)
ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options)
@ -2831,6 +2830,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
ADD_TEST_MACRO(CMakeCommands.add_link_options)
ADD_TEST_MACRO(CMakeCommands.target_link_options)
ADD_TEST_MACRO(CMakeCommands.link_directories)
ADD_TEST_MACRO(CMakeCommands.target_link_directories)
# The cmake server-mode test requires python for a simple client.
find_package(PythonInterp QUIET)