Merge branch 'master' of ctdb into 'master' of samba
[samba.git] / buildtools / wafsamba / samba_cross.py
1 # functions for handling cross-compilation
2
3 import Utils, Logs, sys, os, Options, re
4 from Configure import conf
5
6 real_Popen = None
7
8 ANSWER_UNKNOWN = (254, "")
9 ANSWER_FAIL    = (255, "")
10 ANSWER_OK      = (0, "")
11
12 cross_answers_incomplete = False
13
14
15 def add_answer(ca_file, msg, answer):
16     '''add an answer to a set of cross answers'''
17     try:
18         f = open(ca_file, 'a')
19     except:
20         Logs.error("Unable to open cross-answers file %s" % ca_file)
21         sys.exit(1)
22     if answer == ANSWER_OK:
23         f.write('%s: OK\n' % msg)
24     elif answer == ANSWER_UNKNOWN:
25         f.write('%s: UNKNOWN\n' % msg)
26     elif answer == ANSWER_FAIL:
27         f.write('%s: FAIL\n' % msg)
28     else:
29         (retcode, retstring) = answer
30         f.write('%s: (%d, "%s")' % (msg, retcode, retstring))
31     f.close()
32
33
34 def cross_answer(ca_file, msg):
35     '''return a (retcode,retstring) tuple from a answers file'''
36     try:
37         f = open(ca_file, 'r')
38     except:
39         add_answer(ca_file, msg, ANSWER_UNKNOWN)
40         return ANSWER_UNKNOWN
41     for line in f:
42         line = line.strip()
43         if line == '' or line[0] == '#':
44             continue
45         if line.find(':') != -1:
46             a = line.split(':')
47             thismsg = a[0].strip()
48             if thismsg != msg:
49                 continue
50             ans = a[1].strip()
51             if ans == "OK" or ans == "YES":
52                 f.close()
53                 return ANSWER_OK
54             elif ans == "UNKNOWN":
55                 f.close()
56                 return ANSWER_UNKNOWN
57             elif ans == "FAIL" or ans == "NO":
58                 f.close()
59                 return ANSWER_FAIL
60             elif ans[0] == '"':
61                 return (0, ans.strip('"'))
62             elif ans[0] == "'":
63                 return (0, ans.strip("'"))
64             else:
65                 m = re.match('\(\s*(-?\d+)\s*,\s*\"(.*)\"\s*\)', ans)
66                 if m:
67                     f.close()
68                     return (int(m.group(1)), m.group(2))
69                 else:
70                     raise Utils.WafError("Bad answer format '%s' in %s" % (line, ca_file))
71     f.close()
72     add_answer(ca_file, msg, ANSWER_UNKNOWN)
73     return ANSWER_UNKNOWN
74
75
76 class cross_Popen(Utils.pproc.Popen):
77     '''cross-compilation wrapper for Popen'''
78     def __init__(*k, **kw):
79         (obj, args) = k
80
81         if '--cross-execute' in args:
82             # when --cross-execute is set, then change the arguments
83             # to use the cross emulator
84             i = args.index('--cross-execute')
85             newargs = args[i+1].split()
86             newargs.extend(args[0:i])
87             args = newargs
88         elif '--cross-answers' in args:
89             # when --cross-answers is set, then change the arguments
90             # to use the cross answers if available
91             i = args.index('--cross-answers')
92             ca_file = args[i+1]
93             msg     = args[i+2]
94             ans = cross_answer(ca_file, msg)
95             if ans == ANSWER_UNKNOWN:
96                 global cross_answers_incomplete
97                 cross_answers_incomplete = True
98             (retcode, retstring) = ans
99             args = ['/bin/sh', '-c', "echo -n '%s'; exit %d" % (retstring, retcode)]
100         real_Popen.__init__(*(obj, args), **kw)
101
102
103 @conf
104 def SAMBA_CROSS_ARGS(conf, msg=None):
105     '''get exec_args to pass when running cross compiled binaries'''
106     if not conf.env.CROSS_COMPILE:
107         return []
108
109     global real_Popen
110     if real_Popen is None:
111         real_Popen  = Utils.pproc.Popen
112         Utils.pproc.Popen = cross_Popen
113
114     ret = []
115
116     if conf.env.CROSS_EXECUTE:
117         ret.extend(['--cross-execute', conf.env.CROSS_EXECUTE])
118     elif conf.env.CROSS_ANSWERS:
119         if msg is None:
120             raise Utils.WafError("Cannot have NULL msg in cross-answers")
121         ret.extend(['--cross-answers', os.path.join(Options.launch_dir, conf.env.CROSS_ANSWERS), msg])
122
123     if ret == []:
124         raise Utils.WafError("Cannot cross-compile without either --cross-execute or --cross-answers")
125
126     return ret
127
128 @conf
129 def SAMBA_CROSS_CHECK_COMPLETE(conf):
130     '''check if we have some unanswered questions'''
131     global cross_answers_incomplete
132     if conf.env.CROSS_COMPILE and cross_answers_incomplete:
133         raise Utils.WafError("Cross answers file %s is incomplete" % conf.env.CROSS_ANSWERS)
134     return True