abcmake
or Andrei's Build CMake subsystem is a CMake module providing a set of functions focused on working with a project as a set of components - individually buildable units.
The module is designed to simplify the process of creating and linking components in a project. The view on a source code as a set of component increases the code portability and reusability. The module works best with small and medium-sized projects.
The simplest way of using the module is to use the default project structure:
Default project structure
-------------------------
+📁Root Project
|
|--+📁components <------- nested abcmake projects
| |
| |--+📁component1
| | |---📁include
| | |---📁components
| | |---📁src
| | |---ab.cmake
| | '--CMakeLists.txt
| |
| |--+📁component2
| ...
|
|---📁include <---- public headers
|---📁src <-------- src and private headers
|---ab.cmake
'--CMakeLists.txt
- Create a folder i.e.
PROJECT_NAME
- Move all headers and sources to
PROJECT_NAME/include
andPROJECT_NAME/src
folders respectively. All headers frominclude
will be accessible to the parent project. - Download an
ab.cmake
file to thePROJECT_NAME
folder - Update your cmake file to look like this:
cmake_minimum_required(VERSION 3.5) # abcmake requirement
project(HelloWorld)
include(ab.cmake)
add_main_component(${PROJECT_NAME})
If you want to use the module in your project, you can use the badge:
[![abcmake](https://img.shields.io/badge/uses-abcmake-blue)](https://github.com/an-dr/abcmake)
- CMake 3.5 or higher
The module provides several powerful functions to work with the source code as a set of portable interdependent components.
add_main_component(<name> [INCLUDE_DIR] <includes> ... [SOURCE_DIR] <sources> ...)
Add an executable target. It links all components in the components folder automatically. If the component is not an abcmake component, the directory will be added but the linking has to be done manually using target_link_libraries
.
The default include and source directories are include and src respectively. You can override them with your custom list of directories.
# Will look for `include` and `src` directories in the root folder,
# and will link all components in the `components` folder
add_main_component(HelloWorld)
# Custom include and source directories
add_main_component(HelloWorld INCLUDE_DIR "private_include" "public_include"
SOURCE_DIR "src1" "src2")
add_component(<name> [SHARED] [INCLUDE_DIR] <includes> ... [SOURCE_DIR] <sources> ...)
Add a library target. If the SHARED
keyword is present, the library will be shared, overwise it will be static. Works similarly to add_main_component
.
register_components(<path1> <path2> ...)
Register components by their paths. This function is used to link components by name. For linking use the names defined by the project()
function in the component's CMakeLists.txt
.
NOTE: The order of registration is important, i.e. if component A depends on component B, component B should be registered first.
# Registering components
register_components(${CMAKE_CURRENT_LIST_DIR}/libs/hello
${CMAKE_CURRENT_LIST_DIR}/libs/world)
target_link_components (<target> [PATH] <component_paths> ... [NAME] <component_names> ...)
Add components to the target. Can be used for linking components from custom directories and linking components between each other. Accepts a list of values. For relative paths, use ${CMAKE_CURRENT_LIST_DIR}
. To be able to link components by name, they must be registered via register_components
function.
# Linking a component in the same folder
target_link_components(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/../my_component)
# Linking many components including registered ones
register_components(${CMAKE_CURRENT_LIST_DIR}/common/FirstComponent
${CMAKE_CURRENT_LIST_DIR}/common/SecondComponent)
target_link_components(${PROJECT_NAME} PATH ${CMAKE_CURRENT_LIST_DIR}/libs/hello
${CMAKE_CURRENT_LIST_DIR}/libs/world
NAME FirstComponent
SecondComponent)
- The module allows only one component per CMakelists.txt file.
The module can be configured by setting environment variables:
If set will use emojis in the output.
ABCMAKE_EMOJI = 1
:
ABCMAKE_EMOJI = 0
: