Compare commits

...

13 Commits

Author SHA1 Message Date
Paul Taylor
7644c3a40f Respect FETCHCONTENT_BASE_DIR if set by a user (#244)
* Respect `FETCHCONTENT_BASE_DIR` if set by a user

* Use a single `CPM_FETCHCONTENT_BASE_DIR` var
2021-04-16 17:27:51 +02:00
Lars Melchior
310efb9b17 Update more examples from the readme (#241)
* update examples from the readme

* add explainations to the examples
2021-03-26 18:31:35 +02:00
Lars Melchior
4fad2eac0a remove option consistency check (#240) 2021-03-25 19:24:44 +02:00
flagarde
ee08119642 Scope package options to avoid changing the local scope (#235)
* Fix #222

* Fix #222

* move policy change and local options to cpm_add_subdirectory

* change default policy as well

see https://gitlab.kitware.com/cmake/cmake/-/issues/20312

* add test

* update check to not use the NOT operator

(interestingly it works as expected locally)

* simplify test by not using options

* check options in tests

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>
2021-03-25 15:59:34 +01:00
Lars Melchior
259f1be8e2 update cxxopts and add reasonable options (#239) 2021-03-25 14:20:06 +02:00
Lars Melchior
32b063eba5 Fix support for source subdirectories (#238)
* add support for source subdirectories

* style fixes

* remove debug log

* grammar fix in comment
2021-03-25 10:42:51 +01:00
Lars Melchior
d64d816585 Make CPMFindPackage less prominent in the Readme (#236)
Giving `CPMFindPackage` a less prominent position, as in almost all cases, `CPMAddPackage` should be preferred.

Following a related discussion in #222.
2021-03-22 12:37:11 +01:00
Lars Melchior
8e8dcc9a8d moved test repostitory to CPM.cmake namespace (#228) 2021-03-04 11:01:01 +02:00
Lars Melchior
8afc2af4f9 update more examples to use shorthand syntax (#223)
* update more examples to use shorthand syntax

* revert google-benchmark as tests require googletest to be installed

* update comments

* always quote single-arguments

* undo accidental deletion
2021-02-25 09:53:28 +02:00
Borislav Stanimirov
a3d1048ad6 Infer package name and version from URL (#220)
* Function to extract name and version from url. Some tests

* Rewrite. Previous version was not safe enough. More tests

* Allow underscore as a name-version separator (<name>_<ver>)

* CPMAddPackage can infer name and version from url

* Allow URL parse from single arg and uncomment tests

* Info about shorthand syntax in README

* Fix style

* Fixed typo

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>

* Explicit hash algorithm in shorthand URL example.
Also added tests which include a hash algorithm provided
We can't document a default until it's confirmed here: https://gitlab.kitware.com/cmake/cmake/-/issues/21859

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>
2021-02-23 20:15:45 +01:00
Lars Melchior
492e762591 update examples to use new syntax where possible (#218) 2021-02-23 08:14:32 +02:00
Borislav Stanimirov
3f6cbe7383 Single-argument shorthand syntax for CPMAddPackage (#207)
* Added quotes in equality checks so lists can be compared

* Function to parse argument of CPMAddPackage in case a single one was provided

* Error on URL type in CPMAddPackage single-arg

* Fixed format

* Support single argument syntax of CPMAddPackage

* Documenting and showcasing the new shorthand syntax of CPMAddPackage

* Auto EXCLUDE_FROM_ALL for the shorthand syntax

* Fixed accidental paste of TOLOWER

* Document why some test cases are commented out

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>

* Update README.md

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>

* Removed GitHub as the default package shorthand provider

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>
2021-02-22 21:12:06 +01:00
Borislav Stanimirov
4aadac1972 Improved regex match in cpm_package_name_from_git_uri (#206) 2021-02-19 09:45:04 +01:00
26 changed files with 533 additions and 239 deletions

149
README.md
View File

@@ -27,9 +27,9 @@ For everything else, the targets can be created manually after the dependency ha
## Usage ## Usage
After `CPM.cmake` has been [added](#adding-cpm) to your project, the function `CPMAddPackage` or `CPMFindPackage` can be used to fetch and configure a dependency. After `CPM.cmake` has been [added](#adding-cpm) to your project, the function `CPMAddPackage` can be used to fetch and configure a dependency.
Afterwards, any targets defined in the dependency can be used directly. Afterwards, any targets defined in the dependency can be used directly.
`CPMFindPackage` and `CPMAddPackage` take the following named parameters. `CPMAddPackage` takes the following named parameters.
```cmake ```cmake
CPMAddPackage( CPMAddPackage(
@@ -45,16 +45,42 @@ The origin may be specified by a `GIT_REPOSITORY`, but other sources, such as di
If `GIT_TAG` hasn't been explicitly specified it defaults to `v(VERSION)`, a common convention for git projects. If `GIT_TAG` hasn't been explicitly specified it defaults to `v(VERSION)`, a common convention for git projects.
On the other hand, if `VERSION` hasn't been explicitly specified, CPM can automatically identify the version from the git tag in some common cases. On the other hand, if `VERSION` hasn't been explicitly specified, CPM can automatically identify the version from the git tag in some common cases.
`GIT_TAG` can also be set to a specific commit or a branch name such as `master` to always download the most recent version. `GIT_TAG` can also be set to a specific commit or a branch name such as `master` to always download the most recent version.
The optional argument `FIND_PACKAGE_ARGUMENTS` can be specified to a string of parameters that will be passed to `find_package` if enabled (see below).
After calling `CPMAddPackage` or `CPMFindPackage`, the following variables are defined in the local scope, where `<dependency>` is the name of the dependency. If an additional optional parameter `EXCLUDE_FROM_ALL` is set to a truthy value, then any targets defined inside the dependency won't be built by default. See the [CMake docs](https://cmake.org/cmake/help/latest/prop_tgt/EXCLUDE_FROM_ALL.html) for details.
A single-argument compact syntax is also supported:
```cmake
# A git package from a given uri with a version
CPMAddPackage("uri@version")
# A git package from a given uri with a git tag or commit hash, or branch name
CPMAddPackage("uri#tag")
# A git package with both version and tag provided
CPMAddPackage("uri@version#tag")
```
In the shorthand syntax if the URI is of the form `gh:user/name`, it is interpreted as GitHub URI and converted to `https://github.com/user/name.git`. If the URI is of the form `gl:user/name`, it is interpreted as a [GitLab](https://gitlab.com/explore/) URI and coverted to `https://gitlab.com/user/name.git`. Otherwise the URI used verbatim as a git URL. All packages added using the shorthand syntax will be added using the [EXCLUDE_FROM_ALL](https://cmake.org/cmake/help/latest/prop_tgt/EXCLUDE_FROM_ALL.html) flag.
The single-argument syntax also works for URLs:
```cmake
# An archive package from a given url. The version is inferred
CPMAddPackage("https://example.com/my-package-1.2.3.zip")
# An archive package from a given url with an MD5 hash provided
CPMAddPackage("https://example.com/my-package-1.2.3.zip#MD5=68e20f674a48be38d60e129f600faf7d")
# An archive package from a given url. The version is explicitly given
CPMAddPackage("https://example.com/my-package.zip@1.2.3")
```
After calling `CPMAddPackage`, the following variables are defined in the local scope, where `<dependency>` is the name of the dependency.
- `<dependency>_SOURCE_DIR` is the path to the source of the dependency. - `<dependency>_SOURCE_DIR` is the path to the source of the dependency.
- `<dependency>_BINARY_DIR` is the path to the build directory of the dependency. - `<dependency>_BINARY_DIR` is the path to the build directory of the dependency.
- `<dependency>_ADDED` is set to `YES` if the dependency has not been added before, otherwise it is set to `NO`. - `<dependency>_ADDED` is set to `YES` if the dependency has not been added before, otherwise it is set to `NO`.
The difference between `CPMFindPackage` and `CPMAddPackage` is that `CPMFindPackage` will try to find a local dependency via CMake's `find_package` and fallback to `CPMAddPackage` if the dependency is not found. For using CPM.cmake projects with external package managers, such as conan or vcpkg, setting the variable [`CPM_USE_LOCAL_PACKAGES`](#options) will make CPM.cmake try to add a package through `find_package` first, and add it from source if it doesn't succeed.
This behaviour can be also modified globally via [CPM options](#options).
In rare cases, this behaviour may be desirable by default. The function `CPMFindPackage` will try to find a local dependency via CMake's `find_package` and fallback to `CPMAddPackage`, if the dependency is not found.
## Full CMakeLists Example ## Full CMakeLists Example
@@ -69,11 +95,7 @@ add_executable(tests tests.cpp)
# add dependencies # add dependencies
include(cmake/CPM.cmake) include(cmake/CPM.cmake)
CPMAddPackage("gh:catchorg/Catch2@2.5.0")
CPMAddPackage(
GITHUB_REPOSITORY catchorg/Catch2
VERSION 2.5.0
)
# link dependencies # link dependencies
target_link_libraries(tests Catch2) target_link_libraries(tests Catch2)
@@ -135,7 +157,6 @@ The most notable features are:
- A simpler to use API - A simpler to use API
- Version checking: CPM.cmake will check the version number of any added dependency and omit a warning if another dependency requires a more recent version. - Version checking: CPM.cmake will check the version number of any added dependency and omit a warning if another dependency requires a more recent version.
- Options: any Options passed to a dependency are stored and compared on later use, so if another dependency tries to add an existing dependency with incompatible options a warning will be emitted to the user.
- Offline builds: CPM.cmake will override CMake's download and update commands, which allows new builds to be configured while offline if all dependencies [are available locally](#cpm_source_cache). - Offline builds: CPM.cmake will override CMake's download and update commands, which allows new builds to be configured while offline if all dependencies [are available locally](#cpm_source_cache).
- Automatic shallow clone: if a version tag (e.g. `v2.2.0`) is provided and `CPM_SOURCE_CACHE` is used, CPM.cmake will perform a shallow clone of the dependency, which should be significantly faster while using less storage than a full clone. - Automatic shallow clone: if a version tag (e.g. `v2.2.0`) is provided and `CPM_SOURCE_CACHE` is used, CPM.cmake will perform a shallow clone of the dependency, which should be significantly faster while using less storage than a full clone.
- Overridable: all `CPMAddPackage` can be configured to use `find_package` by setting a [CMake flag](#cpm_use_local_packages), making it easy to integrate into projects that may require local versioning through the system's package manager. - Overridable: all `CPMAddPackage` can be configured to use `find_package` by setting a [CMake flag](#cpm_use_local_packages), making it easy to integrate into projects that may require local versioning through the system's package manager.
@@ -173,6 +194,8 @@ CPM can be configured to use `find_package` to search for locally installed depe
If the option `CPM_LOCAL_PACKAGES_ONLY` is set, CPM will emit an error if the dependency is not found locally. If the option `CPM_LOCAL_PACKAGES_ONLY` is set, CPM will emit an error if the dependency is not found locally.
These options can also be set as environmental variables. These options can also be set as environmental variables.
In the case that `find_package` requires additional arguments, the parameter `FIND_PACKAGE_ARGUMENTS` may be specified in the `CPMAddPackage` call. The value of this parameter will be forwarded to `find_package`.
## Local package override ## Local package override
Library developers are often in the situation where they work on a locally checked out dependency at the same time as on a consumer project. Library developers are often in the situation where they work on a locally checked out dependency at the same time as on a consumer project.
@@ -244,50 +267,47 @@ See the [wiki](https://github.com/cpm-cmake/CPM.cmake/wiki/More-Snippets) for mo
### [Catch2](https://github.com/catchorg/Catch2) ### [Catch2](https://github.com/catchorg/Catch2)
```cmake ```cmake
CPMAddPackage( CPMAddPackage("gh:catchorg/Catch2@2.5.0")
NAME Catch2
GITHUB_REPOSITORY catchorg/Catch2
VERSION 2.5.0
)
``` ```
### [Boost (via boost-cmake)](https://github.com/Orphis/boost-cmake) ### [Boost (via boost-cmake)](https://github.com/Orphis/boost-cmake)
```CMake ```CMake
CPMAddPackage("gh:Orphis/boost-cmake@1.67.0")
```
### [Yaml-cpp](https://github.com/jbeder/yaml-cpp)
```CMake
# as the tag is in an unusual format, we need to explicitly specify the version
CPMAddPackage("gh:jbeder/yaml-cpp#yaml-cpp-0.6.3@0.6.3")
```
### [Range-v3](https://github.com/ericniebler/range-v3)
```Cmake
CPMAddPackage("gh:ericniebler/range-v3#0.11.0")
```
### [nlohmann/json](https://github.com/nlohmann/json)
```cmake
CPMAddPackage( CPMAddPackage(
NAME boost-cmake NAME nlohmann_json
GITHUB_REPOSITORY Orphis/boost-cmake VERSION 3.9.1
VERSION 1.67.0 OPTIONS
"JSON_BuildTests OFF"
) )
``` ```
### [cxxopts](https://github.com/jarro2783/cxxopts) ### [cxxopts](https://github.com/jarro2783/cxxopts)
```cmake ```cmake
# the install option has to be explicitly set to allow installation
CPMAddPackage( CPMAddPackage(
NAME cxxopts
GITHUB_REPOSITORY jarro2783/cxxopts GITHUB_REPOSITORY jarro2783/cxxopts
VERSION 2.2.0 VERSION 2.2.1
OPTIONS OPTIONS "CXXOPTS_BUILD_EXAMPLES NO" "CXXOPTS_BUILD_TESTS NO" "CXXOPTS_ENABLE_INSTALL YES"
"CXXOPTS_BUILD_EXAMPLES Off"
"CXXOPTS_BUILD_TESTS Off"
)
```
### [Yaml-cpp](https://github.com/jbeder/yaml-cpp)
```CMake
CPMAddPackage(
NAME yaml-cpp
GITHUB_REPOSITORY jbeder/yaml-cpp
# 0.6.2 uses deprecated CMake syntax
VERSION 0.6.3
# 0.6.3 is not released yet, so use a recent commit
GIT_TAG 012269756149ae99745b6dafefd415843d7420bb
OPTIONS
"YAML_CPP_BUILD_TESTS Off"
"YAML_CPP_BUILD_CONTRIB Off"
"YAML_CPP_BUILD_TOOLS Off"
) )
``` ```
@@ -297,48 +317,13 @@ CPMAddPackage(
CPMAddPackage( CPMAddPackage(
NAME benchmark NAME benchmark
GITHUB_REPOSITORY google/benchmark GITHUB_REPOSITORY google/benchmark
VERSION 1.4.1 VERSION 1.5.2
OPTIONS OPTIONS "BENCHMARK_ENABLE_TESTING Off"
"BENCHMARK_ENABLE_TESTING Off"
) )
if (benchmark_ADDED) if(benchmark_ADDED)
# compile with C++17 # enable c++11 to avoid compilation errors
set_target_properties(benchmark PROPERTIES CXX_STANDARD 17) set_target_properties(benchmark PROPERTIES CXX_STANDARD 11)
endif()
```
### [nlohmann/json](https://github.com/nlohmann/json)
```cmake
CPMAddPackage(
NAME nlohmann_json
VERSION 3.6.1
# the git repo is incredibly large, so we download the archived include directory
URL https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip
URL_HASH SHA256=69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf
)
if (nlohmann_json_ADDED)
add_library(nlohmann_json INTERFACE IMPORTED)
target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR})
endif()
```
### [Range-v3](https://github.com/ericniebler/range-v3)
```Cmake
CPMAddPackage(
NAME range-v3
URL https://github.com/ericniebler/range-v3/archive/0.5.0.zip
VERSION 0.5.0
# the range-v3 CMakeLists screws with configuration options
DOWNLOAD_ONLY True
)
if(range-v3_ADDED)
add_library(range-v3 INTERFACE IMPORTED)
target_include_directories(range-v3 INTERFACE "${range-v3_SOURCE_DIR}/include")
endif() endif()
``` ```

View File

@@ -132,12 +132,10 @@ if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)
endif() endif()
include(FetchContent) include(FetchContent)
include(CMakeParseArguments)
# Infer package name from git repository uri (path or url) # Try to infer package name from git repository uri (path or url)
function(cpm_package_name_from_git_uri URI RESULT) function(cpm_package_name_from_git_uri URI RESULT)
string(REGEX MATCH "([^/:]+)/?.git/?$" cpmGitUriMatch "${URI}") if("${URI}" MATCHES "([^/:]+)/?.git/?$")
if(DEFINED cpmGitUriMatch)
set(${RESULT} set(${RESULT}
${CMAKE_MATCH_1} ${CMAKE_MATCH_1}
PARENT_SCOPE PARENT_SCOPE
@@ -147,6 +145,52 @@ function(cpm_package_name_from_git_uri URI RESULT)
endif() endif()
endfunction() endfunction()
# Try to infer package name and version from a url
function(cpm_package_name_and_ver_from_url url outName outVer)
if(url MATCHES "[/\\?]([a-zA-Z0-9_\\.-]+)\\.(tar|tar\\.gz|tar\\.bz2|zip|ZIP)(\\?|/|$)")
# We matched an archive
set(filename "${CMAKE_MATCH_1}")
if(filename MATCHES "([a-zA-Z0-9_\\.-]+)[_-]v?(([0-9]+\\.)*[0-9]+[a-zA-Z0-9]*)")
# We matched <name>-<version> (ie foo-1.2.3)
set(${outName}
"${CMAKE_MATCH_1}"
PARENT_SCOPE
)
set(${outVer}
"${CMAKE_MATCH_2}"
PARENT_SCOPE
)
elseif(filename MATCHES "(([0-9]+\\.)+[0-9]+[a-zA-Z0-9]*)")
# We couldn't find a name, but we found a version
#
# In many cases (which we don't handle here) the url would look something like
# `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly
# distinguish the package name from the irrelevant bits. Moreover if we try to match the
# package name from the filename, we'd get bogus at best.
unset(${outName} PARENT_SCOPE)
set(${outVer}
"${CMAKE_MATCH_1}"
PARENT_SCOPE
)
else()
# Boldly assume that the file name is the package name.
#
# Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but
# such cases should be quite rare. No popular service does this... we think.
set(${outName}
"${filename}"
PARENT_SCOPE
)
unset(${outVer} PARENT_SCOPE)
endif()
else()
# No ideas yet what to do with non-archives
unset(${outName} PARENT_SCOPE)
unset(${outVer} PARENT_SCOPE)
endif()
endfunction()
# Initialize logging prefix # Initialize logging prefix
if(NOT CPM_INDENT) if(NOT CPM_INDENT)
set(CPM_INDENT set(CPM_INDENT
@@ -202,7 +246,7 @@ function(CPMFindPackage)
return() return()
endif() endif()
cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")
if(CPM_PACKAGE_ALREADY_ADDED) if(CPM_PACKAGE_ALREADY_ADDED)
cpm_export_variables(${CPM_ARGS_NAME}) cpm_export_variables(${CPM_ARGS_NAME})
return() return()
@@ -218,7 +262,7 @@ function(CPMFindPackage)
endfunction() endfunction()
# checks if a package has been added before # checks if a package has been added before
function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION CPM_ARGS_OPTIONS) function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION)
if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES) if("${CPM_ARGS_NAME}" IN_LIST CPM_PACKAGES)
CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION) CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION)
if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}") if("${CPM_PACKAGE_VERSION}" VERSION_LESS "${CPM_ARGS_VERSION}")
@@ -227,17 +271,6 @@ function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION CPM_A
"${CPM_INDENT} requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})." "${CPM_INDENT} requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION})."
) )
endif() endif()
if(CPM_ARGS_OPTIONS)
foreach(OPTION ${CPM_ARGS_OPTIONS})
cpm_parse_option(${OPTION})
if(NOT "${${OPTION_KEY}}" STREQUAL "${OPTION_VALUE}")
message(
WARNING
"${CPM_INDENT} ignoring package option for ${CPM_ARGS_NAME}: ${OPTION_KEY} = ${OPTION_VALUE} (${${OPTION_KEY}})"
)
endif()
endforeach()
endif()
cpm_get_fetch_properties(${CPM_ARGS_NAME}) cpm_get_fetch_properties(${CPM_ARGS_NAME})
set(${CPM_ARGS_NAME}_ADDED NO) set(${CPM_ARGS_NAME}_ADDED NO)
set(CPM_PACKAGE_ALREADY_ADDED set(CPM_PACKAGE_ALREADY_ADDED
@@ -253,8 +286,80 @@ function(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION CPM_A
endif() endif()
endfunction() endfunction()
# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of
# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted
# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3
function(cpm_parse_add_package_single_arg arg outArgs)
# Look for a scheme
if("${arg}" MATCHES "^([a-zA-Z]+):(.+)$")
string(TOLOWER "${CMAKE_MATCH_1}" scheme)
set(uri "${CMAKE_MATCH_2}")
# Check for CPM-specific schemes
if(scheme STREQUAL "gh")
set(out "GITHUB_REPOSITORY;${uri}")
set(packageType "git")
elseif(scheme STREQUAL "gl")
set(out "GITLAB_REPOSITORY;${uri}")
set(packageType "git")
# A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine
# type
elseif(arg MATCHES ".git/?(@|#|$)")
set(out "GIT_REPOSITORY;${arg}")
set(packageType "git")
else()
# Fall back to a URL
set(out "URL;${arg}")
set(packageType "archive")
# We could also check for SVN since FetchContent supports it, but SVN is so rare these days.
# We just won't bother with the additional complexity it will induce in this function. SVN is
# done by multi-arg
endif()
else()
if(arg MATCHES ".git/?(@|#|$)")
set(out "GIT_REPOSITORY;${arg}")
set(packageType "git")
else()
# Give up
message(FATAL_ERROR "CPM: Can't determine package type of '${arg}'")
endif()
endif()
# For all packages we interpret @... as version. Only replace the last occurence. Thus URIs
# containing '@' can be used
string(REGEX REPLACE "@([^@]+)$" ";VERSION;\\1" out "${out}")
# Parse the rest according to package type
if(packageType STREQUAL "git")
# For git repos we interpret #... as a tag or branch or commit hash
string(REGEX REPLACE "#([^#]+)$" ";GIT_TAG;\\1" out "${out}")
elseif(packageType STREQUAL "archive")
# For archives we interpret #... as a URL hash.
string(REGEX REPLACE "#([^#]+)$" ";URL_HASH;\\1" out "${out}")
# We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url
# should do this at a later point
else()
# We should never get here. This is an assertion and hitting it means there's a bug in the code
# above. A packageType was set, but not handled by this if-else.
message(FATAL_ERROR "CPM: Unsupported package type '${packageType}' of '${arg}'")
endif()
set(${outArgs}
${out}
PARENT_SCOPE
)
endfunction()
# Download and add a package from source # Download and add a package from source
function(CPMAddPackage) function(CPMAddPackage)
list(LENGTH ARGN argnLength)
if(argnLength EQUAL 1)
cpm_parse_add_package_single_arg("${ARGN}" ARGN)
# The shorthand syntax implies EXCLUDE_FROM_ALL
set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES")
endif()
set(oneValueArgs set(oneValueArgs
NAME NAME
@@ -271,9 +376,10 @@ function(CPMAddPackage)
NO_CACHE NO_CACHE
GIT_SHALLOW GIT_SHALLOW
EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL
SOURCE_SUBDIR
) )
set(multiValueArgs OPTIONS) set(multiValueArgs URL OPTIONS)
cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")
@@ -321,6 +427,24 @@ function(CPMAddPackage)
endif() endif()
endif() endif()
if(DEFINED CPM_ARGS_URL)
# If a name or version aren't provided, try to infer them from the URL
list(GET CPM_ARGS_URL 0 firstUrl)
cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl)
# If we fail to obtain name and version from the first URL, we could try other URLs if any.
# However multiple URLs are expected to be quite rare, so for now we won't bother.
# If the caller provided their own name and version, they trump the inferred ones.
if(NOT DEFINED CPM_ARGS_NAME)
set(CPM_ARGS_NAME ${nameFromUrl})
endif()
if(NOT DEFINED CPM_ARGS_VERSION)
set(CPM_ARGS_VERSION ${verFromUrl})
endif()
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL "${CPM_ARGS_URL}")
endif()
# Check for required arguments # Check for required arguments
if(NOT DEFINED CPM_ARGS_NAME) if(NOT DEFINED CPM_ARGS_NAME)
@@ -331,7 +455,7 @@ function(CPMAddPackage)
endif() endif()
# Check if package has been added before # Check if package has been added before
cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")
if(CPM_PACKAGE_ALREADY_ADDED) if(CPM_PACKAGE_ALREADY_ADDED)
cpm_export_variables(${CPM_ARGS_NAME}) cpm_export_variables(${CPM_ARGS_NAME})
return() return()
@@ -358,7 +482,7 @@ function(CPMAddPackage)
CPMAddPackage(${declaration}) CPMAddPackage(${declaration})
cpm_export_variables(${CPM_ARGS_NAME}) cpm_export_variables(${CPM_ARGS_NAME})
# checking again to ensure version and option compatibility # checking again to ensure version and option compatibility
cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}") cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}")
return() return()
endif() endif()
@@ -380,16 +504,6 @@ function(CPMAddPackage)
CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}") CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}")
if(CPM_ARGS_OPTIONS)
foreach(OPTION ${CPM_ARGS_OPTIONS})
cpm_parse_option(${OPTION})
set(${OPTION_KEY}
${OPTION_VALUE}
CACHE INTERNAL ""
)
endforeach()
endif()
if(DEFINED CPM_ARGS_GIT_TAG) if(DEFINED CPM_ARGS_GIT_TAG)
set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}") set(PACKAGE_INFO "${CPM_ARGS_GIT_TAG}")
elseif(DEFINED CPM_ARGS_SOURCE_DIR) elseif(DEFINED CPM_ARGS_SOURCE_DIR)
@@ -398,6 +512,13 @@ function(CPMAddPackage)
set(PACKAGE_INFO "${CPM_ARGS_VERSION}") set(PACKAGE_INFO "${CPM_ARGS_VERSION}")
endif() endif()
if(DEFINED FETCHCONTENT_BASE_DIR)
# respect user's FETCHCONTENT_BASE_DIR if set
set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR})
else()
set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps)
endif()
if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND) if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND)
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND}) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND})
elseif(DEFINED CPM_ARGS_SOURCE_DIR) elseif(DEFINED CPM_ARGS_SOURCE_DIR)
@@ -411,14 +532,14 @@ function(CPMAddPackage)
list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory}) list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory})
if(EXISTS ${download_directory}) if(EXISTS ${download_directory})
# avoid FetchContent modules to improve performance # avoid FetchContent modules to improve performance
set(${CPM_ARGS_NAME}_BINARY_DIR ${CMAKE_BINARY_DIR}/_deps/${lower_case_name}-build) set(${CPM_ARGS_NAME}_BINARY_DIR ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build)
set(${CPM_ARGS_NAME}_ADDED YES) set(${CPM_ARGS_NAME}_ADDED YES)
set(${CPM_ARGS_NAME}_SOURCE_DIR ${download_directory}) set(${CPM_ARGS_NAME}_SOURCE_DIR ${download_directory})
if(NOT CPM_ARGS_DOWNLOAD_ONLY AND EXISTS ${download_directory}/CMakeLists.txt) cpm_add_subdirectory(
cpm_add_subdirectory( "${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}"
${download_directory} ${${CPM_ARGS_NAME}_BINARY_DIR} "${CPM_ARGS_EXCLUDE_FROM_ALL}" "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" "${${CPM_ARGS_NAME}_BINARY_DIR}"
) "${CPM_ARGS_EXCLUDE_FROM_ALL}" "${CPM_ARGS_OPTIONS}"
endif() )
set(CPM_SKIP_FETCH TRUE) set(CPM_SKIP_FETCH TRUE)
set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}") set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}")
else() else()
@@ -432,7 +553,7 @@ function(CPMAddPackage)
endif() endif()
# remove timestamps so CMake will re-download the dependency # remove timestamps so CMake will re-download the dependency
file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/_deps/${lower_case_name}-subbuild) file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild)
set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}") set(PACKAGE_INFO "${PACKAGE_INFO} to ${download_directory}")
endif() endif()
endif() endif()
@@ -457,7 +578,12 @@ function(CPMAddPackage)
cpm_declare_fetch( cpm_declare_fetch(
"${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}" "${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}"
) )
cpm_fetch_package("${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}" "${CPM_ARGS_EXCLUDE_FROM_ALL}") cpm_fetch_package("${CPM_ARGS_NAME}")
cpm_add_subdirectory(
"${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}"
"${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" "${${CPM_ARGS_NAME}_BINARY_DIR}"
"${CPM_ARGS_EXCLUDE_FROM_ALL}" "${CPM_ARGS_OPTIONS}"
)
cpm_get_fetch_properties("${CPM_ARGS_NAME}") cpm_get_fetch_properties("${CPM_ARGS_NAME}")
endif() endif()
@@ -580,36 +706,62 @@ function(cpm_get_fetch_properties PACKAGE)
) )
endfunction() endfunction()
function(cpm_add_subdirectory SOURCE_DIR BINARY_DIR EXCLUDE) # adds a package as a subdirectory if viable, according to provided options
if(EXCLUDE) function(
set(addSubdirectoryExtraArgs EXCLUDE_FROM_ALL) cpm_add_subdirectory
else() PACKAGE
set(addSubdirectoryExtraArgs "") DOWNLOAD_ONLY
SOURCE_DIR
BINARY_DIR
EXCLUDE
OPTIONS
)
if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt)
if(EXCLUDE)
set(addSubdirectoryExtraArgs EXCLUDE_FROM_ALL)
else()
set(addSubdirectoryExtraArgs "")
endif()
if(OPTIONS)
# the policy allows us to change options without caching
cmake_policy(SET CMP0077 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
foreach(OPTION ${OPTIONS})
cpm_parse_option(${OPTION})
set(${OPTION_KEY} ${OPTION_VALUE})
endforeach()
endif()
set(CPM_OLD_INDENT "${CPM_INDENT}")
set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:")
add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs})
set(CPM_INDENT "${CPM_OLD_INDENT}")
endif() endif()
add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs})
endfunction() endfunction()
# downloads a previously declared package via FetchContent # downloads a previously declared package via FetchContent and exports the variables
function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY EXCLUDE) # `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope
function(cpm_fetch_package PACKAGE)
if(${CPM_DRY_RUN}) if(${CPM_DRY_RUN})
message(STATUS "${CPM_INDENT} package ${PACKAGE} not fetched (dry run)") message(STATUS "${CPM_INDENT} package ${PACKAGE} not fetched (dry run)")
return() return()
endif() endif()
FetchContent_GetProperties(${PACKAGE}) FetchContent_GetProperties(${PACKAGE})
string(TOLOWER "${PACKAGE}" lower_case_name)
if(NOT ${lower_case_name}_POPULATED) if(NOT ${lower_case_name}_POPULATED)
FetchContent_Populate(${PACKAGE}) FetchContent_Populate(${PACKAGE})
if(NOT DOWNLOAD_ONLY AND EXISTS ${${lower_case_name}_SOURCE_DIR}/CMakeLists.txt)
set(CPM_OLD_INDENT "${CPM_INDENT}")
set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:")
cpm_add_subdirectory(
${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR} "${EXCLUDE}"
)
set(CPM_INDENT "${CPM_OLD_INDENT}")
endif()
endif() endif()
string(TOLOWER "${PACKAGE}" lower_case_name)
set(${PACKAGE}_SOURCE_DIR
${${lower_case_name}_SOURCE_DIR}
PARENT_SCOPE
)
set(${PACKAGE}_BINARY_DIR
${${lower_case_name}_BINARY_DIR}
PARENT_SCOPE
)
endfunction() endfunction()
# splits a package option # splits a package option

View File

@@ -3,7 +3,7 @@ function(ASSERT_EQUAL)
message(FATAL_ERROR "assertion failed: invalid argument count: ${ARGC}") message(FATAL_ERROR "assertion failed: invalid argument count: ${ARGC}")
endif() endif()
if(NOT ${ARGV0} STREQUAL ${ARGV1}) if(NOT "${ARGV0}" STREQUAL "${ARGV1}")
message(FATAL_ERROR "assertion failed: '${ARGV0}' != '${ARGV1}'") message(FATAL_ERROR "assertion failed: '${ARGV0}' != '${ARGV1}'")
else() else()
message(STATUS "test passed: '${ARGV0}' == '${ARGV1}'") message(STATUS "test passed: '${ARGV0}' == '${ARGV1}'")
@@ -15,7 +15,7 @@ function(ASSERT_NOT_EQUAL)
message(FATAL_ERROR "assertion failed: invalid argument count: ${ARGC}") message(FATAL_ERROR "assertion failed: invalid argument count: ${ARGC}")
endif() endif()
if(${ARGV0} STREQUAL ${ARGV1}) if("${ARGV0}" STREQUAL "${ARGV1}")
message(FATAL_ERROR "assertion failed: '${ARGV0}' == '${ARGV1}'") message(FATAL_ERROR "assertion failed: '${ARGV0}' == '${ARGV1}'")
else() else()
message(STATUS "test passed: '${ARGV0}' != '${ARGV1}'") message(STATUS "test passed: '${ARGV0}' != '${ARGV1}'")
@@ -38,7 +38,7 @@ endfunction()
function(ASSERT_NOT_DEFINED KEY) function(ASSERT_NOT_DEFINED KEY)
if(DEFINED ${KEY}) if(DEFINED ${KEY})
message(FATAL_ERROR "assertion failed: '${KEY}' is defiend") message(FATAL_ERROR "assertion failed: '${KEY}' is defiend (${${KEY}})")
else() else()
message(STATUS "test passed: '${KEY}' is not defined") message(STATUS "test passed: '${KEY}' is not defined")
endif() endif()
@@ -48,7 +48,15 @@ function(ASSERT_TRUTHY KEY)
if(${${KEY}}) if(${${KEY}})
message(STATUS "test passed: '${KEY}' is set truthy") message(STATUS "test passed: '${KEY}' is set truthy")
else() else()
message(FATAL_ERROR "assertion failed: value of '${KEY}' is not true (${${KEY}})") message(FATAL_ERROR "assertion failed: value of '${KEY}' is not truthy (${${KEY}})")
endif()
endfunction()
function(ASSERT_FALSY KEY)
if(${${KEY}})
message(FATAL_ERROR "assertion failed: value of '${KEY}' is not falsy (${${KEY}})")
else()
message(STATUS "test passed: '${KEY}' is set falsy")
endif() endif()
endfunction() endfunction()

View File

@@ -8,12 +8,7 @@ include(../../cmake/CPM.cmake)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
CPMAddPackage( CPMAddPackage("gh:chriskohlhoff/asio#asio-1-18-1@1.18.1")
NAME asio
VERSION 1.18.1
GITHUB_REPOSITORY chriskohlhoff/asio
GIT_TAG asio-1-18-1 # asio uses non-standard version tag, we must specify GIT_TAG
)
# ASIO doesn't use CMake, we have to configure it manually. Extra notes for using on Windows: # ASIO doesn't use CMake, we have to configure it manually. Extra notes for using on Windows:
# #

View File

@@ -6,11 +6,7 @@ project(CPMExampleBenchmark)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:cpm-cmake/testpack-fibonacci@2.0")
NAME fibonacci
GITLAB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)
CPMAddPackage( CPMAddPackage(
NAME benchmark NAME benchmark
@@ -20,7 +16,7 @@ CPMAddPackage(
) )
if(benchmark_ADDED) if(benchmark_ADDED)
# Don't use C++14 because it doesn't work in some configurations. # enable c++11 to avoid compilation errors
set_target_properties(benchmark PROPERTIES CXX_STANDARD 11) set_target_properties(benchmark PROPERTIES CXX_STANDARD 11)
endif() endif()

View File

@@ -15,6 +15,7 @@ CPMFindPackage(
NAME Boost NAME Boost
GITHUB_REPOSITORY Orphis/boost-cmake GITHUB_REPOSITORY Orphis/boost-cmake
VERSION 1.67.0 VERSION 1.67.0
# setting FIND_PACKAGE_ARGUMENTS allow usage with `CPM_USE_LOCAL_PACKAGES`
FIND_PACKAGE_ARGUMENTS "COMPONENTS system" FIND_PACKAGE_ARGUMENTS "COMPONENTS system"
) )

