├── .gitignore ├── .travis.yml ├── Boo ├── CMakeLists.txt └── boo.cpp ├── CMakeLists.txt ├── Foo ├── CMakeLists.txt ├── Source │ └── foo │ │ ├── Bar.cpp │ │ ├── Bar.hpp │ │ ├── Baz.cpp │ │ └── Baz.hpp └── cmake │ └── Config.cmake.in ├── README.md ├── appveyor.yml ├── jenkins.py └── wiki ├── FindPackage.UML-sequence.graphml ├── FindPackage.UML-sequence.png └── README.txt /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeCache.txt 2 | CMakeFiles 3 | Makefile 4 | cmake_install.cmake 5 | install_manifest.txt 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # OSX/Linux (https://github.com/travis-ci-tester/toolchain-table) 2 | 3 | language: 4 | - cpp 5 | 6 | sudo: 7 | - true 8 | 9 | dist: 10 | - trusty 11 | 12 | matrix: 13 | include: 14 | # Linux { 15 | 16 | - os: linux 17 | env: SHARED="" MONOLITHIC="" INSTALL_DIR="" 18 | 19 | - os: linux 20 | env: SHARED=--shared MONOLITHIC="" INSTALL_DIR="" 21 | 22 | - os: linux 23 | env: SHARED="" MONOLITHIC=--monolithic INSTALL_DIR="" 24 | 25 | - os: linux 26 | env: SHARED=--shared MONOLITHIC=--monolithic INSTALL_DIR="" 27 | 28 | - os: linux 29 | env: SHARED="" MONOLITHIC="" INSTALL_DIR="--install-dir /usr" 30 | 31 | - os: linux 32 | env: SHARED=--shared MONOLITHIC="" INSTALL_DIR="--install-dir /usr" 33 | 34 | - os: linux 35 | env: SHARED="" MONOLITHIC=--monolithic INSTALL_DIR="--install-dir /usr" 36 | 37 | - os: linux 38 | env: SHARED=--shared MONOLITHIC=--monolithic INSTALL_DIR="--install-dir /usr" 39 | 40 | # } 41 | 42 | # OSX { 43 | 44 | - os: osx 45 | osx_image: xcode9.2 46 | env: SHARED="" MONOLITHIC="" INSTALL_DIR="" 47 | 48 | - os: osx 49 | osx_image: xcode9.2 50 | env: SHARED=--shared MONOLITHIC="" INSTALL_DIR="" 51 | 52 | - os: osx 53 | osx_image: xcode9.2 54 | env: SHARED="" MONOLITHIC=--monolithic INSTALL_DIR="" 55 | 56 | - os: osx 57 | osx_image: xcode9.2 58 | env: SHARED=--shared MONOLITHIC=--monolithic INSTALL_DIR="" 59 | 60 | # } 61 | 62 | install: 63 | # Info about OS 64 | - uname -a 65 | 66 | - if [[ "`uname`" == "Linux" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi 67 | - if [[ "`uname`" == "Linux" ]]; then sudo apt-get update -qq; fi 68 | - if [[ "`uname`" == "Linux" ]]; then sudo apt-get install g++-7 python3-pip; fi 69 | 70 | # Disable autoupdate 71 | # * https://github.com/Homebrew/brew/blob/7d31a70373edae4d8e78d91a4cbc05324bebc3ba/Library/Homebrew/manpages/brew.1.md.erb#L202 72 | - export HOMEBREW_NO_AUTO_UPDATE=1 73 | 74 | # Install Python 3 75 | - if [[ "`uname`" == "Darwin" ]]; then travis_retry brew install python3; fi 76 | 77 | # Install Python package 'requests' 78 | # 'easy_install3' is not installed by 'brew install python3' on OS X 10.9 Maverick 79 | - if [[ "`uname`" == "Darwin" ]]; then pip3 install requests; fi 80 | - if [[ "`uname`" == "Linux" ]]; then travis_retry pip3 install --user requests; fi 81 | 82 | # Install latest Polly toolchains and scripts 83 | - wget https://github.com/ruslo/polly/archive/master.zip 84 | - unzip master.zip 85 | - POLLY_ROOT="`pwd`/polly-master" 86 | - export PATH="${POLLY_ROOT}/bin:${PATH}" 87 | 88 | # Install dependencies (CMake, Android NDK) 89 | - install-ci-dependencies.py 90 | 91 | # Tune locations 92 | - export PATH="`pwd`/_ci/cmake/bin:${PATH}" 93 | 94 | script: 95 | - sudo PATH=$PATH python3 ./jenkins.py --install-boo ${SHARED} ${MONOLITHIC} ${INSTALL_DIR} 96 | 97 | # https://docs.travis-ci.com/user/customizing-the-build/#Whitelisting-or-blacklisting-branches 98 | branches: 99 | except: 100 | - /^pr\..*/ 101 | -------------------------------------------------------------------------------- /Boo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Since CMake 3.3 'NO_CMAKE_BUILDS_PATH' was removed: 2 | # * https://cmake.org/cmake/help/latest/release/3.3.html#deprecated-and-removed-features 3 | cmake_minimum_required(VERSION 3.3) 4 | project(Boo) 5 | 6 | # Introduce variables: 7 | # * CMAKE_INSTALL_LIBDIR 8 | # * CMAKE_INSTALL_BINDIR 9 | # * CMAKE_INSTALL_INCLUDEDIR 10 | include(GNUInstallDirs) 11 | 12 | set(test_path "") 13 | 14 | if(TARGET bar) 15 | add_library(Foo::bar ALIAS bar) 16 | list(APPEND test_path "$") 17 | else() 18 | find_package(Foo CONFIG REQUIRED) 19 | message("Foo_DIR: ${Foo_DIR}") 20 | 21 | # TODO: Make it robust 22 | list(APPEND test_path "${Foo_DIR}/../../../${CMAKE_INSTALL_BINDIR}") 23 | endif() 24 | 25 | if(IOS) 26 | # TODO 27 | elseif(ANDROID) 28 | # TODO 29 | elseif(UNIX) 30 | if(APPLE) 31 | set(CMAKE_INSTALL_RPATH "@executable_path/../${CMAKE_INSTALL_LIBDIR}") 32 | else() 33 | set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") 34 | endif() 35 | endif() 36 | 37 | add_executable(boo boo.cpp) 38 | 39 | # Note: 40 | # * library Foo::baz will be linked automatically 41 | # * macro FOO_BAZ_DEBUG will be added automatically (Foo::baz usage requirement) 42 | target_link_libraries(boo Foo::bar) 43 | 44 | # CMAKE__POSTFIX has no effect on executable 45 | # * http://www.cmake.org/Bug/view.php?id=7868 46 | set_target_properties(boo PROPERTIES DEBUG_POSTFIX "d") 47 | 48 | enable_testing() 49 | add_test(NAME BooTest COMMAND boo) 50 | 51 | install(TARGETS boo DESTINATION ${CMAKE_INSTALL_BINDIR}) 52 | 53 | if(WIN32 OR CYGWIN) 54 | # Add location of library to PATH (for DLL). 55 | set(new_path "$ENV{PATH};${test_path}") 56 | 57 | if(WIN32) 58 | string(REPLACE ";" "\;" new_path "${new_path}") 59 | elseif(CYGWIN) 60 | string(REPLACE ";" ":" new_path "${new_path}") 61 | else() 62 | message(FATAL_ERROR "Unreachable") 63 | endif() 64 | 65 | set_tests_properties(BooTest PROPERTIES ENVIRONMENT "PATH=${new_path}") 66 | endif() 67 | -------------------------------------------------------------------------------- /Boo/boo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // EXIT_SUCCESS 3 | #include // std::cout 4 | 5 | int main() { 6 | std::cout << "Hello, Boo!" << std::endl; 7 | foo::Bar::say(); 8 | return EXIT_SUCCESS; 9 | } 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(foo-monolithic) 3 | 4 | enable_testing() 5 | 6 | # Monolithic version 7 | add_subdirectory(Foo) 8 | add_subdirectory(Boo) 9 | -------------------------------------------------------------------------------- /Foo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file creates project 'Foo' with two library targets 'bar' and 'baz'. 2 | # Target 'bar' depends on 'baz'. After installation this project can be found 3 | # by 'find_package(... CONFIG)' command: 4 | # 5 | # find_package(Foo CONFIG REQUIRED) 6 | # target_link_libraries(... Foo::bar) 7 | # 8 | # Note that requirements propagated automatically, for example: 9 | # * Foo::baz linked automatically 10 | # * /include added to header search path 11 | # * FOO_BAZ_DEBUG=1/FOO_BAR_DEBUG=1 added on Debug 12 | # * FOO_BAZ_DEBUG=0/FOO_BAR_DEBUG=0 added on other configurations 13 | 14 | #### 15 | # Set minimum version of CMake. 16 | cmake_minimum_required(VERSION 3.9) # GENERATOR_IS_MULTI_CONFIG 17 | 18 | #### 19 | # Set variables: 20 | # * PROJECT_NAME 21 | # * PROJECT_VERSION 22 | project(Foo VERSION 1.2.3) 23 | 24 | # Debug Information Format: 25 | # * https://docs.microsoft.com/en-us/cpp/build/reference/z7-zi-zi-debug-information-format 26 | # 27 | # Notes: 28 | # 29 | # * /Z7 still produce PDB file for DLL and without the PDB file installed 30 | # you can't debug DLL 31 | # 32 | # * /Z7 for static library doesn't produce PDB. It's the best option if you 33 | # want debug library without changing internal CMake code. 34 | # Toolchain example: https://github.com/ruslo/polly/blob/master/vs-15-2017-win64-z7.cmake 35 | # 36 | # * /Zi option is default (produce separate PDB files) 37 | # 38 | # * TARGET_PDB_FILE generator expression doesn't support static libraries. 39 | # See https://gitlab.kitware.com/cmake/cmake/issues/16932 40 | # (that's why it's not used here) 41 | # 42 | # * This code can be implemented as a 'PDB DESTINATION' feature. 43 | # See https://gitlab.kitware.com/cmake/cmake/issues/16935#note_275180 44 | # 45 | # * By default only Debug/RelWithDebInfo produce debug information, 46 | # Release/MinSizeRel do not. 47 | # 48 | # * Generated PDB for static libraries doesn't respect CMAKE__POSTFIX 49 | # variable. It means if you specify Debug and RelWithDebInfo then generated 50 | # PDB files for both will be "md5.pdb". When PDB files installed one will 51 | # overwrite another making it unusable. Release + Debug configurations will 52 | # work fine because Release doesn't produce PDB files. 53 | # 54 | # * All PDB files will be installed, including PDB for targets that will not 55 | # be installed themselves. 56 | 57 | if(MSVC) 58 | set(pdb_output_dir "${CMAKE_CURRENT_BINARY_DIR}/pdb-files") 59 | 60 | set(CMAKE_PDB_OUTPUT_DIRECTORY "${pdb_output_dir}") 61 | set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${pdb_output_dir}") 62 | 63 | get_cmake_property(is_multi GENERATOR_IS_MULTI_CONFIG) 64 | if(is_multi) 65 | set(config_suffix "$") 66 | else() 67 | set(config_suffix "") 68 | endif() 69 | 70 | # Introduce variables: 71 | # * CMAKE_INSTALL_LIBDIR 72 | # * CMAKE_INSTALL_BINDIR 73 | include(GNUInstallDirs) 74 | 75 | if(BUILD_SHARED_LIBS) 76 | set(pdb_dst ${CMAKE_INSTALL_BINDIR}) 77 | else() 78 | set(pdb_dst ${CMAKE_INSTALL_LIBDIR}) 79 | endif() 80 | 81 | install( 82 | DIRECTORY "${pdb_output_dir}/${config_suffix}/" 83 | DESTINATION ${pdb_dst} 84 | ) 85 | endif() 86 | 87 | #### 88 | # Create targets 89 | add_library(bar "Source/foo/Bar.cpp" "Source/foo/Bar.hpp") 90 | add_library(baz "Source/foo/Baz.cpp" "Source/foo/Baz.hpp") 91 | 92 | #### 93 | # Properties of targets 94 | 95 | # Add definitions for targets 96 | # Values: 97 | # * Debug: -DFOO_BAR_DEBUG=1 98 | # * Release: -DFOO_BAR_DEBUG=0 99 | # * other: -DFOO_BAR_DEBUG=0 100 | target_compile_definitions(bar PUBLIC "FOO_BAR_DEBUG=$") 101 | target_compile_definitions(baz PUBLIC "FOO_BAZ_DEBUG=$") 102 | 103 | # Generate: 104 | # * ${CMAKE_CURRENT_BINARY_DIR}/generated_headers/foo/BAR_EXPORT.h with BAR_EXPORT 105 | # * ${CMAKE_CURRENT_BINARY_DIR}/generated_headers/foo/BAZ_EXPORT.h with BAZ_EXPORT 106 | # Renaming because: 107 | # * We need prefix 'foo' to fit OSX/iOS frameworks layout 108 | # * File name match name of the macro 109 | set(generated_headers "${CMAKE_CURRENT_BINARY_DIR}/generated_headers") 110 | set(bar_export "${generated_headers}/foo/BAR_EXPORT.h") 111 | set(baz_export "${generated_headers}/foo/BAZ_EXPORT.h") 112 | 113 | # https://cmake.org/cmake/help/v3.9/module/GenerateExportHeader.html 114 | include(GenerateExportHeader) 115 | generate_export_header(bar EXPORT_FILE_NAME ${bar_export}) 116 | generate_export_header(baz EXPORT_FILE_NAME ${baz_export}) 117 | 118 | # Global includes. Used by all targets 119 | # Note: 120 | # * header location in project: Foo/Source/foo/Bar.hpp 121 | # * header can be included by C++ code `#include ` 122 | # * header location in project: ${CMAKE_CURRENT_BINARY_DIR}/generated_headers/foo/BAR_EXPORT.h 123 | # * header can be included by: `#include ` 124 | target_include_directories( 125 | baz PUBLIC 126 | "$" 127 | "$" 128 | ) 129 | 130 | # Link required library 131 | target_link_libraries(bar PUBLIC baz) 132 | 133 | # Installation (https://github.com/forexample/package-example) { 134 | 135 | # Introduce variables: 136 | # * CMAKE_INSTALL_LIBDIR 137 | # * CMAKE_INSTALL_BINDIR 138 | # * CMAKE_INSTALL_INCLUDEDIR 139 | include(GNUInstallDirs) 140 | 141 | # Layout. This works for all platforms: 142 | # * /lib*/cmake/ 143 | # * /lib*/ 144 | # * /include/ 145 | set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") 146 | 147 | set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") 148 | 149 | # Configuration 150 | set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") 151 | set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") 152 | set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") 153 | set(namespace "${PROJECT_NAME}::") 154 | 155 | # Include module with fuction 'write_basic_package_version_file' 156 | include(CMakePackageConfigHelpers) 157 | 158 | # Configure 'ConfigVersion.cmake' 159 | # Use: 160 | # * PROJECT_VERSION 161 | write_basic_package_version_file( 162 | "${version_config}" COMPATIBILITY SameMajorVersion 163 | ) 164 | 165 | # Configure 'Config.cmake' 166 | # Use variables: 167 | # * TARGETS_EXPORT_NAME 168 | # * PROJECT_NAME 169 | configure_package_config_file( 170 | "cmake/Config.cmake.in" 171 | "${project_config}" 172 | INSTALL_DESTINATION "${config_install_dir}" 173 | ) 174 | 175 | # Targets: 176 | # * /lib/libbar.a 177 | # * /lib/libbaz.a 178 | # * header location after install: /include/foo/Bar.hpp 179 | # * headers can be included by C++ code `#include ` 180 | install( 181 | TARGETS bar baz 182 | EXPORT "${TARGETS_EXPORT_NAME}" 183 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" 184 | ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" 185 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 186 | INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 187 | ) 188 | 189 | # Headers: 190 | # * Source/foo/Bar.hpp -> /include/foo/Bar.hpp 191 | # * Source/foo/Baz.hpp -> /include/foo/Baz.hpp 192 | install( 193 | DIRECTORY "Source/foo" 194 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 195 | FILES_MATCHING PATTERN "*.hpp" 196 | ) 197 | 198 | # Export headers: 199 | # * ${CMAKE_CURRENT_BINARY_DIR}/.../BAR_EXPORT.h -> /include/foo/BAR_EXPORT.h 200 | # * ${CMAKE_CURRENT_BINARY_DIR}/.../BAZ_EXPORT.h -> /include/foo/BAZ_EXPORT.h 201 | install( 202 | FILES "${bar_export}" "${baz_export}" 203 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/foo" 204 | ) 205 | 206 | # Config 207 | # * /lib/cmake/Foo/FooConfig.cmake 208 | # * /lib/cmake/Foo/FooConfigVersion.cmake 209 | install( 210 | FILES "${project_config}" "${version_config}" 211 | DESTINATION "${config_install_dir}" 212 | ) 213 | 214 | # Config 215 | # * /lib/cmake/Foo/FooTargets.cmake 216 | install( 217 | EXPORT "${TARGETS_EXPORT_NAME}" 218 | NAMESPACE "${namespace}" 219 | DESTINATION "${config_install_dir}" 220 | ) 221 | 222 | # } 223 | -------------------------------------------------------------------------------- /Foo/Source/foo/Bar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace foo { 4 | 5 | void Bar::cpp_say() { 6 | #if (FOO_BAR_DEBUG) 7 | const char* m = "Bar.cpp (Debug)"; 8 | #else 9 | const char* m = "Bar.cpp (Not debug)"; 10 | #endif 11 | std::cout << m << std::endl; 12 | } 13 | 14 | } // namespace foo 15 | -------------------------------------------------------------------------------- /Foo/Source/foo/Bar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_BAR_HPP_ 2 | #define FOO_BAR_HPP_ 3 | 4 | #include // std::cout 5 | #include 6 | #include 7 | 8 | namespace foo { 9 | 10 | class BAR_EXPORT Bar { 11 | public: 12 | static void say() { 13 | Baz::say(); 14 | #if (FOO_BAR_DEBUG) 15 | const char* m = "Bar.hpp (Debug)"; 16 | #else 17 | const char* m = "Bar.hpp (Not debug)"; 18 | #endif 19 | std::cout << m << std::endl; 20 | cpp_say(); 21 | } 22 | 23 | private: 24 | static void cpp_say(); 25 | }; 26 | 27 | } 28 | 29 | #endif // FOO_BAR_HPP_ 30 | -------------------------------------------------------------------------------- /Foo/Source/foo/Baz.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace foo { 4 | 5 | void Baz::cpp_say() { 6 | #if (FOO_BAZ_DEBUG) 7 | const char* m = "Baz.cpp (Debug)"; 8 | #else 9 | const char* m = "Baz.cpp (Not debug)"; 10 | #endif 11 | std::cout << m << std::endl; 12 | } 13 | 14 | } // namespace foo 15 | -------------------------------------------------------------------------------- /Foo/Source/foo/Baz.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FOO_BAZ_HPP_ 2 | #define FOO_BAZ_HPP_ 3 | 4 | #include // std::cout 5 | #include 6 | 7 | namespace foo { 8 | 9 | class BAZ_EXPORT Baz { 10 | public: 11 | static void say() { 12 | #if (FOO_BAZ_DEBUG) 13 | const char* m = "Baz.hpp (Debug)"; 14 | #else 15 | const char* m = "Baz.hpp (Not debug)"; 16 | #endif 17 | std::cout << m << std::endl; 18 | cpp_say(); 19 | } 20 | 21 | private: 22 | static void cpp_say(); 23 | }; 24 | 25 | } // namespace foo 26 | 27 | #endif // FOO_BAZ_HPP_ 28 | -------------------------------------------------------------------------------- /Foo/cmake/Config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") 4 | check_required_components("@PROJECT_NAME@") 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status][master]][repo] [![Build status](https://ci.appveyor.com/api/projects/status/oln2ks60gs8fs5ux/branch/master?svg=true)](https://ci.appveyor.com/project/ruslo/package-example/branch/master) 2 | 3 | [master]: https://travis-ci.org/forexample/package-example.svg?branch=master 4 | [repo]: https://travis-ci.org/forexample/package-example 5 | 6 | ### Install Foo 7 | 8 | Install project `Foo` in `Debug` and `Release` variants (`Makefile` generator): 9 | ``` bash 10 | > cmake -HFoo -B_builds/Foo-debug -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_INSTALL_PREFIX="`pwd`/_install" 11 | > cmake --build _builds/Foo-debug --target install 12 | ... 13 | Install the project... 14 | -- Install configuration: "Debug" 15 | -- Installing: /.../_install/lib/libbard.a 16 | -- Installing: /.../_install/lib/libbazd.a 17 | -- Installing: /.../_install/include/foo 18 | -- Installing: /.../_install/include/foo/Bar.hpp 19 | -- Installing: /.../_install/include/foo/Baz.hpp 20 | -- Installing: /.../_install/include/foo/BAR_EXPORT.h 21 | -- Installing: /.../_install/include/foo/BAZ_EXPORT.h 22 | -- Installing: /.../_install/lib/cmake/Foo/FooConfig.cmake 23 | -- Installing: /.../_install/lib/cmake/Foo/FooConfigVersion.cmake 24 | -- Installing: /.../_install/lib/cmake/Foo/FooTargets.cmake 25 | -- Installing: /.../_install/lib/cmake/Foo/FooTargets-debug.cmake 26 | ``` 27 | 28 | ```bash 29 | > cmake -HFoo -B_builds/Foo-release -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="`pwd`/_install" 30 | > cmake --build _builds/Foo-release --target install 31 | ... 32 | Install the project... 33 | -- Install configuration: "Release" 34 | -- Installing: /.../_install/lib/libbar.a 35 | -- Installing: /.../_install/lib/libbaz.a 36 | -- Up-to-date: /.../_install/include/foo 37 | -- Up-to-date: /.../_install/include/foo/Bar.hpp 38 | -- Up-to-date: /.../_install/include/foo/Baz.hpp 39 | -- Installing: /.../_install/include/foo/BAR_EXPORT.h 40 | -- Installing: /.../_install/include/foo/BAZ_EXPORT.h 41 | -- Installing: /.../_install/lib/cmake/Foo/FooConfig.cmake 42 | -- Installing: /.../_install/lib/cmake/Foo/FooConfigVersion.cmake 43 | -- Installing: /.../_install/lib/cmake/Foo/FooTargets.cmake 44 | -- Installing: /.../_install/lib/cmake/Foo/FooTargets-release.cmake 45 | ``` 46 | 47 | Note that: 48 | * library target `bar` for different build types has different names: `libbar.a` and `libbard.a` 49 | * header files is equal for both variants 50 | * cmake-config files `FooConfig.cmake`, `FooConfigVersion.cmake` and `FooTargets.cmake` is equal for both variants 51 | * `FooTargets-release.cmake` set `Release` imported target properties, e.g. `IMPORTED_LOCATION_RELEASE` 52 | * `FooTargets-debug.cmake` set `Debug` imported target properties, e.g. `IMPORTED_LOCATION_DEBUG` 53 | 54 | Note: 55 | * For `-H` see: https://cgold.readthedocs.io/en/latest/glossary/-H.html 56 | 57 | ### Boo (use installed Foo) 58 | 59 | Easiest way to find and include `FooConfig.cmake` file is to set `CMAKE_INSTALL_PREFIX`: 60 | ```bash 61 | > cmake -HBoo -B_builds/Boo -DCMAKE_INSTALL_PREFIX="`pwd`/_install" 62 | ``` 63 | 64 | Also `CMAKE_PREFIX_PATH` and `Foo_DIR` can be used (do not forget to **remove** `_builds/Boo` directory 65 | before every configure): 66 | 67 | ```bash 68 | > cmake -HBoo -B_builds/Boo -DCMAKE_PREFIX_PATH="`pwd`/_install" 69 | > cmake -HBoo -B_builds/Boo -DFoo_DIR="`pwd`/_install/lib/cmake/Foo" 70 | ``` 71 | 72 | `find_package` config-mode command will include `FooConfig.cmake` file and import new target `Foo::bar`: 73 | 74 | ```bash 75 | > cat Boo/CMakeLists.txt 76 | find_package(Foo CONFIG REQUIRED) 77 | add_executable(boo boo.cpp) 78 | target_link_libraries(boo Foo::bar) 79 | ``` 80 | 81 | Note that: 82 | * definition `FOO_BAR_DEBUG` will be added automatically 83 | * include directory for target `Foo::bar` will be added automatically 84 | * in `Debug`-mode macro `FOO_BAR_DEBUG` will be `1` and linker will use `libbard.a` library 85 | * in `Release`-mode macro `FOO_BAR_DEBUG` will be `0` and linker will use `libbar.a` library 86 | * if `find_package` command specify library version then `FooConfigVersion.cmake` module will check compatibility: 87 | 88 | ```bash 89 | > grep find_package Boo/CMakeLists.txt 90 | find_package(Foo 2.0 CONFIG REQUIRED) 91 | > cmake -HBoo -B_builds/Boo -DCMAKE_INSTALL_PREFIX="`pwd`/_install" 92 | CMake Error at CMakeLists.txt:8 (find_package): 93 | Could not find a configuration file for package "Foo" that is compatible 94 | with requested version "2.0". 95 | 96 | The following configuration files were considered but not accepted: 97 | 98 | /.../_install/lib/cmake/Foo/FooConfig.cmake, version: 1.2.3 99 | ``` 100 | 101 | ### Script 102 | 103 | See `jenkins.py` script for automatic testing + options `--install-boo`/`--shared` and `--monolithic`. 104 | 105 | ### UML sequence diagram 106 | 107 | ![uml](https://raw.github.com/forexample/package-example/master/wiki/FindPackage.UML-sequence.png) 108 | 109 | ### More 110 | 111 | * [Package manager](https://github.com/ruslo/hunter) 112 | * [Toolchains](https://github.com/ruslo/polly) 113 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Windows (https://github.com/travis-ci-tester/toolchain-table) 2 | 3 | environment: 4 | matrix: 5 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 6 | SHARED: "" 7 | MONOLITHIC: "" 8 | GENERATOR: "Visual Studio 15 2017 Win64" 9 | 10 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 11 | SHARED: "--shared" 12 | MONOLITHIC: "" 13 | GENERATOR: "Visual Studio 15 2017 Win64" 14 | 15 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 16 | SHARED: "" 17 | MONOLITHIC: "--monolithic" 18 | GENERATOR: "Visual Studio 15 2017 Win64" 19 | 20 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 21 | SHARED: "--shared" 22 | MONOLITHIC: "--monolithic" 23 | GENERATOR: "Visual Studio 15 2017 Win64" 24 | 25 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 26 | SHARED: "" 27 | MONOLITHIC: "" 28 | GENERATOR: "MinGW Makefiles" 29 | 30 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 31 | SHARED: "--shared" 32 | MONOLITHIC: "" 33 | GENERATOR: "MinGW Makefiles" 34 | 35 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 36 | SHARED: "" 37 | MONOLITHIC: "--monolithic" 38 | GENERATOR: "MinGW Makefiles" 39 | 40 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 41 | SHARED: "--shared" 42 | MONOLITHIC: "--monolithic" 43 | GENERATOR: "MinGW Makefiles" 44 | 45 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 46 | SHARED: "" 47 | MONOLITHIC: "" 48 | GENERATOR: "MSYS Makefiles" 49 | 50 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 51 | SHARED: "--shared" 52 | MONOLITHIC: "" 53 | GENERATOR: "MSYS Makefiles" 54 | 55 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 56 | SHARED: "" 57 | MONOLITHIC: "--monolithic" 58 | GENERATOR: "MSYS Makefiles" 59 | 60 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 61 | SHARED: "--shared" 62 | MONOLITHIC: "--monolithic" 63 | GENERATOR: "MSYS Makefiles" 64 | 65 | install: 66 | # Python 3 67 | - cmd: set PATH=C:\Python34-x64;C:\Python34-x64\Scripts;%PATH% 68 | 69 | # Install Python package 'requests' 70 | - cmd: pip install requests 71 | 72 | # Install latest Polly toolchains and scripts 73 | - cmd: appveyor DownloadFile https://github.com/ruslo/polly/archive/master.zip 74 | - cmd: 7z x master.zip 75 | - cmd: set POLLY_ROOT=%cd%\polly-master 76 | 77 | # Install dependencies (CMake, Ninja) 78 | - cmd: python %POLLY_ROOT%\bin\install-ci-dependencies.py 79 | 80 | # Tune locations 81 | - cmd: set PATH=%cd%\_ci\cmake\bin;%PATH% 82 | - cmd: set PATH=%cd%\_ci\ninja;%PATH% 83 | 84 | - cmd: git submodule update --init --recursive 85 | 86 | # Remove entry with sh.exe from PATH to fix error with MinGW toolchain 87 | # (For MinGW make to work correctly sh.exe must NOT be in your path) 88 | # * http://stackoverflow.com/a/3870338/2288008 89 | - cmd: set PATH=%PATH:C:\Program Files\Git\usr\bin;=% 90 | 91 | - cmd: set MINGW_PATH=C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin 92 | 93 | # MSYS2 location 94 | - cmd: set MSYS_PATH=C:\msys64\usr\bin 95 | 96 | # Visual Studio 15 2017: Mimic behavior of older versions 97 | - cmd: set VS150COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools 98 | 99 | build_script: 100 | - cmd: python .\jenkins.py %SHARED% %MONOLITHIC% --generator "%GENERATOR%" 101 | 102 | # http://www.appveyor.com/docs/branches#white-and-blacklisting 103 | branches: 104 | except: 105 | - /^pr\..*/ 106 | -------------------------------------------------------------------------------- /jenkins.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import glob 5 | import os 6 | import platform 7 | import shutil 8 | import subprocess 9 | import sys 10 | 11 | parser = argparse.ArgumentParser(description="Testing script") 12 | parser.add_argument('--shared', action='store_true', help='Build shared libs') 13 | parser.add_argument( 14 | '--install-boo', action='store_true', help='Install boo and run' 15 | ) 16 | parser.add_argument( 17 | '--monolithic', action='store_true', help='Build all in one' 18 | ) 19 | parser.add_argument( 20 | '--install-dir', help='Custom install directory' 21 | ) 22 | parser.add_argument( 23 | '--generator', help='CMake generator' 24 | ) 25 | cmd_args = parser.parse_args() 26 | 27 | cwd = os.getcwd() 28 | 29 | def do_call(args): 30 | oneline = '' 31 | for i in args: 32 | oneline += ' "{}"'.format(i) 33 | print('[{}]>{}'.format(os.getcwd(), oneline)) 34 | try: 35 | subprocess.check_call(args, env=os.environ) 36 | except subprocess.CalledProcessError as error: 37 | print(error) 38 | print(error.output) 39 | sys.exit(1) 40 | 41 | if os.path.exists('_builds'): 42 | shutil.rmtree('_builds') 43 | 44 | # Warning: do not remove cmd_args.install_dir - it may be system! 45 | if os.path.exists('_install'): 46 | shutil.rmtree('_install') 47 | 48 | if os.name == 'nt': 49 | do_call(['where', 'cmake']) 50 | else: 51 | do_call(['which', 'cmake']) 52 | 53 | do_call(['cmake', '--version']) 54 | 55 | if cmd_args.install_dir: 56 | install_dir = cmd_args.install_dir 57 | else: 58 | install_dir = os.path.join(cwd, '_install') 59 | 60 | exe_dir = os.path.join(install_dir, 'bin') 61 | 62 | if platform.system() == 'Windows' or platform.system().startswith('CYGWIN'): 63 | # Update PATH for DLL platforms 64 | windows_path_update = True 65 | else: 66 | windows_path_update = False 67 | 68 | if cmd_args.install_boo: 69 | # We will install 'boo' executable so it should work without PATH modification 70 | windows_path_update = False 71 | 72 | if not cmd_args.shared: 73 | # No need to update PATH if libraries are static 74 | windows_path_update = False 75 | 76 | if windows_path_update: 77 | os.environ['PATH'] = '{};{}'.format(exe_dir, os.environ['PATH']) 78 | 79 | if cmd_args.generator == 'MinGW Makefiles': 80 | os.environ['PATH'] = '{};{}'.format( 81 | os.environ['MINGW_PATH'], os.environ['PATH'] 82 | ) 83 | 84 | if cmd_args.generator == 'MSYS Makefiles': 85 | os.environ['PATH'] = '{};{}'.format( 86 | os.environ['MSYS_PATH'], os.environ['PATH'] 87 | ) 88 | 89 | def run_build(projname, buildtype, install, verbose, test): 90 | os.chdir(cwd) 91 | 92 | print('-' * 80) 93 | print("+ {} {}".format(projname, buildtype)) 94 | print('-' * 80) 95 | 96 | build_dir = os.path.join('_builds', '{}-{}'.format(projname, buildtype)) 97 | 98 | args = [ 99 | 'cmake', 100 | '-H{}'.format(projname), 101 | '-B{}'.format(build_dir), 102 | '-DCMAKE_BUILD_TYPE={}'.format(buildtype) 103 | ] 104 | 105 | if install: 106 | args += ['-DCMAKE_INSTALL_PREFIX={}'.format(install_dir)] 107 | else: 108 | args += ['-DCMAKE_PREFIX_PATH={}'.format(install_dir)] 109 | 110 | if buildtype != 'Release': 111 | args += ['-DCMAKE_{}_POSTFIX=-{}'.format(buildtype.upper(), buildtype)] 112 | 113 | if verbose: 114 | args += ['-DCMAKE_VERBOSE_MAKEFILE=ON'] 115 | 116 | if cmd_args.shared: 117 | args += ['-DBUILD_SHARED_LIBS=ON'] 118 | else: 119 | args += ['-DBUILD_SHARED_LIBS=OFF'] 120 | 121 | if cmd_args.generator: 122 | args += ['-G{}'.format(cmd_args.generator)] 123 | 124 | do_call(args) 125 | 126 | args = ['cmake', '--build', build_dir, '--config', buildtype] 127 | if install: 128 | args += ['--target', 'install'] 129 | do_call(args) 130 | 131 | if test: 132 | os.chdir(build_dir) 133 | args = ['ctest', '-C', buildtype, '-VV'] 134 | do_call(args) 135 | os.chdir(cwd) 136 | 137 | run_test_after_install = False 138 | if cmd_args.monolithic: 139 | run_build('.', 'Release', install=True, verbose=True, test=True) 140 | run_build('.', 'Debug', install=True, verbose=True, test=True) 141 | run_test_after_install = True 142 | else: 143 | run_build('Foo', 'Release', install=True, verbose=False, test=False) 144 | run_build('Foo', 'Debug', install=True, verbose=False, test=False) 145 | 146 | if cmd_args.install_boo: 147 | run_build('Boo', 'Release', install=True, verbose=True, test=True) 148 | run_build('Boo', 'Debug', install=True, verbose=True, test=True) 149 | run_test_after_install = True 150 | else: 151 | run_build('Boo', 'Release', install=False, verbose=True, test=True) 152 | run_build('Boo', 'Debug', install=False, verbose=True, test=True) 153 | 154 | if run_test_after_install: 155 | executables = glob.glob(os.path.join(exe_dir, 'boo*')) 156 | 157 | try: 158 | # when installed to system 159 | executables.remove('/usr/bin/bootctl') 160 | except ValueError: 161 | pass 162 | 163 | if len(executables) != 2: 164 | sys.exit('Expected two executables') 165 | for x in executables: 166 | do_call([x]) 167 | -------------------------------------------------------------------------------- /wiki/FindPackage.UML-sequence.graphml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | CMakeLists.txt 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | CMakeLists.txt 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | FooConfigVersion.cmake 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | FooTargets.cmake 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | FooConfig.cmake 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | FooTargets-release.cmake 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | FooTargets-debug.cmake 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | FooConfigVersion.cmake 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | FooConfig.cmake 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | FooTargets.cmake 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | FooTargets-release.cmake 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | FooTargets-debug.cmake 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | Included automatically 337 | from `find_package` command 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | Written and installed manually 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | This file need to be included manually 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | This files generated by `install(EXPORT ...)` command 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | `FooTarget.cmake` include variants automatically 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | Import library `Foo::foo`, update 423 | INTERFACE_COMPILE_DEFINITIONS, 424 | INTERFACE_INCLUDE_DIRECTORIES 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | set IMPORTED_LOCATION_RELEASE for `Foo::foo` 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | set IMPORTED_LOCATION_DEBUG for `Foo::foo` 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | File generated by 476 | `write_basic_package_version_file` 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | -------------------------------------------------------------------------------- /wiki/FindPackage.UML-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forexample/package-example/ad6249638ba2567b528c36586f4e402159d18e14/wiki/FindPackage.UML-sequence.png -------------------------------------------------------------------------------- /wiki/README.txt: -------------------------------------------------------------------------------- 1 | Created by yEd (http://www.yworks.com/en/products_yed_about.html) 2 | --------------------------------------------------------------------------------