Actions

EmSys

Using Visual Studio Code for ARM Development – Build Tasks

From EdWiki

Revision as of 17:24, 19 April 2022 by Jshankar (Talk | contribs) (CMake: Configure)


CMake: Configure

We are going to use CMake with Make to build the project. CMake needs some information where to find the tools. How does CMake know which compiler to use? It checks the CC and CXX environment variables. They define what is the default compiler in the system. If we manually set CC or CXX to different values, then CMake will use these new settings as default compilers. After successful detection, CMake stores info about the current toolchain in the following variables:

CMAKE_C_COMPILER,
CMAKE_CXX_COMPILER

They contain paths to the C and C++ compilers respectively.

When we cross-compile to another platform, we have to specify completely different toolchain both in terms of name and location of the binaries. This can be done in two ways:

  1. pass values for the toolchain variables from the command line,
  2. specify toolchain file.


First option is very explicit thus easy to understand, but big number of arguments makes it harder to use CMake in terminal:

cmake .. -DCMAKE_C_COMPILER=<path_to_c_compiler> -DCMAKE_CXX_COMPILER=<path_to_cxx_compiler> -DCMAKE_AR=<path_to_ar> -DCMAKE_LINKER=<path_to_linker> etc...


Second option is more elegant and is the preferred way of choosing the toolchain. All we need to do is to put toolchain variables into a separate file (e.g. <toolchain_name>.cmake) and set CMAKE_TOOLCHAIN_FILE variable to the path of that file. This can be done both in the command line or in CMakeLists.txt before project() command:

cmake .. -DCMAKE_TOOLCHAIN_FILE=<path_to_toolchain_file>

OR

cmake_minimum_required(VERSION 3.15)
set(CMAKE_TOOLCHAIN_FILE <path_to_toolchain_file>)
project(<project_name> LANGUAGES C CXX)

A simple and easy way is to to add the following file to the project. I have named it arm-toolchain.cmake and placed it in the project root folder.

Note: It is crucial to set the value of CMAKE_TOOLCHAIN_FILE before project() is invoked, because project() triggers toolchain detection and verification.


CMake: Toolchain File

  1. # File: arm-toolchain.cmake
  2. # Toolchain file for arm-none-eabi-gcc
  3.  
  4. set(CMAKE_SYSTEM_NAME Generic)
  5. set(CMAKE_SYSTEM_PROCESSOR ARM)
  6. set(CMAKE_CROSSCOMPILING "TRUE")
  7.  
  8. # Set system depended extensions
  9. if(WIN32)
  10.   set(ARM_TOOLCHAIN_EXT ".exe" )
  11. else()
  12.   set(ARM_TOOLCHAIN_EXT "" )
  13. endif()
  14.  
  15. if(WIN32)
  16.     set(ARM_TOOLCHAIN_DIR "C:/ProgramData/chocolatey/bin")
  17. else()
  18.     set(ARM_TOOLCHAIN_DIR "/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin")
  19. endif()
  20.  
  21. set(BINUTILS_PATH ${ARM_TOOLCHAIN_DIR}) 
  22.  
  23. set(TOOLCHAIN_PREFIX ${ARM_TOOLCHAIN_DIR}/arm-none-eabi-)
  24.  
  25. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
  26.  
  27. set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}gcc${ARM_TOOLCHAIN_EXT}")
  28. set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
  29. set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}g++${ARM_TOOLCHAIN_EXT}")
  30.  
  31. set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool")
  32. set(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size CACHE INTERNAL "size tool")
  33.  
  34. set(CMAKE_FIND_ROOT_PATH ${BINUTILS_PATH})
  35. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  36. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  37. set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)


ARM_TOOLCHAIN_DIR specifies the compiler to be used. Additionally it defines extra tools as size and objcopy.

CMake: CMakeLists.txt

