Fecha: enero 24, 2023
Autor: Guillermo Garcia
Categorías: Visual Studio Code Etiquetas: Development tools
We have defined a project structure and added the necessary source files in the previous article, Visual Studio Code for ARM with CMake #2 Project. In this article, we will configure the build environment with the CMake Toolchain.
Table of Contents
To generate an executable file, we first need to invoke the GCC compiler, specifying which source files should be compiled to create the executable. Interacting with the compiler directly through commands is often impractical in software development, where the source files increase as the project grows.
How can we make the process of interacting with the compiler more efficient? Well, for that, we will use CMake.
CMake is used to control the software compilation process through a simple platform and configuration files that are independent of the compiler.
The GNU C/C++ GCC compiler is based on GNU Make, which makes it possible to manage the compilation process using the Make utility. The Make utility requires a makefile that defines a set of tasks to be executed.
Creating the makefile is not complicated, but it takes time to write the necessary routine and requires knowledge of the GNU environment. To simplify this, we use CMake.
CMake generates build pipelines, meaning it creates a file for a sub-compilation environment. In conclusion, during the compilation process, CMake will generate a makefile with the necessary instructions for the GNU Make environment to interact with the compiler and generate the executable file.
Every CMake-based project contains a script called CMakeLists.txt, in this file the instructions for performing the compilation are described. We also need to tell CMake where our compilation tools are installed, so we add a file called Buildtools.cmake.
We create the CMakeLists.txt file where we will mainly describe the source files that we want to be compiled, as well as specific parameters of our hardware.
cmake_minimum_required(VERSION 3.23.1) # Optional: print out extra messages to see what is going on. Comment it to have less verbose messages set(CMAKE_VERBOSE_MAKEFILE ON) # Path to toolchain file. This one has to be before 'project()' below set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/Buildtools.cmake) # Setup project, output and linker file project(VSC_G071RB) set(EXECUTABLE ${PROJECT_NAME}.elf) set(LINKER_FILE ${CMAKE_SOURCE_DIR}/Device/STM32G071RBTX_FLASH.ld) enable_language(C ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) # Optional: issue a message to be sure it uses the correct toolchain file. message(STATUS "CMAKE_TOOLCHAIN_FILE is: ${CMAKE_TOOLCHAIN_FILE}") # List of source files set(SRC_FILES main/main.c Device/stm32g0xx_it.c Device/system_stm32g0xx.c Device/startup_stm32g071xx.s Device/stm32g0xx_hal_msp.c Drivers/Src/stm32g0xx_hal.c Drivers/Src/stm32g0xx_hal_rcc.c Drivers/Src/stm32g0xx_hal_rcc_ex.c Drivers/Src/stm32g0xx_hal_flash.c Drivers/Src/stm32g0xx_hal_flash_ex.c Drivers/Src/stm32g0xx_hal_dma.c Drivers/Src/stm32g0xx_hal_dma_ex.c Drivers/Src/stm32g0xx_hal_gpio.c Drivers/Src/stm32g0xx_hal_cortex.c Drivers/Src/stm32g0xx_hal_exti.c Drivers/Src/stm32g0xx_hal_tim.c Drivers/Src/stm32g0xx_hal_tim_ex.c Drivers/Src/stm32g0xx_hal_pwr.c Drivers/Src/stm32g0xx_hal_pwr_ex.c ) # Build the executable based on the source files add_executable(${EXECUTABLE} ${SRC_FILES}) # List of compiler defines, prefix with -D compiler option target_compile_definitions(${EXECUTABLE} PRIVATE -DSTM32G071xx -DUSE_HAL_DRIVER ) # List of includ directories target_include_directories(${EXECUTABLE} PRIVATE main CMSIS/Include CMSIS/Device/ST/STM32G0xx Device Drivers/Inc/ Drivers/Inc/Legacy ) # Compiler options target_compile_options(${EXECUTABLE} PRIVATE -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -fdata-sections -ffunction-sections -Wall -O0 -Og -gdwarf-2 ) # Linker options target_link_options(${EXECUTABLE} PRIVATE -T${LINKER_FILE} -mcpu=cortex-m0 -mthumb -mfloat-abi=soft --specs=rdimon.specs --specs=nano.specs -lc -lm -lnosys -Wl,-Map=${PROJECT_NAME}.map,--cref -Wl,--gc-sections -Xlinker -print-memory-usage -Xlinker ) # Optional: Print executable size as part of the post build process add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE}) # Optional: Create hex, bin and S-Record files after the build add_custom_command(TARGET ${EXECUTABLE} POST_BUILD COMMAND ${CMAKE_OBJCOPY} -O srec --srec-len=64 ${EXECUTABLE} ${PROJECT_NAME}.s19 COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE} ${PROJECT_NAME}.hex COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin)
We create the Buildtools.cmake file so that CMake knows where the compiler is installed.
set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_PROCESSOR ARM) set(ARM_TOOLCHAIN_DIR "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin") set(BINUTILS_PATH ${ARM_TOOLCHAIN_DIR}) set(TOOLCHAIN_PREFIX ${ARM_TOOLCHAIN_DIR}/arm-none-eabi-) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc.exe") set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++.exe") set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool") set(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size CACHE INTERNAL "size tool") set(CMAKE_FIND_ROOT_PATH ${BINUTILS_PATH}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
When we run CMake, two important steps take place. First, a configuration process (Configure step) is executed, where internal CMake files, such as the CMakeCache.txt file, are created. The second process is the generation step (Generate step), where an equivalent makefile for our project is generated.
The CMakeLists.txt script is executed during the configuration step. This script is responsible for defining the targets (source files). Each target represents an executable, a library, or some other result of the (build pipeline).
If the configuration step is successful, meaning CMakeLists.txt completes without errors, CMake will generate a (build pipeline) using the targets defined by the script.
The configuration process should only be done once unless a full cleanup of the build is desired. This is thanks to the cache stored in the CMakeCache.txt file.
Now let’s run CMake and see the result of the compilation.
To start CMake we will specify two important parameters, first CMAKE_MAKE_PROGRAM to indicate that we are using the makefile generator, and CMAKE_TOOLCHAIN_FILE indicating the file where the compilation tools are located.
We will go to the build folder in our project and execute the command:
C:/VSC_G071RB\build>cmake -DCMAKE_MAKE_PROGRAM=make.exe -DCMAKE_TOOLCHAIN_FILE="Buildtools.cmake" -G "Unix Makefiles" .. " -G "Unix Makefiles" .. -- The C compiler identification is GNU 10.3.1 -- The CXX compiler identification is GNU 10.3.1 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-gcc.exe - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-g++.exe - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- The ASM compiler identification is GNU -- Found assembler: C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-gcc.exe -- CMAKE_TOOLCHAIN_FILE is: C:/VSC_G071RB/Buildtools.cmake -- Configuring done -- Generating done -- Build files have been written to: C:/VSC_G071RB/build
We see how this generates files inside the build folder:
If we look at the contents of the build folder we still do not have an executable file, this is because the compiler has not yet been invoked.
It is time to compile the project here is where the makefiles generated by CMake are needed, we execute the command:
C:\VSC_G071RB\build>cmake --build . "C:/Program Files/CMake/bin/cmake.exe" -SC:/VSC_G071RB -BC:/VSC_G071RB/build --check-build-system CMakeFiles/Makefile.cmake 0 "C:/Program Files/CMake/bin/cmake.exe" -E cmake_progress_start C:/VSC_G071RB/build/CMakeFiles C:/VSC_G071RB/build//CMakeFiles/progress.marks make.exe -f CMakeFiles/Makefile2 all make.exe[1]: Entering directory `/c/VSC_G071RB/build' make.exe -f CMakeFiles/VSC_G071RB.elf.dir/build.make CMakeFiles/VSC_G071RB.elf.dir/depend make.exe[2]: Entering directory `/c/VSC_G071RB/build' "C:/Program Files/CMake/bin/cmake.exe" -E cmake_depends "Unix Makefiles" C:/VSC_G071RB C:/VSC_G071RB C:/VSC_G071RB/build C:/VSC_G071RB/build C:/VSC_G071RB/build/CMakeFiles/VSC_G071RB.elf.dir/DependInfo.cmake --color= Scanning dependencies of target VSC_G071RB.elf make.exe[2]: Leaving directory `/c/VSC_G071RB/build' make.exe -f CMakeFiles/VSC_G071RB.elf.dir/build.make CMakeFiles/VSC_G071RB.elf.dir/build make.exe[2]: Entering directory `/c/VSC_G071RB/build' [ 5%] Building C object CMakeFiles/VSC_G071RB.elf.dir/main/main.c.obj [ 95%] Building C object CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_pwr_ex.c.obj "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-gcc.exe" -DSTM32G071xx -DUSE_HAL_DRIVER -IC:/Users/urie_/Documents/FreeRTOS/VSC_G071RB/main -IC:/CMSIS/Include -IC:/Users/urie_/Documents/FreeRTOS/VSC_G071RB/CMSIS/Device/ST/STM32G0xx -IC:/VSC_G071RB/Device -IC:/VSC_G071RB/Drivers/Inc -IC:/VSC_G071RB/Drivers/Inc/Legacy -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -fdata-sections -ffunction-sections -Wall -O0 -Og -gdwarf-2 -std=c99 -MD -MT CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_pwr_ex.c.obj -MF CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_pwr_ex.c.obj.d -o CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_pwr_ex.c.obj -c C:/Users/urie_/Documents/FreeRTOS/VSC_G071RB/Drivers/Src/stm32g0xx_hal_pwr_ex.c [100%] Linking C executable VSC_G071RB.elf "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-gcc.exe" -TC:/Users/urie_/Documents/FreeRTOS/VSC_G071RB/Device/STM32G071RBTX_FLASH.ld -mcpu=cortex-m0 -mthumb -mfloat-abi=soft --specs=rdimon.specs --specs=nano.specs -lc -lm -lnosys -Wl,-Map=VSC_G071RB.map,--cref -Wl,--gc-sections -Xlinker -print-memory-usage "CMakeFiles/VSC_G071RB.elf.dir/main/main.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Device/stm32g0xx_it.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Device/system_stm32g0xx.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Device/startup_stm32g071xx.s.obj" "CMakeFiles/VSC_G071RB.elf.dir/Device/stm32g0xx_hal_msp.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_rcc.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_rcc_ex.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_flash.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_flash_ex.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_dma.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_dma_ex.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_gpio.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_cortex.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_exti.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_tim.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_tim_ex.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_pwr.c.obj" "CMakeFiles/VSC_G071RB.elf.dir/Drivers/Src/stm32g0xx_hal_pwr_ex.c.obj" -o VSC_G071RB.elf Memory region Used Size Region Size %age Used RAM: 1600 B 36 KB 4.34% FLASH: 3740 B 128 KB 2.85% "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-size" VSC_G071RB.elf text data bss dec hex filename 3720 20 1588 5328 14d0 VSC_G071RB.elf "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-objcopy" -O srec --srec-len=64 VSC_G071RB.elf VSC_G071RB.s19 "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-objcopy" -O ihex VSC_G071RB.elf VSC_G071RB.hex "C:/Program Files (x86)/GNU Arm Embedded Toolchain/10 2021.10/bin/arm-none-eabi-objcopy" -O binary VSC_G071RB.elf VSC_G071RB.bin make.exe[2]: Leaving directory `/c/Users/urie_/Documents/FreeRTOS/VSC_G071RB/build' [100%] Built target VSC_G071RB.elf make.exe[1]: Leaving directory `/c/Users/urie_/Documents/FreeRTOS/VSC_G071RB/build' "C:/Program Files/CMake/bin/cmake.exe" -E cmake_progress_start C:/VSC_G071RB/build/CMakeFiles 0
If there are no errors in the compilation we observe our executable file inside the build directory.
Deja una respuesta