Skip to content

Commit

Permalink
Revamp build process
Browse files Browse the repository at this point in the history
What I'm trying to achieve:
 * Better adhere to CMake conventions
 * Better adhere to CMake best practices
 * Reduce build times
 * Allow for building all code in one (and only one) binary dir
 * Improve readability
 * Improve maintainability
  • Loading branch information
ChrisThrasher committed Oct 6, 2021
1 parent 469ce89 commit 15e6aea
Show file tree
Hide file tree
Showing 22 changed files with 102 additions and 340 deletions.
42 changes: 0 additions & 42 deletions .github/workflows/examples.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/install.yml
Expand Up @@ -31,7 +31,7 @@ jobs:
rm -rf build
- name: configure
run: cmake -Stest -Bbuild -DTEST_INSTALLED_VERSION=1
run: cmake -Bbuild -DTEST_INSTALLED_VERSION=1

- name: build
run: cmake --build build --config Debug -j4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/macos.yml
Expand Up @@ -25,7 +25,7 @@ jobs:
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}

- name: configure
run: cmake -Stest -Bbuild -DCMAKE_BUILD_TYPE=Debug
run: cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug

- name: build
run: cmake --build build -j4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/style.yml
Expand Up @@ -29,7 +29,7 @@ jobs:
pip3 install cmake_format==0.6.11 pyyaml
- name: configure
run: cmake -Stest -Bbuild
run: cmake -Bbuild

- name: check style
run: cmake --build build --target check-format
2 changes: 1 addition & 1 deletion .github/workflows/ubuntu.yml
Expand Up @@ -26,7 +26,7 @@ jobs:
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}

- name: configure
run: cmake -Stest -Bbuild -DENABLE_TEST_COVERAGE=1 -DCMAKE_BUILD_TYPE=Debug
run: cmake -Bbuild -DENABLE_TEST_COVERAGE=1 -DCMAKE_BUILD_TYPE=Debug

- name: build
run: cmake --build build -j4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows.yml
Expand Up @@ -25,7 +25,7 @@ jobs:
key: ${{ github.workflow }}-cpm-modules-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}

- name: configure
run: cmake -Stest -Bbuild
run: cmake -Bbuild

- name: build
run: cmake --build build --config Debug -j4
Expand Down
58 changes: 18 additions & 40 deletions CMakeLists.txt
@@ -1,33 +1,22 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)

# ---- Project ----

# Note: update this to your new project's name and version
cmake_minimum_required(VERSION 3.14)
project(
Robotics
VERSION 1.0
LANGUAGES CXX
)

# FIXME: doesn't seem to be caching packages
add_compile_definitions(CPM_SOURCE_CACHE="${CMAKE_CURRENT_LIST_DIR}/build/cache/CPM")

# ---- Include guards ----

if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(
FATAL_ERROR
"In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there."
)
endif()

# ---- Add dependencies via CPM ----
# see https://github.com/TheLartians/CPM.cmake for more info

include(cmake/tools.cmake)
include(cmake/CPM.cmake)

# PackageProject.cmake will be used to make our target installable
CPMAddPackage("gh:TheLartians/PackageProject.cmake@1.6.0")
# FIXME: doesn't seem to be caching packages
add_compile_definitions(CPM_SOURCE_CACHE="${CMAKE_BINARY_DIR}/cache/CPM")

