Fecha: enero 24, 2023
Autor: Guillermo Garcia
Categorías: Visual Studio Code Etiquetas: Development tools
Hemos definido una estructura de proyecto además de agregar los archivos fuente necesarios en el artículo anterior Visual Studio Code for ARM with CMake #2 Proyecto. En este articulo vamos a configurar el entorno de compilación Toolchain CMake.
Table of Contents
Para obtener un archivo ejecutable primero necesitamos invocar al compilador GCC indicando que archivos fuente se deben compilar para generar un archivo ejecutable. Interactuar con el compilador directamente médiate comandos suele ser poco práctico en el desarrollo de software donde los archivos fuente aumentan conforme crece un proyecto.
Como hacemos más ágil el proceso de interactuar con el compilador pues para eso emplearemos CMake.
CMake se usa para controlar el proceso de compilación de software mediante una plataforma simple y archivos de configuración independientes del compilador.
El compilador GNU C/C++ GCC esta basado en GNU make esto hace que sea posible gestionar el proceso de compilación mediante la utilidad make. La utilidad make requiere un archivo makefile que defina un conjunto de tareas a ejecutar.
Crear el archivo makefile no es algo complicado pero requiere algo de tiempo en escribir la rutina necesaria además de conocer el entorno GNU, para hacer esto más simple utilizamos CMake.
CMake genera canalizaciones de compilación (build pipelines) es decir un archivo para un sub entorno de compilación, en conclusión en el proceso de compilación CMake generara un archivo makefile con las instrucciones necesarias para que el entorno GNU make interactúe con el compilador y este genere el archivo ejecutable.
Todos los proyectos basados en CMake contiene un script llamado CMakeLists.txt en este archivo se describen las instrucciones para realizar la compilación. También tenemos que indicarle a CMake donde están instaladas nuestras herramientas de compilación para esto agregamos un archivo llamado Buildtools.cmake.
Creamos el archivo CMakeLists.txt vamos a describir principalmente los archivos fuente que deseamos sean compilados, así como parámetros específicos de nuestro 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)
Creamos el archivo Buildtools.cmake para que CMake conozca donde está instalado el compilador.
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)
Cuando ejecutamos CMake se realizan dos pasos importantes primero se ejecuta un proceso de configuración (Configure step) donde se crean archivos internos de CMake como el archivo CMakeCache.txt. El segundo proceso es de generación (Generate step) es donde se obtiene un archivo makefile equivalente para nuestro proyecto.
El CMakeLists.txt script se ejecuta durante el paso de configuración. Este script se encarga de definir los target (Archivos fuente). Cada target representa un ejecutable, una biblioteca o algún otro resultado de la canalización de compilación (build pipelines).
Si el paso de configuración tiene éxito, es decir, CMakeLists.txt se completó sin errores, CMake generará una canalización de compilación (build pipelines) utilizando los objetivos definidos por el script.
El proceso de configuración solo debe realizarse una vez, sino se desea limpiar toda la compilación esto es gracias al cache almacenado en el archivo CMakeCache.txt.
Ahora vamos a ejecutar CMake observemos el resultado de la compilación.
Para iniciar CMake indicaremos dos parámetros importantes primero CMAKE_MAKE_PROGRAM para indicar que utilizamos generador de makefile, CMAKE_TOOLCHAIN_FILE indicando el archivo donde se encuentran las herramientas de compilación.
Nos dirigiremos a la carpeta build en nuestro proyecto y ejecutamos el comando:
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
Vemos como esto nos genera archivos dentro de la carpeta build :
Si observamos el contenido de la carpeta build aun no tenemos un archivo ejecutable, esto es debido a que aún no se invoca al compilador.
Es momento de compilar el proyecto aquí es donde los archivos makefile generados por CMake son necesarios ejecutamos el comando:
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
Si no hay errores en la compilación observamos nuestro archivo ejecutable dentro del directorio build.
Deja una respuesta