6

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.

Ebrahim Byagowi
  • 10,338
  • 4
  • 70
  • 81
  • 1
    Could you check what you get for `message("${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}")`? I'm not sure anymore what is included `CMAKE_FILES_DIRECTORY`, but that's normally the path to CMake's intermediate directory. – Florian Jan 17 '18 at 09:45
  • Thanks Florian, I am evaluating your and Angew answers, your suggestion is in a correct direction but still no "project.dir", is there any hope for that also? – Ebrahim Byagowi Jan 17 '18 at 11:26
  • Just remembered having seen/answered a question about getting the list of target's object files before: [How to get path to object files with CMake for both multiconfiguration generator and makefile based ones?](https://stackoverflow.com/questions/29884856/how-to-get-path-to-object-files-with-cmake-for-both-multiconfiguration-generator) – Florian Jan 17 '18 at 21:27
  • So I guess this should be marked as duplicate but on the meanwhile I upvoted you answer there at least :) – Ebrahim Byagowi Jan 18 '18 at 20:00
  • Thanks :-) I had another idea utilizing CMake's expansion rules. So would it be ok if it only works for makefile/Ninja generators? – Florian Jan 19 '18 at 07:19
  • That is also good to know. CMake is secondary build script on harfbuzz https://github.com/harfbuzz/harfbuzz/blob/master/CMakeLists.txt and I tried to make it on par with autotools solution. These tests can be ported to Windows someday but maybe not that soon. The main thing I wanted to know was if I have blindspot on finding object files which with your helps I reached to some conclusion. – Ebrahim Byagowi Jan 19 '18 at 09:55

2 Answers2

3

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
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Thank you @Angew, I wanted to test your last idea, adding an object library target, but when I wanted to use $, it was saying `The evaluation of the TARGET_OBJECTS generator expression is only suitable for consumption by CMake. It is not suitable for writing out elsewhere.`, obviously what you was indicating also so there is not hope I guess on that solution also? – Ebrahim Byagowi Jan 17 '18 at 11:53
  • @EbrahimByagowi I've added an example of what I meant with using the static library. Can you compare it to what you did? – Angew is no longer proud of SO Jan 17 '18 at 13:42
  • This looks complicated but great. I will see whether can I integrate it, thanks. – Ebrahim Byagowi Jan 17 '18 at 14:47
  • Your solution was great and I wrote this based on it https://github.com/harfbuzz/harfbuzz/pull/710#issuecomment-358372318 I am not applying that just right now till sometime to think and test it more – Ebrahim Byagowi Jan 17 '18 at 17:06
2

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

Florian
  • 39,996
  • 9
  • 133
  • 149