Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake's objects output folder variable

Tags:

cmake

How "${PROJECT_BINARY_DIR}/CMakeFiles/project.dir/", the place object files resulted from compilation will be placed on, can be un-hardcoded?

Going straightly to the problem, we have some tests that check objects resulted from compilation on harfbuzz cmake and we use a hardcoded string there but that doesn't seem right and I hope some ${} or $<> exist for that.

like image 984
Ebrahim Byagowi Avatar asked Jan 17 '18 07:01

Ebrahim Byagowi


2 Answers

I'm afraid you're out of luck here. CMake keeps this as an internal implementation detail, by design.

I'd say it's unlikely to change, but if you want to be absolutely future-proof, you could use a workaround of creating a static library out of the object files and then manually unpacking it back into object files (using the appropriate archiver/librarian) as part of the test. If the object files are also used by another target, and linking to that static library wouldn't work for that target, you can make an object library out of the files and then use that in both the original target and the for-test static library.

Here's an example of how you might achieve this workaround:

add_library(MyObjectLib OBJECT src/a.cpp src/b.cpp)

add_executable(Main src/main.cpp $<TARGET_OBJECTS:MyObjectLib>)

add_library(LibForTesting STATIC $<TARGET_OBJECTS:MyObjectLib>)

add_test(
  NAME check-static-inits.sh
  COMMAND ${PROJECT_SOURCE_DIR}/src/prepare-and-check-static-inits.sh $<TARGET_FILE:LibForTesting>
)

And here's what the script prepare-and-check-static-inits.sh would look like (pseudo-code):

ar -x $1 -o some_dir
./check-static-inits.sh some_dir
like image 164
Angew is no longer proud of SO Avatar answered Nov 13 '22 04:11

Angew is no longer proud of SO


Turning my comment into an answer

There is at the moment no variable or generator expression to get the list of object files used for linking a archive or library target.

But you could append compiler/archiver/linker calls with any program/script and utilize CMake's expansion rules inside those calls.

Note: That will only work CMake's Command-Line Build Tool Generators. And the list(APPEND ...) calls only have to be there once in your CMake code after your project() call.

Examples

  1. Generate a symbolic link to <OBJECT_DIR> with <TARGET_NAME>

    project(MyLib)
    
    list(
        APPEND CMAKE_CXX_ARCHIVE_FINISH 
            "\"${CMAKE_COMMAND}\" -E create_symlink \"<OBJECT_DIR>\" \"<TARGET_NAME>\""
    )
    
    [...]
    
    add_library(MyLib STATIC src/a.cpp src/b.cpp)
    
  2. Call some program to do something with the <OBJECTS> list (e.g. echo or write to a file)

    project(MyExe)
    
    list(
        APPEND CMAKE_CXX_LINK_EXECUTABLE 
            "\"${CMAKE_COMMAND}\" -E echo \"<OBJECTS>\""
    )
    
    [...]
    
    add_executable(MyExe main.cpp)
    
  3. Directly do something after each object file is generated. In your case where you want to call objdump for each object file it would e.g. be:

    list(
        APPEND CMAKE_CXX_COMPILE_OBJECT
            "${CMAKE_OBJDUMP} -t \"<OBJECT>\" > $(notdir <OBJECT>.dump)"
    )
    

    Unfortunately there is no expansion rule for "output file name" hence the platform/make specific trick with $(notdir ...).

References

  • CMAKE_<LANG>_ARCHIVE_FINISH
  • CMAKE_<LANG>_LINK_EXECUTABLE
  • CMAKE_<LANG>_COMPILE_OBJECT
  • How to get path to object files with CMake for both multiconfiguration generator and makefile based ones?
like image 2
Florian Avatar answered Nov 13 '22 02:11

Florian