Skip to content

cmke: add *_USE_STATIC_LIBS options for 9 dependencies#20015

Closed
vszakats wants to merge 17 commits intocurl:masterfrom
vszakats:cmstatic
Closed

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

Conversation

@vszakats
Copy link
Member

@vszakats vszakats commented Dec 18, 2025

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
Copy link
Member

jay commented Dec 18, 2025

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
Copy link
Member Author

vszakats commented Dec 18, 2025

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.

Copy link

Copilot AI left a comment

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.

@vszakats
Copy link
Member Author

vszakats commented Jan 22, 2026

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
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
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