diff options
-rwxr-xr-x | backends.py | 8 | ||||
-rwxr-xr-x | environment.py | 1 | ||||
-rwxr-xr-x | interpreter.py | 38 | ||||
-rw-r--r-- | test cases/common/31 find program/meson.build | 12 | ||||
-rw-r--r-- | test cases/common/31 find program/source.in | 3 |
5 files changed, 57 insertions, 5 deletions
diff --git a/backends.py b/backends.py index d237e76..cf116a2 100755 --- a/backends.py +++ b/backends.py @@ -442,7 +442,10 @@ class NinjaBackend(Backend): outfilelist = genlist.get_outfilelist() if len(infilelist) != len(outfilelist): raise RuntimeError('Internal data structures broken.') - exe_file = os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe)) + if isinstance(exe, interpreter.BuildTarget): + exe_file = os.path.join(self.environment.get_build_dir(), self.get_target_filename(exe)) + else: + exe_file = exe.get_command() base_args = generator.get_arglist() for i in range(len(infilelist)): infilename = os.path.join(self.build_to_src, infilelist[i]) @@ -452,7 +455,8 @@ class NinjaBackend(Backend): cmdlist = [exe_file] + args elem = NinjaBuildElement(outfilename, 'CUSTOM_COMMAND', infilename) elem.add_item('DESC', 'Generating $out') - elem.add_dep(self.get_target_filename(exe)) + if isinstance(exe, interpreter.BuildTarget): + elem.add_dep(self.get_target_filename(exe)) elem.add_item('COMMAND', cmdlist) elem.write(outfile) diff --git a/environment.py b/environment.py index b8fa5ce..28b2221 100755 --- a/environment.py +++ b/environment.py @@ -228,7 +228,6 @@ def is_osx(): return platform.system().lower() == 'darwin' def is_windows(): - print(platform.system().lower()) return platform.system().lower() == 'windows' header_suffixes = ['h', 'hh', 'hpp', 'hxx', 'H'] diff --git a/interpreter.py b/interpreter.py index 4b95105..94b1c5c 100755 --- a/interpreter.py +++ b/interpreter.py @@ -18,6 +18,7 @@ import mparser import nodes import environment import os, sys, platform +import shutil class InterpreterException(Exception): pass @@ -38,13 +39,33 @@ class InterpreterObject(): return self.methods[method_name](args, kwargs) raise InvalidCode('Unknown method "%s" in object.' % method_name) +class ExternalProgram(InterpreterObject): + + def __init__(self, name, fullpath=None): + InterpreterObject.__init__(self) + self.name = name + self.fullpath = fullpath + + def found(self): + return self.fullpath is not None + + def found_method(self, args, kwargs): + return self.found() + + def get_command(self): + return self.fullpath + + def get_name(self): + return self.name + class Generator(InterpreterObject): def __init__(self, args, kwargs): InterpreterObject.__init__(self) if len(args) != 1: raise InvalidArguments('Generator requires one and only one positional argument') - if not isinstance(args[0], Executable): + if not isinstance(args[0], Executable) and \ + not isinstance(args[0], ExternalProgram): raise InvalidArguments('First generator argument must be an executable object.') self.exe = args[0] self.methods.update({'process' : self.process_method}) @@ -244,7 +265,7 @@ class BuildTarget(InterpreterObject): self.generated = [] self.process_sourcelist(sources) self.process_kwargs(kwargs) - if len(self.sources) == 0: + if len(self.sources) == 0 and len(self.generated) == 0: raise InvalidArguments('Build target %s has no sources.' % name) def process_sourcelist(self, sources): @@ -474,6 +495,7 @@ class Interpreter(): 'configure_file' : self.func_configure_file, 'include_directories' : self.func_include_directories, 'add_global_arguments' : self.func_add_global_arguments, + 'find_program' : self.func_find_program, } def get_build_def_files(self): @@ -587,6 +609,18 @@ class Interpreter(): self.coredata.compilers[lang] = comp self.build.compilers.append(comp) + def func_find_program(self, node, args, kwargs): + self.validate_arguments(args, 1, [str]) + required = kwargs.get('required', False) + if not isinstance(required, bool): + raise InvalidArguments('Line %d: "required" argument must be a boolean.' % node.lineno()) + exename = args[0] + result = shutil.which(exename) # Does .exe appending on Windows. + progobj = ExternalProgram(exename, result) + if required and not progobj.found(): + raise InvalidArguments('Line %d: program "%s" not found.' % (node.lineno(), exename)) + return progobj + def func_find_dep(self, node, args, kwargs): self.validate_arguments(args, 1, [str]) name = args[0] diff --git a/test cases/common/31 find program/meson.build b/test cases/common/31 find program/meson.build new file mode 100644 index 0000000..61913e9 --- /dev/null +++ b/test cases/common/31 find program/meson.build @@ -0,0 +1,12 @@ +project('find program', 'c') + +cp = find_program('cp', required : true) + + +gen = generator(cp, \ + output_name : '@BASENAME@.c', \ + arguments : ['@INPUT@', '@OUTPUT@']) + +generated = gen.process('source.in') +e = executable('prog', generated) +add_test('external exe', e) diff --git a/test cases/common/31 find program/source.in b/test cases/common/31 find program/source.in new file mode 100644 index 0000000..5c2fa9b --- /dev/null +++ b/test cases/common/31 find program/source.in @@ -0,0 +1,3 @@ +int main(int argc, char **argv) { + return 0; +} |