View File

@@ -6,17 +6,8 @@ project(CPMExampleCatch2)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:cpm-cmake/testpack-fibonacci@2.0")
NAME fibonacci CPMAddPackage("gh:catchorg/Catch2@2.13.4")
GITHUB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)
CPMAddPackage(
NAME Catch2
GITHUB_REPOSITORY catchorg/Catch2
VERSION 2.13.4
)
# ---- Create binary ---- # ---- Create binary ----

View File

@@ -6,12 +6,7 @@ project(CPMExampleCXXOpts)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:jarro2783/cxxopts@2.2.0")
NAME cxxopts
GITHUB_REPOSITORY jarro2783/cxxopts
VERSION 2.2.0
OPTIONS "CXXOPTS_BUILD_EXAMPLES Off" "CXXOPTS_BUILD_TESTS Off"
)
# ---- Create binary ---- # ---- Create binary ----

View File

@@ -6,17 +6,8 @@ project(CPMExampleDoctest)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:cpm-cmake/testpack-fibonacci@2.0")
NAME fibonacci CPMAddPackage("gh:onqtam/doctest#2.4.5")
GITLAB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)
CPMAddPackage(
NAME doctest
GITHUB_REPOSITORY onqtam/doctest
GIT_TAG 2.4.5
)
# ---- Create binary ---- # ---- Create binary ----

