Search code examples
gcccmakeavravr-gcclstlisting

How to output the assembly listing of the final executable created by a CMake project?


I am currently working on an embedded project using the avr-gcc compiler to run on an Atmel ATMega328p microcontroller. I decided to use CMake to create my build system as that would be an easy to way integrate my project into VS Code with Intellisense.

One of the settings I would like to set up in my project is the output of a *.map file to view the memory map after the compilation has finished, and a *.lst file for each compilation object and the final binary. I have solved the creation of the map file by adding -Wl,-Map=${CMAKE_PROJECT_NAME}.map to CMAKE_EXE_LINKER_FLAGS. I have also solved the creation of the compilation object lst files by adding -Wa,-anhlmsd=<OBJECT>.lst to CMAKE_C_COMPILE_OBJECT.

The issue I cannot resolve is how to create the final lst file for the final binary, which in this case is "avr-bootloader.elf". I have put -Wa,-adhlns=${CMAKE_PROJECT_NAME}.lst into CMAKE_EXE_LINKER FLAGS and Ninja is running the final call to avr-gcc with the flag in the expected spot. I'm anticipating to find "avr-bootloader.lst" in the build directory after CMake generates the appropriate makefiles and then runs the build but I do not get such a file. Setting an absolute path does not solve the issue. Removing the equal sign and viewing stdout shows that avr-gcc isn't printing any assembly listing out whatsoever. What perplexes me is how the map file creation works without a problem. Is there any detail I'm missing as to why this CMake project isn't creating the final assembly listing? All searches I look up only mention the use of the feature and it's output, not about any situation where it's output is empty or nonexistant.

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)
project(avr-bootloader VERSION 0.1.0)

enable_language(C ASM)

set(mcu atmega328p)

set(CMAKE_EXE_LINKER_FLAGS -mmcu=${mcu})

add_compile_options(
    -mmcu=${mcu}
    -Os
    -g3
    -Wall
    -Wextra
    -Wdouble-promotion
    -Wno-main
    -Wstack-usage=255
    -Wconversion
)

set (src
    main.c)

# Output lst and map file
set(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} -Wa,-adhlns=${CMAKE_PROJECT_NAME}.lst -Wl,-Map=${CMAKE_PROJECT_NAME}.map")
set(CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT} -Wa,-anhlmsd=<OBJECT>.lst")



add_executable(avr-bootloader.elf ${src})
target_link_libraries(avr-bootloader.elf printf_min)
target_include_directories(avr-bootloader.elf PRIVATE .)

Solution

  • After further investigation, it seems like the assembler options aren't used during CMake's final gcc call and any arguments I pass won't output anything. As a result, the best option is to use a custom command to just call avr-objdump when the build is complete.

    add_custom_command(OUTPUT ${CMAKE_PROJECT_NAME}.lst
        MAIN_DEPENDENCY $<TARGET_FILE:${CMAKE_PROJECT_NAME}.elf>
        COMMAND ${CMAKE_OBJDUMP} -h -S $<TARGET_FILE:${CMAKE_PROJECT_NAME}.elf> > ${CMAKE_PROJECT_NAME}.lst
        COMMENT "Invoking: Cross AVR GNU Create Listing")