Package wafadmin :: Package Tools :: Module msvc
[hide private]
[frames] | no frames]

Source Code for Module wafadmin.Tools.msvc

  1  #!/usr/bin/env python 
  2  # encoding: utf-8 
  3  # Carlos Rafael Giani, 2006 (dv) 
  4  # Tamas Pal, 2007 (folti) 
  5  # Visual C support - beta, needs more testing 
  6   
  7  import os, sys, re, string, optparse 
  8  import Utils, TaskGen, Runner, Configure, Task, Options 
  9  from Logs import debug, error, warn 
 10  from Utils import quote_whitespace 
 11  from TaskGen import taskgen, after, before, feature 
 12   
 13  from Configure import conftest 
 14  import ccroot 
 15  from libtool import read_la_file 
 16  from os.path import exists 
17 18 -def msvc_linker(task):
19 """Special linker for MSVC with support for embedding manifests into DLL's 20 and executables compiled by Visual Studio 2005 or probably later. Without 21 the manifest file, the binaries are unusable. 22 See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx 23 Problems with this tool: it is always called whether MSVC creates manifests or not.""" 24 e = task.env 25 linker = e['LINK'] 26 srcf = e['LINK_SRC_F'] 27 trgtf = e['LINK_TGT_F'] 28 linkflags = e.get_flat('LINKFLAGS') 29 libdirs = e.get_flat('_LIBDIRFLAGS') 30 libs = e.get_flat('_LIBFLAGS') 31 32 subsystem='' 33 if task.subsystem: 34 subsystem='/subsystem:%s' % task.subsystem 35 outfile=task.outputs[0].bldpath(e) 36 manifest=outfile+'.manifest' 37 # pdb file containing the debug symbols (if compiled with /Zi or /ZI and linked with /debug 38 pdbnode=task.outputs[0].change_ext('.pdb') 39 pdbfile=pdbnode.bldpath(e) 40 41 objs=" ".join(['"%s"' % a.abspath(e) for a in task.inputs]) 42 43 cmd="%s %s %s%s %s%s %s %s %s" % (linker,subsystem,srcf,objs,trgtf,outfile, linkflags, libdirs,libs) 44 45 # workaround: when run with shell=True, got the following error: 46 # 'C:\Program' is not recognized as an internal or external command, operable program or batch file. 47 ret=Runner.exec_command(cmd, shell=False) 48 if ret: return ret 49 50 # check for the pdb file. if exists, add to the list of outputs 51 if os.path.exists(pdbfile): 52 task.outputs.append(pdbnode) 53 54 if os.path.exists(manifest): 55 debug('msvc: manifesttool') 56 mtool = e['MT'] 57 if not mtool: 58 return 0 59 mode='' 60 # embedding mode. Different for EXE's and DLL's. 61 # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx 62 if task.type == 'program': 63 mode='1' 64 elif task.type == 'shlib': 65 mode='2' 66 67 debug('msvc: embedding manifest') 68 flags = e['MTFLAGS'] 69 if flags: 70 flags=string.join(flags,' ') 71 else: 72 flags='' 73 74 cmd='%s %s -manifest "%s" -outputresource:"%s";#%s' % (mtool, flags, 75 manifest, outfile, mode) 76 ret=Runner.exec_command(cmd) 77 return ret
78 79 # importlibs provided by MSVC/Platform SDK. Do NOT search them.... 80 g_msvc_systemlibs = """ 81 aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet 82 cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs 83 credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d 84 ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp 85 faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid 86 gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop 87 kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi 88 mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree 89 msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm 90 netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp 91 odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 92 osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu 93 ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm 94 rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 95 shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 96 traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg 97 version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm 98 wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp 99 """.split()
100 101 102 -def find_lt_names_msvc(self, libname, is_static=False):
103 """ 104 Win32/MSVC specific code to glean out information from libtool la files. 105 this function is not attached to the task_gen class 106 """ 107 lt_names=[ 108 'lib%s.la' % libname, 109 '%s.la' % libname, 110 ] 111 112 for path in self.libpaths: 113 for la in lt_names: 114 laf=os.path.join(path,la) 115 dll=None 116 if exists(laf): 117 ltdict=read_la_file(laf) 118 lt_libdir=None 119 if ltdict.has_key('libdir') and ltdict['libdir'] != '': 120 lt_libdir=ltdict['libdir'] 121 if not is_static and ltdict.has_key('library_names') and ltdict['library_names'] != '': 122 dllnames=ltdict['library_names'].split() 123 dll=dllnames[0].lower() 124 dll=re.sub('\.dll$', '', dll) 125 return (lt_libdir, dll, False) 126 elif ltdict.has_key('old_library') and ltdict['old_library'] != '': 127 olib=ltdict['old_library'] 128 if exists(os.path.join(path,olib)): 129 return (path, olib, True) 130 elif lt_libdir != '' and exists(os.path.join(lt_libdir,olib)): 131 return (lt_libdir, olib, True) 132 else: 133 return (None, olib, True) 134 else: 135 raise Utils.WafError('invalid libtool object file: %s' % laf) 136 return (None, None, None)
137
138 -def libname_msvc(self, libname, is_static=False):
139 lib=libname.lower() 140 lib=re.sub('\.lib$','',lib) 141 142 if lib in g_msvc_systemlibs: 143 return lib+'.lib' 144 145 lib=re.sub('^lib','',lib) 146 147 if lib == 'm': 148 return None 149 150 (lt_path, lt_libname, lt_static) = find_lt_names_msvc(self, lib, is_static) 151 152 if lt_path != None and lt_libname != None: 153 if lt_static == True: 154 # file existance check has been made by find_lt_names 155 return os.path.join(lt_path,lt_libname) 156 157 if lt_path != None: 158 _libpaths=[lt_path] + self.libpaths 159 else: 160 _libpaths=self.libpaths 161 162 static_libs=[ 163 '%ss.lib' % lib, 164 'lib%ss.lib' % lib, 165 '%s.lib' %lib, 166 'lib%s.lib' % lib, 167 ] 168 169 dynamic_libs=[ 170 'lib%s.dll.lib' % lib, 171 'lib%s.dll.a' % lib, 172 '%s.dll.lib' % lib, 173 '%s.dll.a' % lib, 174 'lib%s_d.lib' % lib, 175 '%s_d.lib' % lib, 176 '%s.lib' %lib, 177 ] 178 179 libnames=static_libs 180 if not is_static: 181 libnames=dynamic_libs + static_libs 182 183 for path in _libpaths: 184 for libn in libnames: 185 if os.path.exists(os.path.join(path,libn)): 186 debug('msvc: lib found: %s' % os.path.join(path,libn)) 187 return libn 188 189 return None
190
191 @taskgen 192 @feature('cc', 'cxx') 193 @after('apply_obj_vars_cc') 194 @after('apply_obj_vars_cxx') 195 -def apply_msvc_obj_vars(self):
196 env = self.env 197 app = env.append_unique 198 199 cpppath_st = env['CPPPATH_ST'] 200 lib_st = env['LIB_ST'] 201 staticlib_st = env['STATICLIB_ST'] 202 libpath_st = env['LIBPATH_ST'] 203 staticlibpath_st = env['STATICLIBPATH_ST'] 204 self.libpaths = [] 205 206 for i in env['RPATH']: app('LINKFLAGS', i) 207 for i in env['LIBPATH']: 208 app('LINKFLAGS', libpath_st % i) 209 if not self.libpaths.count(i): 210 self.libpaths.append(i) 211 for i in env['LIBPATH']: 212 app('LINKFLAGS', staticlibpath_st % i) 213 if not self.libpaths.count(i): 214 self.libpaths.append(i) 215 216 # i doubt that anyone will make a fully static binary anyway 217 if not env['FULLSTATIC']: 218 if env['STATICLIB'] or env['LIB']: 219 app('LINKFLAGS', env['SHLIB_MARKER']) 220 221 if env['STATICLIB']: 222 app('LINKFLAGS', env['STATICLIB_MARKER']) 223 for i in env['STATICLIB']: 224 debug('msvc: libname: %s' % i) 225 libname = libname_msvc(self, i, True) 226 debug('msvc: libnamefixed: %s' % libname) 227 if libname != None: 228 app('LINKFLAGS', libname) 229 230 if self.env['LIB']: 231 for i in env['LIB']: 232 debug('msvc: libname: %s' % i) 233 libname = libname_msvc(self, i) 234 debug('msvc: libnamefixed: %s' % libname) 235 if libname != None: 236 app('LINKFLAGS', libname)
237 268
269 @taskgen 270 @feature('cc', 'cxx') 271 @before('apply_core') 272 -def init_msvc(self):
273 "all methods (msvc and non-msvc) are to be executed, but we remove the ones we do not want" 274 if self.env['CC_NAME'] == 'msvc' or self.env['CXX_NAME'] == 'msvc': 275 self.meths.remove('apply_link') 276 else: 277 for x in ['apply_link_msvc', 'apply_msvc_obj_vars']: 278 self.meths.remove(x) 279 self.libpaths = getattr(self, 'libpaths', '')
280 281 static_link_str = '${STLIBLINK} ${LINK_SRC_F}${SRC} ${LINK_TGT_F}${TGT}' 282 Task.simple_task_type('msvc_ar_link_static', static_link_str, color='YELLOW', ext_in='.o') 283 Task.task_type_from_func('msvc_cc_link', vars=['LINK', 'LINK_SRC_F', 'LINK_TGT_F', 'LINKFLAGS', '_LIBDIRFLAGS', '_LIBFLAGS', 'MT', 'MTFLAGS'] , color='YELLOW', func=msvc_linker, ext_in='.o') 284 Task.task_type_from_func('msvc_cxx_link', vars=['LINK', 'LINK_SRC_F', 'LINK_TGT_F', 'LINKFLAGS', '_LIBDIRFLAGS', '_LIBFLAGS', 'MT', 'MTFLAGS'] , color='YELLOW', func=msvc_linker, ext_in='.o') 285 286 rc_str='${RC} ${RCFLAGS} /fo ${TGT} ${SRC}' 287 Task.simple_task_type('rc', rc_str, color='GREEN', before='cc cxx') 288 289 import winres 290 291 detect = ''' 292 find_msvc 293 msvc_common_flags 294 cc_load_tools 295 cxx_load_tools 296 cc_add_flags 297 cxx_add_flags 298 '''
299 300 @conftest 301 -def find_msvc(conf):
302 # due to path format limitations, limit operation only to native Win32. Yeah it sucks. 303 if sys.platform != 'win32': 304 conf.fatal('MSVC module only works under native Win32 Python! cygwin is not supported yet') 305 306 v = conf.env 307 308 # compiler 309 cxx = None 310 if v['CXX']: cxx = v['CXX'] 311 elif 'CXX' in os.environ: cxx = os.environ['CXX'] 312 if not cxx: cxx = conf.find_program('CL', var='CXX') 313 if not cxx: conf.fatal('CL was not found (compiler)') 314 315 # c/c++ compiler - check for whitespace, and if so, add quotes 316 v['CXX'] = quote_whitespace(cxx) 317 v['CC'] = v['CXX'] 318 v['CXX_NAME'] = 'msvc' 319 v['CC_NAME'] = 'msvc' 320 321 # linker 322 if not v['LINK_CXX']: 323 link = conf.find_program('LINK') 324 if link: v['LINK_CXX'] = link 325 else: conf.fatal('LINK was not found (linker)') 326 v['LINK'] = '\"%s\"' % link 327 328 if not v['LINK_CC']: v['LINK_CC'] = v['LINK_CXX'] 329 330 # staticlib linker 331 if not v['STLIBLINK']: 332 stliblink = conf.find_program('LIB') 333 if not stliblink: return 334 v['STLIBLINK'] = '\"%s\"' % stliblink 335 336 # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later 337 manifesttool = conf.find_program('MT') 338 if manifesttool: 339 v['MT'] = quote_whitespace (manifesttool) 340 v['MTFLAGS']=['/NOLOGO'] 341 342 conf.check_tool('winres') 343 344 if not conf.env['WINRC']: 345 warn('Resource compiler not found. Compiling resource file is disabled')
346
347 @conftest 348 -def msvc_common_flags(conf):
349 v = conf.env 350 351 v['CPPFLAGS'] = ['/W3', '/nologo', '/EHsc', '/errorReport:prompt'] 352 v['CCDEFINES'] = ['WIN32'] # command-line defines 353 v['CXXDEFINES'] = ['WIN32'] # command-line defines 354 355 v['_CCINCFLAGS'] = [] 356 v['_CCDEFFLAGS'] = [] 357 v['_CXXINCFLAGS'] = [] 358 v['_CXXDEFFLAGS'] = [] 359 360 v['CC_SRC_F'] = '' 361 v['CC_TGT_F'] = '/c /Fo' 362 v['CXX_SRC_F'] = '' 363 v['CXX_TGT_F'] = '/c /Fo' 364 365 v['CPPPATH_ST'] = '/I%s' # template for adding include paths 366 367 # Subsystem specific flags 368 v['CPPFLAGS_CONSOLE'] = ['/SUBSYSTEM:CONSOLE'] 369 v['CPPFLAGS_NATIVE'] = ['/SUBSYSTEM:NATIVE'] 370 v['CPPFLAGS_POSIX'] = ['/SUBSYSTEM:POSIX'] 371 v['CPPFLAGS_WINDOWS'] = ['/SUBSYSTEM:WINDOWS'] 372 v['CPPFLAGS_WINDOWSCE'] = ['/SUBSYSTEM:WINDOWSCE'] 373 374 # CRT specific flags 375 v['CPPFLAGS_CRT_MULTITHREADED'] = ['/MT'] 376 v['CPPFLAGS_CRT_MULTITHREADED_DLL'] = ['/MD'] 377 v['CPPDEFINES_CRT_MULTITHREADED'] = ['_MT'] 378 v['CPPDEFINES_CRT_MULTITHREADED_DLL'] = ['_MT', '_DLL'] 379 380 v['CPPFLAGS_CRT_MULTITHREADED_DBG'] = ['/MTd'] 381 v['CPPFLAGS_CRT_MULTITHREADED_DLL_DBG'] = ['/MDd'] 382 v['CPPDEFINES_CRT_MULTITHREADED_DBG'] = ['_DEBUG', '_MT'] 383 v['CPPDEFINES_CRT_MULTITHREADED_DLL_DBG'] = ['_DEBUG', '_MT', '_DLL'] 384