View File

@@ -6,11 +6,7 @@ project(CPMJSONExample)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:fmtlib/fmt#7.1.3")
NAME fmt
GIT_TAG 7.1.3
GITHUB_REPOSITORY fmtlib/fmt
)
# ---- Executable ---- # ---- Executable ----

View File

@@ -6,11 +6,7 @@ project(CPMExampleGtest)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:cpm-cmake/testpack-fibonacci@2.0")
NAME fibonacci
GITLAB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)
CPMAddPackage( CPMAddPackage(
NAME googletest NAME googletest

View File

@@ -5,22 +5,10 @@ project(CPMJSONExample)
# ---- Dependencies ---- # ---- Dependencies ----
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage("gh:nlohmann/json@3.9.1")
CPMAddPackage(
NAME nlohmann_json
VERSION 3.9.1
# not using the repo as it takes forever to clone
URL https://github.com/nlohmann/json/releases/download/v3.9.1/include.zip
URL_HASH SHA256=6bea5877b1541d353bd77bdfbdb2696333ae5ed8f9e8cc22df657192218cad91
)
if(nlohmann_json_ADDED)
add_library(nlohmann_json INTERFACE)
target_include_directories(nlohmann_json SYSTEM INTERFACE ${nlohmann_json_SOURCE_DIR}/include)
endif()
# ---- Executable ---- # ---- Executable ----
add_executable(CPMJSONExample main.cpp) add_executable(CPMJSONExample main.cpp)
target_compile_features(CPMJSONExample PRIVATE cxx_std_17) target_compile_features(CPMJSONExample PRIVATE cxx_std_17)
target_link_libraries(CPMJSONExample nlohmann_json) target_link_libraries(CPMJSONExample nlohmann_json::nlohmann_json)

View File

@@ -6,11 +6,7 @@ project(CPMlinenoiseExample)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:antirez/linenoise#1.0")
NAME linenoise
GIT_TAG 1.0
GITHUB_REPOSITORY antirez/linenoise
)
if(linenoise_ADDED) if(linenoise_ADDED)
add_library(linenoise ${linenoise_SOURCE_DIR}/linenoise.c) add_library(linenoise ${linenoise_SOURCE_DIR}/linenoise.c)

View File

@@ -6,18 +6,7 @@ project(CPMRangev3Example)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:ericniebler/range-v3#0.11.0")
NAME range-v3
URL https://github.com/ericniebler/range-v3/archive/0.11.0.zip
VERSION 0.11.0
# the range-v3 CMakeLists screws with configuration options
DOWNLOAD_ONLY True
)
if(range-v3_ADDED)
add_library(range-v3 INTERFACE IMPORTED)
target_include_directories(range-v3 SYSTEM INTERFACE "${range-v3_SOURCE_DIR}/include")
endif()
# ---- Executable ---- # ---- Executable ----

