I would like to generate a module definition file based on all symbols available in object files in dynamic fashion (think of GTKMM's gendef).
For this, I would like to add_custom_command
for PRE_LINK
step of a target. However, it looks like there is no easy way to get path to all object files with CMake that would work for plain makefiles as well as for multi-configuration generators like Visual Studio.
Right now, I have the following
add_custom_command(TARGET tgt PRE_LINK
COMMAND gendef ${CMAKE_CURRENT_BINARY_DIR}/tgt.def $<TARGET_FILE_NAME:tgt> ${CMAKE_CURRENT_BINARY_DIR}/$<$<BOOL:${CMAKE_BUILD_TYPE}>:${CMAKE_FILES_DIRECTORY}>/tgt.dir/${CMAKE_CFG_INTDIR}/*.obj
)
However this is quite awkward and bulky as I have to use generator expression in my opinion. Is there a better way to achieve this effect, i.e. call a certain external program for each build configuration?
Is it a CMake bug (feature?) that for plain makefiles, all object files go to CMakeFiles/tgt.dir
folder while for multiconfiguration generators all goes to a sibling of CMakeFiles, i.e. tgt.dir/$<CONFIG>
? Did I miss some simple variable that would point me to the right place directly?
Turning my comment into an answer
Makefile projects generated by CMake have a totally different internal structure then solutions/projects generated for Visual Studio. I think this is neither a bug nor a feature, those structures are just optimized for their usecases.
And as far as I know there is no easy CMake internal way to get the list of object files or the path to the intermediate files directory with e.g. reading a target property.
So I have taken your code example and have done some testing for alternatives with CMake 3.3.2 using Visual Studio 14 2015
and NMake Makefiles
generators.
Alternatives
One related discussion on the CMake mailing list named "CMake: Is there an elegant way to get list of object files participating into a library?" does suggest using an intermediate static library:
add_library(tgtlib STATIC tgt.c)
add_custom_command(
OUTPUT tgt.def
COMMAND gendef tgt.def $<TARGET_FILE_NAME:tgt> $<TARGET_FILE:tgtLib>
)
file(WRITE dummy.c "")
add_library(tgt SHARED dummy.c tgt.def)
target_link_libraries(tgt tgtlib)
You could add build environment specific elements to your PRE_LINK
step:
if(CMAKE_CONFIGURATION_TYPES)
set(_obj_files "$(IntermediateOutputPath)*.obj")
else()
set(_obj_files "$?")
endif()
add_custom_command(
TARGET MainProject
PRE_LINK
COMMAND gendef tgt.def $<TARGET_FILE_NAME:tgt> ${_obj_files}
)
References