1 | #! /usr/bin/env python |
---|
2 | # encoding: utf-8 |
---|
3 | # WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file |
---|
4 | |
---|
5 | import os,shlex,shutil,traceback,errno,sys,stat |
---|
6 | from waflib import Utils,Configure,Logs,Options,ConfigSet,Context,Errors,Build,Node |
---|
7 | build_dir_override=None |
---|
8 | no_climb_commands=['configure'] |
---|
9 | default_cmd="build" |
---|
10 | def waf_entry_point(current_directory,version,wafdir): |
---|
11 | Logs.init_log() |
---|
12 | if Context.WAFVERSION!=version: |
---|
13 | Logs.error('Waf script %r and library %r do not match (directory %r)'%(version,Context.WAFVERSION,wafdir)) |
---|
14 | sys.exit(1) |
---|
15 | if'--version'in sys.argv: |
---|
16 | Context.run_dir=current_directory |
---|
17 | ctx=Context.create_context('options') |
---|
18 | ctx.curdir=current_directory |
---|
19 | ctx.parse_args() |
---|
20 | sys.exit(0) |
---|
21 | if len(sys.argv)>1: |
---|
22 | potential_wscript=os.path.join(current_directory,sys.argv[1]) |
---|
23 | if os.path.basename(potential_wscript)=='wscript'and os.path.isfile(potential_wscript): |
---|
24 | current_directory=os.path.normpath(os.path.dirname(potential_wscript)) |
---|
25 | sys.argv.pop(1) |
---|
26 | Context.waf_dir=wafdir |
---|
27 | Context.launch_dir=current_directory |
---|
28 | no_climb=os.environ.get('NOCLIMB',None) |
---|
29 | if not no_climb: |
---|
30 | for k in no_climb_commands: |
---|
31 | for y in sys.argv: |
---|
32 | if y.startswith(k): |
---|
33 | no_climb=True |
---|
34 | break |
---|
35 | cur=current_directory |
---|
36 | while cur: |
---|
37 | lst=os.listdir(cur) |
---|
38 | if Options.lockfile in lst: |
---|
39 | env=ConfigSet.ConfigSet() |
---|
40 | try: |
---|
41 | env.load(os.path.join(cur,Options.lockfile)) |
---|
42 | ino=os.stat(cur)[stat.ST_INO] |
---|
43 | except Exception: |
---|
44 | pass |
---|
45 | else: |
---|
46 | for x in(env.run_dir,env.top_dir,env.out_dir): |
---|
47 | if Utils.is_win32: |
---|
48 | if cur==x: |
---|
49 | load=True |
---|
50 | break |
---|
51 | else: |
---|
52 | try: |
---|
53 | ino2=os.stat(x)[stat.ST_INO] |
---|
54 | except OSError: |
---|
55 | pass |
---|
56 | else: |
---|
57 | if ino==ino2: |
---|
58 | load=True |
---|
59 | break |
---|
60 | else: |
---|
61 | Logs.warn('invalid lock file in %s'%cur) |
---|
62 | load=False |
---|
63 | if load: |
---|
64 | Context.run_dir=env.run_dir |
---|
65 | Context.top_dir=env.top_dir |
---|
66 | Context.out_dir=env.out_dir |
---|
67 | break |
---|
68 | if not Context.run_dir: |
---|
69 | if Context.WSCRIPT_FILE in lst: |
---|
70 | Context.run_dir=cur |
---|
71 | next=os.path.dirname(cur) |
---|
72 | if next==cur: |
---|
73 | break |
---|
74 | cur=next |
---|
75 | if no_climb: |
---|
76 | break |
---|
77 | if not Context.run_dir: |
---|
78 | if'-h'in sys.argv or'--help'in sys.argv: |
---|
79 | Logs.warn('No wscript file found: the help message may be incomplete') |
---|
80 | Context.run_dir=current_directory |
---|
81 | ctx=Context.create_context('options') |
---|
82 | ctx.curdir=current_directory |
---|
83 | ctx.parse_args() |
---|
84 | sys.exit(0) |
---|
85 | Logs.error('Waf: Run from a directory containing a file named %r'%Context.WSCRIPT_FILE) |
---|
86 | sys.exit(1) |
---|
87 | try: |
---|
88 | os.chdir(Context.run_dir) |
---|
89 | except OSError: |
---|
90 | Logs.error('Waf: The folder %r is unreadable'%Context.run_dir) |
---|
91 | sys.exit(1) |
---|
92 | try: |
---|
93 | set_main_module(os.path.join(Context.run_dir,Context.WSCRIPT_FILE)) |
---|
94 | except Errors.WafError ,e: |
---|
95 | Logs.pprint('RED',e.verbose_msg) |
---|
96 | Logs.error(str(e)) |
---|
97 | sys.exit(1) |
---|
98 | except Exception ,e: |
---|
99 | Logs.error('Waf: The wscript in %r is unreadable'%Context.run_dir,e) |
---|
100 | traceback.print_exc(file=sys.stdout) |
---|
101 | sys.exit(2) |
---|
102 | try: |
---|
103 | run_commands() |
---|
104 | except Errors.WafError ,e: |
---|
105 | if Logs.verbose>1: |
---|
106 | Logs.pprint('RED',e.verbose_msg) |
---|
107 | Logs.error(e.msg) |
---|
108 | sys.exit(1) |
---|
109 | except SystemExit: |
---|
110 | raise |
---|
111 | except Exception ,e: |
---|
112 | traceback.print_exc(file=sys.stdout) |
---|
113 | sys.exit(2) |
---|
114 | except KeyboardInterrupt: |
---|
115 | Logs.pprint('RED','Interrupted') |
---|
116 | sys.exit(68) |
---|
117 | def set_main_module(file_path): |
---|
118 | Context.g_module=Context.load_module(file_path) |
---|
119 | Context.g_module.root_path=file_path |
---|
120 | def set_def(obj): |
---|
121 | name=obj.__name__ |
---|
122 | if not name in Context.g_module.__dict__: |
---|
123 | setattr(Context.g_module,name,obj) |
---|
124 | for k in(update,dist,distclean,distcheck,update): |
---|
125 | set_def(k) |
---|
126 | if not'init'in Context.g_module.__dict__: |
---|
127 | Context.g_module.init=Utils.nada |
---|
128 | if not'shutdown'in Context.g_module.__dict__: |
---|
129 | Context.g_module.shutdown=Utils.nada |
---|
130 | if not'options'in Context.g_module.__dict__: |
---|
131 | Context.g_module.options=Utils.nada |
---|
132 | def parse_options(): |
---|
133 | Context.create_context('options').execute() |
---|
134 | for var in Options.envvars: |
---|
135 | (name,value)=var.split('=',1) |
---|
136 | os.environ[name.strip()]=value |
---|
137 | if not Options.commands: |
---|
138 | Options.commands=[default_cmd] |
---|
139 | Options.commands=[x for x in Options.commands if x!='options'] |
---|
140 | Logs.verbose=Options.options.verbose |
---|
141 | if Options.options.zones: |
---|
142 | Logs.zones=Options.options.zones.split(',') |
---|
143 | if not Logs.verbose: |
---|
144 | Logs.verbose=1 |
---|
145 | elif Logs.verbose>0: |
---|
146 | Logs.zones=['runner'] |
---|
147 | if Logs.verbose>2: |
---|
148 | Logs.zones=['*'] |
---|
149 | def run_command(cmd_name): |
---|
150 | ctx=Context.create_context(cmd_name) |
---|
151 | ctx.log_timer=Utils.Timer() |
---|
152 | ctx.options=Options.options |
---|
153 | ctx.cmd=cmd_name |
---|
154 | try: |
---|
155 | ctx.execute() |
---|
156 | finally: |
---|
157 | ctx.finalize() |
---|
158 | return ctx |
---|
159 | def run_commands(): |
---|
160 | parse_options() |
---|
161 | run_command('init') |
---|
162 | while Options.commands: |
---|
163 | cmd_name=Options.commands.pop(0) |
---|
164 | ctx=run_command(cmd_name) |
---|
165 | Logs.info('%r finished successfully (%s)'%(cmd_name,str(ctx.log_timer))) |
---|
166 | run_command('shutdown') |
---|
167 | def _can_distclean(name): |
---|
168 | for k in'.o .moc .exe'.split(): |
---|
169 | if name.endswith(k): |
---|
170 | return True |
---|
171 | return False |
---|
172 | def distclean_dir(dirname): |
---|
173 | for(root,dirs,files)in os.walk(dirname): |
---|
174 | for f in files: |
---|
175 | if _can_distclean(f): |
---|
176 | fname=os.path.join(root,f) |
---|
177 | try: |
---|
178 | os.remove(fname) |
---|
179 | except OSError: |
---|
180 | Logs.warn('Could not remove %r'%fname) |
---|
181 | for x in(Context.DBFILE,'config.log'): |
---|
182 | try: |
---|
183 | os.remove(x) |
---|
184 | except OSError: |
---|
185 | pass |
---|
186 | try: |
---|
187 | shutil.rmtree('c4che') |
---|
188 | except OSError: |
---|
189 | pass |
---|
190 | def distclean(ctx): |
---|
191 | '''removes the build directory''' |
---|
192 | lst=os.listdir('.') |
---|
193 | for f in lst: |
---|
194 | if f==Options.lockfile: |
---|
195 | try: |
---|
196 | proj=ConfigSet.ConfigSet(f) |
---|
197 | except IOError: |
---|
198 | Logs.warn('Could not read %r'%f) |
---|
199 | continue |
---|
200 | if proj['out_dir']!=proj['top_dir']: |
---|
201 | try: |
---|
202 | shutil.rmtree(proj['out_dir']) |
---|
203 | except IOError: |
---|
204 | pass |
---|
205 | except OSError ,e: |
---|
206 | if e.errno!=errno.ENOENT: |
---|
207 | Logs.warn('Could not remove %r'%proj['out_dir']) |
---|
208 | else: |
---|
209 | distclean_dir(proj['out_dir']) |
---|
210 | for k in(proj['out_dir'],proj['top_dir'],proj['run_dir']): |
---|
211 | p=os.path.join(k,Options.lockfile) |
---|
212 | try: |
---|
213 | os.remove(p) |
---|
214 | except OSError ,e: |
---|
215 | if e.errno!=errno.ENOENT: |
---|
216 | Logs.warn('Could not remove %r'%p) |
---|
217 | if not Options.commands: |
---|
218 | for x in'.waf-1. waf-1. .waf3-1. waf3-1.'.split(): |
---|
219 | if f.startswith(x): |
---|
220 | shutil.rmtree(f,ignore_errors=True) |
---|
221 | class Dist(Context.Context): |
---|
222 | '''creates an archive containing the project source code''' |
---|
223 | cmd='dist' |
---|
224 | fun='dist' |
---|
225 | algo='tar.bz2' |
---|
226 | ext_algo={} |
---|
227 | def execute(self): |
---|
228 | self.recurse([os.path.dirname(Context.g_module.root_path)]) |
---|
229 | self.archive() |
---|
230 | def archive(self): |
---|
231 | import tarfile |
---|
232 | arch_name=self.get_arch_name() |
---|
233 | try: |
---|
234 | self.base_path |
---|
235 | except AttributeError: |
---|
236 | self.base_path=self.path |
---|
237 | node=self.base_path.make_node(arch_name) |
---|
238 | try: |
---|
239 | node.delete() |
---|
240 | except OSError: |
---|
241 | pass |
---|
242 | files=self.get_files() |
---|
243 | if self.algo.startswith('tar.'): |
---|
244 | tar=tarfile.open(arch_name,'w:'+self.algo.replace('tar.','')) |
---|
245 | for x in files: |
---|
246 | self.add_tar_file(x,tar) |
---|
247 | tar.close() |
---|
248 | elif self.algo=='zip': |
---|
249 | import zipfile |
---|
250 | zip=zipfile.ZipFile(arch_name,'w',compression=zipfile.ZIP_DEFLATED) |
---|
251 | for x in files: |
---|
252 | archive_name=self.get_base_name()+'/'+x.path_from(self.base_path) |
---|
253 | zip.write(x.abspath(),archive_name,zipfile.ZIP_DEFLATED) |
---|
254 | zip.close() |
---|
255 | else: |
---|
256 | self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip') |
---|
257 | try: |
---|
258 | from hashlib import sha1 as sha |
---|
259 | except ImportError: |
---|
260 | from sha import sha |
---|
261 | try: |
---|
262 | digest=" (sha=%r)"%sha(node.read()).hexdigest() |
---|
263 | except Exception: |
---|
264 | digest='' |
---|
265 | Logs.info('New archive created: %s%s'%(self.arch_name,digest)) |
---|
266 | def get_tar_path(self,node): |
---|
267 | return node.abspath() |
---|
268 | def add_tar_file(self,x,tar): |
---|
269 | p=self.get_tar_path(x) |
---|
270 | tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+x.path_from(self.base_path)) |
---|
271 | tinfo.uid=0 |
---|
272 | tinfo.gid=0 |
---|
273 | tinfo.uname='root' |
---|
274 | tinfo.gname='root' |
---|
275 | fu=None |
---|
276 | try: |
---|
277 | fu=open(p,'rb') |
---|
278 | tar.addfile(tinfo,fileobj=fu) |
---|
279 | finally: |
---|
280 | if fu: |
---|
281 | fu.close() |
---|
282 | def get_tar_prefix(self): |
---|
283 | try: |
---|
284 | return self.tar_prefix |
---|
285 | except AttributeError: |
---|
286 | return self.get_base_name() |
---|
287 | def get_arch_name(self): |
---|
288 | try: |
---|
289 | self.arch_name |
---|
290 | except AttributeError: |
---|
291 | self.arch_name=self.get_base_name()+'.'+self.ext_algo.get(self.algo,self.algo) |
---|
292 | return self.arch_name |
---|
293 | def get_base_name(self): |
---|
294 | try: |
---|
295 | self.base_name |
---|
296 | except AttributeError: |
---|
297 | appname=getattr(Context.g_module,Context.APPNAME,'noname') |
---|
298 | version=getattr(Context.g_module,Context.VERSION,'1.0') |
---|
299 | self.base_name=appname+'-'+version |
---|
300 | return self.base_name |
---|
301 | def get_excl(self): |
---|
302 | try: |
---|
303 | return self.excl |
---|
304 | except AttributeError: |
---|
305 | self.excl=Node.exclude_regs+' **/waf-1.8.* **/.waf-1.8* **/waf3-1.8.* **/.waf3-1.8* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' |
---|
306 | if Context.out_dir: |
---|
307 | nd=self.root.find_node(Context.out_dir) |
---|
308 | if nd: |
---|
309 | self.excl+=' '+nd.path_from(self.base_path) |
---|
310 | return self.excl |
---|
311 | def get_files(self): |
---|
312 | try: |
---|
313 | files=self.files |
---|
314 | except AttributeError: |
---|
315 | files=self.base_path.ant_glob('**/*',excl=self.get_excl()) |
---|
316 | return files |
---|
317 | def dist(ctx): |
---|
318 | '''makes a tarball for redistributing the sources''' |
---|
319 | pass |
---|
320 | class DistCheck(Dist): |
---|
321 | fun='distcheck' |
---|
322 | cmd='distcheck' |
---|
323 | def execute(self): |
---|
324 | self.recurse([os.path.dirname(Context.g_module.root_path)]) |
---|
325 | self.archive() |
---|
326 | self.check() |
---|
327 | def check(self): |
---|
328 | import tempfile,tarfile |
---|
329 | t=None |
---|
330 | try: |
---|
331 | t=tarfile.open(self.get_arch_name()) |
---|
332 | for x in t: |
---|
333 | t.extract(x) |
---|
334 | finally: |
---|
335 | if t: |
---|
336 | t.close() |
---|
337 | cfg=[] |
---|
338 | if Options.options.distcheck_args: |
---|
339 | cfg=shlex.split(Options.options.distcheck_args) |
---|
340 | else: |
---|
341 | cfg=[x for x in sys.argv if x.startswith('-')] |
---|
342 | instdir=tempfile.mkdtemp('.inst',self.get_base_name()) |
---|
343 | ret=Utils.subprocess.Popen([sys.executable,sys.argv[0],'configure','install','uninstall','--destdir='+instdir]+cfg,cwd=self.get_base_name()).wait() |
---|
344 | if ret: |
---|
345 | raise Errors.WafError('distcheck failed with code %i'%ret) |
---|
346 | if os.path.exists(instdir): |
---|
347 | raise Errors.WafError('distcheck succeeded, but files were left in %s'%instdir) |
---|
348 | shutil.rmtree(self.get_base_name()) |
---|
349 | def distcheck(ctx): |
---|
350 | '''checks if the project compiles (tarball from 'dist')''' |
---|
351 | pass |
---|
352 | def update(ctx): |
---|
353 | '''updates the plugins from the *waflib/extras* directory''' |
---|
354 | lst=Options.options.files.split(',') |
---|
355 | if not lst: |
---|
356 | lst=[x for x in Utils.listdir(Context.waf_dir+'/waflib/extras')if x.endswith('.py')] |
---|
357 | for x in lst: |
---|
358 | tool=x.replace('.py','') |
---|
359 | try: |
---|
360 | Configure.download_tool(tool,force=True,ctx=ctx) |
---|
361 | except Errors.WafError: |
---|
362 | Logs.error('Could not find the tool %s in the remote repository'%x) |
---|
363 | def autoconfigure(execute_method): |
---|
364 | def execute(self): |
---|
365 | if not Configure.autoconfig: |
---|
366 | return execute_method(self) |
---|
367 | env=ConfigSet.ConfigSet() |
---|
368 | do_config=False |
---|
369 | try: |
---|
370 | env.load(os.path.join(Context.top_dir,Options.lockfile)) |
---|
371 | except Exception: |
---|
372 | Logs.warn('Configuring the project') |
---|
373 | do_config=True |
---|
374 | else: |
---|
375 | if env.run_dir!=Context.run_dir: |
---|
376 | do_config=True |
---|
377 | else: |
---|
378 | h=0 |
---|
379 | for f in env['files']: |
---|
380 | h=Utils.h_list((h,Utils.readf(f,'rb'))) |
---|
381 | do_config=h!=env.hash |
---|
382 | if do_config: |
---|
383 | Options.commands.insert(0,self.cmd) |
---|
384 | Options.commands.insert(0,'configure') |
---|
385 | if Configure.autoconfig=='clobber': |
---|
386 | Options.options.__dict__=env.options |
---|
387 | return |
---|
388 | return execute_method(self) |
---|
389 | return execute |
---|
390 | Build.BuildContext.execute=autoconfigure(Build.BuildContext.execute) |
---|