-
Notifications
You must be signed in to change notification settings - Fork 1.1k
cmake: Avoid contaminating parent project's cache with BUILD_SHARED_LIBS
#1688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmake: Avoid contaminating parent project's cache with BUILD_SHARED_LIBS
#1688
Conversation
cc @theuni |
@theuni @purpleKarrot Can one of you review this? |
I'd rather drop the complete block of code. Every CMake project should behave well as a subproject. This becomes even more relevant with FetchContent getting more and more adoption. Not only should projects not interfere with superprojects (like setting |
Sigh, this is again confusing as hell (at least to me as someone who is not a CMake expert). Let me try to organize the discussion. What is the cleanest thing to do in a library?
The docs say that top-level projects should call Can we drop the entire block?I might be wrong, but wouldn't dropping the
The thing is that, according to the docs, If we can drop the entire block, should we do it?I'm not sure, but I tend to say no. I'd rather keep the default of building a shared library and accept a few lines of CMake code. If we decide to drop it, we should at least document this in the README. Do we need
|
This excerpt from the docs literally describes how fragile it is to set
Additionally, from Professional CMake: A Practical Guide 21st Edition, Section 40.2:
When set using
The default state of
I agree with that. That's why I chose the suggested approach. A shared library is a real library and should be considered as the default by-product of the build process.
Using project-specific versions of well-known CMake variables is hard to maintain consistent. This project defines its own variable to override CMake's |
I hear you, @real-or-random. That deserves a longer explanation. I will provide extensive information with examples on the weekend. |
I hope to answer most of your questions here: https://njump.me/nevent1qqsyfmk89g3cfvq8u9p6hg3x4nd0j66tjgwkth45wpz493hv4f5z70spp4mhxue69uhkummn9ekx7mqzyq8sv8lyu6zjy5p8fmfa0pn4j95rvmr2rj7urnpdhvkk5r55fndjkd3z5dj |
That's a great post! What's your conclusion for this PR? From the post, it appears that you support the A minor comment, not related to the discussion here:
The point of the |
Note that modern gcc/clang support #if defined(__has_attribute)
# if __has_attribute(visibility)
# define HAS_VISIBILITY_ATTRIBUTE
# endif
#endif
#ifdef HAS_VISIBILITY_ATTRIBUTE
# define DEFAULT_VISIBILITY_ATTRIBUTE __attribute__((visibility("default")))
#else
# define DEFAULT_VISIBILITY_ATTRIBUTE
#endif Of course to be useful for libsecp it'd need a fallback for older versions. |
Thanks! It was a huge effort.
In my post, I show several approaches and possibilities. Project Qux sets In project Bar, I show that no such option is actually needed for building with both In project Baz, I show that even with For this PR, it means I would definitely drop the else part, and preferably the complete block of code. |
Clang supports visibility since version 2.0 and I am aware of 1309c03, but I cannot tell whether there is a actual use case to support compilers older than bitcoin, or whether that change was motivated by because-we-can. But yeah, that is off-topic for this PR. Please use nostr to comment on the blog post. |
Ok, I get that we don't need Maybe it's just me, but I still can't follow why you prefer dropping the "then" branch? I still think that defaulting to a shared library is a good idea.
Okay, I wasn't aware of |
CMakeLists.txt
Outdated
if(PROJECT_IS_TOP_LEVEL) | ||
option(BUILD_SHARED_LIBS "Build shared libraries." ON) | ||
else() | ||
option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF) | ||
if(SECP256K1_DISABLE_SHARED) | ||
set(BUILD_SHARED_LIBS OFF) | ||
endif() | ||
endif() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So my current thinking is that we do this:
if(PROJECT_IS_TOP_LEVEL) | |
option(BUILD_SHARED_LIBS "Build shared libraries." ON) | |
else() | |
option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF) | |
if(SECP256K1_DISABLE_SHARED) | |
set(BUILD_SHARED_LIBS OFF) | |
endif() | |
endif() | |
if(libsecp256k1_IS_TOP_LEVEL) | |
option(BUILD_SHARED_LIBS "Build shared libraries." ON) | |
endif() |
The CMake cache is global in scope. Therefore, setting the standard cache variable `BUILD_SHARED_LIBS` can inadvertently affect the behavior of a parent project. This change: 1. Sets the `BUILD_SHARED_LIBS` cache variable only when libsecp256k1 is the top-level project. 2. Removes the `SECP256K1_DISABLE_SHARED` cache variable. This enables parent projects that include libsecp256k1 as a subproject to rely solely on standard CMake variables for configuring the library type.
533aea1
to
7b07b22
Compare
Reworked per discussion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 7b07b22
@purpleKarrot Want to take a look at the updated version? |
ACK 7b07b22 |
b093a19 cmake: Proactively avoid use of `SECP256K1_DISABLE_SHARED` (Hennadii Stepanov) eb59a19 cmake, refactor: Encapsulate adding secp256k1 subtree in function (Hennadii Stepanov) Pull request description: The `SECP256K1_DISABLE_SHARED` CMake variable has been [removed](bitcoin-core/secp256k1#1688) upstream. This PR removes its usage ahead of the next `secp256k1` subtree update to prevent breakage and simplify integration. ACKs for top commit: fanquake: ACK b093a19 Tree-SHA512: a87cee71cf356f458f68d3163253ca5c4f86e56d268006b6b8e1d4b2c009ba436148a07a6b67b89ddbb2d0e3c1113ab4b4906c5fc5624cb3082b20e916e0e82b
The CMake cache is global in scope. Therefore, setting the standard cache variable
BUILD_SHARED_LIBS
can inadvertently affect the behavior of a parent project.Consider configuring Bitcoin Core without explicit setting
BUILD_SHARED_LIBS
:According to CMake’s documentation, this should configure
libbitcoinkernel
asSTATIC
.However, that's not the case:
This PR:
BUILD_SHARED_LIBS
cache variable only whenlibsecp256k1
is the top-level project.SECP256K1_DISABLE_SHARED
cache variable. This enables parent projects that include libsecp256k1 as a subproject to rely solely on standard CMake variables for configuring the library type. During integration into a parent project, the static library can be forced as demonstrated here.