mirror of
1
0
Fork 0

Adding cpack chapter

This commit is contained in:
Henry Fredrick Schreiner 2018-03-31 07:58:58 +02:00
parent 0e2f838a99
commit 9d05002153
6 changed files with 89 additions and 44 deletions

View File

@ -24,7 +24,10 @@
* [Testing](chapters/testing.md)
* [GoogleTest](chapters/testing/googletest.md)
* [Catch](chapters/testing/catch.md)
* [Exporting and Installing](chapters/exporting.md)
* [Exporting and Installing](chapters/install.md)
* [Installing](chapters/install/installing.md)
* [Exporting](chapters/install/exporting.md)
* [Packaging](chapters/install/packaging.md)
* [Looking for libraries](chapters/packages.md)
* [CUDA](chapters/packages/CUDA.md)
* [OpenMP](chapters/packages/OpenMP.md)

26
chapters/install.md Normal file
View File

@ -0,0 +1,26 @@
# Exporting and Installing
There are three good ways and one bad way to allow others use your library:
## Find module (the bad way)
If you are the library author, don't make a `Find<mypackage>.cmake` script! These were designed for libraries whose authors did not support CMake. Use a `Config<mypackage>.cmake` instead as listed below.
## Add Subproject
A package can include your project in a subdirectory, and then use `add_directory` on the subdirectory. This useful for header-only and quick-to-compile libraries. Note that the install commands may interfere with the parent project, so you can add `EXCLUDE_FROM_ALL` to the `add_subdirectory` command; the targets you explicitly use will still be built.
In order to support this as a library author, make sure you use `CMAKE_CURRENT_SOURCE_DIR` instead of `PROJECT_SOURCE_DIR` (and likewise for other variables, like binary dirs). You can check `CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME` to only add options or defaults that make sense if this is a project.
Also, since namespaces are a good idea, and the usage of your library should be consistent with the other methods below, you should add
```cmake
add_library(MyLib::MyLib ALIAS MyLib)
```
to standardise the usage across all methods. This ALIAS target will not be exported below.
## Exporting
The third way is `*Config.cmake` scripts; that will be the topic of the next chapter in this session.

View File

@ -0,0 +1,20 @@
# Exporting
There are two ways to access a project from another project. First is exporting targets and using them in the build directory. It usually is simply a by-product of setting up the third method (installing), but is useful for development and as a way to prepare to discuss the installation procedure.
First, you should make an export set, probably near the end of your main `CMakeLists.txt`:
```cmake
export(TARGETS MyLib1 MyLib2 NAMESPACE MyLib:: FILE MyLibTargets.cmake)
```
This puts the targets you've listed into a file in the build directory, and optionally prefixes them with a namespace. Now, to allow CMake to find this package, export the package into the `$HOME/.cmake/packages` folder:
```cmake
export(PACKAGE MyLib)
```
Now, if you `find_package(MyLib)`, CMake can find the build folder. Look at the generated MyLibTargets.cmake file to help you understand exactly what is created; it's just a normal CMake file, with the exported targets.
Note that there's a downside: if you have imported dependencies, they will need to be imported before you `find_package`. That will be fixed in the next method.

View File

@ -1,46 +1,4 @@
# Exporting and Installing
There are three good ways and one bad way to allow others use your library:
## Find module (the bad way)
If you are the library author, don't make a `Find<mypackage>.cmake` script! These were designed for libraries whose authors did not support CMake. Use a `Config<mypackage>.cmake` instead as listed below.
## Add Subproject
A package can include your project in a subdirectory, and then use `add_directory` on the subdirectory. This useful for header-only and quick-to-compile libraries. Note that the install commands may interfere with the parent project, so you can add `EXCLUDE_FROM_ALL` to the `add_subdirectory` command; the targets you explicitly use will still be built.
In order to support this as a library author, make sure you use `CMAKE_CURRENT_SOURCE_DIR` instead of `PROJECT_SOURCE_DIR` (and likewise for other variables, like binary dirs). You can check `CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME` to only add options or defaults that make sense if this is a project.
Also, since namespaces are a good idea, and the usage of your library should be consistent with the other methods below, you should add
```cmake
add_library(MyLib::MyLib ALIAS MyLib)
```
to standardise the usage across all methods. This ALIAS target will not be exported below.
## Exporting
The second method is exporting targets and using them in the build directory. It usually is simply a by-product of setting up the third method (installing), but is useful for development and as a way to prepare to discuss the installation procedure.
First, you should make an export set, probably near the end of your main `CMakeLists.txt`:
```cmake
export(TARGETS MyLib1 MyLib2 NAMESPACE MyLib:: FILE MyLibTargets.cmake)
```
This puts the targets you've listed into a file in the build directory, and optionally prefixes them with a namespace. Now, to allow CMake to find this package, export the package into the `$HOME/.cmake/packages` folder:
```cmake
export(PACKAGE MyLib)
```
Now, if you `find_package(MyLib)`, CMake can find the build folder. Look at the generated MyLibTargets.cmake file to help you understand exactly what is created; it's just a normal CMake file, with the exported targets.
Note that there's a downside: if you have imported dependencies, they will need to be imported before you `find_package`. That will be fixed in the next method.
## Installing
# Installing
Install commands cause a file or target to be "installed" into the install tree when you `make install`. Your basic target install command looks like this:

View File

@ -0,0 +1,37 @@
# Packaging
There are two ways to instruct CMake to build your package; one is to use a CPackConfig.cmake file, and the other is to integrate the CPack variables into your CMakeLists.txt file. Since you want variables from your main build to be included, like version number, you'll want to make a configure file if you go that route. I'll show you the integrated version:
```cmake
# Packaging support
set(CPACK_PACKAGE_VENDOR "Vendor name")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Some summary")
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENCE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
```
These are the most common variables you'll need to make a binary package. A binary package uses the install mechanism of CMake, so anything that is installed will be present.
You can also make a source package. You should set `CMAKE_SOUCE_IGNORE_FILES` to regular expressions that ensure you don't pick up any extra files (like the build directory or git details); otherwise `make package_source` will bundle up literally everything in the source directory. You can also set the source generator to make your favorite types of files for source packages:
```cmake
set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
set(CPACK_SOURCE_IGNORE_FILES
/.git
/dist
/.*build.*
/\\\\.DS_Store
)
```
Note that this will not work on Windows, but the generated source packages work on Windows.
Finally, you need to include the CPack module:
```cmake
include(CPack)
```

View File

@ -36,6 +36,7 @@ The next two lists are heavily based on the excellent gist [Effective Modern CMa
* **Write a Config.cmake file**: This is what a library author should do to support clients.
* **Make ALIAS targets to keep usage consistent**: Using `add_subdirectory` and `find_package` should provide the same targets and namespaces.
* **Combine common functionality into clearly documented functions or macros**: Functions are better usually.
* **Use lowercase function names**: CMake functions and macros can be called lower or upper case. Always user lower case. Upper case is for variables.