Skip to content

Commit

Permalink
add transitive object library function
Browse files Browse the repository at this point in the history
  • Loading branch information
jefflongo committed Aug 6, 2023
1 parent 6d4071c commit 677a10e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 51 deletions.
84 changes: 45 additions & 39 deletions cmake/FindSTM32Cube.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,42 @@ cmake_minimum_required(VERSION 3.21)

include(${CMAKE_CURRENT_LIST_DIR}/stm32cube_drivers.cmake)

# Adds an object library named `output name` from the given `object_library`
# which can be use transitively.
#
# object libraries are preferable to static libraries when the library overrides
# a weak symbol with a strong one. this is because, by default, the linker will
# omit the strong symbol if a weak one is already present. the only way to get
# around this is to provide --whole-archive (or OS equivalent), or to use an
# object library. object libraries cannot be used transitively. that is, an
# object library cannot link another object library because object libraries
# have no link stage. this function provides a way to create a transitive object
# library. see here for more info:
# https://cmake.org/cmake/help/latest/command/target_link_libraries.html#linking-object-libraries-via-target-objects
function(add_transitive_object_library output_name object_library)
# make sure the given library is an OBJECT library
get_target_property(library_type ${object_library} TYPE)
if(NOT ${library_type} STREQUAL "OBJECT_LIBRARY")
message(FATAL_ERROR "${object_library} is not an OBJECT library")
endif()

if("${output_name}" STREQUAL "_${object_library}")
message(FATAL_ERROR "Output name cannot be input name prefixed with '_'")
endif()

# create interface library to allow transitive library dependencies
set(interface_object_library "_${object_library}")
add_library(${interface_object_library} INTERFACE)

# inherit the usage requirements and objects
target_link_libraries(
${interface_object_library} INTERFACE ${object_library}
$<TARGET_OBJECTS:${object_library}>)

# create an alias for namespacing
add_library(${output_name} ALIAS ${interface_object_library})
endfunction()

function(generate_stm32cube mcu)
set(options)
set(args)
Expand Down Expand Up @@ -99,15 +135,7 @@ function(generate_stm32cube mcu)
${STM32CUBE_PATH}/Drivers/CMSIS/Core/Include
${STM32CUBE_PATH}/Drivers/CMSIS/Device/ST/STM32${type_core_upper}xx/Include
)

# create interface library to allow transitive OBJECT library dependencies
add_library(_${mcu_lower}_cmsis INTERFACE)
target_link_libraries(
_${mcu_lower}_cmsis INTERFACE ${mcu_lower}_cmsis
$<TARGET_OBJECTS:${mcu_lower}_cmsis>)

# create alias for namespacing
add_library(stm32::${mcu_lower}_cmsis ALIAS _${mcu_lower}_cmsis)
add_transitive_object_library(stm32::${mcu_lower}_cmsis ${mcu_lower}_cmsis)

# build HAL as a link dependency for HAL drivers
if(hal_drivers)
Expand All @@ -123,12 +151,7 @@ function(generate_stm32cube mcu)
${STM32CUBE_PATH}/Drivers/CMSIS/Core/Include
${STM32CUBE_PATH}/Drivers/CMSIS/Device/ST/STM32${type_core_upper}xx/Include
${STM32CUBE_PATH}/Drivers/STM32${type_core_upper}xx_HAL_Driver/Inc)

# create interface library to allow transitive OBJECT library dependencies
add_library(_${mcu_lower}_hal INTERFACE)
target_link_libraries(
_${mcu_lower}_hal INTERFACE ${mcu_lower}_hal
$<TARGET_OBJECTS:${mcu_lower}_hal>)
add_transitive_object_library(stm32::_${mcu_lower}_hal ${mcu_lower}_hal)
endif()

# build HAL libraries
Expand All @@ -137,18 +160,10 @@ function(generate_stm32cube mcu)
${mcu_lower}_hal_${driver} OBJECT
${STM32CUBE_PATH}/Drivers/STM32${type_core_upper}xx_HAL_Driver/Src/stm32${type_core_lower}xx_hal_${driver}.c
)
target_link_libraries(${mcu_lower}_hal_${driver} PUBLIC _${mcu_lower}_hal)

# create interface library to allow transitive OBJECT library dependencies
add_library(_${mcu_lower}_hal_${driver} INTERFACE)
target_link_libraries(
_${mcu_lower}_hal_${driver}
INTERFACE ${mcu_lower}_hal_${driver}
$<TARGET_OBJECTS:${mcu_lower}_hal_${driver}>)

