mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
add_library(): Allow imported object libraries with multi-arch
Fixes: #21276
This commit is contained in:
@@ -3,11 +3,91 @@ IMPORTED_OBJECTS
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
A :ref:`semicolon-separated list <CMake Language Lists>` of absolute paths to the object
|
||||
files on disk for an :ref:`imported <Imported targets>`
|
||||
A :ref:`semicolon-separated list <CMake Language Lists>` of absolute paths
|
||||
to the object files on disk for an :ref:`imported <Imported targets>`
|
||||
:ref:`object library <object libraries>`.
|
||||
|
||||
Ignored for non-imported targets.
|
||||
|
||||
Projects may skip ``IMPORTED_OBJECTS`` if the configuration-specific
|
||||
property :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` is set instead.
|
||||
property :prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` is set instead, except in
|
||||
situations as noted in the section below.
|
||||
|
||||
|
||||
Xcode Generator Considerations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.20
|
||||
|
||||
For Apple platforms, a project may be built for more than one architecture.
|
||||
This is controlled by the :variable:`CMAKE_OSX_ARCHITECTURES` variable.
|
||||
For all but the :generator:`Xcode` generator, CMake invokes compilers once
|
||||
per source file and passes multiple ``-arch`` flags, leading to a single
|
||||
object file which will be a universal binary. Such object files work well
|
||||
when listed in the ``IMPORTED_OBJECTS`` of a separate CMake build, even for
|
||||
the :generator:`Xcode` generator. But producing such object files with the
|
||||
:generator:`Xcode` generator is more difficult, since it invokes the compiler
|
||||
once per architecture for each source file. Unlike the other generators,
|
||||
it does not generate universal object file binaries.
|
||||
|
||||
A further complication with the :generator:`Xcode` generator is that when
|
||||
targeting device platforms (iOS, tvOS or watchOS), the :generator:`Xcode`
|
||||
generator has the ability to use either the device or simulator SDK without
|
||||
needing CMake to be re-run. The SDK can be selected at build time.
|
||||
But since some architectures can be supported by both the device and the
|
||||
simulator SDKs (e.g. ``arm64`` with Xcode 12 or later), not all combinations
|
||||
can be represented in a single universal binary. The only solution in this
|
||||
case is to have multiple object files.
|
||||
|
||||
``IMPORTED_OBJECTS`` doesn't support generator expressions, so every file
|
||||
it lists needs to be valid for every architecture and SDK. If incorporating
|
||||
object files that are not universal binaries, the path and/or file name of
|
||||
each object file has to somehow encapsulate the different architectures and
|
||||
SDKs. With the :generator:`Xcode` generator, Xcode variables of the form
|
||||
``$(...)`` can be used to represent these aspects and Xcode will substitute
|
||||
the appropriate values at build time. CMake doesn't interpret these
|
||||
variables and embeds them unchanged in the Xcode project file.
|
||||
``$(CURRENT_ARCH)`` can be used to represent the architecture, while
|
||||
``$(EFFECTIVE_PLATFORM_NAME)`` can be used to differentiate between SDKs.
|
||||
|
||||
The following shows one example of how these two variables can be used to
|
||||
refer to an object file whose location depends on both the SDK and the
|
||||
architecture:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(someObjs OBJECT IMPORTED)
|
||||
|
||||
set_property(TARGET someObjs PROPERTY IMPORTED_OBJECTS
|
||||
# Quotes are required because of the ()
|
||||
"/path/to/somewhere/objects$(EFFECTIVE_PLATFORM_NAME)/$(CURRENT_ARCH)/func.o"
|
||||
)
|
||||
|
||||
# Example paths:
|
||||
# /path/to/somewhere/objects-iphoneos/arm64/func.o
|
||||
# /path/to/somewhere/objects-iphonesimulator/x86_64/func.o
|
||||
|
||||
In some cases, you may want to have configuration-specific object files
|
||||
as well. The :variable:`CMAKE_CFG_INTDIR` variable can be a convenient
|
||||
way of capturing this in combination with the SDK:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(someObjs OBJECT IMPORTED)
|
||||
set_property(TARGET someObjs PROPERTY IMPORTED_OBJECTS
|
||||
"/path/to/somewhere/${CMAKE_CFG_INTDIR}/$(CURRENT_ARCH)/func.o"
|
||||
)
|
||||
|
||||
# Example paths:
|
||||
# /path/to/somewhere/Release-iphoneos/arm64/func.o
|
||||
# /path/to/somewhere/Debug-iphonesimulator/x86_64/func.o
|
||||
|
||||
When any Xcode variable or :variable:`CMAKE_CFG_INTDIR` is used, CMake is
|
||||
not able to fully evaluate the path(s) at configure time. One consequence
|
||||
of this is that the configuration-specific
|
||||
:prop_tgt:`IMPORTED_OBJECTS_<CONFIG>` properties cannot be used, since
|
||||
CMake cannot determine whether an object file exists at a particular
|
||||
``<CONFIG>`` location. The ``IMPORTED_OBJECTS`` property must be used for
|
||||
these situations and the configuration-specific aspects of the path must be
|
||||
handled by using :variable:`CMAKE_CFG_INTDIR` or with another Xcode variable
|
||||
``$(CONFIGURATION)``.
|
||||
|
@@ -3,7 +3,18 @@ IMPORTED_OBJECTS_<CONFIG>
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
<CONFIG>-specific version of :prop_tgt:`IMPORTED_OBJECTS` property.
|
||||
``<CONFIG>``-specific version of :prop_tgt:`IMPORTED_OBJECTS` property.
|
||||
|
||||
Configuration names correspond to those provided by the project from
|
||||
which the target is imported.
|
||||
|
||||
|
||||
Xcode Generator Considerations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Do not use this ``<CONFIG>``-specific property if you need to use Xcode
|
||||
variables like ``$(CURRENT_ARCH)`` or ``$(EFFECTIVE_PLATFORM_NAME)`` in
|
||||
the value. The ``<CONFIG>``-specific properties will be ignored in such
|
||||
cases because CMake cannot determine whether a file exists at the
|
||||
configuration-specific path at configuration time. For such cases, use
|
||||
:prop_tgt:`IMPORTED_OBJECTS` instead.
|
||||
|
8
Help/release/dev/object-lib-multiarch.rst
Normal file
8
Help/release/dev/object-lib-multiarch.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
object-lib-multiarch
|
||||
--------------------
|
||||
|
||||
* The :command:`add_library` command previously prohibited imported object
|
||||
libraries when using potentially multi-architecture configurations.
|
||||
This mostly affected the :generator:`Xcode` generator, e.g. when targeting
|
||||
iOS or one of the other device platforms. This restriction has now been
|
||||
removed.
|
@@ -238,16 +238,6 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
|
||||
status.SetError("called with IMPORTED argument but no library type.");
|
||||
return false;
|
||||
}
|
||||
if (type == cmStateEnums::OBJECT_LIBRARY) {
|
||||
std::string reason;
|
||||
if (!mf.GetGlobalGenerator()->HasKnownObjectFileLocation(&reason)) {
|
||||
mf.IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
"The OBJECT library type may not be used for IMPORTED libraries" +
|
||||
reason + ".");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (type == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
if (!cmGeneratorExpression::IsValidTargetName(libName)) {
|
||||
status.SetError(cmStrCat(
|
||||
|
15
Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake
Normal file
15
Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake
Normal file
@@ -0,0 +1,15 @@
|
||||
set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/ImportMultiArch.xcodeproj/project.pbxproj")
|
||||
if(NOT EXISTS "${xcProjectFile}")
|
||||
set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(READ ${xcProjectFile} pbxFileContents)
|
||||
foreach(config IN ITEMS Debug Release RelWithDebInfo MinSizeRel)
|
||||
set(regex "--findconfig-${config}[^
|
||||
]*\\$\\(CURRENT_ARCH\\)")
|
||||
if(NOT pbxFileContents MATCHES "${regex}")
|
||||
set(RunCMake_TEST_FAILED "$(CURRENT_ARCH) not preserved for config ${config}")
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
13
Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake
Normal file
13
Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
add_library(A OBJECT IMPORTED)
|
||||
|
||||
# We don't actually build this example so just configure dummy
|
||||
# object files to test. They do not have to exist.
|
||||
set_target_properties(A PROPERTIES
|
||||
IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/$(CURRENT_ARCH)/does_not_exist.o"
|
||||
)
|
||||
|
||||
add_library(B SHARED $<TARGET_OBJECTS:A> b.c)
|
||||
|
||||
# We use this to find the relevant lines of the project.pbx file
|
||||
target_link_options(B PRIVATE --findconfig-$<CONFIG>)
|
@@ -1,5 +0,0 @@
|
||||
CMake Error at ImportNotSupported.cmake:[0-9]+ \(add_library\):
|
||||
The OBJECT library type may not be used for IMPORTED libraries under Xcode
|
||||
with multiple architectures.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@@ -1 +0,0 @@
|
||||
add_library(A OBJECT IMPORTED)
|
@@ -6,7 +6,7 @@ run_cmake(BadSourceExpression3)
|
||||
run_cmake(BadObjSource1)
|
||||
run_cmake(BadObjSource2)
|
||||
if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
|
||||
run_cmake(ImportNotSupported)
|
||||
run_cmake(ImportMultiArch)
|
||||
run_cmake(InstallNotSupported)
|
||||
else()
|
||||
run_cmake(Import)
|
||||
|
@@ -2,3 +2,7 @@ include(RunCMake)
|
||||
|
||||
run_cmake(NoTarget)
|
||||
run_cmake(NotObjlibTarget)
|
||||
|
||||
if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
|
||||
run_cmake(XcodeVariableNoGenexExpansion)
|
||||
endif()
|
||||
|
@@ -0,0 +1,10 @@
|
||||
CMake Error at XcodeVariableNoGenexExpansion\.cmake:9 \(file\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$\<TARGET_OBJECTS:A\>
|
||||
|
||||
The evaluation of the TARGET_OBJECTS generator expression is only suitable
|
||||
for consumption by CMake \(limited under Xcode with multiple architectures\)\.
|
||||
It is not suitable for writing out elsewhere\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:3 \(include\)
|
@@ -0,0 +1,12 @@
|
||||
add_library(A OBJECT IMPORTED)
|
||||
|
||||
# We don't actually build this example so just configure a dummy
|
||||
# object file to test. It does not have to exist.
|
||||
set_target_properties(A PROPERTIES
|
||||
IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/$(CURRENT_ARCH)/does_not_exist.o"
|
||||
)
|
||||
|
||||
file(GENERATE
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objects.txt
|
||||
CONTENT "$<TARGET_OBJECTS:A>"
|
||||
)
|
Reference in New Issue
Block a user