It's fairly common on Linux and *BSD platforms to check for these attributes existence, so it makes sense to me to have this checking build into meson itself. Autotools also has a builtin for handling these, and by building them in we can short circuit cases that we know that these don't exist (MSVC). Additionally this adds support for two common MSVC __declspec attributes, dllimport and dllexport. This implements the declspec version (even though GCC has an __attribute__ version that both it and clang support), since GCC and Clang support the MSVC version as well. Thus it seems reasonable to assume that most projects will use the __declspec version over teh __attribute__ version.pull/3986/head
parent
8ca463f9f1
commit
51e9db370a
9 changed files with 388 additions and 1 deletions
@ -0,0 +1,29 @@ |
||||
## Helper methods added for checking GNU style attributes: __attribute__(...) |
||||
|
||||
A set of new helpers have been added to the C and C++ compiler objects for |
||||
checking GNU style function attributes. These are not just simpler to use, they |
||||
may be optimized to return fast on compilers that don't support these |
||||
attributes. Currently this is true for MSVC. |
||||
|
||||
```meson |
||||
cc = meson.get_compiler('c') |
||||
if cc.has_function_attribute('aligned') |
||||
add_project_arguments('-DHAVE_ALIGNED', language : 'c') |
||||
endif |
||||
``` |
||||
|
||||
Would replace code like: |
||||
|
||||
```meson |
||||
if cc.compiles('''into foo(void) __attribute__((aligned(32)))''') |
||||
add_project_arguments('-DHAVE_ALIGNED', language : 'c') |
||||
endif |
||||
``` |
||||
|
||||
Additionally, a multi argument version has been added: |
||||
|
||||
```meson |
||||
foreach s : cc.get_supported_function_attributes(['hidden', 'alias']) |
||||
add_project_arguments('-DHAVE_@0@'.format(s.to_upper()), language : 'c') |
||||
endforeach |
||||
``` |
@ -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")));'), |
||||
} |
@ -0,0 +1,103 @@ |
||||
# Copyright © 2017-2018 Intel Corporation |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
project('gcc func attributes', ['c', 'cpp']) |
||||
|
||||
# For msvc these will fail because msvc doesn't support __attribute__, for |
||||
# Clang and GCC, they should pass. |
||||
c = meson.get_compiler('c') |
||||
cpp = meson.get_compiler('cpp') |
||||
|
||||
expected_result = c.get_id() != 'msvc' |
||||
|
||||
# Q: Why is ifunc not in this list or any of the below lists? |
||||
# A: It's too damn hard to figure out if you actually support it, since it |
||||
# requires both compiler and libc support, and there isn't a good way to |
||||
# figure that out except by running the code we're trying to test. |
||||
attributes = [ |
||||
'aligned', |
||||
'alloc_size', |
||||
'always_inline', |
||||
'cold', |
||||
'const', |
||||
'constructor', |
||||
'constructor_priority', |
||||
'deprecated', |
||||
'destructor', |
||||
'flatten', |
||||
'format', |
||||
'format_arg', |
||||
'gnu_inline', |
||||
'hot', |
||||
'malloc', |
||||
'noinline', |
||||
'nonnull', |
||||
'noreturn', |
||||
'nothrow', |
||||
'pure', |
||||
'unused', |
||||
'used', |
||||
'warn_unused_result', |
||||
'weak', |
||||
'weakref', |
||||
] |
||||
|
||||
# These are unsupported on darwin with apple clang 9.1.0 |
||||
if host_machine.system() != 'darwin' |
||||
attributes += 'alias' |
||||
attributes += 'visibility' |
||||
endif |
||||
|
||||
if c.get_id() == 'gcc' |
||||
# not supported by clang as of 5.0.0 (at least up to 6.0.1) |
||||
attributes += 'artificial' |
||||
attributes += 'error' |
||||
attributes += 'externally_visible' |
||||
attributes += 'leaf' |
||||
attributes += 'noclone' |
||||
attributes += 'optimize' |
||||
attributes += 'warning' |
||||
|
||||
if c.version().version_compare('>= 7.0.0') |
||||
attributes += 'fallthrough' |
||||
endif |
||||
endif |
||||
|
||||
|
||||
foreach a : attributes |
||||
x = c.has_function_attribute(a) |
||||
assert(x == expected_result, '@0@: @1@'.format(c.get_id(), a)) |
||||
x = cpp.has_function_attribute(a) |
||||
assert(x == expected_result, '@0@: @1@'.format(cpp.get_id(), a)) |
||||
endforeach |
||||
|
||||
win_expect = ['windows', 'cygwin'].contains(host_machine.system()) |
||||
foreach a : ['dllexport', 'dllimport'] |
||||
assert(c.has_function_attribute(a) == win_expect, |
||||
'@0@: @1@'.format(c.get_id(), a)) |
||||
assert(cpp.has_function_attribute(a) == win_expect, |
||||
'@0@: @1@'.format(cpp.get_id(), a)) |
||||
endforeach |
||||
|
||||
message('checking get_supported_function_attributes') |
||||
if c.get_id() != 'msvc' |
||||
multi_expected = attributes |
||||
else |
||||
multi_expected = [] |
||||
endif |
||||
|
||||
multi_check = c.get_supported_function_attributes(attributes) |
||||
assert(multi_check == multi_expected, 'get_supported_function_arguments works (C)') |
||||
multi_check = cpp.get_supported_function_attributes(attributes) |
||||
assert(multi_check == multi_expected, 'get_supported_function_arguments works (C++)') |
Loading…
Reference in new issue