3 # Scott Newton, 2005 (scottn)
4 # Thomas Nagy, 2006 (ita)
6 "Custom command-line options"
8 import os, sys, imp, types, tempfile, optparse
10 from Constants import *
12 cmds = 'distclean configure build install clean uninstall check dist distcheck'.split()
14 # TODO remove in waf 1.6 the following two
22 lockfile = os.environ.get('WAFLOCK', '.lock-wscript')
23 try: cache_global = os.path.abspath(os.environ['WAFCACHE'])
24 except KeyError: cache_global = ''
25 platform = Utils.unversioned_sys_platform()
26 conf_file = 'conf-runs-%s-%d.pickle' % (platform, ABI)
28 remote_repo = ['http://waf.googlecode.com/svn/']
29 """remote directory for the plugins"""
32 # Such a command-line should work: JOBS=4 PREFIX=/opt/ DESTDIR=/tmp/ahoj/ waf configure
33 default_prefix = os.environ.get('PREFIX')
34 if not default_prefix:
35 if platform == 'win32':
36 d = tempfile.gettempdir()
37 default_prefix = d[0].upper() + d[1:]
38 # win32 preserves the case, but gettempdir does not
39 else: default_prefix = '/usr/local/'
41 default_jobs = os.environ.get('JOBS', -1)
44 if 'SC_NPROCESSORS_ONLN' in os.sysconf_names:
45 default_jobs = os.sysconf('SC_NPROCESSORS_ONLN')
47 default_jobs = int(Utils.cmd_output(['sysctl', '-n', 'hw.ncpu']))
49 if os.name == 'java': # platform.system() == 'Java'
50 from java.lang import Runtime
51 default_jobs = Runtime.getRuntime().availableProcessors()
53 # environment var defined on win32
54 default_jobs = int(os.environ.get('NUMBER_OF_PROCESSORS', 1))
56 default_destdir = os.environ.get('DESTDIR', '')
60 module = Utils.g_module
62 # create the help messages for commands
64 keys = list(tbl.keys())
68 if not module.build.__doc__:
69 module.build.__doc__ = 'builds the project'
70 if 'configure' in tbl:
71 if not module.configure.__doc__:
72 module.configure.__doc__ = 'configures the project'
74 ban = ['set_options', 'init', 'shutdown']
76 optlst = [x for x in keys if not x in ban
77 and type(tbl[x]) is type(parse_args_impl)
79 and not x.startswith('_')]
81 just = max([len(x) for x in optlst])
84 cmds_str.append(' %s: %s' % (x.ljust(just), tbl[x].__doc__))
85 ret = '\n'.join(cmds_str)
88 return '''waf [command] [options]
90 Main commands (example: ./waf build -j4)
95 setattr(optparse.OptionParser, 'get_usage', get_usage)
97 def create_parser(module=None):
98 Logs.debug('options: create_parser is called')
99 parser = optparse.OptionParser(conflict_handler="resolve", version = 'waf %s (%s)' % (WAFVERSION, WAFREVISION))
101 parser.formatter.width = Utils.get_term_cols()
102 p = parser.add_option
106 default = default_jobs,
107 help = 'amount of parallel jobs (%r)' % default_jobs,
111 action = 'store_true',
113 help = 'keep running happily on independent task groups',
119 help = 'verbosity level -v -vv or -vvv [default: 0]',
123 action = 'store_true',
125 help = 'ignore the WAFCACHE (if set)',
131 help = 'debugging zones (task_gen, deps, tasks, etc)',
134 p('-p', '--progress',
137 help = '-p: progress bar; -pp: ide output',
138 dest = 'progress_bar')
143 help = 'build given task generators, e.g. "target1,target2"',
144 dest = 'compile_targets')
146 gr = optparse.OptionGroup(parser, 'configuration options')
147 parser.add_option_group(gr)
148 gr.add_option('-b', '--blddir',
151 help = 'out dir for the project (configuration)',
153 gr.add_option('-s', '--srcdir',
156 help = 'top dir for the project (configuration)',
158 gr.add_option('--prefix',
159 help = 'installation prefix (configuration) [default: %r]' % default_prefix,
160 default = default_prefix,
163 gr.add_option('--download',
164 action = 'store_true',
166 help = 'try to download the tools if missing',
169 gr = optparse.OptionGroup(parser, 'installation options')
170 parser.add_option_group(gr)
171 gr.add_option('--destdir',
172 help = 'installation root [default: %r]' % default_destdir,
173 default = default_destdir,
175 gr.add_option('-f', '--force',
176 action = 'store_true',
178 help = 'force file installation',
183 def parse_args_impl(parser, _args=None):
184 global options, commands, arg_line
185 (options, args) = parser.parse_args(args=_args)
188 #arg_line = args[:] # copy
190 # By default, 'waf' is equivalent to 'waf build'
192 for var in cmds: commands[var] = 0
194 commands['build'] = 1
197 # Parse the command arguments
201 # the check thing depends on the build
203 idx = args.index('check')
205 bidx = args.index('build')
207 raise ValueError('build before check')
208 except ValueError, e:
209 args.insert(idx, 'build')
211 if args[0] != 'init':
212 args.insert(0, 'init')
215 if options.keep: options.jobs = 1
216 if options.jobs < 1: options.jobs = 1
218 if 'install' in sys.argv or 'uninstall' in sys.argv:
219 # absolute path only if set
220 options.destdir = options.destdir and os.path.abspath(os.path.expanduser(options.destdir))
222 Logs.verbose = options.verbose
226 Logs.zones = options.zones.split(',')
227 if not Logs.verbose: Logs.verbose = 1
228 elif Logs.verbose > 0:
229 Logs.zones = ['runner']
234 # 1. rename the class to OptionsContext
235 # 2. instead of a class attribute, use a module (static 'parser')
236 # 3. parse_args_impl was made in times when we did not know about binding new methods to classes
238 class Handler(Utils.Context):
239 """loads wscript modules in folders for adding options
240 This class should be named 'OptionsContext'
241 A method named 'recurse' is bound when used by the module Scripting"""
244 # make it possible to access the reference, like Build.bld
246 def __init__(self, module=None):
247 self.parser = create_parser(module)
248 self.cwd = os.getcwd()
249 Handler.parser = self
251 def add_option(self, *k, **kw):
252 self.parser.add_option(*k, **kw)
254 def add_option_group(self, *k, **kw):
255 return self.parser.add_option_group(*k, **kw)
257 def get_option_group(self, opt_str):
258 return self.parser.get_option_group(opt_str)
260 def sub_options(self, *k, **kw):
261 if not k: raise Utils.WscriptError('folder expected')
262 self.recurse(k[0], name='set_options')
264 def tool_options(self, *k, **kw):
265 Utils.python_24_guard()
268 raise Utils.WscriptError('invalid tool_options call %r %r' % (k, kw))
269 tools = Utils.to_list(k[0])
271 # TODO waf 1.6 remove the global variable tooldir
272 path = Utils.to_list(kw.get('tdir', kw.get('tooldir', tooldir)))
275 tool = tool.replace('++', 'xx')
276 if tool == 'java': tool = 'javaw'
277 if tool.lower() == 'unittest': tool = 'unittestw'
278 module = Utils.load_tool(tool, path)
280 fun = module.set_options
281 except AttributeError:
284 fun(kw.get('option_group', self))
286 def parse_args(self, args=None):
287 parse_args_impl(self.parser, args)