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 <daor@demant.com>
This commit is contained in:
Danny Oerndrup 2019-08-01 07:56:45 +02:00 committed by Alberto Escolar
commit 51634cd661
5 changed files with 218 additions and 28 deletions

View file

@ -700,14 +700,18 @@ if(CONFIG_GEN_ISR_TABLES)
# isr_tables.c is generated from ${ZEPHYR_PREBUILT_EXECUTABLE} by # isr_tables.c is generated from ${ZEPHYR_PREBUILT_EXECUTABLE} by
# gen_isr_tables.py # 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 $<TARGET_FILE:${ZEPHYR_PREBUILT_EXECUTABLE}>
FILE_OUTPUT "isrList.bin"
)
add_custom_command( add_custom_command(
OUTPUT isr_tables.c OUTPUT isr_tables.c
COMMAND ${CMAKE_OBJCOPY} ${obj_copy_cmd}
-I ${OUTPUT_FORMAT}
-O binary
--only-section=.intList
$<TARGET_FILE:${ZEPHYR_PREBUILT_EXECUTABLE}>
isrList.bin
COMMAND ${PYTHON_EXECUTABLE} COMMAND ${PYTHON_EXECUTABLE}
${ZEPHYR_BASE}/arch/common/gen_isr_tables.py ${ZEPHYR_BASE}/arch/common/gen_isr_tables.py
--output-source isr_tables.c --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(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( add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_OBJ_RENAMED} OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PRIV_STACKS_OUTPUT_OBJ_RENAMED}
COMMAND ${obj_copy_cmd}
${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}
DEPENDS priv_stacks_output_lib DEPENDS priv_stacks_output_lib
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 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(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( add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_OBJ_RENAMED} OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_OBJ_RENAMED}
COMMAND ${obj_copy_cmd}
${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}
DEPENDS output_lib DEPENDS output_lib
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
@ -1216,7 +1232,7 @@ list(APPEND
if(NOT CONFIG_BUILD_NO_GAP_FILL) if(NOT CONFIG_BUILD_NO_GAP_FILL)
# Use ';' as separator to get proper space in resulting command. # Use ';' as separator to get proper space in resulting command.
set(GAP_FILL "--gap-fill;0xff") set(GAP_FILL "0xff")
endif() endif()
if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE) if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE)
@ -1238,38 +1254,83 @@ if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE)
endif() endif()
if(CONFIG_BUILD_OUTPUT_HEX) 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 list(APPEND
post_build_commands post_build_commands
COMMAND ${out_hex_cmd}
${CMAKE_OBJCOPY} -S -Oihex ${GAP_FILL} -R .comment -R COMMON -R .eh_frame ${KERNEL_ELF_NAME} ${KERNEL_HEX_NAME}
) )
list(APPEND list(APPEND
post_build_byproducts post_build_byproducts
${KERNEL_HEX_NAME} ${KERNEL_HEX_NAME}
${out_hex_byprod}
) )
endif() endif()
if(CONFIG_BUILD_OUTPUT_BIN) 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 list(APPEND
post_build_commands post_build_commands
COMMAND ${out_bin_cmd}
${CMAKE_OBJCOPY} -S -Obinary ${GAP_FILL} -R .comment -R COMMON -R .eh_frame ${KERNEL_ELF_NAME} ${KERNEL_BIN_NAME}
) )
list(APPEND list(APPEND
post_build_byproducts post_build_byproducts
${KERNEL_BIN_NAME} ${KERNEL_BIN_NAME}
${out_bin_byprod}
) )
endif() endif()
if(CONFIG_BUILD_OUTPUT_S19) 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 list(APPEND
post_build_commands post_build_commands
COMMAND ${out_S19_cmd}
${CMAKE_OBJCOPY} ${GAP_FILL} --srec-len 1 --output-target=srec ${KERNEL_ELF_NAME} ${KERNEL_S19_NAME}
) )
list(APPEND list(APPEND
post_build_byproducts post_build_byproducts
${KERNEL_S19_NAME} ${KERNEL_S19_NAME}
${out_S19_byprod}
) )
endif() endif()

View file

@ -15,3 +15,4 @@ find_program(CMAKE_GDB gdb-multiarch PATH ${TOOLCHAIN_HOME}
# Include bin tool abstraction macros # Include bin tool abstraction macros
include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake) include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake)
include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_objcopy.cmake)

View file

@ -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 <List of commands to be executed, usually after build>
# RESULT_BYPROD_LIST <List of command output byproducts>
#
# STRIP_ALL <When present, remove relocation and symbol info>
# STRIP_DEBUG <When present, remove debugging symbols and sections>
#
# TARGET_INPUT <Input file format type>
# TARGET_OUTPUT <Output file format type>
#
# GAP_FILL <Value used for gap fill, empty or not set, no gap fill>
# SREC_LEN <For srec format only, max length of the records>
#
# SECTION_ONLY <One or more section names to be included>
# SECTION_REMOVE <One or more section names to be excluded>
# SECTION_RENAME <One or more section names to be renamed 'from=to'>
#
# FILE_INPUT <The input file>
# FILE_OUTPUT <The output file>
# )
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)

View file

@ -12,3 +12,4 @@ find_program(CMAKE_GDB gdb )
# Use the gnu binutil abstraction macros # Use the gnu binutil abstraction macros
include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake) include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake)
include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_objcopy.cmake)

View file

@ -16,3 +16,4 @@ find_program(CMAKE_READELF readelf ${find_program_binutils_args})
# Use the gnu binutil abstraction macros # Use the gnu binutil abstraction macros
include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake) include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_memusage.cmake)
include(${ZEPHYR_BASE}/cmake/bintools/gnu/target_objcopy.cmake)