Gentoo Archives: gentoo-dev

From: Greg Turner <gmt@×××××.us>
To: gentoo-dev@l.g.o
Subject: Re: [gentoo-dev] Re: crossdev and multilib interference
Date: Sat, 21 Jun 2014 10:31:39
Message-Id: CA+VB3NRVgaNHjgK+m_rXECO-mznhiJndURRK7+brvkUdhZ8vkw@mail.gmail.com
In Reply to: [gentoo-dev] Re: crossdev and multilib interference by Ian Stakenvicius
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

Replies

Subject Author
Re: [gentoo-dev] Re: crossdev and multilib interference "Michał Górny" <mgorny@g.o>