I am using CMake to make the build for my project which is an embedded firmware based on ARM Cortex platform built using arm-none-eabi-gcc-6.3.1 compiler, using VSCode Editor, and on Windows host. I am trying to make a second build for testing on the Windows system I am using for the same project.
The issue I am having is that whenever I need to switch my build from production to test, I have to delete the build files and rerun the CMake command with the test argument, when I do not do that, the build does not change the ARM compiler to the one I intend to use (I am guessing it is a caching problem). I have tried make clean
and make rebuild_cache
thinking that it may clean the cache and solve the problem for me, and did not work.
A first build:
Project\build> cmake -G"MinGW Makefiles" -DTARGET_GROUP=test ..
You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_C_COMPILER= C:/MinGW/bin/gcc.exe
CMAKE_CXX_COMPILER= C:/MinGW/bin/g .exe
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/MinGW/bin/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:/MinGW/bin/g .exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: Path\to\Project\build
Project\build>make
[ 16%] Building C object src/libs/module_a/CMakeFiles/module_a.dir/module_a.c.obj
[ 33%] Linking C static library libmodule_a.a
[ 33%] Built target module_a
[ 50%] Building C object testsuit/CMakeFiles/Unity.dir/unity/src/unity.c.obj
[ 66%] Linking C static library libUnity.a
[ 66%] Built target Unity
[ 83%] Building C object test/suite_1/CMakeFiles/suite_1_app.dir/suite_1.c.obj
[100%] Linking C executable suite_1_app.exe
[100%] Built target suite_1_app
A second build:
Project\build> cmake -G"MinGW Makefiles" -DTARGET_GROUP=production ..
You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_C_COMPILER= Path/to/arm-gnu-toolchain/bin/arm-none-eabi-gcc.exe
CMAKE_CXX_COMPILER= Path/to/arm-gnu-toolchain/bin/arm-none-eabi-g .exe
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/MinGW/bin/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:/MinGW/bin/g .exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: Path\to\Project\build
Project\build>make
Consolidate compiler generated dependencies of target module_a
[ 33%] Built target module_a
Consolidate compiler generated dependencies of target Unity
[ 66%] Built target Unity
Consolidate compiler generated dependencies of target suite_1_app
[100%] Built target suite_1_app
^ The second build should not compile this module since it is included only in the test build.
The CMakeLists.txt:
set(TARGET_GROUP test CACHE STRING "Group to build")
if(TARGET_GROUP STREQUAL production)
# ARM Lib
include("arm-gnu.cmake")
else()
# "Generic" is used when cross compiling
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR amd64)
set(GCC_PATH "C:/MinGW")
set(CMAKE_C_COMPILER ${GCC_PATH}/bin/gcc.exe CACHE PATH "" FORCE)
set(CMAKE_CXX_COMPILER ${GCC_PATH}/bin/g .exe CACHE PATH "" FORCE)
set(CMAKE_LINKER ${GCC_PATH}/bin/ld.exe CACHE PATH "" FORCE)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
#to pass compiler testing as this is cross compilation
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
endif()
# ...
if(TARGET_GROUP STREQUAL production)
# ARM toolchain
include_directories(toolchain/arm/arm-gnu-toolchain/arm-none-eabi/include)
include_directories(toolchain/arm/arm-gnu-toolchain/lib/gcc/arm-none-eabi/6.3.1/include)
include_directories(toolchain/arm/arm-gnu-toolchain/lib/gcc/arm-none-eabi/6.3.1/include-fixed)
# CMSIS V5.4.0
include_directories(target/cmsis/5.4.0/CMSIS/Core/include)
# Other sources -> include_directories(....)
# ...
# ...
elseif(TARGET_GROUP STREQUAL test)
add_subdirectory(src/libs/module_a)
include(CTest)
add_subdirectory(testsuit)
add_subdirectory(test)
else()
message(FATAL_ERROR "Given TARGET_GROUP unknown")
endif()
# ...
if(TARGET_GROUP STREQUAL production)
file(GLOB sources_files
src/*.c
# other sources ...
# ...
# ...
)
set (SOURCES ${sources_files})
add_executable(${PROJECT_NAME}.elf ${SOURCES})
endif(TARGET_GROUP STREQUAL production)
Currently, I have a temporary solution by making a separate folder for each building type and they work perfectly. My question, since I am not an expert in build systems, is my solution the right way to do it?
CodePudding user response:
As @Tsyvarev says, you have to use different directories if you want different builds. Here you are trying to build both in the same build
directory. Instead, create a subdirectory test
to build the -DTARGET_GROUP=test
, and a different subdirectory prod
to build the -DTARGET_GROUP=production
:
Project> mkdir test
Project> cd test
Project\test> cmake -G"MinGW Makefiles" -DTARGET_GROUP=test ..
Project\test> cd ..
Project> mkdir prod
Project> cd prod
Project\prod> cmake -G"MinGW Makefiles" -DTARGET_GROUP=production ..
Of course you can call the directories whatever you like.
CodePudding user response:
Since you'd like this to integrate into VSCode, do the configuration change with the CMake build kits, which is what sets the compiler prior to calling CMake. You can specify additional user kit definitions, and in the VSCode interface choose between compiler kits.
Rewrite the CMake files just enough to condition everything else on the selection of compiler.
THEN, the VSCode cmake-tools extension supports variable expansion for the name of the build directory. Among the options are ${buildKit}
and ${buildKitTargetArch}
. Make this suffix part of the Build Directory setting (your choice of whether to set this only in your workspace, or more globally on your system).
Now, when you switch kits, CMake will pick up the directory change and happily exist with two different build directories.
Alternatively, cmake-tools now provides variants, which could be used to add additional Production and Test to the normal Release, Debug, RelWithDebInfo, etc. There are additional build directory expansion variables for information from the currently selected variant.