问题
I'm trying to get cmake (on linux) to create some static object (.o) files and install them to an external directory. To that end I have a list, object_sources
, containing the project path of the sources, and put this in the top level CMakeLists.txt
:
set(local_objects "")
foreach(file ${object_sources})
get_filename_component(cur ${file} NAME_WE)
add_library("${cur}.o" OBJECT ${file})
list(APPEND local_objects "${cur}.o")
# To confirm these variables are what I think they are:
message("---> ${cur} | ${file}")
endforeach()
install(
# Also tried FILES, see below.
TARGETS ${local_objects}
CONFIGURATIONS Debug
# Also tried nothing instead of 'OBJECTS' (same outcome)
# and LIBRARY (cmake fails on error).
OBJECTS
DESTINATION "/some/external/dir"
)
With regard to using FILES
, it cannot work because in fact a foo.o
is never created, so there is no point in me trying to get the correct project path.
When I get to the actual make
command in the cmake build directory, it spits out Built target foo.o, etc., during the process. However, as mentioned, no foo.o
is ever created anywhere, and the install
creates an objects-Debug
directory in /some/external/dir
containing directories for each target using its name (e.g., foo.o/
) and inside that some more nested directories at the bottom of which is the object I want, with the wrong name: foo.cpp.o
.
Cmake can structure its build tree however it wants and name its temporaries whatever it likes, but I would really like to be able to ask for a final product object foo.o
(not foo.cpp.o
) and have it installed that way.
Is that possible? I'm beginning to think this is all very contrary to the (implicit) purposes of cmake, and that I should keep these kinds of tasks separate in a shell script or makefile (it takes about three lines in either), and just use cmake for the normative libs and executables.
Or: I believe I could get this to work if I created each object as a static archive (lib.a) instead, but part of the issue here is that would require modifying the build scripts of something else, or else extracting them via a script (in which case I might as well do the whole thing in the script).
回答1:
I'm not aware of a good way to do this in CMake, but maybe the least fussy would be to use an OBJECT library. This would allow you to get the object files for a target using generator expressions, more specifically the TARGET_OBJECTS
expression. This is a minimal example with a single foo.c
file containing an empty main
:
cmake_minimum_required(VERSION 3.11)
project(foo C)
set(SOURCES foo.c)
add_library(foo_obj OBJECT ${SOURCES})
add_executable(foo $<TARGET_OBJECTS:foo_obj>)
set(OBJS $<TARGET_OBJECTS:foo_obj>)
message(STATUS "these are my objects: ${OBJS}") # generator expression printed here, not evaluated yet
add_custom_target(print_foo_objs
COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_OBJECTS:foo_obj>)
set(OBJ_ROOT_DIR $<TARGET_PROPERTY:foo,BINARY_DIR>)
add_custom_target(copy_foo_objs
COMMAND ${CMAKE_COMMAND} -E make_directory ${OBJ_ROOT_DIR}/myobjects/
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_OBJECTS:foo_obj> ${OBJ_ROOT_DIR}/myobjects/)
Please note that as a generator expression, you will not have access to it during configuration (hence, that message
will contain the generator expression as it was textually declared), but only during the generation phase.
If you still need to rename the object files (i.e. from foo.c.o
to foo.o
) you can maybe call a custom external script to do that for you.
Moreover, there might be issues with cleanup, etc. which will force you to add more custom targets and/or commands (and associated dependencies) to deal with it. Another downside of this approach.
来源:https://stackoverflow.com/questions/51988350/copy-out-plain-o-files-with-cmake