1 |
From: matoro <matoro@××××××××××××××××××××.com> |
2 |
|
3 |
My take on implementing bug 820101 as conservatively as possible. This |
4 |
will append -latomic only when absolutely necessary (even though it's |
5 |
probably not required to be that conservative due to our use of |
6 |
--as-needed). |
7 |
|
8 |
This will take flags into account when testing as well. For example, if |
9 |
you compile with -march=i386, this would require linking libatomic even |
10 |
if the same toolchain with a higher -march level would not require it. |
11 |
So rebuilding the same package with the same flags may change whether |
12 |
-latomic is linked at build time if the CFLAGS change. Another instance |
13 |
might be switching from GCC to clang - the former requires explicitly |
14 |
linking -latomic, while the latter does not even HAVE libatomic (see bug |
15 |
820095) as all atomic intrinsics are built-in internally. This function |
16 |
would safely detect this and not append -latomic. |
17 |
|
18 |
There is an optional parameter [bytes]. You can use this if you want to |
19 |
be specific about what size atomic support is required. For example, |
20 |
there are several platforms like MIPS where the 32-bit version has 1-, |
21 |
2-, and 4-byte atomics builtin but requires libatomic linkage for 8-byte |
22 |
atomics. If your program only requires, say, 4-byte atomics, you can use |
23 |
append-atomic-flags 4 and this will then not attempt to link libatomic |
24 |
on 32-bit MIPS. |
25 |
|
26 |
I tested using this to solve bug 688574 on 32-bit SPARC. |
27 |
|
28 |
Closes: https://bugs.gentoo.org/820101 |
29 |
Signed-off-by: matoro <matoro@××××××××××××××××××××.com> |
30 |
Closes: https://github.com/gentoo/gentoo/pull/26334 |
31 |
Signed-off-by: Sam James <sam@g.o> |
32 |
--- |
33 |
eclass/flag-o-matic.eclass | 145 +++++++++++++++++++++++++++++++++++++ |
34 |
1 file changed, 145 insertions(+) |
35 |
|
36 |
diff --git a/eclass/flag-o-matic.eclass b/eclass/flag-o-matic.eclass |
37 |
index 0dd2c1191273..503f23a141a1 100644 |
38 |
--- a/eclass/flag-o-matic.eclass |
39 |
+++ b/eclass/flag-o-matic.eclass |
40 |
@@ -875,4 +875,149 @@ no-as-needed() { |
41 |
esac |
42 |
} |
43 |
|
44 |
+# @FUNCTION: _test-compile-PROG |
45 |
+# @USAGE: <language> <code> |
46 |
+# @INTERNAL |
47 |
+# @DESCRIPTION: |
48 |
+# Attempts to compile (and possibly link) the given program. The first |
49 |
+# <language> parameter corresponds to the standard -x compiler argument. |
50 |
+# If the program should additionally be attempted to be linked, the string |
51 |
+# "+ld" should be added to the <language> parameter. |
52 |
+_test-compile-PROG() { |
53 |
+ local lang=$1 |
54 |
+ local code=$2 |
55 |
+ shift 2 |
56 |
+ |
57 |
+ [[ -z "${lang}" ]] && return 1 |
58 |
+ [[ -z "${code}" ]] && return 1 |
59 |
+ |
60 |
+ local compiler filename_in filename_out args=() libs=() |
61 |
+ case "${lang}" in |
62 |
+ c) |
63 |
+ compiler="$(tc-getCC)" |
64 |
+ filename_in="${T}/test.c" |
65 |
+ filename_out="${T}/test.o" |
66 |
+ args+=(${CFLAGS[@]} -xc -c) |
67 |
+ ;; |
68 |
+ c++) |
69 |
+ compiler="$(tc-getCXX)" |
70 |
+ filename_in="${T}/test.cc" |
71 |
+ filename_out="${T}/test.o" |
72 |
+ args+=(${CXXFLAGS[@]} -xc++ -c) |
73 |
+ ;; |
74 |
+ f77) |
75 |
+ compiler="$(tc-getF77)" |
76 |
+ filename_in="${T}/test.f" |
77 |
+ filename_out="${T}/test.o" |
78 |
+ args+=(${FFFLAGS[@]} -xf77 -c) |
79 |
+ ;; |
80 |
+ f95) |
81 |
+ compiler="$(tc-getFC)" |
82 |
+ filename_in="${T}/test.f90" |
83 |
+ filename_out="${T}/test.o" |
84 |
+ args+=(${FCFLAGS[@]} -xf95 -c) |
85 |
+ ;; |
86 |
+ c+ld) |
87 |
+ compiler="$(tc-getCC)" |
88 |
+ filename_in="${T}/test.c" |
89 |
+ filename_out="${T}/test.exe" |
90 |
+ args+=(${CFLAGS[@]} ${LDFLAGS[@]} -xc) |
91 |
+ libs+=(${LIBS[@]}) |
92 |
+ ;; |
93 |
+ c+++ld) |
94 |
+ compiler="$(tc-getCXX)" |
95 |
+ filename_in="${T}/test.cc" |
96 |
+ filename_out="${T}/test.exe" |
97 |
+ args+=(${CXXFLAGS[@]} ${LDFLAGS[@]} -xc++) |
98 |
+ libs+=(${LIBS[@]}) |
99 |
+ ;; |
100 |
+ f77+ld) |
101 |
+ compiler="$(tc-getF77)" |
102 |
+ filename_in="${T}/test.f" |
103 |
+ filename_out="${T}/test.exe" |
104 |
+ args+=(${FFLAGS[@]} ${LDFLAGS[@]} -xf77) |
105 |
+ libs+=(${LIBS[@]}) |
106 |
+ ;; |
107 |
+ f95+ld) |
108 |
+ compiler="$(tc-getFC)" |
109 |
+ filename_in="${T}/test.f90" |
110 |
+ filename_out="${T}/test.exe" |
111 |
+ args+=(${FCFLAGS[@]} ${LDFLAGS[@]} -xf95) |
112 |
+ libs+=(${LIBS[@]}) |
113 |
+ ;; |
114 |
+ *) |
115 |
+ die "Unknown compiled language ${lang}" |
116 |
+ ;; |
117 |
+ esac |
118 |
+ |
119 |
+ printf "%s\n" "${code}" > "${filename_in}" || die "Failed to create '${test_in}'" |
120 |
+ |
121 |
+ "${compiler}" ${args[@]} "${filename_in}" -o "${filename_out}" ${libs[@]} &>/dev/null |
122 |
+} |
123 |
+ |
124 |
+# @FUNCTION: append-atomic-flags |
125 |
+# @USAGE: [bytes] |
126 |
+# @DESCRIPTION: Attempts to detect if appending -latomic is required to use |
127 |
+# a specific-sized atomic intrinsic, and if so, appends it. If the bytesize |
128 |
+# is not specified, then check the four most common byte sizes (1, 2, 4, 8). |
129 |
+# >=16-byte atomics are not included in this default set and must be explicitly |
130 |
+# passed if required. This may require you to add a macro definition like |
131 |
+# -Duint128_t=__uint128_t to your CFLAGS. |
132 |
+append-atomic-flags() { |
133 |
+ # this implementation is as described in bug #820101 |
134 |
+ local code |
135 |
+ |
136 |
+ # first, ensure we can compile a trivial program |
137 |
+ # this is because we can't distinguish if _test-compile-PROG |
138 |
+ # fails because -latomic is actually needed or if we have a |
139 |
+ # broken toolchain (like due to bad FLAGS) |
140 |
+ read -r -d '' code <<- EOF |
141 |
+ int main() |
142 |
+ { |
143 |
+ return 0; |
144 |
+ } |
145 |
+ EOF |
146 |
+ |
147 |
+ # if toolchain is broken, just return silently. it's better to |
148 |
+ # let other pieces of the build fail later down the line than to |
149 |
+ # make people think that something to do with atomic support is the |
150 |
+ # cause of their problems. |
151 |
+ _test-compile-PROG "c+ld" "${code}" || return |
152 |
+ |
153 |
+ local bytesizes |
154 |
+ [[ "${#}" == "0" ]] && bytesizes=( "1" "2" "4" "8" ) || bytesizes="${@}" |
155 |
+ |
156 |
+ for bytesize in ${bytesizes[@]} |
157 |
+ do |
158 |
+ # this sample program is informed by the great testing from the buildroot project: |
159 |
+ # https://github.com/buildroot/buildroot/commit/6856e417da4f3aa77e2a814db2a89429af072f7d |
160 |
+ read -r -d '' code <<- EOF |
161 |
+ #include <stdint.h> |
162 |
+ int main() |
163 |
+ { |
164 |
+ uint$((${bytesize} * 8))_t a = 0; |
165 |
+ __atomic_add_fetch(&a, 3, __ATOMIC_RELAXED); |
166 |
+ __atomic_compare_exchange_n(&a, &a, 2, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED); |
167 |
+ return 0; |
168 |
+ } |
169 |
+ EOF |
170 |
+ |
171 |
+ # do nothing if test program links fine |
172 |
+ _test-compile-PROG "c+ld" "${code}" && continue |
173 |
+ |
174 |
+ # ensure that the toolchain supports -latomic |
175 |
+ test-flags-CCLD "-latomic" &>/dev/null || die "-latomic is required but not supported by $(tc-getCC)" |
176 |
+ |
177 |
+ append-libs "-latomic" |
178 |
+ |
179 |
+ # verify that this did indeed fix the problem |
180 |
+ _test-compile-PROG "c+ld" "${code}" || \ |
181 |
+ die "libatomic does not include an implementation of ${bytesize}-byte atomics for this toolchain" |
182 |
+ |
183 |
+ # if any of the required bytesizes require -latomic, no need to continue |
184 |
+ # checking the others |
185 |
+ return |
186 |
+ done |
187 |
+} |
188 |
+ |
189 |
fi |
190 |
-- |
191 |
2.37.1 |