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
has_function: Improve builtin detection #3675
Conversation
fa2a067
to
5bebeaa
Compare
I think this wrongly attributes the problem to MinGW when this just reveals less than universally true a assumptions in meson. The current code also fails on linux where gcc is one of the two native compilers in #3676. Meson should not assume a fixed relationship between This of course is breaking for projects where the build file failed to specify the needed header. We have to solve that in some way before we can do the proper fix. |
The current commits do not do this.
Now contains a fix for that issue + a test with a note about gcc being broken.
Do tell us if you find a way to fix this. We have no choice but to do this for now. |
I think for compatibility we need to deprecate this implicit assumption. Ideally meson would print a warning, but work as previously for a few releases. One way to do this would be to collect a list of affected functions and their needed includes and just implicitly add that include for the deprecation period. From a grep of my include directory it seems like these functions might be affected.
It also reveals that the naming relation is often a bit different so the old code already does not work reliable, e.g.:
That list seems manageable although it is a bit long. |
mesonbuild/compilers/c.py
Outdated
@@ -678,7 +678,8 @@ def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None | |||
head, main = self._no_prototype_templ() | |||
templ = head + stubs_fail + main | |||
|
|||
if self.links(templ.format(**fargs), env, extra_args, dependencies): | |||
if not funcname.startswith('__builtin_') and \ |
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.
I do not think meson should have this assumption, why is this needed? Optimization?
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.
Yes, that check will always fail with builtins because it tries to take the address of the function.
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.
Which is fine, it just fails and meson goes on to the builtin test.
But what happens if there is a function that matches that pattern that is not a builtin? I think hardcoding that naming convention is just assuming things that might not be true. So i would always let that test fail. And if in some odd environment a function with such an name is an actual external function it will not break just because of naming.
mesonbuild/compilers/c.py
Outdated
t = '''{prefix} | ||
int main() {{ | ||
#ifdef __has_builtin | ||
#if !__has_builtin(__builtin_{func}) | ||
#if !__has_builtin({func}) |
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.
👍
But does this work without also adding implicit includes for the cases where users currently got away with not giving the includes?
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.
Yes, the alloca test checks for this already (on clang).
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.
Yes, it seems to work with alloca
, but with isgreaterequal
it does not. Now it might be my clang install (it's just for compiling qtcreator). But a simple manual build test with clang seems to work. But even has_function('isgreaterequal', prefix: '#include <math.h>')
does not work for me at the moment. It works with a random older meson.
mesonbuild/compilers/c.py
Outdated
__builtin_{func}; | ||
#elif defined(__stub_{func}) || defined(_stub__{func}) |
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.
Do we need a comment similar to the one near stubs_fail to make it easier to understand.
Do we need to make sure that limits.h is included? Because the comment above implies it is needed for this to work.
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.
Fixed.
prefix : '#include <alloca.h>\n#undef alloca', | ||
args : unit_test_args), | ||
'built-in alloca must not be found with #include and #undef') | ||
'built-in alloca must be found with #include and #undef') |
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.
How does this work? It seems like it should not?
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.
The test was added to ensure that the __builtin_foo
codepath is not hit when there is a #include
in prefix because there was a #error
in the other path. That other path is gone now, and we have a fallback check for foo
there now.
alloca
may not be a #define
now, but it is still available as a prototype. See: alloca.h
.
if ['gcc', 'clang'].contains(cc.get_id()) | ||
assert(cc.has_function('__builtin_smul_overflow'), '__builtin_smul_overflow must be found') | ||
# FIXME: this fails on gcc, and we can't fix it without breaking builtin | ||
# detection without headers for things like alloca() |
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.
I think with the implicit include workaround we can enable this test for gcc as well.
mesonbuild/compilers/c.py
Outdated
@@ -704,10 +706,12 @@ def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None | |||
* We would always check for this, but we get false positives on | |||
* MSYS2 if we do. Their toolchain is broken, but we can at least | |||
* give them a workaround. */ | |||
#if {no_includes:d} | |||
#if {no_includes:d} && !{func_is_builtin:d} |
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.
I think we should try if the idea with implicit includes allows us to avoid this.
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.
I think we should do that in a separate PR since it has a large potential for a yak-shave.
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.
If this is the only place where we would need that, i'm ok with splitting that part of into a separate PR.
* __has_builtin(foo) is more correct and more reliable than __has_builtin(__builtin_foo) * If detection of built-ins with headers fails in the first check because we can't take the address of a built-in, we can do an ordinary check. We can't always do this ordinary check because clang on macOS ld removes the symbol when using -Wl,-no_weak_imports, which is needed for being able to target the correct platform with XCode 8 and newer. Closes #3672
Some functions are meant to be used only as compiler builtins, such as __builtin_smul_overflow and friends. Detect this case and don't look for __builtin_foo because such a check will never include a header. Fixes #3676
5bebeaa
to
ce3121b
Compare
Who knows maybe people are dumb and use __builtin_ as a prefix to their own functions
This allows us to also accept functions that are simple pre-processor defines in the header pointing to an inline definition, built-in implementation, etc. Also add a test for all the builtins listed by @textshell here: #3675 (comment)
Sorry, not yet gotten to review the current version. But from discussing with @ePirat and from @ePirat's testing i stumbled over this "nice" loophole with builtins: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html says:
And then goes on to list a ton of functions that are special in this way. So all functions from the list are builtins and still need their implementation to be available for linking. So this basically makes this a lot harder to do right. But i think passing Testing by @ePirat suggests that this would for |
I didn't get enough time to look into this, and it's too dangerous to change this now because it might regress existing users. Will work on this after the 0.47 release which will happen today. |
⚔️ conflicts. |
This is WIP, not ready to merge yet. I have to add the 'loophole' that @textshell pointed out above. |
#3902 is somewhat related |
Fixed by #7116. |
has_function: Improve built-in detection with headers
We can't always do this ordinary check because clang on macOS ld removes the symbol when using -Wl,-no_weak_imports, which is needed for being able to target the correct platform with XCode 8 and newer.
Closes #3672
Some functions are meant to be used only as compiler builtins, such as
__builtin_smul_overflow
and friends.Detect this case and don't look for
__builtin_foo
because such a check will never include a header.Fixes #3676