Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get path to object files with CMake for both multiconfiguration generator and makefile based ones?

Tags:

windows

cmake

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?

like image 260
mlt Avatar asked Nov 10 '22 15:11

mlt


1 Answers

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

  1. 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)
    
  2. 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

  • NMAKE: Filename Macros
like image 197
Florian Avatar answered Nov 15 '22 09:11

Florian