How to express that a map file depends on add_executable?
Asked Answered
A

1

15

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.

Aragats answered 9/5, 2014 at 20:6 Comment(5)
Man, this is the same problem I'm having. Are you working on Solaris?Dioscuri
"I'm adjusting the CMAKE_EXE_LINKER_FLAGS to emit a map file" - please show the code for this. How long does linking take? Are you using the Gold linker? If not, it is much faster.Teillo
@Dioscuri Are you looking for a cross-platform way to generate Mapfiles with CMake and then use that as an input for a custom command? Maybe I just got it wrong, but your problem sounds different from the one described in the question.Enright
Well, we don't distribute a mapfile. Rather, we build it on the fly when needed and write it to disk (in the GNU makefile). So we would like to generate the map file and make the program (.exe) and shared object (.so) a dependency of the mapfile.Dioscuri
@Dioscuri Added an alternative to my answer that also covers your use case (for makefile generators).Enright
E
13

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"
)
Enright answered 27/8, 2017 at 20:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.