# create alias for namespacing
add_library(stm32::${mcu_lower}_hal_${driver} ALIAS
_${mcu_lower}_hal_${driver})
target_link_libraries(${mcu_lower}_hal_${driver}
PUBLIC stm32::_${mcu_lower}_hal)
add_transitive_object_library(stm32::${mcu_lower}_hal_${driver}
${mcu_lower}_hal_${driver})
endforeach()

# build LL libraries
Expand All @@ -170,21 +185,12 @@ function(generate_stm32cube mcu)
${STM32CUBE_PATH}/Drivers/CMSIS/Core/Include
${STM32CUBE_PATH}/Drivers/CMSIS/Device/ST/STM32${type_core_upper}xx/Include
${STM32CUBE_PATH}/Drivers/STM32${type_core_upper}xx_HAL_Driver/Inc)

# create interface library to allow transitive OBJECT library dependencies
add_library(_${mcu_lower}_ll_${driver} INTERFACE)
target_link_libraries(
_${mcu_lower}_ll_${driver}
INTERFACE ${mcu_lower}_ll_${driver}
$<TARGET_OBJECTS:${mcu_lower}_ll_${driver}>)

# create alias for namespacing
add_library(stm32::${mcu_lower}_ll_${driver} ALIAS
_${mcu_lower}_ll_${driver})
add_transitive_object_library(stm32::${mcu_lower}_ll_${driver}
${mcu_lower}_ll_${driver})
endforeach()
endfunction()

set(STM32Cube_VERSION 0.1.0)
set(STM32Cube_VERSION 0.2.0)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
Expand Down
14 changes: 8 additions & 6 deletions examples/blinky-multiboard/src/board/nucleo-l412/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
generate_stm32cube(stm32l412 LL_DRIVERS gpio utils pwr rcc)

# NOTE: object libraries must be used when creating a library that uses
# STM32Cube due to the way the linker handles weak symbols when linking static
# libraries
add_library(board_stm32l412 OBJECT board.c)
target_include_directories(board_stm32l412 PUBLIC ../common/include)
target_link_libraries(
board_stm32l412
PUBLIC stm32::stm32l412_cmsis stm32::stm32l412_ll_gpio
stm32::stm32l412_ll_utils stm32::stm32l412_ll_pwr
stm32::stm32l412_ll_rcc)
# create interface library to allow transitive OBJECT library dependencies
add_library(_board_stm32l412 INTERFACE)
target_link_libraries(
_board_stm32l412 INTERFACE board_stm32l412 $<TARGET_OBJECTS:board_stm32l412>)
# create alias for namespacing
add_library(board::stm32l412 ALIAS _board_stm32l412)

add_library(board::stm32l412 ALIAS board_stm32l412)
# NOTE: object libraries are not transitive. if linking this library to another
# object library, use this instead:
# add_transitive_object_library(board::stm32l412 board_stm32l412)
14 changes: 8 additions & 6 deletions examples/blinky-multiboard/src/board/nucleo-l476/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
generate_stm32cube(stm32l476 LL_DRIVERS gpio utils pwr rcc)

# NOTE: object libraries must be used when creating a library that uses
# STM32Cube due to the way the linker handles weak symbols when linking static
# libraries
add_library(board_stm32l476 OBJECT board.c)
target_include_directories(board_stm32l476 PUBLIC ../common/include)
target_link_libraries(
board_stm32l476
PUBLIC stm32::stm32l476_cmsis stm32::stm32l476_ll_gpio
stm32::stm32l476_ll_utils stm32::stm32l476_ll_pwr
stm32::stm32l476_ll_rcc)
# create interface library to allow transitive OBJECT library dependencies
add_library(_board_stm32l476 INTERFACE)
target_link_libraries(
_board_stm32l476 INTERFACE board_stm32l476 $<TARGET_OBJECTS:board_stm32l476>)
# create alias for namespacing
add_library(board::stm32l476 ALIAS _board_stm32l476)

add_library(board::stm32l476 ALIAS board_stm32l476)
# NOTE: object libraries are not transitive. if linking this library to another
# object library, use this instead:
# add_transitive_object_library(board::stm32l476 board_stm32l476)

0 comments on commit 677a10e

Please sign in to comment.