1 |
On Fri, 04 Jan 2019 16:53:46 +0100 |
2 |
Michał Górny <mgorny@g.o> wrote: |
3 |
|
4 |
> On Thu, 2019-01-03 at 21:39 +0000, James Le Cuirot wrote: |
5 |
> > Python has little concept of cross-compiling but it turns out that |
6 |
> > making it work isn't so hard after all. |
7 |
> > |
8 |
> > Platform-specific details are held within _sysconfigdata.py, |
9 |
> > sysconfig.py, and various distutils files. If we simply symlink these |
10 |
> > from SYSROOT into an empty directory and add that directory to |
11 |
> > PYTHONPATH then we can utilise the build host's Python with the target |
12 |
> > host's settings. |
13 |
> > |
14 |
> > The pkg-config files were already being symlinked in a similar manner |
15 |
> > but now we source them from within SYSROOT. |
16 |
> > |
17 |
> > In order for PYTHONPATH to be respected, Python must be executed via |
18 |
> > the wrapper, which was not the case before. We previously relied |
19 |
> > solely on the PATH but now PYTHON must point to the wrapper rather |
20 |
> > than the usual location under /usr/bin. However, we only do this when |
21 |
> > SYSROOT or EPREFIX are effectively set to avoid unnecessary |
22 |
> > complexity. This has required some rejigging in the way that PYTHON is |
23 |
> > set but it should remain compatible with existing packages. |
24 |
> > |
25 |
> > The python_wrapper_setup function that handles all this has had its |
26 |
> > arguments reordered because no one ever uses the path/workdir |
27 |
> > argument, which makes specifying other arguments tedious. |
28 |
> |
29 |
> This really belongs in a separate patch. |
30 |
|
31 |
Fair enough. |
32 |
|
33 |
> > Some packages rely on python-config but luckily this is just a shell |
34 |
> > script so it can be executed from within SYSROOT. This is bending the |
35 |
> > rules of PMS slightly but Python leaves us with little choice. I also |
36 |
> > wrote those rules so I'm allowed to bend them. ;) |
37 |
> > |
38 |
> > PYTHON_INCLUDEDIR, PYTHON_LIBPATH, and their associated functions are |
39 |
> > generally used during src_configure or src_compile and, as such, they |
40 |
> > now need to have SYSROOT prepended. |
41 |
> > |
42 |
> > python_doheader uses PYTHON_INCLUDEDIR to install new headers and |
43 |
> > therefore needs the value without SYSROOT. It was already stripping |
44 |
> > EPREFIX before so now it simply strips SYSROOT as well. Similar |
45 |
> > instances of this can do likewise or call the functions with SYSROOT |
46 |
> > unset to achieve the same effect. |
47 |
> > |
48 |
> > To make all this work, we are assuming that CPython is located at |
49 |
> > /usr/$(get_libdir)/${EPYTHON}, which is admittedly a little circular |
50 |
> > when we are querying Python for the right paths. I feel the reason |
51 |
> > that python_export was rewritten to query these dynamically was less |
52 |
> > because someone might install Python to some weird location and more |
53 |
> > to avoid special handling for each of the different |
54 |
> > implementations. And what of those other implementations? |
55 |
> |
56 |
> This is a wrong assumption. CPython 3.7 is in /usr/lib/python3.7. |
57 |
|
58 |
It was true at the time I wrote it. I addressed 3.7 later in the patch |
59 |
series. I figured this diff was long enough already so I kept it |
60 |
separate. |
61 |
|
62 |
> > Being Java-based, Jython is installed under the platform-neutral |
63 |
> > /usr/share and presumably has few other platform-specific |
64 |
> > aspects. Enabling native extensions appears non-trivial and none of |
65 |
> > our module packages have enabled support for it anyway. |
66 |
> > |
67 |
> > I think PyPy could potentially support cross-compiling but it |
68 |
> > hardcodes the native extension filename suffix within its own binaries |
69 |
> > with no way to override it. Perhaps we could patch this in somehow but |
70 |
> > I'm afraid I don't care enough. |
71 |
> > |
72 |
> > Together with the following changes to distutils-r1.eclass, I have now |
73 |
> > been able to cross-compile a large number of packages with native |
74 |
> > Python extensions, most with no changes at all, and the rest with only |
75 |
> > minor fixes. |
76 |
> > |
77 |
> > Closes: https://bugs.gentoo.org/503874 |
78 |
> > Bug: https://bugs.gentoo.org/648652 |
79 |
> > Signed-off-by: James Le Cuirot <chewi@g.o> |
80 |
> > --- |
81 |
> > eclass/python-utils-r1.eclass | 120 ++++++++++++++++++++++++++-------- |
82 |
> > 1 file changed, 92 insertions(+), 28 deletions(-) |
83 |
> > |
84 |
> > diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass |
85 |
> > index 1a549f49f3f2..607af1b52f75 100644 |
86 |
> > --- a/eclass/python-utils-r1.eclass |
87 |
> > +++ b/eclass/python-utils-r1.eclass |
88 |
> > @@ -211,9 +211,15 @@ _python_impl_matches() { |
89 |
> > # |
90 |
> > # distutils-r1: Set within any of the python sub-phase functions. |
91 |
> > # |
92 |
> > -# Example value: |
93 |
> > +# If SYSROOT or EPREFIX are effectively set then this will point to an |
94 |
> > +# automatically generated wrapper rather than the usual path under |
95 |
> > +# /usr/bin in order to accommodate cross-compiling. We could do this all |
96 |
> > +# the time but it would add unnecessary complexity. |
97 |
> > +# |
98 |
> > +# Example values: |
99 |
> > # @CODE |
100 |
> > # /usr/bin/python2.7 |
101 |
> > +# /var/tmp/portage/dev-python/pyblake2-1.2.3/temp/python2.7/bin/python2.7 |
102 |
> > # @CODE |
103 |
> > |
104 |
> > # @ECLASS-VARIABLE: EPYTHON |
105 |
> > @@ -256,6 +262,10 @@ _python_impl_matches() { |
106 |
> > # Set and exported on request using python_export(). |
107 |
> > # Requires a proper build-time dependency on the Python implementation. |
108 |
> > # |
109 |
> > +# This is prepended with SYSROOT in order to accommodate |
110 |
> > +# cross-compiling. You may need to strip SYSROOT and EPREFIX if using it |
111 |
> > +# to install new headers. |
112 |
> > +# |
113 |
> > # Example value: |
114 |
> > # @CODE |
115 |
> > # /usr/include/python2.7 |
116 |
> > @@ -270,6 +280,9 @@ _python_impl_matches() { |
117 |
> > # Valid only for CPython. Requires a proper build-time dependency |
118 |
> > # on the Python implementation. |
119 |
> > # |
120 |
> > +# This is prepended with SYSROOT in order to accommodate |
121 |
> > +# cross-compiling. |
122 |
> > +# |
123 |
> > # Example value: |
124 |
> > # @CODE |
125 |
> > # /usr/lib64/libpython2.7.so |
126 |
> > @@ -314,6 +327,10 @@ _python_impl_matches() { |
127 |
> > # Valid only for CPython. Requires a proper build-time dependency |
128 |
> > # on the Python implementation and on pkg-config. |
129 |
> > # |
130 |
> > +# This is prepended with SYSROOT in order to accommodate |
131 |
> > +# cross-compiling. You generally should not execute files within SYSROOT |
132 |
> > +# but python-config is always a shell script. |
133 |
> > +# |
134 |
> > # Example value: |
135 |
> > # @CODE |
136 |
> > # /usr/bin/python2.7-config |
137 |
> > @@ -380,6 +397,10 @@ python_export() { |
138 |
> > esac |
139 |
> > debug-print "${FUNCNAME}: implementation: ${impl}" |
140 |
> > |
141 |
> > + # Many variables below need a PYTHON variable but we should not |
142 |
> > + # export it unless explicitly requested so use _PYTHON instead. |
143 |
> > + local _PYTHON |
144 |
> > + |
145 |
> > for var; do |
146 |
> > case "${var}" in |
147 |
> > EPYTHON) |
148 |
> > @@ -387,21 +408,21 @@ python_export() { |
149 |
> > debug-print "${FUNCNAME}: EPYTHON = ${EPYTHON}" |
150 |
> > ;; |
151 |
> > PYTHON) |
152 |
> > - export PYTHON=${EPREFIX}/usr/bin/${impl} |
153 |
> > + python_wrapper_setup ${impl} PYTHON |
154 |
> > debug-print "${FUNCNAME}: PYTHON = ${PYTHON}" |
155 |
> > ;; |
156 |
> > PYTHON_SITEDIR) |
157 |
> > - [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" |
158 |
> > + python_wrapper_setup ${impl} _PYTHON |
159 |
> > # sysconfig can't be used because: |
160 |
> > # 1) pypy doesn't give site-packages but stdlib |
161 |
> > # 2) jython gives paths with wrong case |
162 |
> > - PYTHON_SITEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die |
163 |
> > + PYTHON_SITEDIR=$("${_PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die |
164 |
> > export PYTHON_SITEDIR |
165 |
> > debug-print "${FUNCNAME}: PYTHON_SITEDIR = ${PYTHON_SITEDIR}" |
166 |
> > ;; |
167 |
> > PYTHON_INCLUDEDIR) |
168 |
> > - [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" |
169 |
> > - PYTHON_INCLUDEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die |
170 |
> > + python_wrapper_setup ${impl} _PYTHON |
171 |
> > + PYTHON_INCLUDEDIR=${SYSROOT}$("${_PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die |
172 |
> > export PYTHON_INCLUDEDIR |
173 |
> > debug-print "${FUNCNAME}: PYTHON_INCLUDEDIR = ${PYTHON_INCLUDEDIR}" |
174 |
> > |
175 |
> > @@ -411,8 +432,8 @@ python_export() { |
176 |
> > fi |
177 |
> > ;; |
178 |
> > PYTHON_LIBPATH) |
179 |
> > - [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" |
180 |
> > - PYTHON_LIBPATH=$("${PYTHON}" -c 'import os.path, sysconfig; print(os.path.join(sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("LDLIBRARY")) if sysconfig.get_config_var("LDLIBRARY") else "")') || die |
181 |
> > + python_wrapper_setup ${impl} _PYTHON |
182 |
> > + PYTHON_LIBPATH=${SYSROOT}$("${_PYTHON}" -c 'import os.path, sysconfig; print(os.path.join(sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("LDLIBRARY")) if sysconfig.get_config_var("LDLIBRARY") else "")') || die |
183 |
> > export PYTHON_LIBPATH |
184 |
> > debug-print "${FUNCNAME}: PYTHON_LIBPATH = ${PYTHON_LIBPATH}" |
185 |
> > |
186 |
> > @@ -457,9 +478,9 @@ python_export() { |
187 |
> > |
188 |
> > case "${impl}" in |
189 |
> > python*) |
190 |
> > - [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it" |
191 |
> > - flags=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die |
192 |
> > - val=${PYTHON}${flags}-config |
193 |
> > + python_wrapper_setup ${impl} _PYTHON |
194 |
> > + flags=$("${_PYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die |
195 |
> > + val=${ESYSROOT-${SYSROOT}${EPREFIX}}/usr/bin/${PYTHON##*/}${flags}-config |
196 |
> > ;; |
197 |
> > *) |
198 |
> > die "${impl}: obtaining ${var} not supported" |
199 |
> > @@ -954,7 +975,7 @@ python_doheader() { |
200 |
> > local d PYTHON_INCLUDEDIR=${PYTHON_INCLUDEDIR} |
201 |
> > [[ ${PYTHON_INCLUDEDIR} ]] || python_export PYTHON_INCLUDEDIR |
202 |
> > |
203 |
> > - d=${PYTHON_INCLUDEDIR#${EPREFIX}} |
204 |
> > + d=${PYTHON_INCLUDEDIR#${ESYSROOT-${SYSROOT}${EPREFIX}}} |
205 |
> > |
206 |
> > ( |
207 |
> > insopts -m 0644 |
208 |
> > @@ -964,7 +985,7 @@ python_doheader() { |
209 |
> > } |
210 |
> > |
211 |
> > # @FUNCTION: python_wrapper_setup |
212 |
> > -# @USAGE: [<path> [<impl>]] |
213 |
> > +# @USAGE: [<impl> [<pyvar> [<path>]]] |
214 |
> > # @DESCRIPTION: |
215 |
> > # Create proper 'python' executable and pkg-config wrappers |
216 |
> > # (if available) in the directory named by <path>. Set up PATH |
217 |
> > @@ -973,6 +994,9 @@ python_doheader() { |
218 |
> > # The wrappers will be created for implementation named by <impl>, |
219 |
> > # or for one named by ${EPYTHON} if no <impl> passed. |
220 |
> > # |
221 |
> > +# The path to the 'python' executable wrapper is exported to the |
222 |
> > +# variable named <pyvar> if given. |
223 |
> |
224 |
> Why do you need that in the first place? The path should be rather |
225 |
> predictable, shouldn't it? |
226 |
|
227 |
I thought about keeping the logic of the PYTHON value back in |
228 |
python_export but it's quite likely someone would export PYTHON without |
229 |
calling python_wrapper_setup and so it would break. If we do that while |
230 |
keeping the call to python_wrapper_setup, you'd need to handle infinite |
231 |
loops for when python_wrapper_setup is called from elsewhere. |
232 |
|
233 |
I initially had it export PYTHON unconditionally but later realised |
234 |
this was impolite and actually caused a problem in dev-lang/python |
235 |
itself. I guess we could export using another variable name but this |
236 |
seemed tidier. |
237 |
|
238 |
The only other way to pass the value back from python_wrapper_setup |
239 |
would be to echo it but that seems ugly and would require amending all |
240 |
the existing invocations. |
241 |
|
242 |
> > +# |
243 |
> > # If the named directory contains a python symlink already, it will |
244 |
> > # be assumed to contain proper wrappers already and only environment |
245 |
> > # setup will be done. If wrapper update is requested, the directory |
246 |
> > @@ -980,25 +1004,41 @@ python_doheader() { |
247 |
> > python_wrapper_setup() { |
248 |
> > debug-print-function ${FUNCNAME} "${@}" |
249 |
> > |
250 |
> > - local impl=${2:-${EPYTHON}} |
251 |
> > - local workdir=${1:-${T}/${impl}} |
252 |
> > + local impl=${1:-${EPYTHON}} |
253 |
> > + local pyvar=${2} |
254 |
> > + local lpyvar=_${pyvar:-PYTHON} |
255 |
> > + |
256 |
> > + # Use separate directories for SYSROOT in case we need to execute |
257 |
> > + # Python in the context of the build host by unsetting SYSROOT. |
258 |
> > + local workdir=${3:-${T}/${impl}${SYSROOT:+-sysroot}} |
259 |
> > |
260 |
> > [[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified." |
261 |
> > [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified." |
262 |
> > |
263 |
> > + local EPYTHON |
264 |
> > + python_export "${impl}" EPYTHON |
265 |
> |
266 |
> I'm getting dizzy because of the amount of circular dependencies between |
267 |
> the two functions you've introduced. This is going to make it trivial |
268 |
> to deadlock it when changing code later. |
269 |
|
270 |
Look below, apart from my removing PYTHON, these lines were already |
271 |
there! Indeed, this made my head hurt too but I tried my best to |
272 |
respect how the eclass works now. If you want to simplify it somehow, |
273 |
I'm totally up for that discussion. |
274 |
|
275 |
> > + |
276 |
> > + # We could use BROOT here but using the PATH accommodates |
277 |
> > + # cross-prefix where the PATH is sometimes manipulated to prefer |
278 |
> > + # build tools from the target prefix (i.e. EPREFIX). |
279 |
> > + # |
280 |
> > + # Also make sure we don't pick up an existing wrapper by replacing |
281 |
> > + # instances of ${T} with a bogus location. The workdir can be |
282 |
> > + # overridden but hopefully it will be somewhere under ${T}. |
283 |
> > + local ${lpyvar}=$(PATH=${PATH//${T}//dev/null} type -P "${EPYTHON}" || die "${FUNCNAME}: can't find ${EPYTHON} in PATH") |
284 |
> |
285 |
> This PATH substitution hack is horrible. |
286 |
|
287 |
It's not my favourite part of the changeset, I'll grant you, but the |
288 |
PATH value only exists for that one line and I wanted to be sure that |
289 |
type -P didn't pick up some other location. I could strip out ${T} more |
290 |
accurately but that would be more code for little benefit. Your call. |
291 |
|
292 |
> > + |
293 |
> > + local pysysroot=${ESYSROOT-${SYSROOT%/}${EPREFIX}} |
294 |
> > + |
295 |
> > if [[ ! -x ${workdir}/bin/python ]]; then |
296 |
> > _python_check_dead_variables |
297 |
> > |
298 |
> > - mkdir -p "${workdir}"/{bin,pkgconfig} || die |
299 |
> > + mkdir -p "${workdir}"/{bin,lib,pkgconfig} || die |
300 |
> > |
301 |
> > # Clean up, in case we were supposed to do a cheap update. |
302 |
> > rm -f "${workdir}"/bin/python{,2,3}{,-config} || die |
303 |
> > rm -f "${workdir}"/bin/2to3 || die |
304 |
> > rm -f "${workdir}"/pkgconfig/python{,2,3}.pc || die |
305 |
> > |
306 |
> > - local EPYTHON PYTHON |
307 |
> > - python_export "${impl}" EPYTHON PYTHON |
308 |
> > - |
309 |
> > local pyver pyother |
310 |
> > if python_is_python3; then |
311 |
> > pyver=3 |
312 |
> > @@ -1012,37 +1052,53 @@ python_wrapper_setup() { |
313 |
> > # note: we don't use symlinks because python likes to do some |
314 |
> > # symlink reading magic that breaks stuff |
315 |
> > # https://bugs.gentoo.org/show_bug.cgi?id=555752 |
316 |
> > - cat > "${workdir}/bin/python" <<-_EOF_ || die |
317 |
> > - #!/bin/sh |
318 |
> > - exec "${PYTHON}" "\${@}" |
319 |
> > - _EOF_ |
320 |
> > - cp "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die |
321 |
> > - chmod +x "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die |
322 |
> > + echo '#!/bin/sh' > "${workdir}/bin/python" || die |
323 |
> > local nonsupp=( "python${pyother}" "python${pyother}-config" ) |
324 |
> > |
325 |
> > # CPython-specific |
326 |
> > if [[ ${EPYTHON} == python* ]]; then |
327 |
> > + local pysysrootlib=${pysysroot}/usr/$(get_libdir) |
328 |
> > + |
329 |
> > cat > "${workdir}/bin/python-config" <<-_EOF_ || die |
330 |
> > #!/bin/sh |
331 |
> > - exec "${PYTHON}-config" "\${@}" |
332 |
> > + exec "${pysysroot}/usr/bin/${EPYTHON}-config" "\${@}" |
333 |
> > _EOF_ |
334 |
> > cp "${workdir}/bin/python-config" \ |
335 |
> > "${workdir}/bin/python${pyver}-config" || die |
336 |
> > chmod +x "${workdir}/bin/python-config" \ |
337 |
> > "${workdir}/bin/python${pyver}-config" || die |
338 |
> > |
339 |
> > + if [[ -n ${pysysroot} ]]; then |
340 |
> > + # Use host-specific data from SYSROOT. Python 2 looks |
341 |
> > + # for _sysconfigdata while Python 3 uses |
342 |
> > + # _PYTHON_SYSCONFIGDATA_NAME. |
343 |
> > + ln -s "${pysysrootlib}/${EPYTHON}"/_sysconfigdata*.py "${workdir}"/lib/_sysconfigdata.py || die |
344 |
> > + |
345 |
> > + # Use distutils/sysconfig from SYSROOT as parts of it |
346 |
> > + # have GENTOO_LIBDIR baked in at Python build time. |
347 |
> > + ln -s "${pysysrootlib}/${EPYTHON}"/{distutils,sysconfig.py} "${workdir}"/lib/ || die |
348 |
> > + |
349 |
> > + # Add env vars to python wrapper accordingly. |
350 |
> > + echo "PYTHONPATH=\"${workdir}/lib\${PYTHONPATH:+:}\${PYTHONPATH}\" _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata \\" \ |
351 |
> > + >> "${workdir}/bin/python" || die |
352 |
> |
353 |
> Use explicit 'export ...' multi-line thing for readability. |
354 |
|
355 |
Okay, I guess using a here document wouldn't be so bad. |
356 |
|
357 |
> > + fi |
358 |
> > + |
359 |
> > # Python 2.6+. |
360 |
> > - ln -s "${PYTHON/python/2to3-}" "${workdir}"/bin/2to3 || die |
361 |
> > + ln -s "${EPYTHON/python/2to3-}" "${workdir}"/bin/2to3 || die |
362 |
> > |
363 |
> > # Python 2.7+. |
364 |
> > - ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}.pc \ |
365 |
> > + ln -s "${pysysrootlib}"/pkgconfig/${EPYTHON/n/n-}.pc \ |
366 |
> > "${workdir}"/pkgconfig/python.pc || die |
367 |
> > ln -s python.pc "${workdir}"/pkgconfig/python${pyver}.pc || die |
368 |
> > else |
369 |
> > nonsupp+=( 2to3 python-config "python${pyver}-config" ) |
370 |
> > fi |
371 |
> > |
372 |
> > + echo "exec \"${!lpyvar}\" \"\${@}\"" >> "${workdir}"/bin/python || die |
373 |
> > + tee "${workdir}"/bin/{python${pyver},"${EPYTHON}"} < "${workdir}"/bin/python >/dev/null || die |
374 |
> |
375 |
> Whatever this is supposed to do, do it simpler. |
376 |
|
377 |
I suppose the one line it saves isn't worth the extra brain time. |
378 |
|
379 |
> > + chmod +x "${workdir}"/bin/{python,python${pyver},"${EPYTHON}"} || die |
380 |
> > + |
381 |
> > local x |
382 |
> > for x in "${nonsupp[@]}"; do |
383 |
> > cat >"${workdir}"/bin/${x} <<-_EOF_ || die |
384 |
> > @@ -1064,6 +1120,14 @@ python_wrapper_setup() { |
385 |
> > PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}} |
386 |
> > fi |
387 |
> > export PATH PKG_CONFIG_PATH |
388 |
> > + |
389 |
> > + if [[ -n ${pyvar} ]]; then |
390 |
> > + if [[ -n ${pysysroot} ]]; then |
391 |
> > + export -- ${pyvar}=${workdir}/bin/${EPYTHON} |
392 |
> > + else |
393 |
> > + export -- ${pyvar}=${!lpyvar} |
394 |
> > + fi |
395 |
> > + fi |
396 |
> |
397 |
> This is just plain ugly. No. |
398 |
|
399 |
Could you be a bit more specific? Whether we make it conditional or |
400 |
not, we need to export something. I have played it safe by only |
401 |
pointing to the wrapper when SYSROOT or EPREFIX are effectively set. If |
402 |
you'd prefer to just use the wrapper all the time then we can do that |
403 |
but I imagine you'd rather minimise the risk to non-cross/prefix users. |
404 |
If ${!lpyvar} is the issue, I did this to ensure that our local |
405 |
variable name doesn't clash with the one being exported but we could |
406 |
just use some fixed obscure name instead. |
407 |
|
408 |
> > } |
409 |
> > |
410 |
> > # @FUNCTION: python_is_python3 |
411 |
> |
412 |
|
413 |
|
414 |
-- |
415 |
James Le Cuirot (chewi) |
416 |
Gentoo Linux Developer |