Skip to content

Commit

Permalink
CubeMX with CMake (#333)
Browse files Browse the repository at this point in the history
* Move to CMake on Demo/CAN/Send project

* Bringup Receive

* BasicIO to new format, except SIL

* Blink to new structure

* RTOS to cmake

* Make link private

* CAN Projects

* Mapper build sys

* AnalogPWM to cmake

* CANError build sys + formatting

* Front Controller

* LVController to cmake system and remove unused OS

* TMS to build system

* Separate toolchain script to avoid Makefile bug

* Fix first sed command

* BSD Compatible?

* Simplify command since this form is BSD compatible
  • Loading branch information
BlakeFreer authored Nov 28, 2024
1 parent 4d66457 commit 8ebc274
Show file tree
Hide file tree
Showing 98 changed files with 215 additions and 582 deletions.
33 changes: 7 additions & 26 deletions firmware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ if(NOT PROJECT_NAME)
endif()

# Check that the project and platform folders exist.

set(DIR_PROJECT "${CMAKE_CURRENT_SOURCE_DIR}/projects/${PROJECT}")
assert_exists(DIR PATH ${DIR_PROJECT}
START "Verifying ${PROJECT} is a project"
Expand Down Expand Up @@ -70,6 +69,7 @@ assert_exists(FILE PATH ${MCAL_CONF_FILE}
)

include(${MCAL_CONF_FILE}) # Should define MCAL

if(NOT DEFINED MCAL)
message(FATAL_ERROR "Expected MCAL to be defined in \"${MCAL_CONF_FILE}\".")
endif()
Expand All @@ -89,22 +89,18 @@ assert_exists(FILE PATH ${POSTBUILD_FILE}
${POSTBUILD_FILE} "\nand leave it empty."
)

# Sets the compiler, linker, etc based on the mcal's Toolchain.cmake file
set(TOOLCHAIN_FILE "${DIR_MCAL}/Toolchain.cmake")
assert_exists(FILE PATH ${TOOLCHAIN_FILE}
START "Finding MCAL toolchain file"
PASS "Found"
FAIL "Not found. If no toolchain setup is required, create the file\n"
${TOOLCHAIN_FILE} "\nand leave it empty."
)

list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "Success")

# Options are parsed. Start building
message(STATUS "Building \"${PROJECT}\" for \"${PLATFORM}\" with mcal \"${MCAL}\".")

set(CMAKE_TOOLCHAIN_FILE ${TOOLCHAIN_FILE})
# clangd export settings
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES OFF)

project(${PROJECT_NAME})

enable_language(C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
Expand All @@ -114,14 +110,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
set(CMAKE_CXX_EXTENSIONS ON)

project(${PROJECT_NAME})

# clangd export settings
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES OFF)

add_executable(main)
add_library(bindings)

add_subdirectory(shared) # provides "shared" (library)
add_subdirectory(${DIR_MCAL}) # provides "mcal-<name>" (library)
Expand All @@ -130,13 +119,5 @@ add_subdirectory(${DIR_PROJECT}) # modifies "main" (executable)
add_subdirectory(${DIR_PLATFORM}) # modifies "bindings" (library)

target_link_libraries(main PRIVATE shared)
target_link_libraries(main PRIVATE bindings)

# Only link/include RTOS if the project supports RTOS
# The project needs to provide an underlying OS target
# in the platform/${PLATFORM_NAME}/CMakeLists.txt
if(TARGET os)
target_link_libraries(main PRIVATE os)
endif()

include("${POSTBUILD_FILE}")
117 changes: 9 additions & 108 deletions firmware/cmake/build_cubemx.cmake
Original file line number Diff line number Diff line change
@@ -1,120 +1,21 @@
# Blake Freer
# April 13, 2023
# This file is included in the cubemx/CMakeLists.txt file of all projects'
# November 2024

# Generate code from CubeMX. The Makefile modifies the toolchain to fit our
# system.
# This file is included in the mcal_conf.cmake file of all projects'
# platforms that use the stm32f767 mcal

message(STATUS "Generating from CubeMX and adding custom targets.")
execute_process(
# Calls generate_cubemx.mk in the context of this file, which is adjacent to
# the board_config.ioc file.
COMMAND ${CMAKE_MAKE_PROGRAM} "--file=${CMAKE_SOURCE_DIR}/cmake/generate_cubemx.mk"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND make "--file=${CMAKE_SOURCE_DIR}/cmake/generate_cubemx.mk"
WORKING_DIRECTORY ${DIR_PLATFORM}/cubemx
RESULT_VARIABLE status
)

if(status AND NOT status EQUAL 0)
message(FATAL_ERROR
"Failed to generate from CubeMX. You should manually 'Generate Code' \
before building."
"${out} Failed to generate from CubeMX. You should manually 'Generate Code' before building."
)
endif()

