3 # Carlos Rafael Giani, 2006 (dv)
4 # Tamas Pal, 2007 (folti)
5 # Nicolas Mercier, 2009
6 # Microsoft Visual C++/Intel C++ compiler support - beta, needs more testing
10 # conf.env['MSVC_VERSIONS'] = ['msvc 9.0', 'msvc 8.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0']
11 # conf.env['MSVC_TARGETS'] = ['x64']
12 # conf.check_tool('msvc')
13 # OR conf.check_tool('msvc', funs='no_autodetect')
14 # conf.check_lib_msvc('gdi32')
15 # conf.check_libs_msvc('kernel32 user32', mandatory=true)
17 # obj.uselib = 'KERNEL32 USER32 GDI32'
19 # platforms and targets will be tested in the order they appear;
20 # the first good configuration will be used
21 # supported platforms :
22 # ia64, x64, x86, x86_amd64, x86_ia64
24 # compilers supported :
25 # msvc => Visual Studio, versions 7.1 (2003), 8,0 (2005), 9.0 (2008)
26 # wsdk => Windows SDK, versions 6.0, 6.1, 7.0
27 # icl => Intel compiler, versions 9,10,11
28 # Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i)
29 # PocketPC => Compiler/SDK for PocketPC devices (armv4/v4i)
32 import os
, sys
, re
, string
, optparse
33 import Utils
, TaskGen
, Runner
, Configure
, Task
, Options
34 from Logs
import debug
, info
, warn
, error
35 from TaskGen
import after
, before
, feature
37 from Configure
import conftest
, conf
38 import ccroot
, cc
, cxx
, ar
, winres
39 from libtool
import read_la_file
44 import winreg
as _winreg
48 # importlibs provided by MSVC/Platform SDK. Do NOT search them....
49 g_msvc_systemlibs
= """
50 aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet
51 cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs
52 credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d
53 ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp
54 faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid
55 gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop
56 kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi
57 mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree
58 msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm
59 netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp
60 odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32
61 osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu
62 ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm
63 rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32
64 shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32
65 traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg
66 version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm
67 wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp
71 all_msvc_platforms
= [ ('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'), ('x86_amd64', 'amd64'), ('x86_ia64', 'ia64') ]
72 all_wince_platforms
= [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ]
73 all_icl_platforms
= [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')]
75 def setup_msvc(conf
, versions
):
76 platforms
= Utils
.to_list(conf
.env
['MSVC_TARGETS']) or [i
for i
,j
in all_msvc_platforms
+all_icl_platforms
+all_wince_platforms
]
77 desired_versions
= conf
.env
['MSVC_VERSIONS'] or [v
for v
,_
in versions
][::-1]
78 versiondict
= dict(versions
)
80 for version
in desired_versions
:
82 targets
= dict(versiondict
[version
])
83 for target
in platforms
:
85 arch
,(p1
,p2
,p3
) = targets
[target
]
86 compiler
,revision
= version
.split()
87 return compiler
,revision
,p1
,p2
,p3
88 except KeyError: continue
89 except KeyError: continue
90 conf
.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)')
93 def get_msvc_version(conf
, compiler
, version
, target
, vcvars
):
94 debug('msvc: get_msvc_version: %r %r %r', compiler
, version
, target
)
95 batfile
= os
.path
.join(conf
.blddir
, 'waf-print-msvc.bat')
96 f
= open(batfile
, 'w')
102 echo INCLUDE=%%INCLUDE%%
104 """ % (vcvars
,target
))
106 sout
= Utils
.cmd_output(['cmd', '/E:on', '/V:on', '/C', batfile
])
107 lines
= sout
.splitlines()
109 for x
in ('Setting environment', 'Setting SDK environment', 'Intel(R) C++ Compiler'):
110 if lines
[0].find(x
) != -1:
113 debug('msvc: get_msvc_version: %r %r %r -> not found', compiler
, version
, target
)
114 conf
.fatal('msvc: Impossible to find a valid architecture for building (in get_msvc_version)')
116 for line
in lines
[1:]:
117 if line
.startswith('PATH='):
119 MSVC_PATH
= path
.split(';')
120 elif line
.startswith('INCLUDE='):
121 MSVC_INCDIR
= [i
for i
in line
[8:].split(';') if i
]
122 elif line
.startswith('LIB='):
123 MSVC_LIBDIR
= [i
for i
in line
[4:].split(';') if i
]
125 # Check if the compiler is usable at all.
126 # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run.
128 env
.update(os
.environ
)
129 env
.update(PATH
= path
)
130 compiler_name
, linker_name
, lib_name
= _get_prog_names(conf
, compiler
)
131 cxx
= conf
.find_program(compiler_name
, path_list
=MSVC_PATH
)
132 # delete CL if exists. because it could contain parameters wich can change cl's behaviour rather catastrophically.
133 if env
.has_key('CL'):
137 p
= pproc
.Popen([cxx
, '/help'], env
=env
, stdout
=pproc
.PIPE
, stderr
=pproc
.PIPE
)
138 out
, err
= p
.communicate()
139 if p
.returncode
!= 0:
140 raise Exception('return code: %r: %r' % (p
.returncode
, err
))
142 debug('msvc: get_msvc_version: %r %r %r -> failure', compiler
, version
, target
)
144 conf
.fatal('msvc: cannot run the compiler (in get_msvc_version)')
146 debug('msvc: get_msvc_version: %r %r %r -> OK', compiler
, version
, target
)
148 return (MSVC_PATH
, MSVC_INCDIR
, MSVC_LIBDIR
)
151 def gather_wsdk_versions(conf
, versions
):
152 version_pattern
= re
.compile('^v..?.?\...?.?')
154 all_versions
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows')
157 all_versions
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows')
163 version
= _winreg
.EnumKey(all_versions
, index
)
167 if not version_pattern
.match(version
):
170 msvc_version
= _winreg
.OpenKey(all_versions
, version
)
171 path
,type = _winreg
.QueryValueEx(msvc_version
,'InstallationFolder')
174 if os
.path
.isfile(os
.path
.join(path
, 'bin', 'SetEnv.cmd')):
176 for target
,arch
in all_msvc_platforms
:
178 targets
.append((target
, (arch
, conf
.get_msvc_version('wsdk', version
, '/'+target
, os
.path
.join(path
, 'bin', 'SetEnv.cmd')))))
179 except Configure
.ConfigurationError
:
181 versions
.append(('wsdk ' + version
[1:], targets
))
184 def gather_msvc_versions(conf
, versions
):
185 # checks SmartPhones SDKs
187 ce_sdk
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs')
190 ce_sdk
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs')
194 supported_wince_platforms
= []
198 sdk_device
= _winreg
.EnumKey(ce_sdk
, ce_index
)
201 ce_index
= ce_index
+ 1
202 sdk
= _winreg
.OpenKey(ce_sdk
, sdk_device
)
203 path
,type = _winreg
.QueryValueEx(sdk
, 'SDKRootDir')
205 path
,device
= os
.path
.split(path
)
207 path
,device
= os
.path
.split(path
)
208 for arch
,compiler
in all_wince_platforms
:
210 if os
.path
.isdir(os
.path
.join(path
, device
, 'Lib', arch
)):
211 platforms
.append((arch
, compiler
, os
.path
.join(path
, device
, 'Include', arch
), os
.path
.join(path
, device
, 'Lib', arch
)))
213 supported_wince_platforms
.append((device
, platforms
))
215 version_pattern
= re
.compile('^..?\...?')
216 for vcver
,vcvar
in [('VCExpress','exp'), ('VisualStudio','')]:
218 all_versions
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Microsoft\\'+vcver
)
221 all_versions
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Microsoft\\'+vcver
)
227 version
= _winreg
.EnumKey(all_versions
, index
)
231 if not version_pattern
.match(version
):
234 msvc_version
= _winreg
.OpenKey(all_versions
, version
+ "\\Setup\\VS")
235 path
,type = _winreg
.QueryValueEx(msvc_version
, 'ProductDir')
239 for device
,platforms
in supported_wince_platforms
:
241 for platform
,compiler
,include
,lib
in platforms
:
242 winCEpath
= os
.path
.join(path
, 'VC', 'ce')
243 if os
.path
.isdir(winCEpath
):
244 common_bindirs
,_1
,_2
= conf
.get_msvc_version('msvc', version
, 'x86', os
.path
.join(path
, 'Common7', 'Tools', 'vsvars32.bat'))
245 if os
.path
.isdir(os
.path
.join(winCEpath
, 'lib', platform
)):
246 bindirs
= [os
.path
.join(winCEpath
, 'bin', compiler
), os
.path
.join(winCEpath
, 'bin', 'x86_'+compiler
)] + common_bindirs
247 incdirs
= [include
, os
.path
.join(winCEpath
, 'include'), os
.path
.join(winCEpath
, 'atlmfc', 'include')]
248 libdirs
= [lib
, os
.path
.join(winCEpath
, 'lib', platform
), os
.path
.join(winCEpath
, 'atlmfc', 'lib', platform
)]
249 cetargets
.append((platform
, (platform
, (bindirs
,incdirs
,libdirs
))))
250 versions
.append((device
+' '+version
, cetargets
))
251 if os
.path
.isfile(os
.path
.join(path
, 'VC', 'vcvarsall.bat')):
252 for target
,realtarget
in all_msvc_platforms
[::-1]:
254 targets
.append((target
, (realtarget
, conf
.get_msvc_version('msvc', version
, target
, os
.path
.join(path
, 'VC', 'vcvarsall.bat')))))
257 elif os
.path
.isfile(os
.path
.join(path
, 'Common7', 'Tools', 'vsvars32.bat')):
259 targets
.append(('x86', ('x86', conf
.get_msvc_version('msvc', version
, 'x86', os
.path
.join(path
, 'Common7', 'Tools', 'vsvars32.bat')))))
260 except Configure
.ConfigurationError
:
262 versions
.append(('msvc '+version
, targets
))
268 def gather_icl_versions(conf
, versions
):
269 version_pattern
= re
.compile('^...?.?\....?.?')
271 all_versions
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++')
274 all_versions
= _winreg
.OpenKey(_winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Intel\\Compilers\\C++')
280 version
= _winreg
.EnumKey(all_versions
, index
)
284 if not version_pattern
.match(version
):
287 for target
,arch
in all_icl_platforms
:
289 icl_version
= _winreg
.OpenKey(all_versions
, version
+'\\'+target
)
290 path
,type = _winreg
.QueryValueEx(icl_version
,'ProductDir')
291 if os
.path
.isfile(os
.path
.join(path
, 'bin', 'iclvars.bat')):
293 targets
.append((target
, (arch
, conf
.get_msvc_version('intel', version
, target
, os
.path
.join(path
, 'bin', 'iclvars.bat')))))
294 except Configure
.ConfigurationError
:
299 versions
.append(('intel ' + major
, targets
))
302 def get_msvc_versions(conf
):
303 if not conf
.env
.MSVC_INSTALLED_VERSIONS
:
305 conf
.gather_msvc_versions(lst
)
306 conf
.gather_wsdk_versions(lst
)
307 conf
.gather_icl_versions(lst
)
308 conf
.env
.MSVC_INSTALLED_VERSIONS
= lst
309 return conf
.env
.MSVC_INSTALLED_VERSIONS
312 def print_all_msvc_detected(conf
):
313 for version
,targets
in conf
.env
['MSVC_INSTALLED_VERSIONS']:
315 for target
,l
in targets
:
318 def detect_msvc(conf
):
319 versions
= get_msvc_versions(conf
)
320 return setup_msvc(conf
, versions
)
323 def find_lt_names_msvc(self
, libname
, is_static
=False):
325 Win32/MSVC specific code to glean out information from libtool la files.
326 this function is not attached to the task_gen class
329 'lib%s.la' % libname
,
333 for path
in self
.env
['LIBPATH']:
335 laf
=os
.path
.join(path
,la
)
337 if os
.path
.exists(laf
):
338 ltdict
=read_la_file(laf
)
340 if ltdict
.get('libdir', ''):
341 lt_libdir
= ltdict
['libdir']
342 if not is_static
and ltdict
.get('library_names', ''):
343 dllnames
=ltdict
['library_names'].split()
344 dll
=dllnames
[0].lower()
345 dll
=re
.sub('\.dll$', '', dll
)
346 return (lt_libdir
, dll
, False)
347 elif ltdict
.get('old_library', ''):
348 olib
=ltdict
['old_library']
349 if os
.path
.exists(os
.path
.join(path
,olib
)):
350 return (path
, olib
, True)
351 elif lt_libdir
!= '' and os
.path
.exists(os
.path
.join(lt_libdir
,olib
)):
352 return (lt_libdir
, olib
, True)
354 return (None, olib
, True)
356 raise Utils
.WafError('invalid libtool object file: %s' % laf
)
357 return (None, None, None)
360 def libname_msvc(self
, libname
, is_static
=False, mandatory
=False):
361 lib
= libname
.lower()
362 lib
= re
.sub('\.lib$','',lib
)
364 if lib
in g_msvc_systemlibs
:
367 lib
=re
.sub('^lib','',lib
)
372 (lt_path
, lt_libname
, lt_static
) = self
.find_lt_names_msvc(lib
, is_static
)
374 if lt_path
!= None and lt_libname
!= None:
375 if lt_static
== True:
376 # file existance check has been made by find_lt_names
377 return os
.path
.join(lt_path
,lt_libname
)
380 _libpaths
=[lt_path
] + self
.env
['LIBPATH']
382 _libpaths
=self
.env
['LIBPATH']
392 'lib%s.dll.lib' % lib
,
403 libnames
=dynamic_libs
+ static_libs
405 for path
in _libpaths
:
406 for libn
in libnames
:
407 if os
.path
.exists(os
.path
.join(path
, libn
)):
408 debug('msvc: lib found: %s', os
.path
.join(path
,libn
))
409 return re
.sub('\.lib$', '',libn
)
411 #if no lib can be found, just return the libname as msvc expects it
413 self
.fatal("The library %r could not be found" % libname
)
414 return re
.sub('\.lib$', '', libname
)
417 def check_lib_msvc(self
, libname
, is_static
=False, uselib_store
=None, mandatory
=False):
418 "This is the api to use"
419 libn
= self
.libname_msvc(libname
, is_static
, mandatory
)
422 uselib_store
= libname
.upper()
424 # Note: ideally we should be able to place the lib in the right env var, either STATICLIB or LIB,
425 # but we don't distinguish static libs from shared libs.
426 # This is ok since msvc doesn't have any special linker flag to select static libs (no env['STATICLIB_MARKER'])
427 if False and is_static
: # disabled
428 self
.env
['STATICLIB_' + uselib_store
] = [libn
]
430 self
.env
['LIB_' + uselib_store
] = [libn
]
433 def check_libs_msvc(self
, libnames
, is_static
=False, mandatory
=False):
434 for libname
in Utils
.to_list(libnames
):
435 self
.check_lib_msvc(libname
, is_static
, mandatory
=mandatory
)
438 def no_autodetect(conf
):
439 conf
.eval_rules(detect
.replace('autodetect', ''))
454 def autodetect(conf
):
456 compiler
, version
, path
, includes
, libdirs
= detect_msvc(conf
)
458 v
['CPPPATH'] = includes
459 v
['LIBPATH'] = libdirs
460 v
['MSVC_COMPILER'] = compiler
462 def _get_prog_names(conf
, compiler
):
463 if compiler
=='intel':
464 compiler_name
= 'ICL'
465 linker_name
= 'XILINK'
472 return compiler_name
, linker_name
, lib_name
476 # due to path format limitations, limit operation only to native Win32. Yeah it sucks.
477 if sys
.platform
!= 'win32':
478 conf
.fatal('MSVC module only works under native Win32 Python! cygwin is not supported yet')
482 compiler
, version
, path
, includes
, libdirs
= detect_msvc(conf
)
484 compiler_name
, linker_name
, lib_name
= _get_prog_names(conf
, compiler
)
485 has_msvc_manifest
= (compiler
== 'msvc' and float(version
) >= 8) or (compiler
== 'wsdk' and float(version
) >= 6) or (compiler
== 'intel' and float(version
) >= 11)
489 if v
.CXX
: cxx
= v
.CXX
490 elif 'CXX' in conf
.environ
: cxx
= conf
.environ
['CXX']
491 if not cxx
: cxx
= conf
.find_program(compiler_name
, var
='CXX', path_list
=path
, mandatory
=True)
492 cxx
= conf
.cmd_to_list(cxx
)
494 # before setting anything, check if the compiler is really msvc
495 env
= dict(conf
.environ
)
496 env
.update(PATH
= ';'.join(path
))
497 if not Utils
.cmd_output([cxx
, '/nologo', '/?'], silent
=True, env
=env
):
498 conf
.fatal('the msvc compiler could not be identified')
502 link
= conf
.find_program(linker_name
, path_list
=path
, mandatory
=True)
505 ar
= conf
.find_program(lib_name
, path_list
=path
, mandatory
=True)
507 # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later
509 if has_msvc_manifest
:
510 mt
= conf
.find_program('MT', path_list
=path
, mandatory
=True)
512 # no more possibility of failure means the data state will be consistent
513 # we may store the data safely now
515 v
.MSVC_MANIFEST
= has_msvc_manifest
522 v
.CC_NAME
= v
.CXX_NAME
= 'msvc'
524 v
.LINK
= v
.LINK_CXX
= link
526 v
.LINK_CC
= v
.LINK_CXX
530 v
.MTFLAGS
= v
.ARFLAGS
= ['/NOLOGO']
533 conf
.check_tool('winres')
535 if not conf
.env
.WINRC
:
536 warn('Resource compiler not found. Compiling resource file is disabled')
539 try: v
.prepend_value('CPPPATH', conf
.environ
['INCLUDE'])
540 except KeyError: pass
541 try: v
.prepend_value('LIBPATH', conf
.environ
['LIB'])
542 except KeyError: pass
545 def msvc_common_flags(conf
):
548 v
['CPPFLAGS'] = ['/W3', '/nologo']
550 v
['CCDEFINES_ST'] = '/D%s'
551 v
['CXXDEFINES_ST'] = '/D%s'
553 # TODO just use _WIN32, which defined by the compiler itself!
554 v
['CCDEFINES'] = ['WIN32'] # avoid using this, any compiler predefines the _WIN32 marcro anyway
555 v
['CXXDEFINES'] = ['WIN32'] # avoid using this, any compiler predefines the _WIN32 marcro anyway
557 v
['_CCINCFLAGS'] = []
558 v
['_CCDEFFLAGS'] = []
559 v
['_CXXINCFLAGS'] = []
560 v
['_CXXDEFFLAGS'] = []
563 v
['CC_TGT_F'] = ['/c', '/Fo']
565 v
['CXX_TGT_F'] = ['/c', '/Fo']
567 v
['CPPPATH_ST'] = '/I%s' # template for adding include paths
569 v
['AR_TGT_F'] = v
['CCLNK_TGT_F'] = v
['CXXLNK_TGT_F'] = '/OUT:'
571 # Subsystem specific flags
572 v
['CPPFLAGS_CONSOLE'] = ['/SUBSYSTEM:CONSOLE']
573 v
['CPPFLAGS_NATIVE'] = ['/SUBSYSTEM:NATIVE']
574 v
['CPPFLAGS_POSIX'] = ['/SUBSYSTEM:POSIX']
575 v
['CPPFLAGS_WINDOWS'] = ['/SUBSYSTEM:WINDOWS']
576 v
['CPPFLAGS_WINDOWSCE'] = ['/SUBSYSTEM:WINDOWSCE']
579 v
['CPPFLAGS_CRT_MULTITHREADED'] = ['/MT']
580 v
['CPPFLAGS_CRT_MULTITHREADED_DLL'] = ['/MD']
582 # TODO these are defined by the compiler itself!
583 v
['CPPDEFINES_CRT_MULTITHREADED'] = ['_MT'] # this is defined by the compiler itself!
584 v
['CPPDEFINES_CRT_MULTITHREADED_DLL'] = ['_MT', '_DLL'] # these are defined by the compiler itself!
586 v
['CPPFLAGS_CRT_MULTITHREADED_DBG'] = ['/MTd']
587 v
['CPPFLAGS_CRT_MULTITHREADED_DLL_DBG'] = ['/MDd']
589 # TODO these are defined by the compiler itself!
590 v
['CPPDEFINES_CRT_MULTITHREADED_DBG'] = ['_DEBUG', '_MT'] # these are defined by the compiler itself!
591 v
['CPPDEFINES_CRT_MULTITHREADED_DLL_DBG'] = ['_DEBUG', '_MT', '_DLL'] # these are defined by the compiler itself!
593 # compiler debug levels
594 v
['CCFLAGS'] = ['/TC']
595 v
['CCFLAGS_OPTIMIZED'] = ['/O2', '/DNDEBUG']
596 v
['CCFLAGS_RELEASE'] = ['/O2', '/DNDEBUG']
597 v
['CCFLAGS_DEBUG'] = ['/Od', '/RTC1', '/ZI']
598 v
['CCFLAGS_ULTRADEBUG'] = ['/Od', '/RTC1', '/ZI']
600 v
['CXXFLAGS'] = ['/TP', '/EHsc']
601 v
['CXXFLAGS_OPTIMIZED'] = ['/O2', '/DNDEBUG']
602 v
['CXXFLAGS_RELEASE'] = ['/O2', '/DNDEBUG']
604 v
['CXXFLAGS_DEBUG'] = ['/Od', '/RTC1', '/ZI']
605 v
['CXXFLAGS_ULTRADEBUG'] = ['/Od', '/RTC1', '/ZI']
610 v
['LIB_ST'] = '%s.lib' # template for adding libs
611 v
['LIBPATH_ST'] = '/LIBPATH:%s' # template for adding libpaths
612 v
['STATICLIB_ST'] = 'lib%s.lib' # Note: to be able to distinguish between a static lib and a dll import lib, it's a good pratice to name the static lib 'lib%s.lib' and the dll import lib '%s.lib'
613 v
['STATICLIBPATH_ST'] = '/LIBPATH:%s'
615 v
['LINKFLAGS'] = ['/NOLOGO']
616 if v
['MSVC_MANIFEST']:
617 v
.append_value('LINKFLAGS', '/MANIFEST')
618 v
['LINKFLAGS_DEBUG'] = ['/DEBUG']
619 v
['LINKFLAGS_ULTRADEBUG'] = ['/DEBUG']
622 v
['shlib_CCFLAGS'] = ['']
623 v
['shlib_CXXFLAGS'] = ['']
624 v
['shlib_LINKFLAGS']= ['/DLL']
625 v
['shlib_PATTERN'] = '%s.dll'
626 v
['implib_PATTERN'] = '%s.lib'
627 v
['IMPLIB_ST'] = '/IMPLIB:%s'
630 v
['staticlib_LINKFLAGS'] = ['']
631 v
['staticlib_PATTERN'] = 'lib%s.lib' # Note: to be able to distinguish between a static lib and a dll import lib, it's a good pratice to name the static lib 'lib%s.lib' and the dll import lib '%s.lib'
634 v
['program_PATTERN'] = '%s.exe'
637 #######################################################################################################
638 ##### conf above, build below
641 @feature('cc', 'cxx')
642 def apply_flags_msvc(self
):
643 if self
.env
.CC_NAME
!= 'msvc' or not self
.link_task
:
646 subsystem
= getattr(self
, 'subsystem', '')
648 subsystem
= '/subsystem:%s' % subsystem
649 flags
= 'cstaticlib' in self
.features
and 'ARFLAGS' or 'LINKFLAGS'
650 self
.env
.append_value(flags
, subsystem
)
652 if getattr(self
, 'link_task', None) and not 'cstaticlib' in self
.features
:
653 for f
in self
.env
.LINKFLAGS
:
656 pdbnode
= self
.link_task
.outputs
[0].change_ext('.pdb')
657 pdbfile
= pdbnode
.bldpath(self
.env
)
658 self
.link_task
.outputs
.append(pdbnode
)
659 self
.bld
.install_files(self
.install_path
, [pdbnode
], env
=self
.env
)
662 @feature('cprogram', 'cshlib', 'cstaticlib')
663 @after('apply_lib_vars')
664 @before('apply_obj_vars')
665 def apply_obj_vars_msvc(self
):
666 if self
.env
['CC_NAME'] != 'msvc':
670 self
.meths
.remove('apply_obj_vars')
674 libpaths
= getattr(self
, 'libpaths', [])
675 if not libpaths
: self
.libpaths
= libpaths
678 app
= env
.append_unique
680 cpppath_st
= env
['CPPPATH_ST']
681 lib_st
= env
['LIB_ST']
682 staticlib_st
= env
['STATICLIB_ST']
683 libpath_st
= env
['LIBPATH_ST']
684 staticlibpath_st
= env
['STATICLIBPATH_ST']
686 for i
in env
['LIBPATH']:
687 app('LINKFLAGS', libpath_st
% i
)
688 if not libpaths
.count(i
):
691 for i
in env
['LIBPATH']:
692 app('LINKFLAGS', staticlibpath_st
% i
)
693 if not libpaths
.count(i
):
696 # i doubt that anyone will make a fully static binary anyway
697 if not env
['FULLSTATIC']:
698 if env
['STATICLIB'] or env
['LIB']:
699 app('LINKFLAGS', env
['SHLIB_MARKER']) # TODO does SHLIB_MARKER work?
701 for i
in env
['STATICLIB']:
702 app('LINKFLAGS', staticlib_st
% i
)
705 app('LINKFLAGS', lib_st
% i
)
707 # split the manifest file processing from the link task, like for the rc processing
709 @feature('cprogram', 'cshlib')
711 def apply_manifest(self
):
712 """Special linker for MSVC with support for embedding manifests into DLL's
713 and executables compiled by Visual Studio 2005 or probably later. Without
714 the manifest file, the binaries are unusable.
715 See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx"""
717 if self
.env
.CC_NAME
== 'msvc' and self
.env
.MSVC_MANIFEST
:
718 out_node
= self
.link_task
.outputs
[0]
719 man_node
= out_node
.parent
.find_or_declare(out_node
.name
+ '.manifest')
720 self
.link_task
.outputs
.append(man_node
)
721 self
.link_task
.do_manifest
= True
729 self
.do_manifest
= False
731 outfile
= self
.outputs
[0].bldpath(env
)
734 for out_node
in self
.outputs
:
735 if out_node
.name
.endswith('.manifest'):
736 manifest
= out_node
.bldpath(env
)
739 # Should never get here. If we do, it means the manifest file was
740 # never added to the outputs list, thus we don't have a manifest file
741 # to embed, so we just return.
744 # embedding mode. Different for EXE's and DLL's.
745 # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx
747 if 'cprogram' in self
.generator
.features
:
749 elif 'cshlib' in self
.generator
.features
:
752 debug('msvc: embedding manifest')
753 #flags = ' '.join(env['MTFLAGS'] or [])
756 lst
.extend([env
['MT']])
757 lst
.extend(Utils
.to_list(env
['MTFLAGS']))
758 lst
.extend(Utils
.to_list("-manifest"))
759 lst
.extend(Utils
.to_list(manifest
))
760 lst
.extend(Utils
.to_list("-outputresource:%s;%s" % (outfile
, mode
)))
762 #cmd='%s %s -manifest "%s" -outputresource:"%s";#%s' % (mtool, flags,
763 # manifest, outfile, mode)
765 return self
.exec_command(*lst
)
767 ########## stupid evil command modification: concatenate the tokens /Fx, /doc, and /x: with the next token
769 def exec_command_msvc(self
, *k
, **kw
):
770 "instead of quoting all the paths and keep using the shell, we can just join the options msvc is interested in"
771 if self
.env
['CC_NAME'] == 'msvc':
772 if isinstance(k
[0], list):
776 if len(a
) == 3 and a
.startswith('/F') or a
== '/doc' or a
[-1] == ':':
779 lst
.append(carry
+ a
)
783 env
= dict(os
.environ
)
784 env
.update(PATH
= ';'.join(self
.env
['PATH']))
787 ret
= self
.generator
.bld
.exec_command(*k
, **kw
)
789 if getattr(self
, 'do_manifest', None):
793 for k
in 'cc cxx winrc cc_link cxx_link static_link qxx'.split():
794 cls
= Task
.TaskBase
.classes
.get(k
, None)
796 cls
.exec_command
= exec_command_msvc