diff options
Diffstat (limited to 'mesonbuild/compilers')
-rw-r--r-- | mesonbuild/compilers/c.py | 29 | ||||
-rw-r--r-- | mesonbuild/compilers/c_function_attributes.py | 123 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 4 | ||||
-rw-r--r-- | mesonbuild/compilers/cpp.py | 6 |
4 files changed, 161 insertions, 1 deletions
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 436f699..bde9f63 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -24,9 +24,10 @@ from .. import mlog from .. import coredata from . import compilers from ..mesonlib import ( - EnvironmentException, version_compare, Popen_safe, listify, + EnvironmentException, MesonException, version_compare, Popen_safe, listify, for_windows, for_darwin, for_cygwin, for_haiku, for_openbsd, ) +from .c_function_attributes import C_FUNC_ATTRIBUTES from .compilers import ( GCC_MINGW, @@ -57,6 +58,13 @@ class CCompiler(Compiler): find_library_cache = {} internal_libs = gnu_compiler_internal_libs + @staticmethod + def attribute_check_func(name): + try: + return C_FUNC_ATTRIBUTES[name] + except KeyError: + raise MesonException('Unknown function attribute "{}"'.format(name)) + def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs): # If a child ObjC or CPP class has already set it, don't set it ourselves if not hasattr(self, 'language'): @@ -1045,6 +1053,19 @@ class CCompiler(Compiler): m = pattern.match(ret) return ret + def has_func_attribute(self, name, env): + # Just assume that if we're not on windows that dllimport and dllexport + # don't work + if not (for_windows(env.is_cross_build(), env) or + for_cygwin(env.is_cross_build(), env)): + if name in ['dllimport', 'dllexport']: + return False + + # Clang and GCC both return warnings if the __attribute__ is undefined, + # so set -Werror + return self.compiles(self.attribute_check_func(name), env, extra_args='-Werror') + + class ClangCCompiler(ClangCompiler, CCompiler): def __init__(self, exelist, version, clang_type, is_cross, exe_wrapper=None, **kwargs): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) @@ -1490,6 +1511,12 @@ class VisualStudioCCompiler(CCompiler): assert(buildtype == 'custom') raise EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') + def has_func_attribute(self, name, env): + # MSVC doesn't have __attribute__ like Clang and GCC do, so just return + # false without compiling anything + return name in ['dllimport', 'dllexport'] + + class ArmCCompiler(ArmCompiler, CCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwargs): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) diff --git a/mesonbuild/compilers/c_function_attributes.py b/mesonbuild/compilers/c_function_attributes.py new file mode 100644 index 0000000..9aeaaf2 --- /dev/null +++ b/mesonbuild/compilers/c_function_attributes.py @@ -0,0 +1,123 @@ +# These functions are based on the following code: +# https://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_gcc_func_attribute.m4, +# which is licensed under the following terms: +# +# Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. +# + +C_FUNC_ATTRIBUTES = { + 'alias': ''' + int foo(void) { return 0; } + int bar(void) __attribute__((alias("foo")));''', + 'aligned': + 'int foo(void) __attribute__((aligned(32)));', + 'alloc_size': + 'void *foo(int a) __attribute__((alloc_size(1)));', + 'always_inline': + 'inline __attribute__((always_inline)) int foo(void) { return 0; }', + 'artificial': + 'inline __attribute__((artificial)) int foo(void) { return 0; }', + 'cold': + 'int foo(void) __attribute__((cold));', + 'const': + 'int foo(void) __attribute__((const));', + 'constructor': + 'int foo(void) __attribute__((constructor));', + 'constructor_priority': + 'int foo( void ) __attribute__((__constructor__(65535/2)));', + 'deprecated': + 'int foo(void) __attribute__((deprecated("")));', + 'destructor': + 'int foo(void) __attribute__((destructor));', + 'dllexport': + '__declspec(dllexport) int foo(void) { return 0; }', + 'dllimport': + '__declspec(dllimport) int foo(void);', + 'error': + 'int foo(void) __attribute__((error("")));', + 'externally_visible': + 'int foo(void) __attribute__((externally_visible));', + 'fallthrough': ''' + int foo( void ) { + switch (0) { + case 1: __attribute__((fallthrough)); + case 2: break; + } + return 0; + };''', + 'flatten': + 'int foo(void) __attribute__((flatten));', + 'format': + 'int foo(const char * p, ...) __attribute__((format(printf, 1, 2)));', + 'format_arg': + 'char * foo(const char * p) __attribute__((format_arg(1)));', + 'gnu_inline': + 'inline __attribute__((gnu_inline)) int foo(void) { return 0; }', + 'hot': + 'int foo(void) __attribute__((hot));', + 'ifunc': + ('int my_foo(void) { return 0; }' + 'static int (*resolve_foo(void))(void) { return my_foo; }' + 'int foo(void) __attribute__((ifunc("resolve_foo")));'), + 'leaf': + '__attribute__((leaf)) int foo(void) { return 0; }', + 'malloc': + 'int *foo(void) __attribute__((malloc));', + 'noclone': + 'int foo(void) __attribute__((noclone));', + 'noinline': + '__attribute__((noinline)) int foo(void) { return 0; }', + 'nonnull': + 'int foo(char * p) __attribute__((nonnull(1)));', + 'noreturn': + 'int foo(void) __attribute__((noreturn));', + 'nothrow': + 'int foo(void) __attribute__((nothrow));', + 'optimize': + '__attribute__((optimize(3))) int foo(void) { return 0; }', + 'packed': + 'struct __attribute__((packed)) foo { int bar; };', + 'pure': + 'int foo(void) __attribute__((pure));', + 'returns_nonnull': + 'int *foo(void) __attribute__((returns_nonnull));', + 'unused': + 'int foo(void) __attribute__((unused));', + 'used': + 'int foo(void) __attribute__((used));', + 'visibility': ''' + int foo_def(void) __attribute__((visibility(("default")))); + int foo_hid(void) __attribute__((visibility(("hidden")))); + int foo_int(void) __attribute__((visibility(("internal")))); + int foo_pro(void) __attribute__((visibility(("protected"))));''', + 'warning': + 'int foo(void) __attribute__((warning("")));', + 'warn_unused_result': + 'int foo(void) __attribute__((warn_unused_result));', + 'weak': + 'int foo(void) __attribute__((weak));', + 'weakref': ''' + static int foo(void) { return 0; } + static int var(void) __attribute__((weakref("foo")));''', +} + +CXX_FUNC_ATTRIBUTES = { + # Alias must be applied to the mangled name in C++ + 'alias': + ('extern "C" {' + 'int foo(void) { return 0; }' + '}' + 'int bar(void) __attribute__((alias("foo")));' + ), + 'ifunc': + ('extern "C" {' + 'int my_foo(void) { return 0; }' + 'static int (*resolve_foo(void))(void) { return my_foo; }' + '}' + 'int foo(void) __attribute__((ifunc("resolve_foo")));'), +} diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 36507b0..88e9bce 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1137,6 +1137,10 @@ class Compiler: def get_gui_app_args(self, value): return [] + def has_func_attribute(self, name, env): + raise EnvironmentException( + 'Language {} does not support function attributes.'.format(self.get_display_language())) + GCC_STANDARD = 0 GCC_OSX = 1 GCC_MINGW = 2 diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 85766f7..2173655 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -31,8 +31,14 @@ from .compilers import ( ArmCompiler, ArmclangCompiler, ) +from .c_function_attributes import CXX_FUNC_ATTRIBUTES class CPPCompiler(CCompiler): + + @classmethod + def attribute_check_func(cls, name): + return CXX_FUNC_ATTRIBUTES.get(name, super().attribute_check_func(name)) + def __init__(self, exelist, version, is_cross, exe_wrap, **kwargs): # If a child ObjCPP class has already set it, don't set it ourselves if not hasattr(self, 'language'): |