Feature request: working with generated object files.
It is common in some workflows to work with object files that were generated to be compatible with the active toolchain, but were not created by the active toolchain. Two applications that jump to mind are using Halide's generated objects and bundling static libraries together into one.
The workaround I've found is to create an IMPORTED
, GLOBAL
, OBJECT
library with the IMPORTED_OBJECTS
property set to some generated object files. This library gets a dependency on a custom target, which depends on the generated object files, which are produced by a custom command.
This works, but is awkward for several reasons. Having to make it GLOBAL
is not obvious at the start. Forgetting that can lead to strange errors if the target name does not contain ::
. Adding the objects to the sources of a non-IMPORTED
OBJECT
library completely and silently ignores them. Adding them to the INTERFACE_SOURCES
property of an INTERFACE
(not-IMPORTED
) library results in "file not found" errors (because they don't exist yet). Lastly, because they are IMPORTED
, they may not be exported or installed. This poses a challenge for exporting usage requirements that might be attached to the IMPORTED OBJECT
library.
I propose allowing generated object files to appear in the sources of a non-IMPORTED
OBJECT
library. The semantics of this would be to add those objects to the final list of objects, accessible via $<TARGET_OBJECTS:>
or by linking.
Here's an example of doing this to create a library from the objects of vendor/proprietary.a
. Suppose the following code is in vendor/CMakeLists.txt
:
set(proprietary_lib "${CMAKE_CURRENT_SOURCE_DIR}/proprietary.a")
execute_process(
COMMAND "${CMAKE_AR}" -t "${proprietary_lib}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
OUTPUT_VARIABLE proprietary_objects)
string(STRIP "${proprietary_objects}" proprietary_objects)
string(REPLACE "\n" ";" proprietary_objects "${proprietary_objects}")
set_property(DIRECTORY . APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS proprietary.a)
add_custom_command(
OUTPUT ${proprietary_objects}
COMMAND "${CMAKE_AR}" -x "${proprietary_lib}"
DEPENDS "${proprietary_lib}")
list(TRANSFORM proprietary_objects PREPEND "${CMAKE_CURRENT_BINARY_DIR}/")
add_custom_target(proprietary.extract DEPENDS ${proprietary_objects})
add_library(proprietary OBJECT IMPORTED GLOBAL)
set_target_properties(proprietary PROPERTIES IMPORTED_OBJECTS "${proprietary_objects}")
add_dependencies(proprietary proprietary.extract)
This is obviously dependent on GNU ar (or compatible), but I think the example is illustrative. Ideally the last few lines would become:
add_library(proprietary OBJECT ${proprietary_objects}) # now first-class!
add_dependencies(proprietary proprietary.extract)
This currently fails with CMake Error: CMake can not determine linker language for target: proprietary
. Adding set_property(TARGET proprietary PROPERTY LINKER_LANGUAGE C)
to the file allows generation to complete, but the resulting build commands do not add ${proprietary_objects}
to the linkees of proprietary
.