1 # functions for handling cross-compilation
3 import os
, sys
, re
, shlex
4 import Utils
, Logs
, Options
5 from Configure
import conf
9 ANSWER_UNKNOWN
= (254, "")
13 cross_answers_incomplete
= False
16 def add_answer(ca_file
, msg
, answer
):
17 '''add an answer to a set of cross answers'''
19 f
= open(ca_file
, 'a')
21 Logs
.error("Unable to open cross-answers file %s" % ca_file
)
23 (retcode
, retstring
) = answer
24 # if retstring is more than one line then we probably
25 # don't care about its actual content (the tests should
26 # yield one-line output in order to comply with the cross-answer
28 retstring
= retstring
.strip()
29 if len(retstring
.split('\n')) > 1:
31 answer
= (retcode
, retstring
)
33 if answer
== ANSWER_OK
:
34 f
.write('%s: OK\n' % msg
)
35 elif answer
== ANSWER_UNKNOWN
:
36 f
.write('%s: UNKNOWN\n' % msg
)
37 elif answer
== ANSWER_NO
:
38 f
.write('%s: NO\n' % msg
)
41 f
.write('%s: "%s"\n' % (msg
, retstring
))
43 f
.write('%s: (%d, "%s")\n' % (msg
, retcode
, retstring
))
47 def cross_answer(ca_file
, msg
):
48 '''return a (retcode,retstring) tuple from a answers file'''
50 f
= open(ca_file
, 'r')
55 if line
== '' or line
[0] == '#':
57 if line
.find(':') != -1:
58 a
= line
.split(':', 1)
59 thismsg
= a
[0].strip()
63 if ans
== "OK" or ans
== "YES":
66 elif ans
== "UNKNOWN":
69 elif ans
== "FAIL" or ans
== "NO":
74 return (0, ans
.strip('"'))
77 return (0, ans
.strip("'"))
79 m
= re
.match('\(\s*(-?\d+)\s*,\s*\"(.*)\"\s*\)', ans
)
82 return (int(m
.group(1)), m
.group(2))
84 raise Utils
.WafError("Bad answer format '%s' in %s" % (line
, ca_file
))
89 class cross_Popen(Utils
.pproc
.Popen
):
90 '''cross-compilation wrapper for Popen'''
91 def __init__(*k
, **kw
):
96 # Three possibilities:
97 # 1. Only cross-answers - try the cross-answers file, and if
98 # there's no corresponding answer, add to the file and mark
99 # the configure process as unfinished.
100 # 2. Only cross-execute - get the answer from cross-execute
101 # 3. Both - try the cross-answers file, and if there is no
102 # corresponding answer - use cross-execute to get an answer,
103 # and add that answer to the file.
104 if '--cross-answers' in args
:
105 # when --cross-answers is set, then change the arguments
106 # to use the cross answers if available
108 i
= args
.index('--cross-answers')
111 ans
= cross_answer(ca_file
, msg
)
113 if '--cross-execute' in args
and ans
== ANSWER_UNKNOWN
:
114 # when --cross-execute is set, then change the arguments
115 # to use the cross emulator
116 i
= args
.index('--cross-execute')
117 newargs
= shlex
.split(args
[i
+1])
118 newargs
.extend(args
[0:i
])
120 p
= real_Popen(newargs
,
121 stdout
=Utils
.pproc
.PIPE
,
122 stderr
=Utils
.pproc
.PIPE
)
123 ce_out
, ce_err
= p
.communicate()
124 ans
= (p
.returncode
, ce_out
)
125 add_answer(ca_file
, msg
, ans
)
130 if ans
== ANSWER_UNKNOWN
:
131 global cross_answers_incomplete
132 cross_answers_incomplete
= True
133 add_answer(ca_file
, msg
, ans
)
134 (retcode
, retstring
) = ans
135 args
= ['/bin/sh', '-c', "echo -n '%s'; exit %d" % (retstring
, retcode
)]
136 real_Popen
.__init
__(*(obj
, args
), **kw
)
140 def SAMBA_CROSS_ARGS(conf
, msg
=None):
141 '''get exec_args to pass when running cross compiled binaries'''
142 if not conf
.env
.CROSS_COMPILE
:
146 if real_Popen
is None:
147 real_Popen
= Utils
.pproc
.Popen
148 Utils
.pproc
.Popen
= cross_Popen
152 if conf
.env
.CROSS_EXECUTE
:
153 ret
.extend(['--cross-execute', conf
.env
.CROSS_EXECUTE
])
155 if conf
.env
.CROSS_ANSWERS
:
157 raise Utils
.WafError("Cannot have NULL msg in cross-answers")
158 ret
.extend(['--cross-answers', os
.path
.join(Options
.launch_dir
, conf
.env
.CROSS_ANSWERS
), msg
])
161 raise Utils
.WafError("Cannot cross-compile without either --cross-execute or --cross-answers")
166 def SAMBA_CROSS_CHECK_COMPLETE(conf
):
167 '''check if we have some unanswered questions'''
168 global cross_answers_incomplete
169 if conf
.env
.CROSS_COMPILE
and cross_answers_incomplete
:
170 raise Utils
.WafError("Cross answers file %s is incomplete" % conf
.env
.CROSS_ANSWERS
)