]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #!/usr/bin/python |
2 | ||
3 | # Copyright (C) 2013 Steven Watanabe | |
4 | # Distributed under the Boost Software License, Version 1.0. | |
5 | # (See accompanying file LICENSE_1_0.txt or copy at | |
6 | # http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | import sys | |
9 | ||
10 | def create(t): | |
11 | t.write('''mockinfo.py''', ''' | |
12 | import re | |
13 | import optparse | |
14 | import os | |
15 | ||
16 | parser = optparse.OptionParser() | |
17 | parser.add_option('-o', dest="output_file") | |
18 | parser.add_option('-x', dest="language") | |
19 | parser.add_option('-c', dest="compile", action="store_true") | |
20 | parser.add_option('-I', dest="includes", action="append") | |
11fdf7f2 | 21 | parser.add_option('-D', dest="defines", action="append") |
7c673cae FG |
22 | parser.add_option('-L', dest="library_path", action="append") |
23 | parser.add_option('--dll', dest="dll", action="store_true") | |
24 | parser.add_option('--archive', dest="archive", action="store_true") | |
25 | parser.add_option('--static-lib', dest="static_libraries", action="append") | |
26 | parser.add_option('--shared-lib', dest="shared_libraries", action="append") | |
27 | ||
28 | cwd = os.environ["JAM_CWD"] | |
29 | ||
30 | class MockInfo(object): | |
31 | def __init__(self, verbose=False): | |
32 | self.files = dict() | |
33 | self.commands = list() | |
34 | self.verbose = verbose | |
35 | def source_file(self, name, pattern): | |
36 | self.files[name] = pattern | |
37 | def action(self, command, status=0): | |
11fdf7f2 TL |
38 | if isinstance(command, str): |
39 | command = command.split() | |
7c673cae FG |
40 | self.commands.append((command, status)) |
41 | def check(self, command): | |
42 | print "Testing command", command | |
43 | for (raw, status) in self.commands: | |
44 | if self.matches(raw, command): | |
45 | return status | |
46 | def matches(self, raw, command): | |
11fdf7f2 | 47 | (expected_options, expected_args) = parser.parse_args(raw) |
7c673cae FG |
48 | options = command[0] |
49 | input_files = list(command[1]) | |
50 | if self.verbose: | |
51 | print " - matching against", (expected_options, expected_args) | |
52 | if len(expected_args) != len(input_files): | |
53 | if self.verbose: | |
54 | print " argument list sizes differ" | |
55 | return False | |
56 | for arg in expected_args: | |
57 | if arg.startswith('$'): | |
58 | fileid = arg[1:] | |
59 | pattern = self.files[fileid] if fileid in self.files else fileid | |
60 | matching_file = None | |
61 | for input_file in input_files: | |
62 | with open(input_file, 'r') as f: | |
63 | contents = f.read() | |
64 | if pattern == contents: | |
65 | matching_file = input_file | |
66 | break | |
67 | if matching_file is not None: | |
68 | input_files.remove(matching_file) | |
69 | else: | |
70 | if self.verbose: | |
71 | print " Failed to match input file contents: %s" % arg | |
72 | return False | |
73 | else: | |
74 | if arg in input_files: | |
75 | input_files.remove(arg) | |
76 | else: | |
77 | if self.verbose: | |
78 | print " Failed to match input file: %s" % arg | |
79 | return False | |
80 | ||
81 | if options.language != expected_options.language: | |
82 | if self.verbose: | |
83 | print " Failed to match -c" | |
84 | return False | |
85 | ||
86 | if options.compile != expected_options.compile: | |
87 | if self.verbose: | |
88 | print " Failed to match -x" | |
89 | return False | |
90 | ||
91 | # Normalize a path for comparison purposes | |
92 | def adjust_path(p): | |
93 | return os.path.normcase(os.path.normpath(os.path.join(cwd, p))) | |
94 | ||
95 | # order matters | |
96 | if options.includes is None: | |
97 | options.includes = [] | |
98 | if expected_options.includes is None: | |
99 | expected_options.includes = [] | |
100 | if map(adjust_path, options.includes) != \ | |
101 | map(adjust_path, expected_options.includes): | |
102 | if self.verbose: | |
103 | print " Failed to match -I ", map(adjust_path, options.includes), \ | |
104 | " != ", map(adjust_path, expected_options.includes) | |
105 | return False | |
106 | ||
11fdf7f2 TL |
107 | if options.defines is None: |
108 | options.defines = [] | |
109 | if expected_options.defines is None: | |
110 | expected_options.defines = [] | |
111 | if options.defines != expected_options.defines: | |
112 | if self.verbose: | |
113 | print " Failed to match -I ", options.defines, \ | |
114 | " != ", expected_options.defines | |
115 | return False | |
116 | ||
7c673cae FG |
117 | if options.library_path is None: |
118 | options.library_path = [] | |
119 | if expected_options.library_path is None: | |
120 | expected_options.library_path = [] | |
121 | if map(adjust_path, options.library_path) != \ | |
122 | map(adjust_path, expected_options.library_path): | |
123 | if self.verbose: | |
124 | print " Failed to match -L ", map(adjust_path, options.library_path), \ | |
125 | " != ", map(adjust_path, expected_options.library_path) | |
126 | return False | |
127 | ||
128 | if options.static_libraries != expected_options.static_libraries: | |
129 | if self.verbose: | |
130 | print " Failed to match --static-lib" | |
131 | return False | |
132 | ||
133 | if options.shared_libraries != expected_options.shared_libraries: | |
134 | if self.verbose: | |
135 | print " Failed to match --shared-lib" | |
136 | return False | |
137 | ||
138 | if options.dll != expected_options.dll: | |
139 | if self.verbose: | |
140 | print " Failed to match --dll" | |
141 | return False | |
142 | ||
143 | if options.archive != expected_options.archive: | |
144 | if self.verbose: | |
145 | print " Failed to match --archive" | |
146 | return False | |
147 | ||
148 | # The output must be handled after everything else | |
149 | # is validated | |
150 | if expected_options.output_file is not None: | |
151 | if options.output_file is not None: | |
152 | if expected_options.output_file.startswith('$'): | |
153 | fileid = expected_options.output_file[1:] | |
154 | if fileid not in self.files: | |
155 | self.files[fileid] = fileid | |
156 | else: | |
157 | assert(self.files[fileid] == fileid) | |
158 | with open(options.output_file, 'w') as output: | |
159 | output.write(fileid) | |
160 | else: | |
161 | if self.verbose: | |
162 | print "Failed to match -o" | |
163 | return False | |
164 | elif options.output_file is not None: | |
165 | if self.verbose: | |
166 | print "Failed to match -o" | |
167 | return False | |
168 | ||
169 | # if we've gotten here, then everything matched | |
170 | if self.verbose: | |
171 | print " Matched" | |
172 | return True | |
173 | ''') | |
174 | ||
175 | t.write('mock.py', ''' | |
176 | import mockinfo | |
177 | import markup | |
178 | import sys | |
179 | ||
180 | status = markup.info.check(mockinfo.parser.parse_args()) | |
181 | if status is not None: | |
182 | exit(status) | |
183 | else: | |
184 | print("Unrecognized command: " + ' '.join(sys.argv)) | |
185 | exit(1) | |
186 | ''') | |
187 | ||
188 | t.write('mock.jam', ''' | |
189 | import feature ; | |
190 | import toolset ; | |
191 | import path ; | |
192 | import modules ; | |
193 | import common ; | |
194 | import type ; | |
195 | ||
196 | .python-cmd = "\"%s\"" ; | |
197 | ||
198 | # Behave the same as gcc on Windows, because that's what | |
199 | # the test system expects | |
200 | type.set-generated-target-prefix SHARED_LIB : <toolset>mock <target-os>windows : lib ; | |
201 | type.set-generated-target-suffix STATIC_LIB : <toolset>mock <target-os>windows : a ; | |
202 | ||
203 | rule init ( ) | |
204 | { | |
205 | local here = [ path.make [ modules.binding $(__name__) ] ] ; | |
206 | here = [ path.native [ path.root [ path.parent $(here) ] [ path.pwd ] ] ] ; | |
207 | .config-cmd = [ common.variable-setting-command JAM_CWD : $(here) ] $(.python-cmd) -B ; | |
208 | } | |
209 | ||
210 | feature.extend toolset : mock ; | |
211 | ||
212 | generators.register-c-compiler mock.compile.c++ : CPP : OBJ : <toolset>mock ; | |
213 | generators.register-c-compiler mock.compile.c : C : OBJ : <toolset>mock ; | |
214 | ||
215 | generators.register-linker mock.link : LIB OBJ : EXE : <toolset>mock ; | |
216 | generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : <toolset>mock ; | |
217 | generators.register-archiver mock.archive : OBJ : STATIC_LIB : <toolset>mock ; | |
218 | ||
11fdf7f2 TL |
219 | toolset.flags mock.compile OPTIONS <link>shared : -fPIC ; |
220 | toolset.flags mock.compile INCLUDES : <include> ; | |
221 | toolset.flags mock.compile DEFINES : <define> ; | |
7c673cae FG |
222 | |
223 | actions compile.c | |
224 | { | |
11fdf7f2 | 225 | $(.config-cmd) mock.py -c -x c -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)" |
7c673cae FG |
226 | } |
227 | ||
228 | actions compile.c++ | |
229 | { | |
11fdf7f2 | 230 | $(.config-cmd) mock.py -c -x c++ -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)" |
7c673cae FG |
231 | } |
232 | ||
233 | toolset.flags mock.link USER_OPTIONS <linkflags> ; | |
234 | toolset.flags mock.link FINDLIBS-STATIC <find-static-library> ; | |
235 | toolset.flags mock.link FINDLIBS-SHARED <find-shared-library> ; | |
236 | toolset.flags mock.link LINK_PATH <library-path> ; | |
237 | toolset.flags mock.link LIBRARIES <library-file> ; | |
238 | ||
239 | actions link | |
240 | { | |
241 | $(.config-cmd) mock.py "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED) | |
242 | } | |
243 | ||
244 | actions archive | |
245 | { | |
246 | $(.config-cmd) mock.py --archive "$(>)" -o "$(<)" $(USER_OPTIONS) | |
247 | } | |
248 | ||
249 | actions link.dll | |
250 | { | |
251 | $(.config-cmd) mock.py --dll "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED) | |
252 | } | |
253 | ||
254 | ''' % sys.executable.replace('\\', '\\\\')) | |
255 | ||
256 | def set_expected(t, markup): | |
257 | verbose = "True" if t.verbose else "False" | |
258 | t.write('markup.py', ''' | |
259 | import mockinfo | |
260 | info = mockinfo.MockInfo(%s) | |
261 | def source_file(name, contents): | |
262 | info.source_file(name, contents) | |
263 | def action(command, status=0): | |
264 | info.action(command, status) | |
265 | ''' % verbose + markup) |