Gentoo Archives: gentoo-dev

From: Sam James <sam@g.o>
To: gentoo-dev@l.g.o
Cc: toolchain@g.o, sparc@g.o, matoro <matoro@××××××××××××××××××××.com>, Sam James <sam@g.o>
Subject: [gentoo-dev] [PATCH] flag-o-matic.eclass: implement append-atomic-flags
Date: Tue, 19 Jul 2022 21:29:38
Message-Id: 20220719212916.855084-1-sam@gentoo.org
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