After limiting `find_package()`/`find_dependency()` calls to curl local
Find modules via the `MODULES` keyword, it became possible to detect
dependencies via CMake Configs from within those local Find modules, by
calling `find_package()` again with the `CONFIG` keyword. This patch
implements this. Then maps detection results to the result variables and
curl-specific imported targets the rest of the build expects.
Also honor recently introduced `*_USE_STATIC_LIBS` (experimental) flags
to map to the static target when requested.
This adds CMake Configs as an alternative to the existing `pkg-config`
and `find_path()`/`find_library()` auto-detection methods.
Enabled by default for MSVC, outside vcpkg and when not cross-building.
To enable for other cases, or override the default, you can use
`-DCURL_USE_CMAKECONFIG=ON` or `OFF`.
When enabled, Config detection happens after `pkg-config` and before
`find_path()`/`find_library()`. Using CMake's built-in options, you may
also manually point to the absolute directory holding Config files:
`Libssh2_DIR`, `MbedTLS_DIR`, `NGHTTP2_DIR`, `NGHTTP3_DIR`,
`NGTCP2_DIR` v1.19.0+ (with non-fork OpenSSL only), `Zstd_DIR` v1.4.5+
E.g. `-DMbedTLS_DIR=/path/to/mbedtls/lib/cmake/MbedTLS`
These dependencies typically need to be built with CMake to support
this.
Tagged as experimental.
Refs:
#20013#19156#19117https://github.com/curl/curl/pull/20784#issuecomment-3984318492
Depends-on: fad1ebaecc#20840
Follow-up to 91e06fde1b#20784
Follow-up to 26c39d8df1#20015Closes#20814
Require CMake 3.18 (2020-07-15) or newer, up from 3.7 (2016-11-11)
prior to this patch.
This requirement also applies to the distributed `curl-config.cmake`.
To allow dropping compatibility code maintained for old versions, and to
use features which were unpractical in separate code paths. Also to make
testing, documentation and development easier, CI builds faster due to
CMake performance improvements over time. (e.g. integration tests on
macOS run 8x faster (10 minutes is now under 1.5m) in CI, 2.5x faster on
Windows.)
CMake offers pre-built binaries for major platforms. They work without
an install step, just by unpacking and pointing the cmake command to
them. Making upgrades easy in many cases:
https://cmake.org/download/https://cmake.org/files/https://github.com/Kitware/CMake/releases
CMake 3.18 brings these feature as generally available when building or
consuming curl/libcurl:
LTO support, improved performance, `pkg-config` and interface target
support, `OBJECT` target (for faster libcurl builds), modern invocation
with `-S`/`-B` options, better support for custom linker options,
FetchContent, `GnuTLS::GnuTLS` target, `--verbose` and `--install`
options, `CMAKE_GENERATOR` env, last but not least unity mode and Ninja
generator.
For maximum build speed, use:
`-DCMAKE_UNITY_BUILD=ON -DCURL_DROP_UNUSED=ON`
As for deprecations, C++11 is required to build CMake itself, which may
be a limit on some platforms. autotools continues to cover them.
Follow-up to 9bcdfb3809#20408
Follow-up to a7c974e038#19902
Follow-up to dfbe035c8b#10161
Discussion: https://github.com/curl/curl/discussions/18704Closes#20407
Via options:
- `BROTLI_USE_STATIC_LIBS`
- `CARES_USE_STATIC_LIBS`
- `LIBSSH_USE_STATIC_LIBS`
- `LIBSSH2_USE_STATIC_LIBS`
- `MBEDTLS_USE_STATIC_LIBS`
- `NGHTTP2_USE_STATIC_LIBS`
- `NGHTTP3_USE_STATIC_LIBS`
- `NGTCP2_USE_STATIC_LIBS`
- `ZSTD_USE_STATIC_LIBS`
When enabled, make a "best effort" finding static libs first and set
the "build static" macro (on Windows) as required by the dependency.
When doing `pkg-config`-based detections, make curl select the static
configuration, which shall set the "build static" macro also.
These options resemble CMake's `OPENSSL_USE_STATIC_LIBS` and
`ZLIB_USE_STATIC_LIBS` (the latter does not support `pkg-config` as of
CMake v4.2.2).
Shared/static library selection based on loose filename conventions is
fragile and prone to break if the non-static-suffixed library is found
and happens to be a shared library, or, if the linker decides to pick up
a shared copy (e.g. `.a.dll`) that shadows the static one. It may help
to provide either static or shared, but not both, on the disk, and match
that with this setting.
Experimental.
Ref: #20013Closes#20015
Rework the way curl's custom Find modules advertise their properties.
Before this patch, Find modules returned detected dependency properties
(header dirs, libs, libdirs, C flags, etc.) via global variables. curl's
main `CMakeLists.txt` copied their values into global lists, which it
later applied to targets. This solution worked internally, but it was
unsuited for the public, distributed `CURLConfig.cmake` and publishing
curl's Find modules with it, due to polluting the namespace of consumer
projects. It's also impractical to apply the many individual variables
to every targets depending on libcurl.
To allow using Find modules in consumer projects, this patch makes them
define as imported interface targets, named `CURL::<dependency>`. Then
store dependency information as target properties. It avoids namespace
pollution and makes the dependency information apply automatically
to all targets using `CURL::libcurl_static`.
Find modules continue to return `*_FOUND` and `*_VERSION` variables.
For dependencies detected via `pkg-config`, CMake 3.16+ is recommended.
Older CMake versions have a varying degree of support for
propagating/handling library directories. This may cause issues in envs
where dependencies reside in non-system locations and detected via
`pkg-config` (e.g. macOS + Homebrew). Use `CURL_USE_PKGCONFIG=OFF`
to fix these issues. Or upgrade to newer CMake, or link libcurl
dynamically.
Also:
- re-enable `pkg-config` for old cmake `find_library()` integration
tests.
- make `curlinfo` build after these changes.
- distribute local Find modules.
- export the raw list of lib dependencies via `CURL_LIBRARIES_PRIVATE`.
- `CURLconfig.cmake`: use curl's Find modules to detect dependencies in
the consumer env.
- add custom property to target property debug function.
- the curl build process no longer modifies `CMAKE_C_FLAGS`.
Follow-up to e86542038d#17047
Ref: #14930
Ref: https://github.com/libssh2/libssh2/pull/1535
Ref: https://github.com/libssh2/libssh2/pull/1571
Ref: https://github.com/libssh2/libssh2/pull/1581
Ref: https://github.com/libssh2/libssh2/pull/1623Closes#16973
To not have to guess. Also to sync with autotools, which already uses
this wording.
Also:
- replace the stray term 'folder' with 'directory' for consistency.
- store help text in a temp variable to avoid overly long strings
(mandatory in CMake <4.2.0 and can't be trivially split), also
to avoid repeating this string 4 times.
Ref: https://cmake.org/cmake/help/v4.2/command/set.htmlCloses#19169
For Find modules where `<Modulename>` is not fully uppercase.
`<Modulename>` is case-exact name used in the Find modules filename:
`CMake/Find<Moduleame>.cmake`.
`find_package_handle_standard_args()` sets both `<MODULENAME>_FOUND` and
`<Modulename>_FOUND` when detecting the dependency. Some CMake code
relies on this and 3rd-party code may rely on it too. Make sure to set
the latter variant when detecting the dependency via `pkg-config`, where
we don't call `find_package_handle_standard_args()`.
CMake sets these variable to `TRUE` (not `ON` or `1`). Replicate this
for compatibility.
Closes#16153
Make the Find modules set and return their respective `pkg-config`
module name(s) to the CMake build process, which then adds those
to the `Requires:` list.
Before this patch, `pkg-config` module names were maintainted in two
separate places. After this patch, they are maintained in the Find
modules for dependencies that have one (most do).
Re-align existing modules with this change: msh3, mbedtls, rustls.
These modules return their `pkg-config` module name only when
detected via `pkg-config`.
Follow-up to d511ec8b0a#15573Closes#15800
brotli, c-ares, libpsl, libssh2, nghttp2, nghttp3, ntgcp2, zstd.
Also:
Add workaround for CMake reporting successful libssh2 detection, but
leaving the header directory empty, and causing `libssh2.h` not found
while compiling. It happens when `pkgconf` is not detecting libssh2
dependency libcrypto in Homebrew after `brew unlink openssl` (as in
GHA/macos). The workaround is to require a non-empty header directory
to consider the detection successful. This workaround may need to be
tweaked and/or applied to other Find modules.
Follow-up to 7bab201abe#15193Closes#15408
Extend `INSTALL-CMAKE` document with the list of available options,
a short description and default values.
The list may not be 100% complete.
There are no component boundaries in CMake, so the line is blurry
between curl options, CMake options, CMake Find modules options.
I included certain CMake options that seemed useful, and/or have
dedicated use withing curl's CMake source. But, all CMake built-in
options are usable, as documented upstream in CMake.
The naming of the options has a heritage and the inconsistencies with
it, including a lack of clear namespace. This may be subject to future
updates, also after figuring out which name has special meaning within
CMake and/or CMake projects out of unwritten convention or something
more tangible.
CMake allows to initialize any internal variable via `-D`. This may be
useful to pre-initialize/override feature check results. The list
doesn't contain these, and they remain officially undocumented.
Also:
- make adjustments to keep the spellchecker happy.
- retrofit description changes to the cmake sources.
- stop documenting deprecated `Find*` variables.
Reported-by: Daniel Stenberg
Fixes https://github.com/curl/curl/discussions/14885Closes#15388
- `FindCARES` -> `FindCares`
- `FindLibPSL` -> `FindLibpsl`
- `FindLibSSH2` -> `FindLibssh2`
- `FindQUICHE` -> `FindQuiche`
- `Findrustls` -> `FindRustls`
Our convention for naming Find modules (the part after the `Find`
prefix, also called as 'package name') is:
Always start with uppercase. Follow with lowercase, unless there is
a clear preference for a stylized name. E.g. the project itself uses it
that way with a matching `<Name>Config.cmake` file, or we use it that
way elsewhere, or the name is an acronym.
Ref: #14580Closes#14601