set(CUSTOM_MAKEFILE "${CMAKE_CURRENT_SOURCE_DIR}/CustomMakefile.mk")

message(STATUS "Building CubeMX objects with the auto-generated Makefile")
execute_process(
# Build all cubemx sources to their objects. This target is added to the
# cubemx Makefile by generate_cubemx.mk.
COMMAND ${CMAKE_MAKE_PROGRAM} "objects" "--file=${CUSTOM_MAKEFILE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

function(extract_make_variable output makefile var_name)
# Get a variable from a Makefile
# This requires the Makefile to have the following target & recipe
#
# %.value:
# @echo $($*)
#
# generate_cubemx.mk appends this target to the cubemx Makefile
# See custom_cubemx_targets.mk
execute_process(
COMMAND ${CMAKE_MAKE_PROGRAM} "--file=${makefile}" "${var_name}.value" "--no-print-directory"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND_ECHO STDOUT
OUTPUT_VARIABLE value
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(VERBOSE "The make variable ${var_name} has the value \"${value}\"")
set(${output} ${value} PARENT_SCOPE)
endfunction()

# Get C_INCLUDES, split string to a list, and remove the -I prefix
extract_make_variable(include_str "${CUSTOM_MAKEFILE}" "C_INCLUDES")
separate_arguments(C_INCLUDES NATIVE_COMMAND ${include_str})
list(TRANSFORM C_INCLUDES REPLACE "^-I" "")

# Get Global #defines
extract_make_variable(c_def_str "${CUSTOM_MAKEFILE}" "C_DEFS")
separate_arguments(C_DEFS NATIVE_COMMAND ${c_def_str})
list(TRANSFORM C_DEFS REPLACE "^-D" "")

# Get MCU which includes the CPU name (cortex-m7), floating point unit, etc
extract_make_variable(MCU "${CUSTOM_MAKEFILE}" "MCU")
separate_arguments(MCU NATIVE_COMMAND ${MCU})

# Get the linker flags. These are needed since we manually link the objects
# instead of using the cubemx Makefile.
extract_make_variable(ldflags_str "${CUSTOM_MAKEFILE}" "LDFLAGS")
separate_arguments(LDFLAGS NATIVE_COMMAND ${ldflags_str})
# Need to fully specify the link script path
list(TRANSFORM LDFLAGS REPLACE "^-T" "-T${CMAKE_CURRENT_SOURCE_DIR}/")
# Cannot have "build/" in front of the map output.
list(TRANSFORM LDFLAGS REPLACE "Map=.*\\.map" "Map=${CMAKE_PROJECT_NAME}.map")

# Prepare the driver target
add_library(driver)
set_target_properties(driver PROPERTIES LINKER_LANGUAGE C) # required since the source files are object files

# The sources are all the object files compiled with the CubeMX Makefile
FILE(GLOB OBJ_DRIVER CONFIGURE_DEPENDS "build/*.o")
target_sources(driver PUBLIC ${OBJ_DRIVER})

# Apply the Makefile settings to the targets
target_include_directories(driver PUBLIC ${C_INCLUDES})
target_compile_definitions(driver PUBLIC ${C_DEFS})

target_compile_options(driver
PUBLIC
${MCU}
-fdata-sections
-ffunction-sections
-Wall
-Wextra
-Wpedantic
-Wshadow
-Wdouble-promotion
-Wformat=2 -Wformat-truncation
-Wundef
-fno-common
-Wno-unused-parameter
-Wno-missing-field-initializers
$<$<COMPILE_LANGUAGE:CXX>:
-Wno-old-style-cast
-Wno-useless-cast
-Wconversion
-Wno-volatile
-Wsuggest-override>
$<$<CONFIG:Debug>:-Og -g3 -ggdb>
$<$<CONFIG:Release>:-Og -g0>
)

# Notice that the linker settings are set for the "main" target.
target_link_options(main
PRIVATE
${LDFLAGS}
$<$<VERSION_GREATER:$<C_COMPILER_VERSION>,10.3.1>:-Wl,--no-warn-rwx-segments>
-Wl,--start-group
-Wl,--end-group
-Wl,--print-memory-usage
)
set(CMAKE_TOOLCHAIN_FILE "${DIR_PLATFORM}/cubemx/cmake/racecar-toolchain.cmake")
17 changes: 0 additions & 17 deletions firmware/cmake/custom_cubemx_targets.mk

This file was deleted.

14 changes: 14 additions & 0 deletions firmware/cmake/custom_toolchain.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Modify the CubeMX-generated toolchain file to work with out build system.
# These commands are not in the Makefile since Make messes with the ${} characters
# in the `sed` replacement string.

# CubeMX forces CMake to skip its automatic compiler detection, which messes
# with our clangd setup. Comment out the lines that do this.
sed -E '/set\(CMAKE.*COMPILER_FORCED.*$/s/^/# /g' $1 > tmp.txt
mv tmp.txt $1

# CubeMX incorrectly assumes that our top-level CMakeLists.txt is in the same
# directory as the .ioc file. This means that the linker script directory is wrong.
# Find the "-T ** .ld" line and replace the CMAKE variable with the current directory.
sed -E "/-T.*\.ld/s|\\\$\{CMAKE_SOURCE_DIR\}|${PWD}|g" $1 > tmp.txt
mv tmp.txt $1
20 changes: 9 additions & 11 deletions firmware/cmake/generate_cubemx.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ endif
# Find the JAVA which is installed with CubeMX. Spaces in path are escaped.
space := $(subst ,, )

# Known bug: Expanding CUBEMX_JAVA twice does not work.
ifeq ($(shell uname), Darwin)
# MacOS
CUBEMX_JAVA := $(dir $(subst $(space),\$(space),$(CUBEMX_PATH)))jre/Contents/Home/bin/java
Expand All @@ -17,8 +18,6 @@ else
CUBEMX_JAVA := $(dir $(subst $(space),\$(space),$(CUBEMX_PATH)))jre/bin/java
endif

# Known bug: Expanding CUBEMX_JAVA twice does not work.

IOC_FILE = board_config.ioc

CUBEMX_GEN_SCRIPT = cubemx_script.txt
Expand All @@ -29,18 +28,17 @@ CUSTOM_TARGETS_FILE = $(BUILD_SYS_DIR)custom_cubemx_targets.mk

CUBEMX_GEN_SCRIPT_TEMPLATE := $(BUILD_SYS_DIR)generate_cubemx_script.txt.template

# Copy the CubeMX makefile and custom targets into a new makefile
CustomMakefile.mk: Makefile $(CUSTOM_TARGETS_FILE)
@echo "Creating $@ from [$^]"
cat Makefile > $@
cat $(CUSTOM_TARGETS_FILE) >> $@
cmake/racecar-toolchain.cmake: cmake/gcc-arm-none-eabi.cmake
@echo "Modifying autogen toolchain file."
cp $< $@
. $(BUILD_SYS_DIR)custom_toolchain.sh $@

# This recipe will execute whenever IOC_FILE has a newer timestamp than the
# Makefile, i.e. whenever IOC_FILE has been updated but new code has not been
# generated.
Makefile: $(IOC_FILE) $(CUBEMX_GEN_SCRIPT_TEMPLATE)
# generated toolchain file, i.e. whenever IOC_FILE has been updated but new code
# has not been generated.
cmake/gcc-arm-none-eabi.cmake: $(IOC_FILE) $(CUBEMX_GEN_SCRIPT_TEMPLATE)
@echo "Autogenerating from CubeMX. If you don't want to do this, you must manually 'Generate Code' before building."
# Create an file containing commands to generate the cubemx code.
# Create a file containing commands to generate the cubemx code.
sed -e 's/IOC_FILE/$(IOC_FILE)/g' $(CUBEMX_GEN_SCRIPT_TEMPLATE) > $(CUBEMX_GEN_SCRIPT)

# Run the cubemx program to generate code.
Expand Down
3 changes: 0 additions & 3 deletions firmware/mcal/cli/Toolchain.cmake

This file was deleted.

3 changes: 0 additions & 3 deletions firmware/mcal/linux/Toolchain.cmake

This file was deleted.

3 changes: 0 additions & 3 deletions firmware/mcal/raspi/Toolchain.cmake

This file was deleted.

24 changes: 0 additions & 24 deletions firmware/mcal/stm32f767/Toolchain.cmake

This file was deleted.

2 changes: 1 addition & 1 deletion firmware/projects/Demo/AnalogPWM/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
target_sources(main PUBLIC main.cc)
target_sources(main PRIVATE main.cc)
5 changes: 2 additions & 3 deletions firmware/projects/Demo/AnalogPWM/platforms/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
target_sources(bindings PRIVATE bindings.cc)

target_link_libraries(bindings PUBLIC mcal-cli)
target_sources(main PRIVATE bindings.cc)
target_link_libraries(main PRIVATE mcal-cli)
5 changes: 0 additions & 5 deletions firmware/projects/Demo/BasicIO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,5 @@

target_sources(main PRIVATE main.cc)

target_include_directories(main
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/inc
)

# Notice that we don't include any mcal/ or platform /subdirectory in this CMake
# file. The master CMakeLists handles platform selection and library linking.
12 changes: 12 additions & 0 deletions firmware/projects/Demo/BasicIO/bindings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "shared/periph/gpio.h"

namespace bindings {

extern shared::periph::DigitalInput& button_di;
extern shared::periph::DigitalOutput& indicator_do;

extern void Initialize();

} // namespace bindings
Loading

0 comments on commit 8ebc274

Please sign in to comment.