diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2016-04-13 19:09:22 +0300 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2016-04-13 19:09:22 +0300 |
commit | 5d65c4b6789f159a6d83aa93696dac5030cae81e (patch) | |
tree | c842c5c70d9b5737553c56d62d8e97e1670b7ca3 /mesonbuild/compilers.py | |
parent | 48e678db76948cc4b02369b64bc072810535f12f (diff) | |
parent | e72523ae410d780c3a703f0e3296105408fcc122 (diff) | |
download | meson-5d65c4b6789f159a6d83aa93696dac5030cae81e.zip meson-5d65c4b6789f159a6d83aa93696dac5030cae81e.tar.gz meson-5d65c4b6789f159a6d83aa93696dac5030cae81e.tar.bz2 |
Merge pull request #490 from centricular/has_function_link
Use the linker to check if a specific function is provided by the toolchain or runtime
Diffstat (limited to 'mesonbuild/compilers.py')
-rw-r--r-- | mesonbuild/compilers.py | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index f80a28d..0535653 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -260,6 +260,9 @@ class Compiler(): def has_header(self, *args, **kwargs): raise EnvironmentException('Language %s does not support header checks.' % self.language) + def has_header_symbol(self, *args, **kwargs): + raise EnvironmentException('Language %s does not support header symbol checks.' % self.language) + def compiles(self, *args, **kwargs): raise EnvironmentException('Language %s does not support compile checks.' % self.language) @@ -349,6 +352,9 @@ class CCompiler(Compiler): def get_compile_only_args(self): return ['-c'] + def get_no_optimization_args(self): + return ['-O0'] + def get_output_args(self, target): return ['-o', target] @@ -462,6 +468,14 @@ int someSymbolHereJustForFun; ''' return self.compiles(templ % hname, extra_args) + def has_header_symbol(self, hname, symbol, prefix, extra_args=[]): + templ = '''{2} +#include <{0}> +int main () {{ {1}; }}''' + # Pass -O0 to ensure that the symbol isn't optimized away + extra_args += self.get_no_optimization_args() + return self.compiles(templ.format(hname, symbol, prefix), extra_args) + def compile(self, code, srcname, extra_args=[]): commands = self.get_exelist() commands.append(srcname) @@ -639,15 +653,41 @@ int main(int argc, char **argv) { return align def has_function(self, funcname, prefix, env, extra_args=[]): - # This fails (returns true) if funcname is a ptr or a variable. - # The correct check is a lot more difficult. - # Fix this to do that eventually. - templ = '''%s -int main(int argc, char **argv) { - void *ptr = (void*)(%s); - return 0; -}; -''' + # Define the symbol to something else in case it is defined by the + # includes or defines listed by the user `{0}` or by the compiler. + # Then, undef the symbol to get rid of it completely. + templ = ''' + #define {1} meson_disable_define_of_{1} + {0} + #undef {1} + ''' + + # Override any GCC internal prototype and declare our own definition for + # the symbol. Use char because that's unlikely to be an actual return + # value for a function which ensures that we override the definition. + templ += ''' + #ifdef __cplusplus + extern "C" + #endif + char {1} (); + ''' + + # glibc defines functions that are not available on Linux as stubs that + # fail with ENOSYS (such as e.g. lchmod). In this case we want to fail + # instead of detecting the stub as a valid symbol. + templ += ''' + #if defined __stub_{1} || defined __stub___{1} + fail fail fail this function is not going to work + #endif + ''' + + # And finally the actual function call + templ += ''' + int + main () + {{ + return {1} (); + }}''' varname = 'has function ' + funcname varname = varname.replace(' ', '_') if self.is_cross: @@ -656,7 +696,15 @@ int main(int argc, char **argv) { if isinstance(val, bool): return val raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) - return self.compiles(templ % (prefix, funcname), extra_args) + if self.links(templ.format(prefix, funcname), extra_args): + return True + # Some functions like alloca() are defined as compiler built-ins which + # are inlined by the compiler, so test for that instead. Built-ins are + # special functions that ignore all includes and defines, so we just + # directly try to link via main(). + # Add -O0 to ensure that the symbol isn't optimized away by the compiler + extra_args += self.get_no_optimization_args() + return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), extra_args) def has_member(self, typename, membername, prefix, extra_args=[]): templ = '''%s @@ -1257,6 +1305,9 @@ class VisualStudioCCompiler(CCompiler): def get_compile_only_args(self): return ['/c'] + def get_no_optimization_args(self): + return ['/Od'] + def get_output_args(self, target): if target.endswith('.exe'): return ['/Fe' + target] |