| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- #!/usr/bin/python
- # Copyright (C) 2013 Steven Watanabe
- # Distributed under the Boost Software License, Version 1.0.
- # (See accompanying file LICENSE.txt or copy at
- # https://www.bfgroup.xyz/b2/LICENSE.txt)
- import sys
- def create(t):
- t.write('''mockinfo.py''', '''
- from __future__ import print_function
- import re
- import optparse
- import os
- parser = optparse.OptionParser()
- parser.add_option('-o', dest="output_file")
- parser.add_option('-x', dest="language")
- parser.add_option('-c', dest="compile", action="store_true")
- parser.add_option('-I', dest="includes", action="append")
- parser.add_option('-D', dest="defines", action="append")
- parser.add_option('-L', dest="library_path", action="append")
- parser.add_option('--dll', dest="dll", action="store_true")
- parser.add_option('--archive', dest="archive", action="store_true")
- parser.add_option('--static-lib', dest="static_libraries", action="append")
- parser.add_option('--shared-lib', dest="shared_libraries", action="append")
- cwd = os.environ["JAM_CWD"]
- class MockInfo(object):
- def __init__(self, verbose=False):
- self.files = dict()
- self.commands = list()
- self.verbose = verbose
- def source_file(self, name, pattern):
- self.files[name] = pattern
- def action(self, command, status=0):
- if isinstance(command, str):
- command = command.split()
- self.commands.append((command, status))
- def check(self, command):
- print("Testing command", command)
- for (raw, status) in self.commands:
- if self.matches(raw, command):
- return status
- def matches(self, raw, command):
- (expected_options, expected_args) = parser.parse_args(raw)
- options = command[0]
- input_files = list(command[1])
- if self.verbose:
- print(" - matching against", (expected_options, expected_args))
- if len(expected_args) != len(input_files):
- if self.verbose:
- print(" argument list sizes differ")
- return False
- for arg in expected_args:
- if arg.startswith('$'):
- fileid = arg[1:]
- pattern = self.files[fileid] if fileid in self.files else fileid
- matching_file = None
- for input_file in input_files:
- with open(input_file, 'r') as f:
- contents = f.read()
- if pattern == contents:
- matching_file = input_file
- break
- if matching_file is not None:
- input_files.remove(matching_file)
- else:
- if self.verbose:
- print(" Failed to match input file contents: %s" % arg)
- return False
- else:
- if arg in input_files:
- input_files.remove(arg)
- else:
- if self.verbose:
- print(" Failed to match input file: %s" % arg)
- return False
- if options.language != expected_options.language:
- if self.verbose:
- print(" Failed to match -c")
- return False
- if options.compile != expected_options.compile:
- if self.verbose:
- print(" Failed to match -x")
- return False
- # Normalize a path for comparison purposes
- def adjust_path(p):
- return os.path.normcase(os.path.normpath(os.path.join(cwd, p)))
- # order matters
- if options.includes is None:
- options.includes = []
- if expected_options.includes is None:
- expected_options.includes = []
- if list(map(adjust_path, options.includes)) != \
- list(map(adjust_path, expected_options.includes)):
- if self.verbose:
- print(" Failed to match -I ", list(map(adjust_path, options.includes)), \
- " != ", list(map(adjust_path, expected_options.includes)))
- return False
- if options.defines is None:
- options.defines = []
- if expected_options.defines is None:
- expected_options.defines = []
- if options.defines != expected_options.defines:
- if self.verbose:
- print(" Failed to match -I ", options.defines, \
- " != ", expected_options.defines)
- return False
- if options.library_path is None:
- options.library_path = []
- if expected_options.library_path is None:
- expected_options.library_path = []
- if list(map(adjust_path, options.library_path)) != \
- list(map(adjust_path, expected_options.library_path)):
- if self.verbose:
- print(" Failed to match -L ", list(map(adjust_path, options.library_path)), \
- " != ", list(map(adjust_path, expected_options.library_path)))
- return False
- if options.static_libraries != expected_options.static_libraries:
- if self.verbose:
- print(" Failed to match --static-lib")
- return False
- if options.shared_libraries != expected_options.shared_libraries:
- if self.verbose:
- print(" Failed to match --shared-lib")
- return False
- if options.dll != expected_options.dll:
- if self.verbose:
- print(" Failed to match --dll")
- return False
- if options.archive != expected_options.archive:
- if self.verbose:
- print(" Failed to match --archive")
- return False
- # The output must be handled after everything else
- # is validated
- if expected_options.output_file is not None:
- if options.output_file is not None:
- if expected_options.output_file.startswith('$'):
- fileid = expected_options.output_file[1:]
- if fileid not in self.files:
- self.files[fileid] = fileid
- else:
- assert(self.files[fileid] == fileid)
- with open(options.output_file, 'w') as output:
- output.write(fileid)
- else:
- if self.verbose:
- print("Failed to match -o")
- return False
- elif options.output_file is not None:
- if self.verbose:
- print("Failed to match -o")
- return False
- # if we've gotten here, then everything matched
- if self.verbose:
- print(" Matched")
- return True
- ''')
- t.write('mock.py', '''
- from __future__ import print_function
- import mockinfo
- import markup
- import sys
- status = markup.info.check(mockinfo.parser.parse_args())
- if status is not None:
- exit(status)
- else:
- print("Unrecognized command: " + ' '.join(sys.argv))
- exit(1)
- ''')
- t.write('mock.jam', '''
- import feature ;
- import toolset ;
- import path ;
- import modules ;
- import common ;
- import type ;
- .python-cmd = "\"%s\"" ;
- # Behave the same as gcc on Windows, because that's what
- # the test system expects
- type.set-generated-target-prefix SHARED_LIB : <toolset>mock <target-os>windows : lib ;
- type.set-generated-target-suffix STATIC_LIB : <toolset>mock <target-os>windows : a ;
- rule init ( )
- {
- local here = [ path.make [ modules.binding $(__name__) ] ] ;
- here = [ path.native [ path.root [ path.parent $(here) ] [ path.pwd ] ] ] ;
- .config-cmd = [ common.variable-setting-command JAM_CWD : $(here) ] $(.python-cmd) -B ;
- }
- feature.extend toolset : mock ;
- generators.register-c-compiler mock.compile.c++ : CPP : OBJ : <toolset>mock ;
- generators.register-c-compiler mock.compile.c : C : OBJ : <toolset>mock ;
- generators.register-linker mock.link : LIB OBJ : EXE : <toolset>mock ;
- generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : <toolset>mock ;
- generators.register-archiver mock.archive : OBJ : STATIC_LIB : <toolset>mock ;
- toolset.flags mock.compile OPTIONS <link>shared : -fPIC ;
- toolset.flags mock.compile INCLUDES : <include> ;
- toolset.flags mock.compile DEFINES : <define> ;
- actions compile.c
- {
- $(.config-cmd) mock.py -c -x c -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)"
- }
- actions compile.c++
- {
- $(.config-cmd) mock.py -c -x c++ -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)"
- }
- toolset.flags mock.link USER_OPTIONS <linkflags> ;
- toolset.flags mock.link FINDLIBS-STATIC <find-static-library> ;
- toolset.flags mock.link FINDLIBS-SHARED <find-shared-library> ;
- toolset.flags mock.link LINK_PATH <library-path> ;
- toolset.flags mock.link LIBRARIES <library-file> ;
- actions link
- {
- $(.config-cmd) mock.py "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED)
- }
- actions archive
- {
- $(.config-cmd) mock.py --archive "$(>)" -o "$(<)" $(USER_OPTIONS)
- }
- actions link.dll
- {
- $(.config-cmd) mock.py --dll "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED)
- }
- ''' % sys.executable.replace('\\', '\\\\'))
- def set_expected(t, markup):
- verbose = "True" if t.verbose else "False"
- t.write('markup.py', '''
- import mockinfo
- info = mockinfo.MockInfo(%s)
- def source_file(name, contents):
- info.source_file(name, contents)
- def action(command, status=0):
- info.action(command, status)
- ''' % (verbose) + markup)
|