1 |
On Fri, Jun 20, 2014 at 1:10 PM, Ian Stakenvicius <axs@g.o> wrote: |
2 |
> Thoughts [about wrapping gcc, so that non-native multilib-build ABI's can |
3 |
finally return to a world where [[ ${GCC} != *' '* ]] ]? |
4 |
|
5 |
TLDR: good idea, I'm strongly in favor of it. |
6 |
|
7 |
A wrapper would fix horrors like the following, which, last I checked, was |
8 |
sort-of required* on ABI_X86="*32*" DEFAULT_ABI="amd64" systems with |
9 |
crossdev i686-pc-linux-gnu targets in ${PATH}: |
10 |
|
11 |
--- /usr/portage/eclass/cmake-utils.eclass 2014-05-06 |
12 |
08:31:17.000000000 -0700 |
13 |
+++ /usr/local/portage/gogogmt/eclass/cmake-utils.eclass 2014-06-01 |
14 |
12:36:40.753904765 -0700 |
15 |
@@ -373,14 +373,115 @@ enable_cmake-utils_src_prepare() { |
16 |
} |
17 |
+ |
18 |
+# retrieve a variable (i.e.: FOO) using i.e.: tc_getFOO, |
19 |
+# unless the variable is already defined to a nonempty value, |
20 |
|
21 |
|
22 |
+# in which case, it is returned unaltered |
23 |
|
24 |
|
25 |
+_cmake-utils_tc_get_if_needed() { |
26 |
|
27 |
|
28 |
+ local v="$1" s |
29 |
|
30 |
|
31 |
+ if [[ ${!v} ]] ; then |
32 |
+ s="${!v}" |
33 |
+ else |
34 |
+ s=$(tc-get${v}) |
35 |
+ fi |
36 |
+ echo "${s}" |
37 |
+} |
38 |
|
39 |
+ + |
40 |
|
41 |
|
42 |
+# trim the preceeding and trailing whitespace from a string, |
43 |
+# leaving inner spaces intact |
44 |
+_cmake-utils_trimmed() { |
45 |
+ local s="$*" |
46 |
+ while [[ ${s:0:1} =~ [[:space:]] ]] ; do |
47 |
+ s="${s:1}" |
48 |
+ done |
49 |
+ while [[ ${s:$((${#s}-1))} =~ [[:space:]] ]] ; do |
50 |
+ s="${s:0:$((${#s}-1))}" |
51 |
+ done |
52 |
+ echo "${s}" |
53 |
+} |
54 |
+ |
55 |
+# given a string, retrieve the first word (consisting of non-space |
56 |
characters) |
57 |
+# after trimming any leading whitespace. |
58 |
+_cmake-utils_first_word_of() { |
59 |
+ local s=$(_cmake-utils_trimmed "$*") |
60 |
+ echo "${s%% *}" |
61 |
+} |
62 |
+ |
63 |
+# given a string, retrieve the rest of the string after the first word, |
64 |
+# with any whitespace trimmed, retaining any whitespace between words |
65 |
+# (except whitespace that was between the first and second word) |
66 |
+_cmake-utils_subsequent_words_of() { |
67 |
+ local s=$(_cmake-utils_trimmed "$*") |
68 |
+ if [[ ${s} ]] ; then |
69 |
+ s="${s#$(_cmake-utils_first_word_of "${s}")}" |
70 |
+ echo "$(_cmake-utils_trimmed "${s}")" |
71 |
+ else |
72 |
+ echo "" |
73 |
+ fi |
74 |
+} |
75 |
+ |
76 |
+# given a variable-name, retrieve it with _cmake-utils_tc_get_if_needed |
77 |
+# and then from that retreive the first word |
78 |
+_cmake-utils_get_first_word() { |
79 |
+ local s=$(_cmake-utils_tc_get_if_needed "$1") |
80 |
+ echo "$(_cmake-utils_first_word_of "${s}")" |
81 |
+} |
82 |
+ |
83 |
+# given a command-containing variable as the first argument, |
84 |
+# uses _cmake-utils_tc_get_if_needed to retrieve the var, and then |
85 |
+# returns type -P of the first word of it, ignoring rest. |
86 |
+_cmake-utils_get_first_word_executable() { |
87 |
+ local w=$(_cmake-utils_get_first_word "$1") |
88 |
+ if [[ ${w} ]] ; then |
89 |
+ echo "$(type -P "${w}")" |
90 |
+ else |
91 |
+ echo "" |
92 |
+ fi |
93 |
+} |
94 |
+ |
95 |
+# fetches any additional bits of a variable not included in |
96 |
+# _cmake-utils_get_first_word. takes the variable name as an input. |
97 |
+# May return an empty string. |
98 |
+_cmake-utils_get_subsequent_words() { |
99 |
+ local s=$(_cmake-utils_tc_get_if_needed "$1") |
100 |
+ echo "$(_cmake-utils_subsequent_words_of "${s}")" |
101 |
} |
102 |
|
103 |
# @VARIABLE: mycmakeargs |
104 |
@@ -433,17 +534,46 @@ enable_cmake-utils_src_configure() { |
105 |
|
106 |
# Prepare Gentoo override rules (set valid compiler, append |
107 |
CPPFLAGS etc.) |
108 |
local build_rules=${BUILD_DIR}/gentoo_rules.cmake |
109 |
+ |
110 |
+ local _CMAKE_C_COMPILER=$(_cmake-utils_get_first_word_executable CC) |
111 |
+ local _CCORPHANS=$(_cmake-utils_get_subsequent_words CC) |
112 |
+ local _CMAKE_C_COMPILER_ARG1_COMMAND= |
113 |
+ local _CMAKE_CXX_COMPILER=$(_cmake-utils_get_first_word_executable |
114 |
CXX) |
115 |
+ local _CXXORPHANS=$(_cmake-utils_get_subsequent_words CXX) |
116 |
+ local _CMAKE_CXX_COMPILER_ARG1_COMMAND= |
117 |
+ |
118 |
+ # This seems fairly rediculous to me, but if C{,XX}ORPHANS is |
119 |
nonempty, then, in order to prevent |
120 |
+ # duplication of the first argument, we must handle the first word |
121 |
specially |
122 |
+ if [[ ${_CCORPHANS} ]] ; then |
123 |
+ _CMAKE_C_COMPILER_ARG1_COMMAND="SET (CMAKE_C_COMPILER_ARG1 |
124 |
$(_cmake-utils_first_word_of "${_CCORPHANS}") CACHE STRING \"C compiler |
125 |
first argument\" FORCE)" |
126 |
+ _CCORPHANS=$(_cmake-utils_subsequent_words_of |
127 |
"${_CCORPHANS}") |
128 |
+ fi |
129 |
+ if [[ ${_CXXORPHANS} ]] ; then |
130 |
+ _CMAKE_CXX_COMPILER_ARG1_COMMAND="SET |
131 |
(CMAKE_CXX_COMPILER_ARG1 $(_cmake-utils_first_word_of "${_CXXORPHANS}") |
132 |
CACHE STRING \"C++ compiler first argument\" FORCE)" |
133 |
+ _CXXORPHANS=$(_cmake-utils_subsequent_words_of |
134 |
"${_CXXORPHANS}") |
135 |
+ fi |
136 |
+ |
137 |
cat > "${build_rules}" <<- _EOF_ |
138 |
- SET (CMAKE_AR $(type -P $(tc-getAR)) CACHE FILEPATH |
139 |
"Archive manager" FORCE) |
140 |
- SET (CMAKE_ASM_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> |
141 |
${CFLAGS} <FLAGS> -o <OBJECT> -c <SOURCE>" CACHE STRING "ASM compile |
142 |
command" FORCE) |
143 |
- SET (CMAKE_C_COMPILER $(type -P $(tc-getCC)) CACHE FILEPATH |
144 |
"C compiler" FORCE) |
145 |
- SET (CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> <DEFINES> |
146 |
${CPPFLAGS} <FLAGS> -o <OBJECT> -c <SOURCE>" CACHE STRING "C compile |
147 |
command" FORCE) |
148 |
- SET (CMAKE_CXX_COMPILER $(type -P $(tc-getCXX)) CACHE |
149 |
FILEPATH "C++ compiler" FORCE) |
150 |
- SET (CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> |
151 |
<DEFINES> ${CPPFLAGS} <FLAGS> -o <OBJECT> -c <SOURCE>" CACHE STRING "C++ |
152 |
compile command" FORCE) |
153 |
- SET (CMAKE_RANLIB $(type -P $(tc-getRANLIB)) CACHE FILEPATH |
154 |
"Archive index generator" FORCE) |
155 |
- SET (PKG_CONFIG_EXECUTABLE $(type -P $(tc-getPKG_CONFIG)) |
156 |
CACHE FILEPATH "pkg-config executable" FORCE) |
157 |
+ SET (CMAKE_C_COMPILER "${_CMAKE_C_COMPILER}" CACHE FILEPATH |
158 |
"C compiler" FORCE) |
159 |
+ ${_CMAKE_C_COMPILER_ARG1_COMMAND} |
160 |
+ SET (CMAKE_CXX_COMPILER "${_CMAKE_CXX_COMPILER}" CACHE |
161 |
FILEPATH "C++ compiler" FORCE) |
162 |
+ ${_CMAKE_CXX_COMPILER_ARG1_COMMAND} |
163 |
+ SET (CMAKE_AR "$(_cmake-utils_get_first_word_executable |
164 |
AR)" CACHE FILEPATH "Archive manager" FORCE) |
165 |
+ SET (CMAKE_RANLIB "$(_cmake-utils_get_first_word_executable |
166 |
RANLIB)" CACHE FILEPATH "Archive index generator" FORCE) |
167 |
+ SET (CMAKE_ASM_COMPILE_OBJECT "<CMAKE_C_COMPILER> |
168 |
${_CCORPHANS}${_CCORPHANS:+ }<DEFINES> ${CFLAGS}${CFLAGS:+ }<FLAGS> -o |
169 |
<OBJECT> -c <SOURCE>" CACHE STRING "ASM compile command" FORCE) |
170 |
+ SET (CMAKE_C_COMPILE_OBJECT "<CMAKE_C_COMPILER> |
171 |
${_CCORPHANS}${_CCORPHANS:+ }<DEFINES> ${CFLAGS}${CFLAGS:+ }<FLAGS> -o |
172 |
<OBJECT> -c <SOURCE>" CACHE STRING "C compile command" FORCE) |
173 |
+ SET (CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> |
174 |
${_CXXORPHANS}${_CXXORPHANS:+ }<DEFINES> ${CXXFLAGS}${CXXFLAGS:+ }<FLAGS> |
175 |
-o <OBJECT> -c <SOURCE>" CACHE STRING "C++ compile command" FORCE) |
176 |
+ SET (CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> |
177 |
${_CCORPHANS}${_CCORPHANS:+ }<FLAGS> ${LDFLAGS}${LDFLAGS:+ |
178 |
}<CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" |
179 |
CACHE STRING "C link command for executables" FORCE) |
180 |
+ SET (CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> |
181 |
${_CCORPHANS}${_CCORPHANS:+ }<CMAKE_SHARED_LIBRARY_C_FLAGS> |
182 |
<LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${LDFLAGS}${LDFLAGS:+ |
183 |
}<CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> |
184 |
<CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> |
185 |
<LINK_LIBRARIES>" CACHE STRING "C shared library link command" FORCE) |
186 |
+ SET (CMAKE_C_CREATE_SHARED_MODULE |
187 |
"\${CMAKE_C_CREATE_SHARED_LIBRARY}" CACHE STRING "C shared module link |
188 |
command" FORCE) |
189 |
+ SET (CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> |
190 |
${_CXXORPHANS}${_CXXORPHANS:+ }<FLAGS> ${LDFLAGS}${LDFLAGS:+ |
191 |
}<CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> |
192 |
<LINK_LIBRARIES>" CACHE STRING "C++ link command for executables" FORCE) |
193 |
+ SET (CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> |
194 |
${_CXXORPHANS}${_CXXORPHANS:+ }<CMAKE_SHARED_LIBRARY_CXX_FLAGS> |
195 |
<LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${LDFLAGS}${LDFLAGS:+ |
196 |
}<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> |
197 |
<CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> |
198 |
<LINK_LIBRARIES>" CACHE STRING "C++ shared library link command" FORCE) |
199 |
+ SET (CMAKE_CXX_CREATE_SHARED_MODULE |
200 |
"\${CMAKE_CXX_CREATE_SHARED_LIBRARY}" CACHE STRING "C++ shared module link |
201 |
command" FORCE) |
202 |
+ SET (PKG_CONFIG_EXECUTABLE |
203 |
"$(_cmake-utils_get_first_word_executable PKG_CONFIG)" CACHE FILEPATH |
204 |
"pkg-config executable" FORCE) |
205 |
_EOF_ |
206 |
|
207 |
has "${EAPI:-0}" 0 1 2 && ! use prefix && EPREFIX= |
208 |
|
209 |
Perhaps a straw-man argument, since, the above code could be made more |
210 |
beautiful, and then it would not be so ugly :P |
211 |
|
212 |
But, it's not just that cmake can't properly handle a C{C,XX} variables |
213 |
with spaces in them**. There are a bunch of similar places where we had to |
214 |
patch Makefiles and autotools to wedge GCC="foo bar" support in. |
215 |
|
216 |
Without hyperbole, I can honestly say, it's a lame and inelegant hack to |
217 |
put an /argument/ into GCC. -m${foo} is a CFLAG, not a compiler. |
218 |
"Everyone" knows GCC is a variable that names an executable -- but in |
219 |
multilib-build, for some god-awful reason, we've made it into some other |
220 |
thing, a hybrid-psuedo-thing that really only makes sense in a shell |
221 |
script, and even then, only in an improperly coded shell script :). |
222 |
|
223 |
Even if that rubicon was already crossed by ccache, distcc, etc, there is a |
224 |
reason none of them /require/ it. It's just asking for trouble. We'll |
225 |
just keep wasting time fixing subtle bugs like the above, because of it |
226 |
until we break down and fix it. I'd lay pretty long odds that five years |
227 |
from now we are still clinging to it, should we decide to stick with the |
228 |
status quo for now. So why not bite the bullet and save ourselves the |
229 |
hassle? |
230 |
|
231 |
-gmt |
232 |
|
233 |
* perhaps today the problem is mitigated, due to the same |
234 |
gcc-${pseudo-CHOST} executables now existing for upstream multilib-build |
235 |
pseudo-targets -- but, I'll bet, not solved. Usually trouble only crops up |
236 |
for larger framework builds with lots of sub-dirs, like qt or mysql-server, |
237 |
and manifests as incorrect attempts to link native libraries in -- which |
238 |
the compiler might or might not manage to save you from at the last |
239 |
moment... also note that patch is mocked up for easy reading -- it won't |
240 |
apply. See my overlay for the real code. Finally, sorry for the HTML -- |
241 |
I'm writing from the gmail ajax which obstinately refuses to allow |
242 |
plain-text inline patches. |
243 |
|
244 |
** IIRC, it would be more precise to say something like "cmake's in-built |
245 |
hacks for the CC='exectutable argument' circumstance are subtly |
246 |
incompatible with our means of injecting the portage compiler values into |
247 |
cmake (or so things used to be; I suspect the problem still lurks to some |
248 |
extent), and that this ultimately manifests as confusing, intermittent |
249 |
build failures and correctly issued QA warnings in larger |
250 |
multilib-build-based ebuilds (or will in the near future; I actually |
251 |
wouldn't know as I run with the above patches :P), esp. in cases where a |
252 |
${CC}-${CHOST} or ${CXX}-${CHOST} executables are to be found in ${PATH}." |
253 |
But if any unlucky person is still reading, they can see fully why I |
254 |
didn't bother to say all that :P |