CPMAddPackage(
NAME Eigen3
Expand All @@ -37,38 +26,18 @@ CPMAddPackage(
# not intended for library use
DOWNLOAD_ONLY YES
)

if(Eigen3_ADDED)
add_library(Eigen3 INTERFACE IMPORTED)
target_include_directories(Eigen3 INTERFACE ${Eigen3_SOURCE_DIR})
endif()

# ---- Add source files ----

# Note: globbing sources is considered bad practice as CMake's generators may not detect new files
# automatically. Keep that in mind when changing files, or explicitly mention them here.
file(GLOB_RECURSE headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")

# ---- Create library ----
add_library(Eigen3::Eigen INTERFACE IMPORTED)
target_include_directories(Eigen3::Eigen INTERFACE ${Eigen3_SOURCE_DIR})

add_library(Robotics INTERFACE)

# being a cross-platform target, we enforce standards conformance on MSVC
target_compile_options(Robotics INTERFACE "$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/permissive->")

# Link dependencies
target_link_libraries(Robotics INTERFACE Eigen3)

target_include_directories(
Robotics INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/${PROJECT_NAME}-${PROJECT_VERSION}>
)
target_link_libraries(Robotics INTERFACE Eigen3::Eigen)
target_compile_features(Robotics INTERFACE cxx_std_17)

# ---- Create an installable target ----
# this allows users to install and find the library via `find_package()`.

# the location where the project's version header will be placed should match the project's regular
# header paths
CPMAddPackage("gh:TheLartians/PackageProject.cmake@1.6.0")
string(TOLOWER ${PROJECT_NAME}/version.h VERSION_HEADER_LOCATION)

packageProject(
Expand All @@ -82,3 +51,12 @@ packageProject(
COMPATIBILITY SameMajorVersion
DEPENDENCIES "Eigen3 3.3.9"
)

if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
return()
endif()

include(CTest)
add_subdirectory(documentation)
add_subdirectory(examples)
add_subdirectory(tests)
49 changes: 15 additions & 34 deletions README.md
Expand Up @@ -84,25 +84,25 @@ CppRobotics aims to be modular, which means:
### Building and running the examples

Given a generic `EXAMPLE` that you want to run, the following commands build it:
By default, example programs will be built. Use the `BUILD_EXAMPLES` option to disable them.

```bash
cmake -S examples/EXAMPLE -B build/EXAMPLE
cmake --build build/EXAMPLE
cmake -B build
cmake --build build
```

On Windows, this will default to a Debug configuration. To build the project in release mode, you can add `--config=Release` after the first command.

To run the example on Linux, macOS, and most Unix-based systems:

```bash
./build/EXAMPLE/main
./build/examples/main
```

On Windows:

```bash
./build/EXAMPLE/CONFIG_TYPE/main
./build/examples/CONFIG_TYPE/main
```

where `CONFIG_TYPE` is either `Debug` or `Release`, depending on how you configured the project.
Expand Down Expand Up @@ -193,15 +193,15 @@ Check out [TheLartians/ModernCppStarter](https://github.com/TheLartians/ModernCp

### Running tests

From the root directory:
By default, tests are built. Use the `BUILD_TESTING` option to disable them.

```bash
cmake -S test -B build/test
cmake --build build/test
CTEST_OUTPUT_ON_FAILURE=1 cmake --build build/test --target test
cmake -B build
cmake --build build
CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test

# or simply call the executable:
./build/test/RoboticsTests
./build/tests/RoboticsTests
```

To also collect code coverage information, run CMake with the `-DENABLE_TEST_COVERAGE=1` option.
Expand All @@ -211,13 +211,13 @@ To also collect code coverage information, run CMake with the `-DENABLE_TEST_COV
This requires _clang-format_, _cmake-format_ and _pyyaml_ to be installed on the current system.

```bash
cmake -S test -B build/test
cmake -B build

# view changes
cmake --build build/test --target format
cmake --build build --target format

# apply changes
cmake --build build/test --target fix-format
cmake --build build --target fix-format
```

See [Format.cmake](https://github.com/TheLartians/Format.cmake) for details.
Expand All @@ -228,33 +228,14 @@ The documentation is automatically built and [published](https://giacomo-b.githu
To manually build documentation, call the following command.

```bash
cmake -S documentation -B build/doc
cmake --build build/doc --target GenerateDocs
cmake -B build
cmake --build build --target GenerateDocs
# view the docs
open build/doc/doxygen/html/index.html
```

To build the documentation locally, you will need _Doxygen_, _jinja2_ and _Pygments_ installed in your system.

### Build everything at once

The project also includes an `all` directory that allows building all targets at the same time.
This is useful during development, as it exposes all subprojects to your IDE and avoids redundant builds of the library.

```bash
cmake -S all -B build
cmake --build build

# run tests
./build/test/RoboticsTests
# format code
cmake --build build --target fix-format
# run standalone
./build/standalone/Robotics --help
# build docs
cmake --build build --target GenerateDocs
```

### Additional tools

The test and standalone subprojects include the [tools.cmake](cmake/tools.cmake) file which is used to import additional tools on-demand through CMake configuration arguments.
Expand Down
24 changes: 0 additions & 24 deletions all/CMakeLists.txt

This file was deleted.

15 changes: 4 additions & 11 deletions documentation/CMakeLists.txt
@@ -1,24 +1,17 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
option(BUILD_DOCS "Build the documentation" ON)

project(RoboticsDocs)

# ---- Dependencies ----

include(../cmake/CPM.cmake)
if(NOT BUILD_DOCS)
return()
endif()

CPMAddPackage("gh:mosra/m.css#42d4a9a48f31f5df6e246c948403b54b50574a2a")
CPMAddPackage(NAME Robotics SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/..)

# ---- Doxygen variables ----

# set Doxyfile variables
set(DOXYGEN_PROJECT_NAME Robotics)
set(DOXYGEN_PROJECT_VERSION ${Robotics_VERSION})
set(DOXYGEN_PROJECT_ROOT "${CMAKE_CURRENT_LIST_DIR}/..")
set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doxygen")

configure_file(${CMAKE_CURRENT_LIST_DIR}/Doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)

configure_file(${CMAKE_CURRENT_LIST_DIR}/conf.py ${CMAKE_CURRENT_BINARY_DIR}/conf.py)

add_custom_target(
Expand Down
5 changes: 0 additions & 5 deletions documentation/pages/about.dox

This file was deleted.

23 changes: 23 additions & 0 deletions examples/CMakeLists.txt
@@ -0,0 +1,23 @@
option(BUILD_EXAMPLES "Build the examples" ON)

if(NOT BUILD_EXAMPLES)
return()
endif()

CPMAddPackage(
NAME matplotplusplus
GITHUB_REPOSITORY alandefreitas/matplotplusplus
GIT_TAG master
OPTIONS "BUILD_EXAMPLES OFF" "BUILD_TESTS OFF" "BUILD_INSTALLER OFF" "BUILD_PACKAGE OFF"
)

if(CMAKE_CXX_COMPILER_ID MATCHES "(Clang|GNU)")
add_compile_options(-Werror -Wall -Wextra -Wpedantic)
elseif(MSVC)
add_compile_options(/WX /W4 /permissive-)
endif()

add_subdirectory(extended_kalman_filter)
add_subdirectory(infinite_horizon_lqr)
add_subdirectory(infinite_horizon_lqr_plot)
add_subdirectory(pid)

0 comments on commit 15e6aea

Please sign in to comment.