Reputation: 595
I am trying to think through how to design a new project build system.
I want to use CMake to compile for Windows and Linux. I want to have Release and Debug builds, which are pretty straight forward.
The problem is that I will want to deploy this software for multiple hardware projects over the course of the next few years. This means that I will have pre-processor definitions to turn on/off and or alter functionality in my C++ program. I will also want to link configuration specific libraries. A current legacy project uses a header with a list of defines and then links all possible project dependencies.
An example header:
// projects.h
//#define project1
//#define project2
#define project3
Which means that to change hardware/project configurations you have to edit this file to make sure the correct hardware configuration is selected.
What I want to do is to have a configuration for each project which can also be configured for Release or Debug build.
Is there any advice on how to more optimally deal with this in CMake?
Upvotes: 1
Views: 4433
Reputation: 141768
for multiple hardware projects
For me it got messy and got messy real quick.
My goals were:
What I discovered is that:
makefile
. This makefile
then configures cmake
, which in turn configures the build system, that can then be used to build the application. This is so, because cmake supports one configuration per toolchain. So for architectures with different compilers/compiler options I have to re-run cmake.I have basically such a directory structure:
- app
- CMakeLists.txt
- main.c
- lib.c
- boards # this is actually git submodule shared between multiple projects
- boardapi # generic board api library
- CMakeLists.txt
- uart_api.h # exposes an api to access uart
- spi_api.h
- timer_api.h
- board_api.h
- some_defines.h # includes some_defines_impl.h
- BOARD1
- toolchain.cmake
- CMakeLists.txt
- implementation1.c
- implementation2.c
- some_defines_impl.h
- BOARD2
- toolchain.cmake
- CMakeLists.txt
- implementation1.c
- implementation2.c
- some_defines_impl.h
- linux
- ... as above ...
- armv5te
- ... as above ...
- CMakeLists.txt
- CMakeLists.txt
- Makefile
boards
directory with multiple folders per one board.toolchain.cmake
file and CMakeLists.txt
fileCMakeLists.txt
in the board folder a library with the name of the folder is added.cmake
+ make
for each of the boards. Basically BOARDS=BOARD1 BOARD2
and then all: $(foreach board,$(BOARDS),cmake;make;)
cmake -DCMAKE_TOOLCHAIN_FILE=board/$(BOARD)/toolchain.cmake -DBOARD=$(BOARD)
board/CMakeLists.txt
file all does is add_subdirectory(${BOARD})
and add_library(board INTERFACE ${BOARD})
.CMakeLists.txt
does add_subdirectory(boards)
and after that link_libraries(boards)
. That should link all libraries with the board library.board
directory in turn controls the specific board configuration.app/CMakeLists.txt
, like so:foreach(i IN LISTS project1 project2 project3)
add_executable(main+${i} main.c app.c)
target_add_definitions(${i})
endforeach()
Alternatively, if ex. there are many macros, you could create another structure projects/{project1,project2,project3}
and recreate the same structure as for boards, but without the toolchain.cmake file. Then just iterate foreach project and do target_link_libraries(main+${i} ${i})
that will effectively bring all the macro definitions to main application.
Upvotes: 3