IMPORTED_OBJECTS

版本 3.9 中添加。

一个由分号分隔的列表,包含导入的对象库在磁盘上的目标文件绝对路径。

对于非导入目标,此项会被忽略。

如果已设置了配置特定的属性 IMPORTED_OBJECTS_<CONFIG>,则项目可以跳过 IMPORTED_OBJECTS,除非出现下文所述的情况。

Xcode 生成器注意事项

在 3.20 版本中添加。

对于 Apple 平台,项目可以针对多种架构进行构建。这由 CMAKE_OSX_ARCHITECTURES 变量控制。除 Xcode 生成器外,CMake 会为每个源文件调用一次编译器并传入多个 -arch 标志,从而生成一个通用二进制格式(universal binary)的单一对象文件。当在另一个 CMake 构建的 IMPORTED_OBJECTS 中列出此类对象文件时,它们工作良好,即便是对于 Xcode 生成器也是如此。但使用 Xcode 生成器生成此类对象文件则更为困难,因为它针对每个源文件的每种架构都会调用一次编译器。与其他生成器不同,它不会生成通用的对象二进制文件。

Xcode 生成器的另一个复杂之处在于,当目标平台为设备平台(iOS、tvOS、visionOS 或 watchOS)时,Xcode 生成器无需重新运行 CMake 即可使用设备或模拟器 SDK。SDK 可以在构建时进行选择。但由于某些架构可能同时支持设备和模拟器 SDK(例如 Xcode 12 或更高版本中的 arm64),并非所有组合都能在单一的通用二进制文件中表示。在这种情况下,唯一的解决方案是拥有多个对象文件。

IMPORTED_OBJECTS 不支持生成器表达式,因此它列出的每个文件对于所有架构和 SDK 都必须是有效的。如果包含非通用二进制格式的对象文件,每个对象文件的路径和/或文件名必须以某种方式封装不同的架构和 SDK。使用 Xcode 生成器时,可以使用 $(...) 形式的 Xcode 变量来表示这些方面,Xcode 会在构建时替换相应的值。CMake 不会解析这些变量,而是将其原样嵌入到 Xcode 项目文件中。$(CURRENT_ARCH) 可用于表示架构,而 $(EFFECTIVE_PLATFORM_NAME) 可用于区分 SDK。

以下示例展示了如何使用这两个变量来引用其位置依赖于 SDK 和架构的对象文件:

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

在某些情况下,您可能还需要特定于配置的对象文件。Xcode 变量 $(CONFIGURATION) 通常用于此目的,并且可以与上述提到的其他变量结合使用。

add_library(someObjs OBJECT IMPORTED)
set_property(TARGET someObjs PROPERTY IMPORTED_OBJECTS
  "/path/to/somewhere/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/$(CURRENT_ARCH)/func.o"
)

# Example paths:
#   /path/to/somewhere/Release-iphoneos/arm64/func.o
#   /path/to/somewhere/Debug-iphonesimulator/x86_64/func.o

当使用任何 Xcode 变量时,CMake 无法在配置时完全评估路径。其后果之一是无法使用特定于配置的 IMPORTED_OBJECTS_<CONFIG> 属性,因为 CMake 无法确定对象文件是否存在于特定的 <CONFIG> 位置。在这种情况下,必须使用 IMPORTED_OBJECTS 属性,且路径中特定于配置的方面应通过 $(CONFIGURATION) Xcode 变量来处理。