To tell CMake what to do, create a file named CMakeList.txt in the project root.

  1. # File: CMakeList.txt
  2. # CMake file for tm4c123gxl
  3.  
  4. cmake_minimum_required(VERSION 3.15.3)
  5.  
  6. # Optional: print out extra messages to see what is going on. Comment it to have less verbose messages
  7. set(CMAKE_VERBOSE_MAKEFILE ON)
  8.  
  9. # Path to toolchain file. This one has to be before 'project()' below
  10. set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/arm-toolchain.cmake)
  11.  
  12. # Setup project, output and linker file
  13. project(blinky VERSION 0.1)
  14. set(EXECUTABLE ${PROJECT_NAME}.elf)
  15. set(LINKER_FILE ${CMAKE_SOURCE_DIR}/ld/tm4c123gh6pm.ld)
  16.  
  17. enable_language(C ASM)
  18. set(CMAKE_C_STANDARD 99)
  19. set(CMAKE_C_STANDARD_REQUIRED ON)
  20. set(CMAKE_C_EXTENSIONS OFF)
  21.  
  22. # Optional: issue a message to be sure it uses the correct toolchain file.
  23. message(STATUS "CMAKE_TOOLCHAIN_FILE is: ${CMAKE_TOOLCHAIN_FILE}")
  24.  
  25. # List of source files
  26. set(SRC_FILES
  27.         src/main.c
  28.         src/tm4c_startup.c
  29.         inc/tm4c_startup.h
  30.     )
  31.  
  32. # Build the executable based on the source files
  33. add_executable(${EXECUTABLE} ${SRC_FILES})
  34.  
  35. # List of compiler defines, prefix with -D compiler option
  36. target_compile_definitions(${EXECUTABLE} PRIVATE -DPART_TM4C123GH6PM)
  37.  
  38. # List of include directories
  39. target_include_directories(${EXECUTABLE} PRIVATE
  40.         src 
  41.         inc
  42. if(WIN32)        
  43.         "E:/ti/TivaWare_C_Series-2.2.0.295"
  44. else()
  45.         "/home/jshankar/ti/TivaWare_C_Series-2.2.0.295"
  46. endif()
  47.         )
  48.  
  49. # Compiler options
  50. target_compile_options(${EXECUTABLE} PRIVATE
  51.         -mcpu=cortex-m4
  52.         -mthumb
  53.         -mfpu=fpv4-sp-d16
  54.         -mfloat-abi=hard
  55.  
  56.         -fdata-sections
  57.         -ffunction-sections
  58.  
  59.         -Wall
  60.         -O0
  61.         -g3
  62.         )
  63.  
  64. # Linker options
  65. target_link_options(${EXECUTABLE} PRIVATE
  66.         -T${LINKER_FILE}
  67.         -mcpu=cortex-m4
  68.         -mthumb
  69.         -mfpu=fpv4-sp-d16
  70.         -mfloat-abi=hard
  71.         -specs=nano.specs
  72.         -specs=nosys.specs
  73.         -lc
  74.         -lm
  75.         -Wl,-Map=${PROJECT_NAME}.map,--cref
  76.         -Wl,--gc-sections
  77.         -Xlinker -print-memory-usage -Xlinker
  78.         )
  79.  
  80. # Optional: Print executable size as part of the post build process
  81. add_custom_command(TARGET ${EXECUTABLE}
  82.         POST_BUILD
  83.         COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE})
  84.  
  85. # Optional: Create hex, bin and S-Record files after the build
  86. add_custom_command(TARGET ${EXECUTABLE}
  87.         POST_BUILD
  88.         COMMAND ${CMAKE_OBJCOPY} -O srec --srec-len=64 ${EXECUTABLE} ${PROJECT_NAME}.s19
  89.         COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE} ${PROJECT_NAME}.hex
  90.         COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin)


The most important sections/entries are:

  • project(<your project name here>): Give your project a name
  • set(LINKER_FILE <your linker file here>): specify the linker file name
  • set(SRC_FILES <your source files here>): list of source files to compile
  • target_compile_definitions(${EXECUTABLE} PRIVATE <compiler defines here>): list of compiler #defines
  • target_include_directories(${EXECUTABLE} PRIVATE <list of include dir>): list of include directories
  • target_compile_options(${EXECUTABLE} PRIVATE <compiler options>): list of compiler options
  • target_link_options(${EXECUTABLE} PRIVATE <linker options>): list of linker options


This completes setting up the configuration for the build.

Configure

Next we are going to build it. Actually we need to ‘configure’ it first. With CMake it is a two stage process: running CMake to create (or configure) the make files and then we use ‘make’ to build it.

  • Close VSCode and Restart again
  • Open Command Palette ... (CTL+SHIFT+P)
  • Select CMake:Delete cache and Reconfigure
Vscode cmake delete-cache-reconfigure.png

CMake: Config Output

[variant] Loaded new set of variants
[kit] Successfully loaded 3 kits from /home/jshankar/.local/share/CMakeTools/cmake-tools-kits.json
[proc] Executing command: /opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -v
[cmakefileapi-driver] This version of CMake does not support the "toolchains" object kind. Compiler paths will be determined by reading CMakeCache.txt.
[main] Configuring folder: blinky 
[proc] Executing command: /usr/bin/cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -DCMAKE_CXX_COMPILER:FILEPATH=/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-g++ -S/home/jshankar/codeprojects/tm4c123gxl/blinky -B/home/jshankar/codeprojects/tm4c123gxl/blinky/build -G "Unix Makefiles"
[cmake] Not searching for unused variables given on the command line.
[cmake] -- CMAKE_TOOLCHAIN_FILE is: /home/jshankar/codeprojects/tm4c123gxl/blinky/arm-toolchain.cmake
[cmake] -- Configuring done
[cmake] -- Generating done
[cmake] -- Build files have been written to: /home/jshankar/codeprojects/tm4c123gxl/blinky/build

