summaryrefslogtreecommitdiff
path: root/jam-files/boost-build/tools/midl.jam
blob: 0aa5dda31c6e535b0c12fb1cfd652348cc2c5877 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Copyright (c) 2005 Alexey Pakhunov.
#
# 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

import common ;
import generators ;
import feature : feature get-values ;
import os ;
import scanner ;
import toolset : flags ;
import type ;

rule init ( )
{
}

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 '<implicit-dependency>' will be ignored.
type.register MSTYPELIB : tlb : H ;


# Register scanner for MIDL files
class midl-scanner : scanner 
{
    import path property-set regex scanner type virtual-target ;
    
    rule __init__ ( includes * )
    {
        scanner.__init__ ;
    
        self.includes = $(includes) ;

        # List of quoted strings 
        self.re-strings = "[ \t]*\"([^\"]*)\"([ \t]*,[ \t]*\"([^\"]*)\")*[ \t]*" ;

        # 'import' and 'importlib' directives 
        self.re-import    = "import"$(self.re-strings)"[ \t]*;" ;
        self.re-importlib = "importlib[ \t]*[(]"$(self.re-strings)"[)][ \t]*;" ;

        # C preprocessor 'include' directive
        self.re-include-angle  = "#[ \t]*include[ \t]*<(.*)>" ;
        self.re-include-quoted = "#[ \t]*include[ \t]*\"(.*)\"" ;
    }    

    rule pattern ( )
    {
        # Match '#include', 'import' and 'importlib' directives
        return "((#[ \t]*include|import(lib)?).+(<(.*)>|\"(.*)\").+)" ;
    }

    rule process ( target : matches * : binding )
    {
        local included-angle  = [ regex.transform $(matches) : $(self.re-include-angle)  : 1 ] ;
        local included-quoted = [ regex.transform $(matches) : $(self.re-include-quoted) : 1 ] ;
        local imported        = [ regex.transform $(matches) : $(self.re-import)         : 1 3 ] ;
        local imported_tlbs   = [ regex.transform $(matches) : $(self.re-importlib)      : 1 3 ] ;

        # CONSIDER: the new scoping rule seem to defeat "on target" variables.
        local g = [ on $(target) return $(HDRGRIST) ] ;  
        local b = [ NORMALIZE_PATH $(binding:D) ] ;

        # 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.      
        local g2 = $(g)"#"$(b) ;

        included-angle = $(included-angle:G=$(g)) ;
        included-quoted = $(included-quoted:G=$(g2)) ;
        imported = $(imported:G=$(g2)) ;
        imported_tlbs = $(imported_tlbs:G=$(g2)) ;

        local all = $(included-angle) $(included-quoted) $(imported) ;

        INCLUDES $(target) : $(all) ;
        DEPENDS $(target) : $(imported_tlbs) ;
        NOCARE $(all) $(imported_tlbs) ;
        SEARCH on $(included-angle)  = $(self.includes:G=) ;
        SEARCH on $(included-quoted) = $(b) $(self.includes:G=) ;
        SEARCH on $(imported)        = $(b) $(self.includes:G=) ;
        SEARCH on $(imported_tlbs)   = $(b) $(self.includes:G=) ;
        
        scanner.propagate 
            [ type.get-scanner CPP : [ property-set.create $(self.includes) ] ] : 
            $(included-angle) $(included-quoted) : $(target) ;

        scanner.propagate $(__name__) : $(imported) : $(target) ;
    }        
}

scanner.register midl-scanner : include ;
type.set-scanner IDL : midl-scanner ;


# Command line options
feature midl-stubless-proxy : yes no : propagated ;
feature midl-robust : yes no : propagated ;

flags midl.compile.idl MIDLFLAGS <midl-stubless-proxy>yes : /Oicf ;
flags midl.compile.idl MIDLFLAGS <midl-stubless-proxy>no : /Oic ;
flags midl.compile.idl MIDLFLAGS <midl-robust>yes : /robust ;
flags midl.compile.idl MIDLFLAGS <midl-robust>no : /no_robust ;

# Architecture-specific options
architecture-x86 = <architecture> <architecture>x86 ;
address-model-32 = <address-model> <address-model>32 ;
address-model-64 = <address-model> <address-model>64 ;

flags midl.compile.idl MIDLFLAGS $(architecture-x86)/$(address-model-32) : /win32 ;
flags midl.compile.idl MIDLFLAGS $(architecture-x86)/<address-model>64 : /x64 ;
flags midl.compile.idl MIDLFLAGS <architecture>ia64/$(address-model-64) : /ia64 ;


flags midl.compile.idl DEFINES <define> ;
flags midl.compile.idl UNDEFS <undef> ;
flags midl.compile.idl INCLUDES <include> ;


generators.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.
TOUCH_FILE = [ common.file-touch-command ] ;

actions compile.idl
{
    midl /nologo @"@($(<[1]:W).rsp:E=$(nl)"$(>:W)" $(nl)-D$(DEFINES) $(nl)"-I$(INCLUDES)" $(nl)-U$(UNDEFS) $(nl)$(MIDLFLAGS) $(nl)/tlb "$(<[1]:W)" $(nl)/h "$(<[2]:W)" $(nl)/iid "$(<[3]:W)" $(nl)/proxy "$(<[4]:W)" $(nl)/dlldata "$(<[5]:W)")"
    $(TOUCH_FILE) "$(<[4]:W)"  
    $(TOUCH_FILE) "$(<[5]:W)"  
}