Merge topic 'link-implicit-libs-full-path'
882f48e5
Link libraries by full path even in implicit directories318cd370
Help: Add link target for Find Modules section of cmake-developer.71535dcd8
Tests: Teach RunCMake to optionally merge command output to stdout
This commit is contained in:
commit
1a1bdbfd87
|
@ -34,14 +34,20 @@ Each ``<item>`` may be:
|
|||
automatically be added in the build system to make sure the named
|
||||
library target is up-to-date before the ``<target>`` links.
|
||||
|
||||
If an imported library has the :prop_tgt:`IMPORTED_NO_SONAME`
|
||||
target property set, CMake may ask the linker to search for
|
||||
the library instead of using the full path
|
||||
(e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``).
|
||||
|
||||
* **A full path to a library file**: The generated link line will
|
||||
normally preserve the full path to the file. However, there are
|
||||
some cases where CMake must ask the linker to search for the library
|
||||
(e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``), such as when it
|
||||
appears in a system library directory that the compiler front-end
|
||||
may replace with an alternative. Either way, the buildsystem will
|
||||
normally preserve the full path to the file. The buildsystem will
|
||||
have a dependency to re-link ``<target>`` if the library file changes.
|
||||
|
||||
There are some cases where CMake may ask the linker to search for
|
||||
the library (e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``), such
|
||||
as when a shared library is detected to have no ``SONAME`` field.
|
||||
See policy :policy:`CMP0060` for discussion of another case.
|
||||
|
||||
If the library file is in a Mac OSX framework, the ``Headers`` directory
|
||||
of the framework will also be processed as a
|
||||
:ref:`usage requirement <Target Usage Requirements>`. This has the same
|
||||
|
|
|
@ -605,6 +605,7 @@ have a .cmake file in this directory NOT show up in the modules
|
|||
documentation, simply leave out the ``Help/module/<module-name>.rst``
|
||||
file and the ``Help/manual/cmake-modules.7.rst`` toctree entry.
|
||||
|
||||
.. _`Find Modules`:
|
||||
|
||||
Find Modules
|
||||
------------
|
||||
|
|
|
@ -117,3 +117,4 @@ All Policies
|
|||
/policy/CMP0057
|
||||
/policy/CMP0058
|
||||
/policy/CMP0059
|
||||
/policy/CMP0060
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
CMP0060
|
||||
-------
|
||||
|
||||
Link libraries by full path even in implicit directories.
|
||||
|
||||
Policy :policy:`CMP0003` was introduced with the intention of always
|
||||
linking library files by full path when a full path is given to the
|
||||
:command:`target_link_libraries` command. However, on some platforms
|
||||
(e.g. HP-UX) the compiler front-end adds alternative library search paths
|
||||
for the current architecture (e.g. ``/usr/lib/<arch>`` has alternatives
|
||||
to libraries in ``/usr/lib`` for the current architecture).
|
||||
On such platforms the :command:`find_library` may find a library such as
|
||||
``/usr/lib/libfoo.so`` that does not belong to the current architecture.
|
||||
|
||||
Prior to policy :policy:`CMP0003` projects would still build in such
|
||||
cases because the incorrect library path would be converted to ``-lfoo``
|
||||
on the link line and the linker would find the proper library in the
|
||||
arch-specific search path provided by the compiler front-end implicitly.
|
||||
At the time we chose to remain compatible with such projects by always
|
||||
converting library files found in implicit link directories to ``-lfoo``
|
||||
flags to ask the linker to search for them. This approach allowed existing
|
||||
projects to continue to build while still linking to libraries outside
|
||||
implicit link directories via full path (such as those in the build tree).
|
||||
|
||||
CMake does allow projects to override this behavior by using an
|
||||
:ref:`IMPORTED library target <Imported Targets>` with its
|
||||
:prop_tgt:`IMPORTED_LOCATION` property set to the desired full path to
|
||||
a library file. In fact, many :ref:`Find Modules` are learning to provide
|
||||
:ref:`Imported Targets` instead of just the traditional ``Foo_LIBRARIES``
|
||||
variable listing library files. However, this makes the link line
|
||||
generated for a library found by a Find Module depend on whether it
|
||||
is linked through an imported target or not, which is inconsistent.
|
||||
Furthermore, this behavior has been a source of confusion because the
|
||||
generated link line for a library file depends on its location. It is
|
||||
also problematic for projects trying to link statically because flags
|
||||
like ``-Wl,-Bstatic -lfoo -Wl,-Bdynamic`` may be used to help the linker
|
||||
select ``libfoo.a`` instead of ``libfoo.so`` but then leak dynamic linking
|
||||
to following libraries. (See the :prop_tgt:`LINK_SEARCH_END_STATIC`
|
||||
target property for a solution typically used for that problem.)
|
||||
|
||||
When the special case for libraries in implicit link directories was first
|
||||
introduced the list of implicit link directories was simply hard-coded
|
||||
(e.g. ``/lib``, ``/usr/lib``, and a few others). Since that time, CMake
|
||||
has learned to detect the implicit link directories used by the compiler
|
||||
front-end. If necessary, the :command:`find_library` command could be
|
||||
taught to use this information to help find libraries of the proper
|
||||
architecture.
|
||||
|
||||
For these reasons, CMake 3.3 and above prefer to drop the special case
|
||||
and link libraries by full path even when they are in implicit link
|
||||
directories. Policy ``CMP0060`` provides compatibility for existing
|
||||
projects.
|
||||
|
||||
The OLD behavior for this policy is to ask the linker to search for
|
||||
libraries whose full paths are known to be in implicit link directories.
|
||||
The NEW behavior for this policy is to link libraries by full path even
|
||||
if they are in implicit link directories.
|
||||
|
||||
This policy was introduced in CMake version 3.3. Unlike most policies,
|
||||
CMake version |release| does *not* warn by default when this policy
|
||||
is not set and simply uses OLD behavior. See documentation of the
|
||||
:variable:`CMAKE_POLICY_WARNING_CMP0060 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
|
||||
variable to control the warning.
|
|
@ -0,0 +1,6 @@
|
|||
link-implicit-libs-full-path
|
||||
----------------------------
|
||||
|
||||
* Linking to library files by a full path in an implicit linker search
|
||||
directory (e.g. ``/usr/lib/libfoo.a``) no longer asks the linker to
|
||||
search for the library (e.g. ``-lfoo``). See policy :policy:`CMP0060`.
|
|
@ -11,6 +11,8 @@ warn by default:
|
|||
policy :policy:`CMP0047`.
|
||||
* ``CMAKE_POLICY_WARNING_CMP0056`` controls the warning for
|
||||
policy :policy:`CMP0056`.
|
||||
* ``CMAKE_POLICY_WARNING_CMP0060`` controls the warning for
|
||||
policy :policy:`CMP0060`.
|
||||
|
||||
This variable should not be set by a project in CMake code. Project
|
||||
developers running CMake may set this variable in their cache to
|
||||
|
|
|
@ -411,6 +411,10 @@ cmComputeLinkInformation
|
|||
std::vector<std::string> const& dirs = this->Target->GetLinkDirectories();
|
||||
this->OldLinkDirMask.insert(dirs.begin(), dirs.end());
|
||||
}
|
||||
|
||||
this->CMP0060Warn =
|
||||
this->Makefile->PolicyOptionalWarningEnabled(
|
||||
"CMAKE_POLICY_WARNING_CMP0060");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -548,6 +552,22 @@ bool cmComputeLinkInformation::Compute()
|
|||
// Add implicit language runtime libraries and directories.
|
||||
this->AddImplicitLinkInfo();
|
||||
|
||||
if (!this->CMP0060WarnItems.empty())
|
||||
{
|
||||
std::ostringstream w;
|
||||
w << (this->Makefile->GetCMakeInstance()->GetPolicies()
|
||||
->GetPolicyWarning(cmPolicies::CMP0060)) << "\n"
|
||||
"Some library files are in directories implicitly searched by "
|
||||
"the linker when invoked for " << this->LinkLanguage << ":\n"
|
||||
" " << cmJoin(this->CMP0060WarnItems, "\n ") << "\n"
|
||||
"For compatibility with older versions of CMake, the generated "
|
||||
"link line will ask the linker to search for these by library "
|
||||
"name."
|
||||
;
|
||||
this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
|
||||
this->Target->GetBacktrace());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1190,6 +1210,28 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check the policy for whether we should use the approach below.
|
||||
switch (this->Target->GetPolicyStatusCMP0060())
|
||||
{
|
||||
case cmPolicies::WARN:
|
||||
if (this->CMP0060Warn)
|
||||
{
|
||||
// Print the warning at most once for this item.
|
||||
std::string const& wid = "CMP0060-WARNING-GIVEN-" + item;
|
||||
if (!this->CMakeInstance->GetPropertyAsBool(wid))
|
||||
{
|
||||
this->CMakeInstance->SetProperty(wid, "1");
|
||||
this->CMP0060WarnItems.insert(item);
|
||||
}
|
||||
}
|
||||
case cmPolicies::OLD:
|
||||
break;
|
||||
case cmPolicies::REQUIRED_ALWAYS:
|
||||
case cmPolicies::REQUIRED_IF_USED:
|
||||
case cmPolicies::NEW:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Many system linkers support multiple architectures by
|
||||
// automatically selecting the implicit linker search path for the
|
||||
// current architecture. If the library appears in an implicit link
|
||||
|
|
|
@ -175,6 +175,10 @@ private:
|
|||
std::vector<std::string> OldUserFlagItems;
|
||||
bool OldLinkDirMode;
|
||||
|
||||
// CMP0060 warnings.
|
||||
bool CMP0060Warn;
|
||||
std::set<std::string> CMP0060WarnItems;
|
||||
|
||||
// Runtime path computation.
|
||||
cmOrderDirectories* OrderRuntimeSearchPath;
|
||||
void AddLibraryRuntimeInfo(std::string const& fullPath,
|
||||
|
|
|
@ -390,6 +390,11 @@ cmPolicies::cmPolicies()
|
|||
CMP0059, "CMP0059",
|
||||
"Do no treat DEFINITIONS as a built-in directory property.",
|
||||
3,3,0, cmPolicies::WARN);
|
||||
|
||||
this->DefinePolicy(
|
||||
CMP0060, "CMP0060",
|
||||
"Link libraries by full path even in implicit directories.",
|
||||
3,3,0, cmPolicies::WARN);
|
||||
}
|
||||
|
||||
cmPolicies::~cmPolicies()
|
||||
|
|
|
@ -118,6 +118,7 @@ public:
|
|||
CMP0058, ///< Ninja requires custom command byproducts to be explicit
|
||||
CMP0059, ///< Do not treat ``DEFINITIONS`` as a built-in directory
|
||||
/// property.
|
||||
CMP0060, ///< Link libraries by full path even in implicit directories.
|
||||
|
||||
/** \brief Always the last entry.
|
||||
*
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
F(CMP0041) \
|
||||
F(CMP0042) \
|
||||
F(CMP0046) \
|
||||
F(CMP0052)
|
||||
F(CMP0052) \
|
||||
F(CMP0060)
|
||||
|
||||
class cmake;
|
||||
class cmMakefile;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Always build in a predictable configuration. For multi-config
|
||||
# generators we depend on RunCMakeTest.cmake to do this for us.
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
# Convince CMake that it can instruct the linker to search for the
|
||||
# library of the proper linkage type, but do not really pass flags.
|
||||
set(CMAKE_EXE_LINK_STATIC_C_FLAGS " ")
|
||||
set(CMAKE_EXE_LINK_DYNAMIC_C_FLAGS " ")
|
||||
|
||||
# Make a link line asking for the linker to search for the library
|
||||
# look like a missing object file so we will get predictable content
|
||||
# in the error message. This also ensures that cases expected to use
|
||||
# the full path can be verified by confirming that they link.
|
||||
set(CMAKE_LINK_LIBRARY_FLAG LINKFLAG_)
|
||||
set(CMAKE_LINK_LIBRARY_SUFFIX _LINKSUFFIX${CMAKE_C_OUTPUT_EXTENSION})
|
||||
|
||||
# Convince CMake that our library is in an implicit linker search directory.
|
||||
list(APPEND CMAKE_C_IMPLICIT_LINK_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
||||
|
||||
# Create a simple library file. Place it in our library directory.
|
||||
add_library(CMP0060 STATIC cmp0060.c)
|
||||
set_property(TARGET CMP0060 PROPERTY
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
||||
|
||||
# Add a target to link the library file by full path.
|
||||
add_executable(main1 main.c)
|
||||
target_link_libraries(main1 $<TARGET_FILE:CMP0060>)
|
||||
add_dependencies(main1 CMP0060)
|
||||
|
||||
# Add a second target to verify the warning only appears once.
|
||||
add_executable(main2 main.c)
|
||||
target_link_libraries(main2 $<TARGET_FILE:CMP0060>)
|
||||
add_dependencies(main2 CMP0060)
|
|
@ -0,0 +1,2 @@
|
|||
cmake_policy(SET CMP0060 NEW)
|
||||
include(CMP0060-Common.cmake)
|
|
@ -0,0 +1 @@
|
|||
[^0]
|
|
@ -0,0 +1 @@
|
|||
LINKFLAG_CMP0060_LINKSUFFIX
|
|
@ -0,0 +1,2 @@
|
|||
cmake_policy(SET CMP0060 OLD)
|
||||
include(CMP0060-Common.cmake)
|
|
@ -0,0 +1 @@
|
|||
[^0]
|
|
@ -0,0 +1 @@
|
|||
LINKFLAG_CMP0060_LINKSUFFIX
|
|
@ -0,0 +1 @@
|
|||
include(CMP0060-Common.cmake)
|
|
@ -0,0 +1 @@
|
|||
[^0]
|
|
@ -0,0 +1 @@
|
|||
LINKFLAG_CMP0060_LINKSUFFIX
|
|
@ -0,0 +1,16 @@
|
|||
^CMake Warning \(dev\) at CMP0060-Common.cmake:[0-9]+ \(add_executable\):
|
||||
Policy CMP0060 is not set: Link libraries by full path even in implicit
|
||||
directories. Run "cmake --help-policy CMP0060" for policy details. Use
|
||||
the cmake_policy command to set the policy and suppress this warning.
|
||||
|
||||
Some library files are in directories implicitly searched by the linker
|
||||
when invoked for C:
|
||||
|
||||
.*/Tests/RunCMake/CMP0060/CMP0060-WARN-ON-build/lib/(lib)?CMP0060.(a|lib)
|
||||
|
||||
For compatibility with older versions of CMake, the generated link line
|
||||
will ask the linker to search for these by library name.
|
||||
Call Stack \(most recent call first\):
|
||||
CMP0060-WARN-ON.cmake:[0-9]+ \(include\)
|
||||
CMakeLists.txt:3 \(include\)
|
||||
This warning is for project developers. Use -Wno-dev to suppress it.$
|
|
@ -0,0 +1,2 @@
|
|||
set(CMAKE_POLICY_WARNING_CMP0060 1)
|
||||
include(CMP0060-Common.cmake)
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 3.2)
|
||||
project(${RunCMake_TEST} C)
|
||||
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1,19 @@
|
|||
include(RunCMake)
|
||||
|
||||
function(run_cmake_CMP0060 CASE)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0060-${CASE}-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||
|
||||
run_cmake(CMP0060-${CASE})
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
run_cmake_command(CMP0060-${CASE}-Build
|
||||
${CMAKE_COMMAND} --build . --config Debug
|
||||
)
|
||||
endfunction()
|
||||
|
||||
run_cmake_CMP0060(OLD)
|
||||
run_cmake_CMP0060(WARN-OFF)
|
||||
run_cmake_CMP0060(WARN-ON)
|
||||
run_cmake_CMP0060(NEW)
|
|
@ -0,0 +1,4 @@
|
|||
int libCMP0060(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
extern int libCMP0060(void);
|
||||
int main(void)
|
||||
{
|
||||
return libCMP0060();
|
||||
}
|
|
@ -65,6 +65,7 @@ add_RunCMake_test(CMP0054)
|
|||
add_RunCMake_test(CMP0055)
|
||||
add_RunCMake_test(CMP0057)
|
||||
add_RunCMake_test(CMP0059)
|
||||
add_RunCMake_test(CMP0060)
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
add_RunCMake_test(Ninja)
|
||||
endif()
|
||||
|
|
|
@ -54,12 +54,18 @@ function(run_cmake test)
|
|||
if(RunCMake_MAKE_PROGRAM)
|
||||
list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}")
|
||||
endif()
|
||||
if(RunCMake_TEST_OUTPUT_MERGE)
|
||||
set(actual_stderr_var actual_stdout)
|
||||
set(actual_stderr "")
|
||||
else()
|
||||
set(actual_stderr_var actual_stderr)
|
||||
endif()
|
||||
if(RunCMake_TEST_COMMAND)
|
||||
execute_process(
|
||||
COMMAND ${RunCMake_TEST_COMMAND}
|
||||
WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
|
||||
OUTPUT_VARIABLE actual_stdout
|
||||
ERROR_VARIABLE actual_stderr
|
||||
ERROR_VARIABLE ${actual_stderr_var}
|
||||
RESULT_VARIABLE actual_result
|
||||
)
|
||||
else()
|
||||
|
@ -73,7 +79,7 @@ function(run_cmake test)
|
|||
${RunCMake_TEST_OPTIONS}
|
||||
WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
|
||||
OUTPUT_VARIABLE actual_stdout
|
||||
ERROR_VARIABLE actual_stderr
|
||||
ERROR_VARIABLE ${actual_stderr_var}
|
||||
RESULT_VARIABLE actual_result
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
\* CMP0042
|
||||
\* CMP0046
|
||||
\* CMP0052
|
||||
\* CMP0060
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
|
Loading…
Reference in New Issue