Build it with make

Open a terminal in the build output folder:
View-->Terminal

cd build 
make


Instead of calling ‘make’ inside the build folder, following can be used which does the one or the other:

cmake --build .
  • The advantage of doing it this way is that if there has been a change in the CMakeList.txt it will run a configuration step first too.
  • If doing changes in the structure: make sure you do a configure to make sure things are correctly set up.

Cleaning

A ‘clean’ is to delete all the files inside the build folder. But CMake has a ‘clean’ command too:

cd build
cmake --build . --target clean
make


To do a ‘clean followed by a build’ use the following:


cd build

cmake --build . --clean-first

Make: Build Output

/usr/bin/cmake -S/home/jshankar/codeprojects/tm4c123gxl/blinky -B/home/jshankar/codeprojects/tm4c123gxl/blinky/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
make -f CMakeFiles/blinky.elf.dir/build.make CMakeFiles/blinky.elf.dir/depend
make[2]: Entering directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
cd /home/jshankar/codeprojects/tm4c123gxl/blinky/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/jshankar/codeprojects/tm4c123gxl/blinky /home/jshankar/codeprojects/tm4c123gxl/blinky /home/jshankar/codeprojects/tm4c123gxl/blinky/build /home/jshankar/codeprojects/tm4c123gxl/blinky/build /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles/blinky.elf.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
make -f CMakeFiles/blinky.elf.dir/build.make CMakeFiles/blinky.elf.dir/build
make[2]: Entering directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
[ 33%] Building C object CMakeFiles/blinky.elf.dir/src/main.c.obj
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -DPART_TM4C123GH6PM -I/home/jshankar/codeprojects/tm4c123gxl/blinky/src -I/home/jshankar/codeprojects/tm4c123gxl/blinky/inc -I/home/jshankar/codeprojects/tm4c123gxl/blinky/if -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/(" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/WIN32 -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/)" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/E:/ti/TivaWare_C_Series-2.2.0.295 -I/home/jshankar/codeprojects/tm4c123gxl/blinky/else -I/home/jshankar/ti/TivaWare_C_Series-2.1.4.178 -I/home/jshankar/codeprojects/tm4c123gxl/blinky/endif  -g   -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fdata-sections -ffunction-sections -Wall -O0 -g3 -std=c99 -o CMakeFiles/blinky.elf.dir/src/main.c.obj   -c /home/jshankar/codeprojects/tm4c123gxl/blinky/src/main.c
[ 66%] Building C object CMakeFiles/blinky.elf.dir/src/tm4c_startup.c.obj
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -DPART_TM4C123GH6PM -I/home/jshankar/codeprojects/tm4c123gxl/blinky/src -I/home/jshankar/codeprojects/tm4c123gxl/blinky/inc -I/home/jshankar/codeprojects/tm4c123gxl/blinky/if -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/(" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/WIN32 -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/)" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/E:/ti/TivaWare_C_Series-2.2.0.295 -I/home/jshankar/codeprojects/tm4c123gxl/blinky/else -I/home/jshankar/ti/TivaWare_C_Series-2.1.4.178 -I/home/jshankar/codeprojects/tm4c123gxl/blinky/endif  -g   -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fdata-sections -ffunction-sections -Wall -O0 -g3 -std=c99 -o CMakeFiles/blinky.elf.dir/src/tm4c_startup.c.obj   -c /home/jshankar/codeprojects/tm4c123gxl/blinky/src/tm4c_startup.c
[100%] Linking C executable blinky.elf
/usr/bin/cmake -E cmake_link_script CMakeFiles/blinky.elf.dir/link.txt --verbose=1
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -g  -T/home/jshankar/codeprojects/tm4c123gxl/blinky/ld/tm4c123gh6pm.ld -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -specs=nano.specs -specs=nosys.specs -lc -lm -Wl,-Map=blinky.map,--cref -Wl,--gc-sections -Xlinker -print-memory-usage CMakeFiles/blinky.elf.dir/src/main.c.obj CMakeFiles/blinky.elf.dir/src/tm4c_startup.c.obj  -o blinky.elf 
Memory region         Used Size  Region Size  %age Used
           FLASH:         980 B       256 KB      0.37%
            SRAM:         540 B        32 KB      1.65%
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-size blinky.elf
   text    data     bss     dec     hex filename
    980       0     540    1520     5f0 blinky.elf
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy -O srec --srec-len=64 blinky.elf blinky.s19
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy -O ihex blinky.elf blinky.hex
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy -O binary blinky.elf blinky.bin
make[2]: Leaving directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
[100%] Built target blinky.elf
make[1]: Leaving directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
/usr/bin/cmake -E cmake_progress_start /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles 0


Sample Project

You can download sample project from here


References