Skip to content

[libc++] Avoid including <features.h> on arbitrary platforms #125587

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

Merged
merged 2 commits into from
Feb 15, 2025

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Feb 3, 2025

This partially reverts commit 5f2389d. That commit started checking whether
<features.h> was a valid include unconditionally, however codebases are free
to have such a header on their search path, which breaks compilation. LLVM
libc should instead provide a more standard way of getting configuration
macros like LLVM_LIBC.

After this patch, we only include <features.h> when we're on Linux or
when we're compiling for GPUs.

@ldionne ldionne added this to the LLVM 20.X Release milestone Feb 3, 2025
@ldionne ldionne requested a review from a team as a code owner February 3, 2025 21:26
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 3, 2025
@ldionne
Copy link
Member Author

ldionne commented Feb 3, 2025

CF #102036 (comment)

@llvmbot
Copy link
Member

llvmbot commented Feb 3, 2025

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

This reverts commit 5f2389d. That commit started checking whether <features.h> was a valid include, however codebases are free to have such a header on their search path, which breaks compilation. LLVM libc should instead provide a more standard way of getting configuration macros like LLVM_LIBC.


Full diff: https://github.com/llvm/llvm-project/pull/125587.diff

2 Files Affected:

  • (modified) libcxx/include/__configuration/platform.h (+3-6)
  • (modified) libcxx/include/__random/binomial_distribution.h (+1-2)
diff --git a/libcxx/include/__configuration/platform.h b/libcxx/include/__configuration/platform.h
index 2a92ce209b91f8b..27f68d04e8a8d9c 100644
--- a/libcxx/include/__configuration/platform.h
+++ b/libcxx/include/__configuration/platform.h
@@ -30,18 +30,15 @@
 // ... add new file formats here ...
 #endif
 
-// To detect which libc we're using
-#if __has_include(<features.h>)
-#  include <features.h>
-#endif
-
+// Need to detect which libc we're using if we're on Linux.
 #if defined(__linux__)
+#  include <features.h>
 #  if defined(__GLIBC_PREREQ)
 #    define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b)
 #  else
 #    define _LIBCPP_GLIBC_PREREQ(a, b) 0
 #  endif // defined(__GLIBC_PREREQ)
-#endif
+#endif   // defined(__linux__)
 
 #ifndef __BYTE_ORDER__
 #  error                                                                                                               \
diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h
index 9538c15e2dc97b5..47790b674db5882 100644
--- a/libcxx/include/__random/binomial_distribution.h
+++ b/libcxx/include/__random/binomial_distribution.h
@@ -97,8 +97,7 @@ class _LIBCPP_TEMPLATE_VIS binomial_distribution {
   }
 };
 
-// The LLVM C library provides this with conflicting `noexcept` attributes.
-#if !defined(_LIBCPP_MSVCRT_LIKE) && !defined(__LLVM_LIBC__)
+#ifndef _LIBCPP_MSVCRT_LIKE
 extern "C" double lgamma_r(double, int*);
 #endif
 

@philnik777
Copy link
Contributor

Would it make sense to partially revert? IIUC this still works when targeting linux with the LLVM libc, so we could just revert the inclusion of <features.h> if available.

@jhuber6
Copy link
Contributor

jhuber6 commented Feb 3, 2025

I'd prefer a partial revert because this would break the GPU libc++ build. (Sorry I got sidetracked about setting up that build on a bot. I need to get @jplehr or @Artem-B to help me with that). We still can't run the tests clean, but a build is better than nothing.

@jhuber6
Copy link
Contributor

jhuber6 commented Feb 3, 2025

Might need to check for __AMDGPU__ and __NVPTX__ or something, since this is what lets us use lgamma and stuff. alternatively we could replace this with a cmake check that just sees if the environment can call lgamma_r.

@ldionne
Copy link
Member Author

ldionne commented Feb 4, 2025

My strong preference would be to include a standard header instead, but that would require LLVM libc to define its detection macro when such header is included.

I'd be okay with a partial revert only, but @jhuber6 would have to tell me what the check should be instead.

@jhuber6
Copy link
Contributor

jhuber6 commented Feb 4, 2025

My strong preference would be to include a standard header instead, but that would require LLVM libc to define its detection macro when such header is included.

I'd be okay with a partial revert only, but @jhuber6 would have to tell me what the check should be instead.

I think we already have a handful of __LLVM_LIBC__ tests that might also break on baremetal, cc @petrhosek. For my purposes specifically, you'd just put this in it.

#if (defined(__AMDGPU__) || defined(__NVPTX__))
#endif

Though that might break during offloading usage on Windows if the user has features.h?

LLVM libc should instead provide a more standard way of getting configuration macros like LLVM_LIBC.

But features.h is the standard way on Linux at least. We could always emit __features.h or something if we're really concerned.

This partially reverts commit 5f2389d. That commit started checking whether
<features.h> was a valid include unconditionally, however codebases are free
to have such a header on their search path, which breaks compilation. LLVM
libc should instead provide a more standard way of getting configuration
macros like __LLVM_LIBC__.

After this patch, we only include <features.h> when we're on Linux or
when we're compiling for GPUs.
@ldionne ldionne changed the title [libc++] Revert "Do not redeclare lgamma_r when targeting the LLVM C library (#102036) [libc++] Avoid including <features.h> on arbitrary platforms Feb 4, 2025
@petrhosek
Copy link
Member

