From 51634cd661475244c91cdcc9f317d10899e77d06 Mon Sep 17 00:00:00 2001 From: Danny Oerndrup Date: Thu, 1 Aug 2019 07:56:45 +0200 Subject: [PATCH] cmake: Toolchain abstraction: Abstraction of binary tool, objcopy. This abstracts the interface for generation of the objcopy command line, by naming the desired actions instead of directly setting the command parameters, which then opens up for other binary tool sets which may require different arguments to achieve the desired result. The intent here is to abstract Zephyr's dependence on toolchains, thus allowing for easier porting to other, perhaps commercial, toolchains and/or usecases. No functional change expected. Signed-off-by: Danny Oerndrup --- CMakeLists.txt | 117 ++++++++++++++++------ cmake/bintools/gnu/target.cmake | 1 + cmake/bintools/gnu/target_objcopy.cmake | 126 ++++++++++++++++++++++++ cmake/bintools/host-gnu/target.cmake | 1 + cmake/bintools/llvm/target.cmake | 1 + 5 files changed, 218 insertions(+), 28 deletions(-) create mode 100644 cmake/bintools/gnu/target_objcopy.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b4abd30f0fd..1be6a4e74c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -700,14 +700,18 @@ if(CONFIG_GEN_ISR_TABLES) # isr_tables.c is generated from ${ZEPHYR_PREBUILT_EXECUTABLE} by # gen_isr_tables.py + set(obj_copy_cmd "") + bintools_objcopy( + RESULT_CMD_LIST obj_copy_cmd + TARGET_INPUT ${OUTPUT_FORMAT} + TARGET_OUTPUT "binary" + SECTION_ONLY ".intList" + FILE_INPUT $ + FILE_OUTPUT "isrList.bin" + ) add_custom_command( OUTPUT isr_tables.c - COMMAND ${CMAKE_OBJCOPY} - -I ${OUTPUT_FORMAT} - -O binary - --only-section=.intList - $ - isrList.bin + ${obj_copy_cmd} COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/arch/common/gen_isr_tables.py --output-source isr_tables.c @@ -839,16 +843,22 @@ if(CONFIG_ARM AND CONFIG_USERSPACE) set(PRIV_STACKS_OUTPUT_OBJ_PATH ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/priv_stacks_output_lib.dir/${PRIV_STACKS_OUTPUT_OBJ}) + set(obj_copy_cmd "") + set(obj_copy_sections_rename + .bss=.priv_stacks.noinit + .data=.priv_stacks.data + .text=.priv_stacks.text + .rodata=.priv_stacks.rodata + ) + bintools_objcopy( + RESULT_CMD_LIST obj_copy_cmd + SECTION_RENAME ${obj_copy_sections_rename} + FILE_INPUT ${PRIV_STACKS_OUTPUT_OBJ_PATH} + FILE_OUTPUT ${PRIV_STACKS_OUTPUT_OBJ_RENAMED} + ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_OBJ_RENAMED} - COMMAND - ${CMAKE_OBJCOPY} - --rename-section .bss=.priv_stacks.noinit - --rename-section .data=.priv_stacks.data - --rename-section .text=.priv_stacks.text - --rename-section .rodata=.priv_stacks.rodata - ${PRIV_STACKS_OUTPUT_OBJ_PATH} - ${PRIV_STACKS_OUTPUT_OBJ_RENAMED} + ${obj_copy_cmd} DEPENDS priv_stacks_output_lib WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) @@ -964,15 +974,21 @@ if(CONFIG_USERSPACE) set(OUTPUT_OBJ_PATH ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/output_lib.dir/${OUTPUT_OBJ}) + set(obj_copy_cmd "") + set(obj_copy_sections_rename + .data=.kobject_data.data + .text=.kobject_data.text + .rodata=.kobject_data.rodata + ) + bintools_objcopy( + RESULT_CMD_LIST obj_copy_cmd + SECTION_RENAME ${obj_copy_sections_rename} + FILE_INPUT ${OUTPUT_OBJ_PATH} + FILE_OUTPUT ${OUTPUT_OBJ_RENAMED} + ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_OBJ_RENAMED} - COMMAND - ${CMAKE_OBJCOPY} - --rename-section .data=.kobject_data.data - --rename-section .text=.kobject_data.text - --rename-section .rodata=.kobject_data.rodata - ${OUTPUT_OBJ_PATH} - ${OUTPUT_OBJ_RENAMED} + ${obj_copy_cmd} DEPENDS output_lib WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) @@ -1216,7 +1232,7 @@ list(APPEND if(NOT CONFIG_BUILD_NO_GAP_FILL) # Use ';' as separator to get proper space in resulting command. - set(GAP_FILL "--gap-fill;0xff") + set(GAP_FILL "0xff") endif() if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE) @@ -1238,38 +1254,83 @@ if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE) endif() if(CONFIG_BUILD_OUTPUT_HEX) + set(out_hex_cmd "") + set(out_hex_byprod "") + set(out_hex_sections_remove + .comment + COMMON + .eh_frame + ) + bintools_objcopy( + RESULT_CMD_LIST out_hex_cmd + RESULT_BYPROD_LIST out_hex_byprod + STRIP_ALL + GAP_FILL ${GAP_FILL} + TARGET_OUTPUT "ihex" + SECTION_REMOVE ${out_hex_sections_remove} + FILE_INPUT ${KERNEL_ELF_NAME} + FILE_OUTPUT ${KERNEL_HEX_NAME} + ) list(APPEND post_build_commands - COMMAND - ${CMAKE_OBJCOPY} -S -Oihex ${GAP_FILL} -R .comment -R COMMON -R .eh_frame ${KERNEL_ELF_NAME} ${KERNEL_HEX_NAME} + ${out_hex_cmd} ) list(APPEND post_build_byproducts ${KERNEL_HEX_NAME} + ${out_hex_byprod} ) endif() if(CONFIG_BUILD_OUTPUT_BIN) + set(out_bin_cmd "") + set(out_bin_byprod "") + set(out_bin_sections_remove + .comment + COMMON + .eh_frame + ) + bintools_objcopy( + RESULT_CMD_LIST out_bin_cmd + RESULT_BYPROD_LIST out_bin_byprod + STRIP_ALL + GAP_FILL ${GAP_FILL} + TARGET_OUTPUT "binary" + SECTION_REMOVE ${out_bin_sections_remove} + FILE_INPUT ${KERNEL_ELF_NAME} + FILE_OUTPUT ${KERNEL_BIN_NAME} + ) list(APPEND post_build_commands - COMMAND - ${CMAKE_OBJCOPY} -S -Obinary ${GAP_FILL} -R .comment -R COMMON -R .eh_frame ${KERNEL_ELF_NAME} ${KERNEL_BIN_NAME} + ${out_bin_cmd} ) list(APPEND post_build_byproducts ${KERNEL_BIN_NAME} + ${out_bin_byprod} ) endif() if(CONFIG_BUILD_OUTPUT_S19) + set(out_S19_cmd "") + set(out_S19_byprod "") + bintools_objcopy( + RESULT_CMD_LIST out_S19_cmd + RESULT_BYPROD_LIST out_S19_byprod + GAP_FILL ${GAP_FILL} + TARGET_OUTPUT "srec" + SREC_LEN 1 + FILE_INPUT ${KERNEL_ELF_NAME} + FILE_OUTPUT ${KERNEL_S19_NAME} + ) list(APPEND post_build_commands - COMMAND - ${CMAKE_OBJCOPY} ${GAP_FILL} --srec-len 1 --output-target=srec ${KERNEL_ELF_NAME} ${KERNEL_S19_NAME} + ${out_S19_cmd} ) list(APPEND post_build_byproducts ${KERNEL_S19_NAME} + ${out_S19_byprod} ) endif() diff --git a/cmake/bintools/gnu/target.cmake b/cmake/bintools/gnu/target.cmake index 7359abcb187..141c1e0a432 100644 --- a/cmake/bintools/gnu/target.cmake +++ b/cmake/bintools/gnu/target.cmake @@ -15,3 +15,4 @@ find_program(CMAKE_GDB gdb-multiarch PATH ${TOOLCHAIN_HOME} # Include bin tool abstraction macros include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake) +include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_objcopy.cmake) diff --git a/cmake/bintools/gnu/target_objcopy.cmake b/cmake/bintools/gnu/target_objcopy.cmake new file mode 100644 index 00000000000..703e0680674 --- /dev/null +++ b/cmake/bintools/gnu/target_objcopy.cmake @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Construct a commandline suitable for calling the toolchain binary tools +# version of objcopy. +# +# Usage: +# bintools_objcopy( +# RESULT_CMD_LIST +# RESULT_BYPROD_LIST +# +# STRIP_ALL +# STRIP_DEBUG +# +# TARGET_INPUT +# TARGET_OUTPUT +# +# GAP_FILL +# SREC_LEN +# +# SECTION_ONLY +# SECTION_REMOVE +# SECTION_RENAME +# +# FILE_INPUT +# FILE_OUTPUT +# ) +function(bintools_objcopy) + cmake_parse_arguments( + # Prefix of output variables + BINTOOLS_OBJCOPY + # List of argument names without values, hence boolean + "STRIP_ALL;STRIP_DEBUG" + # List of argument names with one value + "RESULT_CMD_LIST;RESULT_BYPROD_LIST;TARGET_INPUT;TARGET_OUTPUT;GAP_FILL;SREC_LEN;FILE_INPUT;FILE_OUTPUT" + # List of argument names with multible values + "SECTION_ONLY;SECTION_RENAME;SECTION_REMOVE" + # Parser input + ${ARGN} + ) + + # Verify arguments + if(NOT DEFINED BINTOOLS_OBJCOPY_RESULT_CMD_LIST OR NOT DEFINED ${BINTOOLS_OBJCOPY_RESULT_CMD_LIST}) + message(FATAL_ERROR "RESULT_CMD_LIST is required.") + elseif(NOT DEFINED BINTOOLS_OBJCOPY_FILE_INPUT OR NOT DEFINED BINTOOLS_OBJCOPY_FILE_OUTPUT) + message(FATAL_ERROR "Both FILE_INPUT and FILE_OUTPUT is required.") + endif() + + # Handle stripping + set(obj_copy_strip "") + if(${BINTOOLS_OBJCOPY_STRIP_ALL}) + set(obj_copy_strip "-S") + elseif(${BINTOOLS_OBJCOPY_STRIP_DEBUG}) + set(obj_copy_strip "-g") + endif() + + # Handle gap filling + set(obj_copy_gap_fill "") + if(DEFINED BINTOOLS_OBJCOPY_GAP_FILL) + set(obj_copy_gap_fill "--gap-fill;${BINTOOLS_OBJCOPY_GAP_FILL}") + endif() + + # Handle srec len, but only if target output is srec + set(obj_copy_srec_len "") + if(DEFINED BINTOOLS_OBJCOPY_SREC_LEN) + if(NOT ${BINTOOLS_OBJCOPY_TARGET_OUTPUT} STREQUAL "srec") + message(WARNING "Ignoring srec len, for non srec target: ${BINTOOLS_OBJCOPY_TARGET_OUTPUT}") + else() + set(obj_copy_srec_len "--srec-len;${BINTOOLS_OBJCOPY_SREC_LEN}") + endif() + endif() + + # Handle Input and Output target types + set(obj_copy_target_input "") + if(DEFINED BINTOOLS_OBJCOPY_TARGET_INPUT) + set(obj_copy_target_input "--input-target=${BINTOOLS_OBJCOPY_TARGET_INPUT}") + endif() + set(obj_copy_target_output "") + if(DEFINED BINTOOLS_OBJCOPY_TARGET_OUTPUT) + set(obj_copy_target_output "--output-target=${BINTOOLS_OBJCOPY_TARGET_OUTPUT}") + endif() + + # Handle sections, if any + # 1. Section only selection(s) + set(obj_copy_sections_only "") + if(DEFINED BINTOOLS_OBJCOPY_SECTION_ONLY) + foreach(section_only ${BINTOOLS_OBJCOPY_SECTION_ONLY}) + list(APPEND obj_copy_sections_only "--only-section=${section_only}") + endforeach() + endif() + + # 2. Section rename selection(s) + set(obj_copy_sections_rename "") + if(DEFINED BINTOOLS_OBJCOPY_SECTION_RENAME) + foreach(section_rename ${BINTOOLS_OBJCOPY_SECTION_RENAME}) + if(NOT ${section_rename} MATCHES "^.*=.*$") + message(FATAL_ERROR "Malformed section renaming. Must be from=to, have ${section_rename}") + else() + list(APPEND obj_copy_sections_rename "--rename-section;${section_rename}") + endif() + endforeach() + endif() + + # 3. Section remove selection(s) + set(obj_copy_sections_remove "") + if(DEFINED BINTOOLS_OBJCOPY_SECTION_REMOVE) + foreach(section_remove ${BINTOOLS_OBJCOPY_SECTION_REMOVE}) + list(APPEND obj_copy_sections_remove "--remove-section=${section_remove}") + endforeach() + endif() + + # Construct the command + set(obj_copy_cmd + # Base command + COMMAND ${CMAKE_OBJCOPY} ${obj_copy_strip} ${obj_copy_gap_fill} ${obj_copy_srec_len} + # Input and Output target types + ${obj_copy_target_input} ${obj_copy_target_output} + # Sections + ${obj_copy_sections_only} ${obj_copy_sections_rename} ${obj_copy_sections_remove} + # Input and output files + ${BINTOOLS_OBJCOPY_FILE_INPUT} ${BINTOOLS_OBJCOPY_FILE_OUTPUT} + ) + + # Place command in the parent provided variable + set(${BINTOOLS_OBJCOPY_RESULT_CMD_LIST} ${obj_copy_cmd} PARENT_SCOPE) + +endfunction(bintools_objcopy) diff --git a/cmake/bintools/host-gnu/target.cmake b/cmake/bintools/host-gnu/target.cmake index 9f31b392316..d802ddf8339 100644 --- a/cmake/bintools/host-gnu/target.cmake +++ b/cmake/bintools/host-gnu/target.cmake @@ -12,3 +12,4 @@ find_program(CMAKE_GDB gdb ) # Use the gnu binutil abstraction macros include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake) +include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_objcopy.cmake) diff --git a/cmake/bintools/llvm/target.cmake b/cmake/bintools/llvm/target.cmake index f973a6d02c1..4c547364de2 100644 --- a/cmake/bintools/llvm/target.cmake +++ b/cmake/bintools/llvm/target.cmake @@ -16,3 +16,4 @@ find_program(CMAKE_READELF readelf ${find_program_binutils_args}) # Use the gnu binutil abstraction macros include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake) +include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_objcopy.cmake)