# Copyright (c) 2005 Alexey Pakhunov. # Copyright (c) 2011 Juraj Ivancic # # Use, modification and distribution is subject to the Boost Software # License Version 1.0. (See accompanying file LICENSE_1_0.txt or # http://www.boost.org/LICENSE_1_0.txt) # Microsoft Interface Definition Language (MIDL) related routines from b2.build import scanner, type from b2.build.toolset import flags from b2.build.feature import feature from b2.manager import get_manager from b2.tools import builtin, common from b2.util import regex, utility def init(): pass type.register('IDL', ['idl']) # A type library (.tlb) is generated by MIDL compiler and can be included # to resources of an application (.rc). In order to be found by a resource # compiler its target type should be derived from 'H' - otherwise # the property '' will be ignored. type.register('MSTYPELIB', ['tlb'], 'H') # Register scanner for MIDL files class MidlScanner(scanner.Scanner): def __init__ (self, includes=[]): scanner.Scanner.__init__(self) self.includes = includes # List of quoted strings re_strings = "[ \t]*\"([^\"]*)\"([ \t]*,[ \t]*\"([^\"]*)\")*[ \t]*" ; # 'import' and 'importlib' directives self.re_import = "import" + re_strings + "[ \t]*;" ; self.re_importlib = "importlib[ \t]*[(]" + re_strings + "[)][ \t]*;" ; # C preprocessor 'include' directive self.re_include_angle = "#[ \t]*include[ \t]*<(.*)>" ; self.re_include_quoted = "#[ \t]*include[ \t]*\"(.*)\"" ; def pattern(): # Match '#include', 'import' and 'importlib' directives return "((#[ \t]*include|import(lib)?).+(<(.*)>|\"(.*)\").+)" def process(self, target, matches, binding): included_angle = regex.transform(matches, self.re_include_angle) included_quoted = regex.transform(matches, self.re_include_quoted) imported = regex.transform(matches, self.re_import, [1, 3]) imported_tlbs = regex.transform(matches, self.re_importlib, [1, 3]) # CONSIDER: the new scoping rule seem to defeat "on target" variables. g = bjam.call('get-target-variable', target, 'HDRGRIST')[0] b = os.path.normpath(os.path.dirname(binding)) # Attach binding of including file to included targets. # When target is directly created from virtual target # this extra information is unnecessary. But in other # cases, it allows to distinguish between two headers of the # same name included from different places. g2 = g + "#" + b g = "<" + g + ">" g2 = "<" + g2 + ">" included_angle = [ g + x for x in included_angle ] included_quoted = [ g + x for x in included_quoted ] imported = [ g + x for x in imported ] imported_tlbs = [ g + x for x in imported_tlbs ] all = included_angle + included_quoted + imported bjam.call('INCLUDES', [target], all) bjam.call('DEPENDS', [target], imported_tlbs) bjam.call('NOCARE', all + imported_tlbs) engine.set_target_variable(included_angle , 'SEARCH', [utility.get_value(inc) for inc in self.includes]) engine.set_target_variable(included_quoted, 'SEARCH', [utility.get_value(inc) for inc in self.includes]) engine.set_target_variable(imported , 'SEARCH', [utility.get_value(inc) for inc in self.includes]) engine.set_target_variable(imported_tlbs , 'SEARCH', [utility.get_value(inc) for inc in self.includes]) get_manager().scanners().propagate(type.get_scanner('CPP', PropertySet(self.includes)), included_angle + included_quoted) get_manager().scanners().propagate(self, imported) scanner.register(MidlScanner, 'include') type.set_scanner('IDL', MidlScanner) # Command line options feature('midl-stubless-proxy', ['yes', 'no'], ['propagated'] ) feature('midl-robust', ['yes', 'no'], ['propagated'] ) flags('midl.compile.idl', 'MIDLFLAGS', ['yes'], ['/Oicf' ]) flags('midl.compile.idl', 'MIDLFLAGS', ['no' ], ['/Oic' ]) flags('midl.compile.idl', 'MIDLFLAGS', ['yes' ], ['/robust' ]) flags('midl.compile.idl', 'MIDLFLAGS', ['no' ], ['/no_robust']) # Architecture-specific options architecture_x86 = ['' , 'x86'] address_model_32 = ['', '32'] address_model_64 = ['', '64'] flags('midl.compile.idl', 'MIDLFLAGS', [ar + '/' + m for ar in architecture_x86 for m in address_model_32 ], ['/win32']) flags('midl.compile.idl', 'MIDLFLAGS', [ar + '/64' for ar in architecture_x86], ['/x64']) flags('midl.compile.idl', 'MIDLFLAGS', ['ia64/' + m for m in address_model_64], ['/ia64']) flags('midl.compile.idl', 'DEFINES', [], ['']) flags('midl.compile.idl', 'UNDEFS', [], ['']) flags('midl.compile.idl', 'INCLUDES', [], ['']) builtin.register_c_compiler('midl.compile.idl', ['IDL'], ['MSTYPELIB', 'H', 'C(%_i)', 'C(%_proxy)', 'C(%_dlldata)'], []) # MIDL does not always generate '%_proxy.c' and '%_dlldata.c'. This behavior # depends on contents of the source IDL file. Calling TOUCH_FILE below ensures # that both files will be created so bjam will not try to recreate them # constantly. get_manager().engine().register_action( 'midl.compile.idl', '''midl /nologo @"@($(<[1]:W).rsp:E= "$(>:W)" -D$(DEFINES) "-I$(INCLUDES)" -U$(UNDEFS) $(MIDLFLAGS) /tlb "$(<[1]:W)" /h "$(<[2]:W)" /iid "$(<[3]:W)" /proxy "$(<[4]:W)" /dlldata "$(<[5]:W)")" {touch} "$(<[4]:W)" {touch} "$(<[5]:W)"'''.format(touch=common.file_creation_command()))