Question

I'm building an executable using the standard command:

add_executable(MyExe a.c b.c)

I'm adjusting the CMAKE_EXE_LINKER_FLAGS to emit a map file, and it works.

If I delete the map file, though, performing an incremental build doesn't regenerate the map file. This makes sense, since I haven't expressed to cmake that the map file depends on MyExe. In the above scenario, the MyExe.map isn't even a target, so cmake doesn't even know it exists.

I've tried creating a custom target, but I can't create a custom command that regenerates the map file, since it comes from add_executable(). I then tried to use add_dependencies(), but that seems to only influence the build order.

I could explicitly re-run the linker as a custom command that builds a custom target, but that seems wasteful since linking does take a bit of time.

It almost seems like I need some way to tell add_executable that there are more outputs than just the executable image. Is there a way to do this?

If anybody could point me in the right direction, I'd appreciate it! Thanks in advance for reading.

Était-ce utile?

La solution

I've seen the same question was also asked on CMake's mailing list and never received an answer. So let me try to answer it here.

CMake doesn't have an official support for map files nor - if you add the necessary linker flags manually - to have more then one output of an executable target.

If you don't want to add it as an extra custom command/target step, you could link to an object file being part of you executable with OBJECT_OUTPUTS source file property (works unfortunately only with Makefile generators).

I've successfully tested the following example with a GNU toolchain:

cmake_minimum_required(VERSION 2.6)

project(MapFileDep)

file(WRITE "main.cpp" "int main() { return 0; }")

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set(
        CMAKE_EXE_LINKER_FLAGS 
        "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=output.map"
    )
endif()

add_executable(${PROJECT_NAME} "main.cpp")

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set_source_files_properties(
        "main.cpp" 
        PROPERTIES OBJECT_OUTPUTS "output.map"
    )
endif()

Alternative

And here the more advanced alternative (also covering @jww's use case):

Add something that generates/creates/copies the output.map file (when it's not there) and use LINK_DEPENDS target property to make CMake aware of re-linking when output.map changes:

add_custom_command(
    OUTPUT "output.map"
    COMMAND "${CMAKE_COMMAND}" -E touch "output.map"
)

add_executable(${PROJECT_NAME} "main.cpp" "output.map")

set_target_properties(
    ${PROJECT_NAME} 
    PROPERTIES 
        LINK_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/output.map"
)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top