View File

@@ -32,7 +32,7 @@ auto is_six = [](int i) { return i == 6; };
int main() { int main() {
std::vector<int> v{6, 2, 3, 4, 5, 6}; std::vector<int> v{6, 2, 3, 4, 5, 6};
cout << std::boolalpha; cout << std::boolalpha;
cout << "vector: " << ranges::view::all(v) << '\n'; cout << "vector: " << ranges::views::all(v) << '\n';
cout << "vector any_of is_six: " << ranges::any_of(v, is_six) << '\n'; cout << "vector any_of is_six: " << ranges::any_of(v, is_six) << '\n';
cout << "vector all_of is_six: " << ranges::all_of(v, is_six) << '\n'; cout << "vector all_of is_six: " << ranges::all_of(v, is_six) << '\n';

View File

@@ -6,11 +6,7 @@ project(CPMSpdlogExample)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:gabime/spdlog@1.8.2")
NAME spdlog
GITHUB_REPOSITORY gabime/spdlog
VERSION 1.8.2
)
# ---- Executable ---- # ---- Executable ----

View File

@@ -6,13 +6,7 @@ project(CPMYamlExample)
include(../../cmake/CPM.cmake) include(../../cmake/CPM.cmake)
CPMAddPackage( CPMAddPackage("gh:jbeder/yaml-cpp#yaml-cpp-0.6.3@0.6.3")
NAME yaml-cpp
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
VERSION 0.6.3
GIT_TAG yaml-cpp-0.6.3
OPTIONS "YAML_CPP_BUILD_TESTS Off" "YAML_CPP_BUILD_CONTRIB Off" "YAML_CPP_BUILD_TOOLS Off"
)
# ---- Executable ---- # ---- Executable ----

View File

@@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
project(CPMTest)
# ---- Options ----
option(ENABLE_TEST_COVERAGE "Enable test coverage" OFF)
# ---- Dependencies ----
include(@CPM_PATH@/CPM.cmake)
CPMAddPackage(
NAME Dependency
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/dependency
OPTIONS "DEFINE_ALTERNATIVE_FUNCTION YES"
EXCLUDE_FROM_ALL YES
)
# ---- Dependencies ----
alternative_dependency_function()
# ---- Check parameters ----
include(@CPM_PATH@/testing.cmake)
message("DEFINE_ALTERNATIVE_FUNCTION: ${DEFINE_ALTERNATIVE_FUNCTION}")
# this option is overridden by CPM.cmake
ASSERT_NOT_DEFINED(DEFINE_ALTERNATIVE_FUNCTION)
# this option is leaked by the dependency
ASSERT_EQUAL(${LEAKED_OPTION} "OFF")

View File

@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
project(CPMTest)
# ---- Dependencies ----
include(@CPM_PATH@/CPM.cmake)
CPMAddPackage(
NAME Dependency
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/dependency
SOURCE_SUBDIR inner
)
# ---- Call inner dependency method to validate correct addition of subdirectory ----
inner_dependency_function()

View File

@@ -1,3 +1,14 @@
function(dependency_function) cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
message("called external method")
endfunction() option(DEFINE_ALTERNATIVE_FUNCTION "define the alternative function" OFF)
option(LEAKED_OPTION "this option will be leaked to the outer scope" OFF)
if(NOT DEFINE_ALTERNATIVE_FUNCTION)
function(dependency_function)
message("called external method")
endfunction()
else()
function(alternative_dependency_function)
message("called alternative external method")
endfunction()
endif()

View File

@@ -0,0 +1,3 @@
function(inner_dependency_function)
message("called inner method")
endfunction()

19
test/unit/options.cmake Normal file
View File

@@ -0,0 +1,19 @@
include(CMakePackageConfigHelpers)
include(${CPM_PATH}/testing.cmake)
set(TEST_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/source_dir)
set(TEST_DEPENDENCY_NAME Dependency)
configure_package_config_file(
"${CMAKE_CURRENT_LIST_DIR}/local_dependency/OptionsCMakeLists.txt.in"
"${CMAKE_CURRENT_LIST_DIR}/local_dependency/CMakeLists.txt"
INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/junk
)
execute_process(
COMMAND ${CMAKE_COMMAND} "-H${CMAKE_CURRENT_LIST_DIR}/local_dependency" "-B${TEST_BUILD_DIR}"
RESULT_VARIABLE ret
)
assert_equal(${ret} "0")

View File

@@ -0,0 +1,60 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
include(${CPM_PATH}/CPM.cmake)
include(${CPM_PATH}/testing.cmake)
cpm_package_name_and_ver_from_url("https://example.com/coolpack-1.2.3.zip" name ver)
assert_equal("coolpack" ${name})
assert_equal("1.2.3" ${ver})
cpm_package_name_and_ver_from_url("https://example.com/cool-pack-v1.3.tar.gz" name ver)
assert_equal("cool-pack" ${name})
assert_equal("1.3" ${ver})
cpm_package_name_and_ver_from_url(
"https://subd.zip.com/download.php?Cool.Pack-v1.2.3rc0.tar" name ver
)
assert_equal("Cool.Pack" ${name})
assert_equal("1.2.3rc0" ${ver})
cpm_package_name_and_ver_from_url(
"http://evil-1.2.tar.gz.com/Plan9_1.2.3a.tar.bz2?download" name ver
)
assert_equal("Plan9" ${name})
assert_equal("1.2.3a" ${ver})
cpm_package_name_and_ver_from_url(
"http://evil-1.2.tar.gz.com/Plan_9-1.2.3a.tar.bz2?download" name ver
)
assert_equal("Plan_9" ${name})
assert_equal("1.2.3a" ${ver})
cpm_package_name_and_ver_from_url(
"http://evil-1.2.tar.gz.com/Plan-9_1.2.3a.tar.bz2?download" name ver
)
assert_equal("Plan-9" ${name})
assert_equal("1.2.3a" ${ver})
cpm_package_name_and_ver_from_url("https://sf.com/distrib/SFLib-0.999.4.tar.gz/download" name ver)
assert_equal("SFLib" ${name})
assert_equal("0.999.4" ${ver})
cpm_package_name_and_ver_from_url("https://example.com/coolpack/v5.6.5rc44.zip" name ver)
assert_not_defined(name)
assert_equal("5.6.5rc44" ${ver})
cpm_package_name_and_ver_from_url("evil-1.3.zip.com/coolpack/release999.000beta.ZIP" name ver)
assert_not_defined(name)
assert_equal("999.000beta" ${ver})
cpm_package_name_and_ver_from_url("https://example.com/Foo55.tar.gz" name ver)
assert_equal("Foo55" ${name})
assert_not_defined(ver)
cpm_package_name_and_ver_from_url("https://example.com/foo" name ver)
assert_not_defined(name)
assert_not_defined(ver)
cpm_package_name_and_ver_from_url("example.zip.com/foo" name ver)
assert_not_defined(name)
assert_not_defined(ver)

View File

@@ -0,0 +1,65 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
include(${CPM_PATH}/CPM.cmake)
include(${CPM_PATH}/testing.cmake)
cpm_parse_add_package_single_arg("gh:cpm-cmake/CPM.cmake" args)
assert_equal("GITHUB_REPOSITORY;cpm-cmake/CPM.cmake" "${args}")
cpm_parse_add_package_single_arg("gh:cpm-cmake/CPM.cmake@1.2.3" args)
assert_equal("GITHUB_REPOSITORY;cpm-cmake/CPM.cmake;VERSION;1.2.3" "${args}")
cpm_parse_add_package_single_arg("gh:cpm-cmake/CPM.cmake#master" args)
assert_equal("GITHUB_REPOSITORY;cpm-cmake/CPM.cmake;GIT_TAG;master" "${args}")
cpm_parse_add_package_single_arg("gh:cpm-cmake/CPM.cmake@0.20.3#asdf" args)
assert_equal("GITHUB_REPOSITORY;cpm-cmake/CPM.cmake;VERSION;0.20.3;GIT_TAG;asdf" "${args}")
cpm_parse_add_package_single_arg("gh:a/b#c@d" args)
assert_equal("GITHUB_REPOSITORY;a/b;GIT_TAG;c;VERSION;d" "${args}")
cpm_parse_add_package_single_arg("gh:foo#c@d" args)
assert_equal("GITHUB_REPOSITORY;foo;GIT_TAG;c;VERSION;d" "${args}")
cpm_parse_add_package_single_arg("gh:Foo@5" args)
assert_equal("GITHUB_REPOSITORY;Foo;VERSION;5" "${args}")
cpm_parse_add_package_single_arg("gl:foo/bar" args)
assert_equal("GITLAB_REPOSITORY;foo/bar" "${args}")
cpm_parse_add_package_single_arg("gl:foo/Bar" args)
assert_equal("GITLAB_REPOSITORY;foo/Bar" "${args}")
cpm_parse_add_package_single_arg("https://github.com/cpm-cmake/CPM.cmake.git@0.30.5" args)
assert_equal("GIT_REPOSITORY;https://github.com/cpm-cmake/CPM.cmake.git;VERSION;0.30.5" "${args}")
cpm_parse_add_package_single_arg("git@host.xz:user/pkg.git@0.1.2" args)
assert_equal("GIT_REPOSITORY;git@host.xz:user/pkg.git;VERSION;0.1.2" "${args}")
cpm_parse_add_package_single_arg("git@host.xz:user/pkg.git@0.1.2#rc" args)
assert_equal("GIT_REPOSITORY;git@host.xz:user/pkg.git;VERSION;0.1.2;GIT_TAG;rc" "${args}")
cpm_parse_add_package_single_arg(
"ssh://user@host.xz:123/path/to/pkg.git#fragment@1.2.3#branch" args
)
assert_equal(
"GIT_REPOSITORY;ssh://user@host.xz:123/path/to/pkg.git#fragment;VERSION;1.2.3;GIT_TAG;branch"
"${args}"
)
cpm_parse_add_package_single_arg("https://example.org/foo.tar.gz" args)
assert_equal("URL;https://example.org/foo.tar.gz" "${args}")
cpm_parse_add_package_single_arg("https://example.org/foo.tar.gz#baadf00d@1.2.0" args)
assert_equal("URL;https://example.org/foo.tar.gz;URL_HASH;baadf00d;VERSION;1.2.0" "${args}")
cpm_parse_add_package_single_arg("https://example.org/foo.tar.gz#MD5=baadf00d" args)
assert_equal("URL;https://example.org/foo.tar.gz;URL_HASH;MD5=baadf00d" "${args}")
cpm_parse_add_package_single_arg("https://example.org/Foo.zip#SHA3_512=1337" args)
assert_equal("URL;https://example.org/Foo.zip;URL_HASH;SHA3_512=1337" "${args}")
cpm_parse_add_package_single_arg("ftp://user:pass@server/pathname.zip#fragment#0ddb411@0" args)
assert_equal(
"URL;ftp://user:pass@server/pathname.zip#fragment;URL_HASH;0ddb411;VERSION;0" "${args}"
)

View File

@@ -12,7 +12,7 @@ include(@CPM_PATH@/CPM.cmake)
CPMAddPackage( CPMAddPackage(
NAME fibonacci NAME fibonacci
GIT_REPOSITORY https://github.com/TheLartians/Fibonacci.git GIT_REPOSITORY https://github.com/cpm-cmake/testpack-fibonacci.git
VERSION @FIBONACCI_VERSION@ VERSION @FIBONACCI_VERSION@
@FIBONACCI_PACKAGE_ARGS@ @FIBONACCI_PACKAGE_ARGS@
) )

17
test/unit/subdir.cmake Normal file
View File

@@ -0,0 +1,17 @@
include(CMakePackageConfigHelpers)
include(${CPM_PATH}/testing.cmake)
set(TEST_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/source_dir)
configure_package_config_file(
"${CMAKE_CURRENT_LIST_DIR}/local_dependency/SubdirCMakeLists.txt.in"
"${CMAKE_CURRENT_LIST_DIR}/local_dependency/CMakeLists.txt"
INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/junk
)
execute_process(
COMMAND ${CMAKE_COMMAND} "-H${CMAKE_CURRENT_LIST_DIR}/local_dependency" "-B${TEST_BUILD_DIR}"
RESULT_VARIABLE ret
)
assert_equal(${ret} "0")