Template repository for C++ projects using CMake, libigl, etc.
Create a new github repository using this project as template:
Then replace all placeholders with your new project name using this simple python script:
./misc/bootstrap.py <new_project_name>
The main file you want to be looking at to add/update dependencies is cmake/@Project_Name@External.cmake
. Do not look at @Project_Name@Boilerplate.cmake
, this is the file doing the dirty laundry so that @Project_Name@External.cmake
looks pretty. Everything else should speak for itself, mostly.
We use CMake's FetchContent mechanism to download external dependencies at CMake time so that they can be built alongside your main project. External dependencies are compiled statically so the produced executable is as self-contained as possible. The goal of this project is to provide a modern template for C++ project using CMake. Thus, you will need at least:
- CMake 3.11
- C++17
The core mechanism used to import an external dependencies (download + create a CMake target) is the @project_name@_import()
function. For example, to create a new executable that depends on libigl, CLI11 and tinyfiledialogs, you can use the following:
add_executable(MyViewer
main.cpp
filedialogs.cpp
filedialogs.h
viewer.cpp
viewer.h
)
@project_name@_import(libigl cli11 tinyfiledialogs)
target_link_libraries(MyViewer
PRIVATE
igl::opengl_glfw_imgui
CLI11::CLI11
tinyfiledialogs::tinyfiledialogs
)
# Use C++17
target_compile_features(MyViewer PUBLIC cxx_std_17)
where @project_name@
should be replaced by your project name when you run the ./misc/bootstrap.py
script. Note that the name given to the @project_name@_import()
function is different from the target name (Foo::Bar
) available once the library is imported. The table below lists all libraries which are available for import in this current template. One important detail to note is that nothing is downloaded if you do not import a library. Thus, adding libraries to this template will not "bloat" your starting project unless you decide to actually use it. The reasoning is that it should be easier to remove imported libraries from this template than to add a new one should you need it.
FetchContent name | Target name | Url |
---|---|---|
catch2 |
Catch2::Catch2 |
Catch2 |
cli11 |
CLI11::CLI11 |
CLI11 |
cppoptlib |
cppoptlib::cppoptlib |
CppNumericalSolvers |
eigen |
Eigen3::Eigen |
Eigen |
ghc_filesystem |
ghc::filesystem |
Filesystem |
fmt |
fmt::fmt |
{fmt} |
json |
nlohmann_json::nlohmann_json |
JSON |
libigl |
igl::core , ... |
libigl |
nanoflann |
nanoflann::nanoflann |
nanoflann |
pcg |
pcg::pcg |
PCG |
simple_svg |
simple_svg::simple_svg |
simple-svg |
spdlog |
spdlog::spdlog |
spdlog |
tbb |
tbb::tbb |
Threading Building Blocks |
tinyfiledialogs |
tinyfiledialogs::tinyfiledialogs |
tiny file dialogs |
windingnumber |
windingnumber::windingnumber |
WindingNumber |
It is a good idea to ensure that your code always builds, and does so on all platforms (Windows, Linux, macOS). You do not want to push code that might leave your coworkers unhappy because they cannot build the project anymore. To that end, we use continuous integration via the following services:
Both support Windows, Linux and macOS. Feel free to adapt existing scripts to your needs. Travis can be used for private projects if you have an education account.
By default, we use libigl in header-only mode, single building in static mode takes a long time. However, as your project grows, you might want to switch the CMake option LIBIGL_USE_STATIC_LIBRARY
to ON
to accelerate incremental builds (this is especially useful in combination with a caching compiler such as ccache
).
With C++17, in theory the <filesystem>
header from the Standard Template Library provides a cross-platform filesystem library. Unfortunately, compiler support is still lacking, in particular on macOS -- you need at least Xcode 11 and macOS 10.15, which may not be supported by our CI platforms yet. To that end, we define an alias target std::filesystem
. This target will add the necessary linking flags if <filesystem>
or <experimental/filesystem>
are supported on your system. If not, it will download ghc::filesystem and use that as an alias. Automatic namespace forwarding is implemented in filesystem.h so you can use it directly.
TODO
TODO
TODO