From d7614381ab270d6c43be65eebd195372fcdf9903 Mon Sep 17 00:00:00 2001 From: Simon Gene Gottlieb Date: Sat, 3 May 2025 19:12:08 +0200 Subject: [PATCH] feature: allow URI to use shorthand syntax with additional options (#617) * feature: add URI to use shorthand syntax with additional options This allows to combine the shorthand syntax with URI and additional arguments: ``` CPMAddPackage(URI "gh:nlohmann/json@3.9.1" OPTIONS "JSON_BUildTests OFF") ``` This is much shorter than the longer syntax way of writing: ``` CPMAddPackage( NAME nlohmann_json VERSION 3.9.1 GITHUB_REPOSITORY nlohmann/json OPTIONS "JSON_BuildTests OFF" ) ``` * fix: use shorthand syntax in examples * test: add test for shorthand syntax with options * doc: extend README mentioning shorthand syntax with options * feat: URI keyword also sets EXCLUDE_FROM AND SYSTEM * doc: more explicit about the behavior of URI * doc: adjust README accordingly to PR-Review * test: fix inline documentation of test_simple * move URI comment * added new test for shorthand syntax * reset simple test * add that URI must be the first argument --------- Co-authored-by: Lars Melchior --- README.md | 29 +++++--- cmake/CPM.cmake | 26 ++++--- test/integration/test_shorthand_syntax.rb | 86 +++++++++++++++++++++++ 3 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 test/integration/test_shorthand_syntax.rb diff --git a/README.md b/README.md index 18e8510..13e31ed 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ If an additional optional parameter `SYSTEM` is set to a truthy value, the SYSTE See the [add_subdirectory ](https://cmake.org/cmake/help/latest/command/add_subdirectory.html?highlight=add_subdirectory) and [SYSTEM](https://cmake.org/cmake/help/latest/prop_tgt/SYSTEM.html#prop_tgt:SYSTEM) target property for details. -A single-argument compact syntax is also supported: +A shorthand syntax is also supported: ```cmake # A git package from a given uri with a version @@ -112,6 +112,19 @@ CPMAddPackage("https://example.com/my-package-1.2.3.zip#MD5=68e20f674a48be38d60e CPMAddPackage("https://example.com/my-package.zip@1.2.3") ``` +Additionally, if needed, extra arguments can be provided while using single argument syntax by using the shorthand syntax with the `URI` specifier. + +```cmake +CPMAddPackage( + URI "gh:nlohmann/json@3.9.1" + OPTIONS "JSON_BuildTests OFF" +) +``` + +The `URI` argument must be the first argument to `CPMAddPackage`. +`URI` automatically sets `EXCLUDE_FROM_ALL YES` and `SYSTEM YES`. +If this is not desired, `EXCLUDE_FROM_ALL NO` and `SYSTEM NO` can be set afterwards. + After calling `CPMAddPackage`, the following variables are defined in the local scope, where `` is the name of the dependency. - `_SOURCE_DIR` is the path to the source of the dependency. @@ -412,11 +425,8 @@ CPMAddPackage("gh:jbeder/yaml-cpp#yaml-cpp-0.6.3@0.6.3") ```cmake CPMAddPackage( - NAME nlohmann_json - VERSION 3.9.1 - GITHUB_REPOSITORY nlohmann/json - OPTIONS - "JSON_BuildTests OFF" + URI "gh:nlohmann/json@3.9.1" + OPTIONS "JSON_BuildTests OFF" ) ``` @@ -446,8 +456,7 @@ For a working example of using CPM to download and configure the Boost C++ Libra ```cmake # the install option has to be explicitly set to allow installation CPMAddPackage( - GITHUB_REPOSITORY jarro2783/cxxopts - VERSION 2.2.1 + URI "gh:jarro2783/cxxopts@2.2.1" OPTIONS "CXXOPTS_BUILD_EXAMPLES NO" "CXXOPTS_BUILD_TESTS NO" "CXXOPTS_ENABLE_INSTALL YES" ) ``` @@ -456,9 +465,7 @@ CPMAddPackage( ```cmake CPMAddPackage( - NAME benchmark - GITHUB_REPOSITORY google/benchmark - VERSION 1.5.2 + URI "gh:google/benchmark@1.5.2" OPTIONS "BENCHMARK_ENABLE_TESTING Off" ) diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake index addc20f..bee6131 100644 --- a/cmake/CPM.cmake +++ b/cmake/CPM.cmake @@ -594,14 +594,6 @@ endfunction() function(CPMAddPackage) cpm_set_policies() - list(LENGTH ARGN argnLength) - if(argnLength EQUAL 1) - cpm_parse_add_package_single_arg("${ARGN}" ARGN) - - # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM - set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;") - endif() - set(oneValueArgs NAME FORCE @@ -624,10 +616,26 @@ function(CPMAddPackage) set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES) + list(LENGTH ARGN argnLength) + + # Parse single shorthand argument + if(argnLength EQUAL 1) + cpm_parse_add_package_single_arg("${ARGN}" ARGN) + + # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM + set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;") + + # Parse URI shorthand argument + elseif(argnLength GREATER 1 AND "${ARGV0}" STREQUAL "URI") + list(REMOVE_AT ARGN 0 1) # remove "URI gh:<...>@version#tag" + cpm_parse_add_package_single_arg("${ARGV1}" ARGV0) + + set(ARGN "${ARGV0};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;${ARGN}") + endif() + cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}") # Set default values for arguments - if(NOT DEFINED CPM_ARGS_VERSION) if(DEFINED CPM_ARGS_GIT_TAG) cpm_get_version_from_git_tag("${CPM_ARGS_GIT_TAG}" CPM_ARGS_VERSION) diff --git a/test/integration/test_shorthand_syntax.rb b/test/integration/test_shorthand_syntax.rb new file mode 100644 index 0000000..c41bbd6 --- /dev/null +++ b/test/integration/test_shorthand_syntax.rb @@ -0,0 +1,86 @@ +require_relative './lib' + +class TestShorthandSyntax < IntegrationTest + + def get_project_binaries prj + exe_dir = File.join(prj.bin_dir, 'bin') + assert File.directory? exe_dir + return Dir[exe_dir + '/**/*'].filter { + # on multi-configuration generators (like Visual Studio) the executables will be in bin/ + # also filter-out other artifacts like .pdb or .dsym + !File.directory?(_1) && File.stat(_1).executable? + }.map { + # remove .exe extension if any (there will be one on Windows) + File.basename(_1, '.exe') + }.sort + end + + def test_create_with_commit_sha + prj = make_project from_template: 'using-adder' + prj.create_lists_from_default_template package: + 'CPMAddPackage("gh:cpm-cmake/testpack-adder#cad1cd4b4cdf957c5b59e30bc9a1dd200dbfc716")' + assert_success prj.configure + + cache = prj.read_cache + assert_equal 1, cache.packages.size + assert_equal '0', cache.packages['testpack-adder'].ver + + assert_success prj.build + exes = get_project_binaries prj + # No adder projects were built as EXCLUDE_FROM_ALL is implicitly set + assert_equal ['using-adder'], exes + end + + def test_create_with_version + prj = make_project from_template: 'using-adder' + prj.create_lists_from_default_template package: + 'CPMAddPackage("gh:cpm-cmake/testpack-adder@1.0.0")' + assert_success prj.configure + + cache = prj.read_cache + assert_equal 1, cache.packages.size + assert_equal '1.0.0', cache.packages['testpack-adder'].ver + + assert_success prj.build + exes = get_project_binaries prj + assert_equal ['using-adder'], exes + end + + def test_create_with_all + prj = make_project from_template: 'using-adder' + prj.create_lists_from_default_template package: + 'CPMAddPackage( + URI "gh:cpm-cmake/testpack-adder@1.0.0" + EXCLUDE_FROM_ALL false + )' + assert_success prj.configure + + cache = prj.read_cache + assert_equal cache.packages.size, 1 + assert_equal cache.packages['testpack-adder'].ver, '1.0.0' + + assert_success prj.build + exes = get_project_binaries prj + assert_equal exes, ['simple', 'test-adding', 'using-adder'] + end + + def test_create_with_tests_but_without_examples + prj = make_project from_template: 'using-adder' + prj.create_lists_from_default_template package: + 'CPMAddPackage( + URI "gh:cpm-cmake/testpack-adder@1.0.0" + OPTIONS "ADDER_BUILD_EXAMPLES OFF" "ADDER_BUILD_TESTS TRUE" + EXCLUDE_FROM_ALL false + )' + assert_success prj.configure + + cache = prj.read_cache + assert_equal cache.packages.size, 1 + assert_equal cache.packages['testpack-adder'].ver, '1.0.0' + + assert_success prj.build + exes = get_project_binaries prj + assert_equal exes, ['test-adding', 'using-adder'] + end + +end