summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@crascit.com>2021-02-04 09:30:49 (GMT)
committerCraig Scott <craig.scott@crascit.com>2021-02-06 00:34:28 (GMT)
commit4d46b1401f9d1624fa5afc3995844d7aebc7ccf4 (patch)
treee2396c9fab9f6c9e694ae3e281d0d28c8f6a446d
parent1a915e89531adb426be6db6f648ef496ee8c38e8 (diff)
downloadCMake-4d46b1401f9d1624fa5afc3995844d7aebc7ccf4.zip
CMake-4d46b1401f9d1624fa5afc3995844d7aebc7ccf4.tar.gz
CMake-4d46b1401f9d1624fa5afc3995844d7aebc7ccf4.tar.bz2
add_library(): Allow imported object libraries with multi-arch
Fixes: #21276
-rw-r--r--Help/prop_tgt/IMPORTED_OBJECTS.rst86
-rw-r--r--Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst13
-rw-r--r--Help/release/dev/object-lib-multiarch.rst8
-rw-r--r--Source/cmAddLibraryCommand.cxx10
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake15
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake13
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/TargetObjects/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-result.txt (renamed from Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt)0
-rw-r--r--Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt10
-rw-r--r--Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake12
13 files changed, 158 insertions, 21 deletions
diff --git a/Help/prop_tgt/IMPORTED_OBJECTS.rst b/Help/prop_tgt/IMPORTED_OBJECTS.rst
index bbbcd86..f3577eb 100644
--- a/Help/prop_tgt/IMPORTED_OBJECTS.rst
+++ b/Help/prop_tgt/IMPORTED_OBJECTS.rst
@@ -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)``.
diff --git a/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
index b12ca38..238395a 100644
--- a/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
+++ b/Help/prop_tgt/IMPORTED_OBJECTS_CONFIG.rst
@@ -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.
diff --git a/Help/release/dev/object-lib-multiarch.rst b/Help/release/dev/object-lib-multiarch.rst
new file mode 100644
index 0000000..0d309d6
--- /dev/null
+++ b/Help/release/dev/object-lib-multiarch.rst
@@ -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.
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index f262fac..92e04e4 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -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(
diff --git a/Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake b/Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake
new file mode 100644
index 0000000..af1df78
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ImportMultiArch-check.cmake
@@ -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()
diff --git a/Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake b/Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake
new file mode 100644
index 0000000..64029ee
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ImportMultiArch.cmake
@@ -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>)
diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt
deleted file mode 100644
index 0fadac2..0000000
--- a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-stderr.txt
+++ /dev/null
@@ -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\)
diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake b/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake
deleted file mode 100644
index 806b44a..0000000
--- a/Tests/RunCMake/ObjectLibrary/ImportNotSupported.cmake
+++ /dev/null
@@ -1 +0,0 @@
-add_library(A OBJECT IMPORTED)
diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
index 5ec4018..8515ba5 100644
--- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -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)
diff --git a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
index 30b9fee..d2b3032 100644
--- a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake
@@ -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()
diff --git a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/ObjectLibrary/ImportNotSupported-result.txt
+++ b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-result.txt
diff --git a/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt
new file mode 100644
index 0000000..1360015
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion-stderr.txt
@@ -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\)
diff --git a/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake
new file mode 100644
index 0000000..83d7210
--- /dev/null
+++ b/Tests/RunCMake/TargetObjects/XcodeVariableNoGenexExpansion.cmake
@@ -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>"
+)