Adding features, strike out unfinished chapters
This commit is contained in:
parent
9b61fdaf38
commit
7ff521c44e
@ -68,5 +68,5 @@ And, since CMake will dumb itself down to the minimum required version in your C
|
|||||||
You should *at least* install it locally.
|
You should *at least* install it locally.
|
||||||
It's easy (1-2 lines in many cases), and you'll find that 5 minutes of work will save you hundreds of lines and hours of CMakeLists.txt writing, and will be much easier to maintain in the long run.
|
It's easy (1-2 lines in many cases), and you'll find that 5 minutes of work will save you hundreds of lines and hours of CMakeLists.txt writing, and will be much easier to maintain in the long run.
|
||||||
|
|
||||||
This book tries to solve the problem of the poor examples and best practices that you'll find proliferating the web.
|
This book tries to solve the problem of the poor examples and best practices that you'll find proliferating the web. A nice, slighly dated post with a similar intent can be found [here](https://rix0r.nl/blog/2015/08/13/cmake-guide/). You might also find that helpful for a fast introduction.
|
||||||
|
|
||||||
|
27
SUMMARY.md
27
SUMMARY.md
@ -7,22 +7,23 @@
|
|||||||
## Making a CMakeLists
|
## Making a CMakeLists
|
||||||
|
|
||||||
* [Introduction to the Basics](chapters/basics.md)
|
* [Introduction to the Basics](chapters/basics.md)
|
||||||
|
* [~~Variables and the Options Cache~~](chapters/options)
|
||||||
* [C++11 and Beyond](chapters/cpp11.md)
|
* [C++11 and Beyond](chapters/cpp11.md)
|
||||||
* [Adding Features](chapters/features.md)
|
* [Adding Features](chapters/features.md)
|
||||||
* [The Options Cache](chapters/options)
|
|
||||||
* [How to Structure Your Project](chapters/structure.md)
|
* [How to Structure Your Project](chapters/structure.md)
|
||||||
* [Including Small Projects](chapters/smallinc.md)
|
* [~~Configuration Information~~](chapters/configure.md)
|
||||||
* [Including Large Projects](chapters/largeinc.md)
|
* [~~Including Small Projects~~](chapters/smallinc.md)
|
||||||
* [Running Other Programs](chapters/programs.md)
|
* [~~Including Large Projects~~](chapters/largeinc.md)
|
||||||
* [Testing](chapters/testing.md)
|
* [~~Running Other Programs~~](chapters/programs.md)
|
||||||
* [Tidy and Format](chapters/testing.md)
|
* [~~Testing~~](chapters/testing.md)
|
||||||
* [IDEs](chapters/IDEs.md)
|
* [~~Tidy and Format~~](chapters/testing.md)
|
||||||
* [Debugging](chapters/IDEs.md)
|
* [~~IDEs~~](chapters/IDEs.md)
|
||||||
|
* [~~Debugging~~](chapters/IDEs.md)
|
||||||
|
|
||||||
## Specific packages
|
## Specific packages
|
||||||
|
|
||||||
* [CUDA](specifics/CUDA.md)
|
* [~~CUDA~~](specifics/CUDA.md)
|
||||||
* [OpenMP](specifics/OpenMP.md)
|
* [~~OpenMP~~](specifics/OpenMP.md)
|
||||||
* [Boost](specifics/Boost.md)
|
* [~~Boost~~](specifics/Boost.md)
|
||||||
* [MPI](specifics/MPI.md)
|
* [~~MPI~~](specifics/MPI.md)
|
||||||
* [ROOT](specifics/ROOT.md)
|
* [~~ROOT~~](specifics/ROOT.md)
|
||||||
|
50
chapters/features.md
Normal file
50
chapters/features.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# Adding Features
|
||||||
|
|
||||||
|
There are lots of compiler and linker settings. When you need to add something special, you could check first to see if CMake supports it; if it does, you can avoid explicitly tying yourself to a compiler version. And, better yet, you explain what you mean in your CMakeLists, rather than spewing flags.
|
||||||
|
|
||||||
|
The first and most common feature was C++ standards support, which got it's own chapter.
|
||||||
|
|
||||||
|
## Platform independent code
|
||||||
|
|
||||||
|
[This](https://cmake.org/cmake/help/v3.9/variable/CMAKE_POSITION_INDEPENDENT_CODE.html) is best known as the `-fPIC` flag. Much of the time, you don't need to do anything. CMake will include the flag for `SHARED` or `MODULE` libraries. If you do explicitly need it:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
```
|
||||||
|
|
||||||
|
will do it globally, or:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
set_target_properties(lib1 PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
|
```
|
||||||
|
|
||||||
|
to explicitly turn it `ON` (or `OFF`) for a target.
|
||||||
|
|
||||||
|
## Little libraries
|
||||||
|
|
||||||
|
If you need to link to the `dl` library, with `-ldl` on Linux, just use the built-in CMake variable [`${CMAKE_DL_LIBS}`](https://cmake.org/cmake/help/v3.9/variable/CMAKE_DL_LIBS.html) in a `target_link_libraries` command. No module or `find_package` needed. (This adds whatever is needed to get `dlopen` and `dlclose`)
|
||||||
|
|
||||||
|
Unfortunately, the math library is not so lucky. If you need to explicitly link to it, you can always do `target_link_libraries(MyTarget PUBLIC m)`, but it might be better to use CMake's generic [`find_library`](https://cmake.org/cmake/help/v3.9/command/find_library.html):
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
find_library(MATH_LIBRARY m)
|
||||||
|
if(MATH_LIBRARY)
|
||||||
|
target_link_libraries(MyTarget PUBLIC ${MATH_LIBRARY})
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
You can pretty easily find `Find*.cmake`'s for this and other libraries that you need with a quick search; most major packages have a helper library of CMake modules. See the chapter on existing package inclusion for more.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Interprocedural optimization
|
||||||
|
|
||||||
|
[This](https://cmake.org/cmake/help/v3.9/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.html) is available on very recent versions of CMake. You can turn this on with `CMAKE_INTERPROCEDURAL_OPTIMIZATION` (CMake 3.9 only) or the `INTERPROCEDURAL_OPTIMIZATION` property on targets. Support for GCC and Clang was added in CMake 3.8. In `cmake_minimum_required(VERSION 3.9)`, setting this to `ON` on a target is an error if the compiler doesn't support it. You can use [`check_ipo_supported()`](https://cmake.org/cmake/help/v3.9/module/CheckIPOSupported.html), from the built-in `CheckIPOSupported` module, to see if support is available before hand. An example of 3.9 style usage:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT result)
|
||||||
|
if(result)
|
||||||
|
set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
|
endif()
|
||||||
|
```
|
@ -1,6 +1,8 @@
|
|||||||
# Installing CMake
|
# Installing CMake
|
||||||
|
|
||||||
> Your CMake version should be newer than your compiler. It should be newer than the libraries you are using (especially Boost). New versions work better for everyone.
|
{% hint style='tip' %}
|
||||||
|
Your CMake version should be newer than your compiler. It should be newer than the libraries you are using (especially Boost). New versions work better for everyone.
|
||||||
|
{% endhint %}
|
||||||
|
|
||||||
If you have a built in copy of CMake, it isn't special or customized for your system. You can easily install a new one instead, either on the system level or the user level. Feel free to instruct your users here if they complain about a CMake requirement being set too high. Especially if they want < 3.1 support. Maybe even if they want CMake < 3.8 support...
|
If you have a built in copy of CMake, it isn't special or customized for your system. You can easily install a new one instead, either on the system level or the user level. Feel free to instruct your users here if they complain about a CMake requirement being set too high. Especially if they want < 3.1 support. Maybe even if they want CMake < 3.8 support...
|
||||||
|
|
||||||
@ -23,7 +25,8 @@ If you just want a local folder with CMake only:
|
|||||||
|
|
||||||
You'll obviously want to append to the PATH every time you start a new terminal, or add it to your `.bashrc` or to an [LMod] system.
|
You'll obviously want to append to the PATH every time you start a new terminal, or add it to your `.bashrc` or to an [LMod] system.
|
||||||
|
|
||||||
And, if you want a system install (I'm only brave enough to run this in Docker):
|
And, if you want a system install, install to `/usr/local`. (I'm only brave enough to run this in Docker):
|
||||||
|
|
||||||
|
|
||||||
You can also build CMake on any system, it's pretty easy, but binaries are faster.
|
You can also build CMake on any system, it's pretty easy, but binaries are faster.
|
||||||
|
|
||||||
@ -40,11 +43,11 @@ And as long as a binary exists for your system, you'll be up-and-running almost
|
|||||||
This has the benefit of respecting your current virtual environment, as well.
|
This has the benefit of respecting your current virtual environment, as well.
|
||||||
|
|
||||||
{% hint style='info' %}
|
{% hint style='info' %}
|
||||||
Personally, on Linux, I put versions of CMake in folders, like `/opt/cmake39` or `~/opt/cmake39`, and then add them to [LMod]. See [`envmodule_setup`] for help setting up an LMod system on macOS or Linux. It's takes a bit to learn, but is a great way to manage package and compiler versions.
|
Personally, on Linux, I put versions of CMake in folders, like `/opt/cmake39` or `~/opt/cmake39`, and then add them to [LMod]. See [`envmodule_setup`][envmodule_setup] for help setting up an LMod system on macOS or Linux. It's takes a bit to learn, but is a great way to manage package and compiler versions.
|
||||||
{% endhint %}
|
{% endhint %}
|
||||||
|
|
||||||
[^1]: If don't have a `.local` in your home directory, it's easy to start. Just make the folder, then add `export PATH="$HOME/.local/bin:$PATH"` to your `.bashrc` or `.bash_profile` or `.profile` file in your home directory. Now you can install any packages you build to `-DCMAKE_INSTALL_PREFIX=~/.local` instead of `/usr/local`!
|
[^1]: If don't have a `.local` in your home directory, it's easy to start. Just make the folder, then add `export PATH="$HOME/.local/bin:$PATH"` to your `.bashrc` or `.bash_profile` or `.profile` file in your home directory. Now you can install any packages you build to `-DCMAKE_INSTALL_PREFIX=~/.local` instead of `/usr/local`!
|
||||||
|
|
||||||
[cmake-download]: https://cmake.org/download/
|
[cmake-download]: https://cmake.org/download/
|
||||||
[LMod]: http://lmod.readthedocs.io/en/latest/
|
[LMod]: http://lmod.readthedocs.io/en/latest/
|
||||||
[`envmodule_setup`]: https://github.com/CLIUtils/envmodule_setup
|
[envmodule_setup]: https://github.com/CLIUtils/envmodule_setup
|
||||||
|
@ -14,6 +14,8 @@ First, this is what your files should look like when you start if your project i
|
|||||||
- README.md
|
- README.md
|
||||||
- LICENCE.md
|
- LICENCE.md
|
||||||
- CMakeLists.txt
|
- CMakeLists.txt
|
||||||
|
- cmake
|
||||||
|
- FindSomeLib.cmake
|
||||||
- include
|
- include
|
||||||
- project
|
- project
|
||||||
- lib.hpp
|
- lib.hpp
|
||||||
@ -35,8 +37,24 @@ First, this is what your files should look like when you start if your project i
|
|||||||
|
|
||||||
The names are not absolute; you'll see contention about `test/` vs. `tests/`, and the application folder may be called something else (or not exist for a library-only project). You'll also sometime see a `python` folder for python bindings, or a `cmake` folder for helper CMake files, like `Find<library>.cmake` files. But the basics are there.
|
The names are not absolute; you'll see contention about `test/` vs. `tests/`, and the application folder may be called something else (or not exist for a library-only project). You'll also sometime see a `python` folder for python bindings, or a `cmake` folder for helper CMake files, like `Find<library>.cmake` files. But the basics are there.
|
||||||
|
|
||||||
Notice a few things already apparent; the `CMakeLists.txt` files are split up over all source directories, and are not in the include directories. This is because you should be able to copy the contents of the include directory to `/usr/include` or similar directly (except for configuration headers, which I go over in another chapter), and not have any extra files or cause any conflicts. That's also why there is a directory for your project inside the include directory.
|
Notice a few things already apparent; the `CMakeLists.txt` files are split up over all source directories, and are not in the include directories. This is because you should be able to copy the contents of the include directory to `/usr/include` or similar directly (except for configuration headers, which I go over in another chapter), and not have any extra files or cause any conflicts. That's also why there is a directory for your project inside the include directory. Use `add_subdirectory` to add a subdirectory containing a `CMakeLists.txt`.
|
||||||
|
|
||||||
|
You often want a `cmake` folder, with all of your helper modules. This is where your `Find*.cmake` files go. An set of some common helpers is at [github.com/CLIUtils/cmake](https://github.com/CLIUtils/cmake). To add this folder to your CMake path:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
|
```
|
||||||
|
|
||||||
Your `extern` folder should contain git submodules almost exclusively. That way, you can control the version of the dependencies explicitly, but still upgrade easily. See the Testing chapter for an example of adding a submodule.
|
Your `extern` folder should contain git submodules almost exclusively. That way, you can control the version of the dependencies explicitly, but still upgrade easily. See the Testing chapter for an example of adding a submodule.
|
||||||
|
|
||||||
You should have something like `/build*` in your `.gitignore`, so that users can make build directories in the source directory and use those to build. A few packages prohibit this, but it's much better than doing a true out-of-source build and having to type something different for each package you build.
|
You should have something like `/build*` in your `.gitignore`, so that users can make build directories in the source directory and use those to build. A few packages prohibit this, but it's much better than doing a true out-of-source build and having to type something different for each package you build.
|
||||||
|
|
||||||
|
If you want to avoid the build directory being in a valid source directory, add this near the top of your CMakeLists:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
### Require out-of-source builds
|
||||||
|
file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH)
|
||||||
|
if(EXISTS "${LOC_PATH}")
|
||||||
|
message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.")
|
||||||
|
endif()
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user