Skip to content

cmke: add *_USE_STATIC_LIBS options for 9 dependencies#20015

Closed
vszakats wants to merge 17 commits into
curl:masterfrom
vszakats:cmstatic
Closed

cmke: add *_USE_STATIC_LIBS options for 9 dependencies#20015
vszakats wants to merge 17 commits into
curl:masterfrom
vszakats:cmstatic

Conversation

@vszakats

@vszakats vszakats commented Dec 18, 2025

Copy link
Copy Markdown
Member

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: #20013


https://github.com/curl/curl/pull/20015/files?w=1

  • potentially extend to brotli, libssh2, mbedtls, zstd. These may
    have static-suffix lib names, but have no (AFAIK) macro to set.
  • possibly limit existing static-only system lib dependencies to the *_USE_STATIC_LIBS option.
    This may potentially be breaking, though technically the accurate thing to do. (in c-ares, libssh, wolfSSL, Rustls, librtmp)
    [SKIP, let's rather overlink than underlink]
  • maybe add a global option to enable this option for all deps? That seems closer to how this is actually used in practice. It also makes it easier to document. → NO, until we know it's solving a real problem.
  • perhaps extend to all deps, for the pkg-config track? [FUTURE]
  • once/if added to all deps, maybe document it just once in INSTALL-CMAKE.md.
    Skip for now. Not all dependencies have this. (Those that have no clear
    distinct name for static libs (or I couldn't spot it), don't.)
  • allow setting a custom static suffix via -D*_USE_STATIC_LIBS=_mystatic? (some deps support it out of the box) → Looks like a lot of complication to address niche cases. For customization it's simpler to just point to the exact library name via <name>_LIBRARY. Skip this.
  • pick <name>_STATIC_<var> variables returned by pkg-config
    when this option is set.
  • possibly prefix the config name with CURL_ to stay within the
    namespace. (that ship had sailed? maybe fix it in future for all, otherwise
    these new vars would confusingly be misaligned with the existing ones.)
  • replace COMPILE_DEFINITIONS with CFLAGS and limit it for non-pkg-config track. pkg-config already does that via the STATIC options, and shall do it more accurately.

@jay

jay commented Dec 18, 2025

Copy link
Copy Markdown
Member

I don't think this is our responsibility and (like anything else) it adds to maintenance.

Something like below may? work, at least on Windows. I don't think you can or would want static glibc

CPPFLAGS="-DNGHTTP2_STATICLIB" LDFLAGS="-static" PKG_CONFIG="pkg-config --static" ./configure ...

@vszakats

vszakats commented Dec 18, 2025

Copy link
Copy Markdown
Member Author

I don't think this is our responsibility and (like anything else) it adds to maintenance.

In this case my doubt is if this would actually help people trying
to build statically, to justify the tiny maintenance it needs. I already
deal with half of this in curl-for-win anyway, and this stuff rarely
changes.

edit: after extending it to pkg-config and more deps, the maintenance
angle is more relevant. Though this may be justified if this is actually
useful.

Hence marked experimental, so if it causes more problems, or
doesn't seem to help anyone, we can back off from it.

[ An aside I find insteresting is that some libs do not require the annoying
"build static" macro (including libssh2, which I'm familiar with).
libssh2 requires the opposite, which is somehow working out more
smoothly when consuming the lib. The declspec thing is one of
the many Windows decisions that keep haunting and puzzling decades in. ]

Something like below may? work, at least on Windows. I don't think you can or would want static glibc

CPPFLAGS="-DNGHTTP2_STATICLIB" LDFLAGS="-static" PKG_CONFIG="pkg-config --static" ./configure ...

How to choose static with the pkg-config integrated to CMake,
I haven't looked closely yet. It could be picking the static lib name,
extra lib deps, and adding the macro when necessary. This is
little bit more than this patch does for the non-pkg-config path, and yes,
both still miss the other half of the problem, aka telling the linker to
pick the static lib if both flavors exist on disk, and do that on a
per-lib-basis, not with a global -static which may break other things.

(enclosing each lib in -Wl,-Bstatic / -Wl,-Bdynamic could help
(but can break the global default), but getting little exposure. There
is a rarer, per-lib, solution, which I can't recall ATM, oops.)

edit: it's -l:<name>, but still can't recally its drawbacks and why
it remains almost unknown and unused.

On a quick look, even the oldest CMake version supported now, loads
--static results into <name>_STATIC_<var> variables, so these
curl options may be able to use them, with more added logic of course.

The issue remains that it's ultimately the linker what decides what gets
actually linked.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds *_USE_STATIC_LIBS options for several CMake Find modules (brotli, c-ares, libssh, libssh2, mbedtls, nghttp2, nghttp3, ngtcp2, zstd) to enable "best effort" detection and configuration of static libraries. The implementation attempts to find static library variants by checking for static-suffixed library names first, and sets appropriate compile-time macros when required by the dependency (similar to existing OPENSSL_USE_STATIC_LIBS and ZLIB_USE_STATIC_LIBS options).

  • Adds new *_USE_STATIC_LIBS CMake input variables for 9 dependencies
  • Modifies each Find module to prioritize static library variants when the option is set
  • Sets required *_STATICLIB compile definitions for libraries that need them (c-ares, libssh, nghttp2, nghttp3, ngtcp2)
  • Updates pkg-config integration to use STATIC_* variables when static libs are requested

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
docs/INSTALL-CMAKE.md Documents the new *_USE_STATIC_LIBS options for each affected dependency
CMake/FindZstd.cmake Adds ZSTD_USE_STATIC_LIBS option with static library name variants and pkg-config static variable support
CMake/FindNGTCP2.cmake Adds NGTCP2_USE_STATIC_LIBS option, sets -DNGTCP2_STATICLIB macro, searches for static library variants
CMake/FindNGHTTP3.cmake Adds NGHTTP3_USE_STATIC_LIBS option, sets -DNGHTTP3_STATICLIB macro, searches for static library variants
CMake/FindNGHTTP2.cmake Adds NGHTTP2_USE_STATIC_LIBS option, sets -DNGHTTP2_STATICLIB macro, reorders library search to prioritize static variants
CMake/FindMbedTLS.cmake Adds MBEDTLS_USE_STATIC_LIBS option with static library name variants for all three mbedTLS libraries
CMake/FindLibssh2.cmake Adds LIBSSH2_USE_STATIC_LIBS option with static library name variants
CMake/FindLibssh.cmake Adds LIBSSH_USE_STATIC_LIBS option, sets -DLIBSSH_STATIC macro, searches for static library variants
CMake/FindCares.cmake Adds CARES_USE_STATIC_LIBS option, sets -DCARES_STATICLIB macro, searches for static library variants
CMake/FindBrotli.cmake Adds BROTLI_USE_STATIC_LIBS option with static library name variants for both brotli libraries

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CMake/FindNGHTTP3.cmake Outdated
@vszakats

vszakats commented Jan 22, 2026

Copy link
Copy Markdown
Member Author

I'm still on the fence with this one. The maintenance burden is IMO
manageable at 10-12 lines of fairly trivial code per dependency,
which I expect to rarely change.

We've seen requests, reports and PRs to this intended effect, but
it's hard to say if this change would actually work in practice, in
actual use-cases. If it does, it's useful, but if it doesn't, it's just
extra weight to carry.

My impression during the last few decades is that the
static/shared-lib-selection "story" is a use-case that sees no love
from platforms, toolchains and build tools alike. It's an afterthought,
leaving this to chance or as a puzzle to solve build-case by
build-case. Short of toolchain support to tell ones shared/static
lib preference on a per-lib basis, I found best not to have both
shared and static lib for the same dependency next to each other
on the disk. In which case this PR has a chance to help to setup
the necessary macro and pull in lib dependencies, assuming
the *_USE_STATIC_LIBS setting matches what's on the disk.

In other cases, not so much.

I can't assess if this scenario is common enough to justify this PR,
or perhaps extending it to the other Find* modules in the future.
I may also be missing other useful scenarios.

Feel free to comment what you think.

(edit: the PR is ready to merge as-is, in case it's useful.)

@vszakats vszakats changed the title cmke: add *_USE_STATIC_LIBS option for some dependencies cmke: add *_USE_STATIC_LIBS option for 9 dependencies Jan 22, 2026
@vszakats vszakats removed the feature-window A merge of this requires an open feature window label Jan 22, 2026
@vszakats vszakats changed the title cmke: add *_USE_STATIC_LIBS option for 9 dependencies cmke: add *_USE_STATIC_LIBS options for 9 dependencies Jan 22, 2026
@vszakats vszakats closed this in 26c39d8 Jan 26, 2026
@vszakats

Copy link
Copy Markdown
Member Author

Merged as experimental.

@vszakats vszakats deleted the cmstatic branch January 26, 2026 04:22
vszakats added a commit to vszakats/curl that referenced this pull request Jan 27, 2026
vszakats added a commit that referenced this pull request Jan 27, 2026
vszakats added a commit to curl/curl-for-win that referenced this pull request Feb 12, 2026
Replacing manual `CPPFLAGS` with curl 8.19.0+.

They are no-ops for dependencies that do not need a macro to enable
static mode. I've added them there anyway for consistency.

These settings also affect how the dependency is searched, but in case
of these builds, all dependencies are explicitly set with absolute
paths, skipping any search.

curl/curl@26c39d8
curl/curl#20015
vszakats added a commit that referenced this pull request Mar 21, 2026
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 #19117
#20784 (comment)

Depends-on: fad1eba #20840
Follow-up to 91e06fd #20784
Follow-up to 26c39d8 #20015

Closes #20814
outcast36 pushed a commit to greearb/curl that referenced this pull request Jun 3, 2026
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:
curl#20013 curl#19156 curl#19117
curl#20784 (comment)

Depends-on: fad1eba curl#20840
Follow-up to 91e06fd curl#20784
Follow-up to 26c39d8 curl#20015

Closes curl#20814
vszakats added a commit to libssh2/libssh2 that referenced this pull request Jul 9, 2026
When enabled, make a "best effort" finding static lib first and set
the "build static" macro (on Windows) as required by the dependency.

When doing `pkg-config`-based detections, make the build select the
static configuration, which shall set the "build static" macro also.

This option 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.

Refs:
curl/curl@26c39d8
curl/curl#20015

Closes #2263
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants