1# Copyright Vladimir Prus 2004.
2# Copyright Peter Dimov 2018
3#
4# Distributed under the Boost Software License, Version 1.0.
5# (See accompanying file LICENSE_1_0.txt
6# or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8import common ;
9import errors ;
10import feature ;
11import clang ;
12import msvc ;
13import os ;
14import toolset ;
15import generators ;
16import path ;
17import regex ;
18
19feature.extend-subfeature toolset clang : platform : win ;
20
21toolset.inherit-generators clang-win <toolset>clang <toolset-clang:platform>win : msvc : msvc.compile.c.pch msvc.compile.c++.pch ;
22toolset.inherit-flags clang-win : msvc ;
23toolset.inherit-rules clang-win : msvc ;
24
25# Override default do-nothing generators.
26generators.override clang-win.compile.rc : rc.compile.resource ;
27generators.override clang-win.compile.mc : mc.compile ;
28
29if [ MATCH (--debug-(clang-(win-)?)?configuration) : [ modules.peek : ARGV ] ]
30{
31    local rule .notice ( messages * )
32    {
33        ECHO "notice: [clang-win]" $(messages) ;
34    }
35}
36else
37{
38    local rule .notice ( messages * )
39    {
40    }
41}
42
43# [ get-option archiver : 32 : $(options) ]
44#
45# returns <archiver-32>, or <archiver>
46
47local rule get-option ( option : addr : options * )
48{
49    local r = [ feature.get-values "<$(option)-$(addr)>" : $(options) ] ;
50    r ?= [ feature.get-values "<$(option)>" : $(options) ] ;
51    return $(r) ;
52}
53
54# init
55#
56# options:
57#
58# <assembler>ml.exe (or <assembler-32>, or <assembler-64>)
59# <archiver>lib.exe
60# <manifest-tool>mt.exe
61# <resource-compiler>rc.exe
62# <mc-compiler>mc.exe
63# <idl-compiler>midl.exe
64
65rule init ( version ? : command * : options * )
66{
67    command = [ common.get-invocation-command-nodefault clang-win : clang-cl.exe : $(command) ] ;
68
69    if ! $(command)
70    {
71        errors.error "Cannot configure toolset clang-win: no 'clang-cl.exe' command found or given" ;
72    }
73
74    local compiler = "\"$(command)\"" ;
75    compiler = "$(compiler:J= )" ;
76
77    version ?= [ MATCH "version ([0-9.]+)" : [ SHELL "$(compiler) -v 2>&1" ] ] ;
78
79    .notice "using compiler '$(compiler)', version '$(version)'" ;
80
81    local condition = [  common.check-init-parameters clang-win : version $(version) ] ;
82
83    common.handle-options clang-win : $(condition) : $(command) : $(options) ;
84
85    for local addr in 32 64
86    {
87        local config = [ SPLIT_BY_CHARACTERS [ SHELL "$(compiler) -m$(addr) -### foo.obj /link 2>&1" ] : "\n" ] ;
88
89        local match = 1 ;
90        local items ;
91
92        while $(match)
93        {
94            match = [ MATCH "^ *(\"[^\"]*\")(.*)" : $(config) ] ;
95
96            if $(match)
97            {
98                items += $(match[1]) ;
99                config = $(match[2]) ;
100            }
101        }
102
103        local ml ;
104
105        if $(items)
106        {
107            ml = [ regex.replace $(items[1]) "x64\\\\+link\\.exe" "x64\\ml64.exe" ] ;
108            ml = [ regex.replace $(ml) "x86\\\\+link\\.exe" "x86\\ml.exe" ] ;
109
110            if ! [ MATCH "(ml\\.exe)" "(ml64\\.exe)" : $(ml) ]
111            {
112                ml = ;
113            }
114        }
115
116        local assembler = [ get-option "assembler" : $(addr) : $(options) ] ;
117        assembler ?= $(ml) ;
118        if $(addr) = 32 { assembler ?= ml.exe ; } else { assembler ?= ml64.exe ; }
119
120        local link ;
121
122        if $(items)
123        {
124            link = [ regex.replace $(items[1]) "\\\\+HostX64\\\\+x86\\\\+" "\\HostX86\\x86\\" ] ;
125        }
126
127        local archiver = [ get-option "archiver" : $(addr) : $(options) ] ;
128
129        if $(link)
130        {
131            archiver ?= "$(link) /lib" ;
132        }
133        archiver ?= lib.exe ;
134
135        .notice "$(addr):" "using assembler '$(assembler)'" ;
136        .notice "$(addr):" "using archiver '$(archiver)'" ;
137
138        local manifest-tool = [ get-option "manifest-tool" : $(addr) : $(options) ] ;
139        local resource-compiler = [ get-option "resource-compiler" : $(addr) : $(options) ] ;
140        local mc-compiler = [ get-option "mc-compiler" : $(addr) : $(options) ] ;
141        local idl-compiler = [ get-option "idl-compiler" : $(addr) : $(options) ] ;
142
143        for local item in $(items)
144        {
145            match = [ MATCH "\"-libpath:(.*)\\\\+Lib\\\\.*\\\\um\\\\+x(.*)\"" : $(item) ] ;
146
147            if $(match)
148            {
149                local sdk-path = "$(match[1])\\bin\\x$(match[2])" ;
150                .notice "$(addr):" "using SDK path '$(sdk-path)'" ;
151
152                manifest-tool ?= "\"$(sdk-path)\\mt.exe\"" ;
153                resource-compiler ?= "\"$(sdk-path)\\rc.exe\"" ;
154                mc-compiler ?= "\"$(sdk-path)\\mc.exe\"" ;
155                idl-compiler ?= "\"$(sdk-path)\\midl.exe\"" ;
156            }
157        }
158
159        manifest-tool ?= mt.exe ;
160        resource-compiler ?= rc.exe ;
161        mc-compiler ?= mc.exe ;
162        idl-compiler ?= midl.exe ;
163
164        .notice "$(addr):" "using manifest-tool '$(manifest-tool)'" ;
165        .notice "$(addr):" "using resource-compiler '$(resource-compiler)'" ;
166        .notice "$(addr):" "using mc-compiler '$(mc-compiler)'" ;
167        .notice "$(addr):" "using idl-compiler '$(idl-compiler)'" ;
168
169        local cond = "$(condition)/<architecture>/<address-model>$(addr)" "$(condition)/<architecture>x86/<address-model>$(addr)" ;
170        if $(addr) = 32 { cond += "$(condition)/<architecture>/<address-model>" ; }
171
172        toolset.flags clang-win.compile .CC $(cond) : $(compiler) -m$(addr) ;
173        toolset.flags clang-win.link .LD $(cond) : $(compiler) -m$(addr) /link "/incremental:no" "/manifest" ;
174        toolset.flags clang-win.compile .ASM $(cond) : $(assembler) -nologo -c -Zp4 -Cp -Cx ;
175        toolset.flags clang-win.compile .ASM_OUTPUT $(cond) : -Fo ;
176        toolset.flags clang-win.archive .LD $(cond) : $(archiver) /nologo ;
177        toolset.flags clang-win.link .MT $(cond) : $(manifest-tool) -nologo ;
178        toolset.flags clang-win.compile .MC $(cond) : $(mc-compiler) ;
179        toolset.flags clang-win.compile .RC $(cond) : $(resource-compiler) ;
180        toolset.flags clang-win.compile .IDL $(cond) : $(idl-compiler) ;
181    }
182
183    toolset.flags clang-win.link LIBRARY_OPTION <toolset>clang-win : "" : unchecked ;
184}
185