petrhosek commented Feb 5, 2025

This is going to break other platforms supported by LLVM libc, most notably baremetal (for which we don't really have a great detection mechanism since there's no OS).

An alternative to using an LLVM libc provided header would be to store the value of LIBCXX_LIBC CMake option in __config_site and then use that. This could also eventually replace _LIBCPP_HAS_MUSL_LIBC.

@ldionne
Copy link
Member Author

ldionne commented Feb 5, 2025

This is going to break other platforms supported by LLVM libc, most notably baremetal (for which we don't really have a great detection mechanism since there's no OS).

An alternative to using an LLVM libc provided header would be to store the value of LIBCXX_LIBC CMake option in __config_site and then use that. This could also eventually replace _LIBCPP_HAS_MUSL_LIBC.

At first glance, I'm really not a huge fan of hardcoding the libc we're building on top of in __config_site. However, I do think that this is potentially a more elegant approach than what we do right now (a mix of _LIBCPP_HAS_MUSL_LIBC and auto-detection), and it would also solve some problems we have downstream so I think this might be generally useful.

I'm willing to work on that, but it's not something we'd be able to cherry-pick back to LLVM 20 given its complexity and the time it'll take to put something together. In the meantime, I think it's pretty urgent to restore to a behavior that works on mainstream platforms. If you have specific concerns about this patch breaking some new setups since the last release, perhaps we can carve them out using additional #ifdefs?

@jhuber6
Copy link
Contributor

jhuber6 commented Feb 5, 2025

I'm personally not concerned with the GPU stuff being broken on Clang-20 since the support is still experimental and I doubt anyone's depending on it.

@ldionne
Copy link
Member Author

ldionne commented Feb 7, 2025

@petrhosek Gentle ping. If you have specific concerns about landing this partial revert, please let me know ASAP so we can work on addressing them. Landing this patch addresses a regression that was introduced in LLVM 20 so I'd like to do this sooner rather than later.

@petrhosek
Copy link
Member

@petrhosek Gentle ping. If you have specific concerns about landing this partial revert, please let me know ASAP so we can work on addressing them. Landing this patch addresses a regression that was introduced in LLVM 20 so I'd like to do this sooner rather than later.

I believe this change should be fine, but I'll test it locally against our embedded projects just to be sure that nothing breaks.

@petrhosek
Copy link
Member

@petrhosek Gentle ping. If you have specific concerns about landing this partial revert, please let me know ASAP so we can work on addressing them. Landing this patch addresses a regression that was introduced in LLVM 20 so I'd like to do this sooner rather than later.

I believe this change should be fine, but I'll test it locally against our embedded projects just to be sure that nothing breaks.

I tested this locally and it looks like this change breaks the libc++ on baremetal. Specifically this condition no longer evaluates as true:

#if defined(__LLVM_LIBC__)
# define _LIBCPP_HAS_TIMESPEC_GET
#endif

We'll need some alternative. We could move the __LLVM_LIBC__ to __llvm-libc-common.h which is included from all other libc headers. We could also try to detect whether timespec_get is available without checking for a specific libc.

@petrhosek
Copy link
Member

Now that #126877 landed, this should be safe to land.

@ldionne ldionne merged commit cffc1ac into llvm:main Feb 15, 2025
81 checks passed
@ldionne ldionne deleted the review/fix-features-h-inclusion branch February 15, 2025 09:54
@ldionne
Copy link
Member Author

ldionne commented Feb 15, 2025

/cherry-pick cffc1ac

@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2025

/pull-request #127310

@nico
Copy link
Contributor

nico commented Feb 15, 2025

Looks like this breaks cuda tests on Mac, at least in the gn build: http://45.33.8.238/macm1/100921/step_6.txt

I think the test isn't sufficiently hermetic and the test is to blame, but nevertheless check-clang is currently broken due to this PR.

@ldionne
Copy link
Member Author

ldionne commented Feb 18, 2025

Looks like this breaks cuda tests on Mac, at least in the gn build: http://45.33.8.238/macm1/100921/step_6.txt

I think the test isn't sufficiently hermetic and the test is to blame, but nevertheless check-clang is broken.

Ack, just saw this. I think it's easy to add another layer of guard with __has_include.

Edit: #127691

swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Feb 19, 2025
…5587)

This partially reverts commit 5f2389d. That commit started checking
whether <features.h> was a valid include unconditionally, however codebases
are free to have such a header on their search path, which breaks compilation.
LLVM libc now provides a more standard way of getting configuration macros
like __LLVM_LIBC__.

After this patch, we only include <features.h> when we're on Linux or
when we're compiling for GPUs.

(cherry picked from commit cffc1ac)
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Feb 24, 2025
…5587)

This partially reverts commit 5f2389d. That commit started checking
whether <features.h> was a valid include unconditionally, however codebases
are free to have such a header on their search path, which breaks compilation.
LLVM libc now provides a more standard way of getting configuration macros
like __LLVM_LIBC__.

After this patch, we only include <features.h> when we're on Linux or
when we're compiling for GPUs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
Development

Successfully merging this pull request may close these issues.

6 participants