3
# WARNING! All changes made to this file will be lost!
5
import os,sys,re,tempfile
10
import winreg as _winreg
13
from waflib import Utils,TaskGen,Runner,Configure,Task,Options
14
from waflib.Logs import debug,info,warn,error
15
from waflib.TaskGen import after,before,feature
16
from waflib.Configure import conf
17
from waflib.Tools import ccroot,c,cxx,ar,winres
19
aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet
20
cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs
21
credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d
22
ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp
23
faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid
24
gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop
25
kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi
26
mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree
27
msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm
28
netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp
29
odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32
30
osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu
31
ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm
32
rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32
33
shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32
34
traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg
35
version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm
36
wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp
38
all_msvc_platforms=[('x64','amd64'),('x86','x86'),('ia64','ia64'),('x86_amd64','amd64'),('x86_ia64','ia64')]
39
all_wince_platforms=[('armv4','arm'),('armv4i','arm'),('mipsii','mips'),('mipsii_fp','mips'),('mipsiv','mips'),('mipsiv_fp','mips'),('sh4','sh'),('x86','cex86')]
40
all_icl_platforms=[('intel64','amd64'),('em64t','amd64'),('ia32','x86'),('Itanium','ia64')]
41
def setup_msvc(conf,versions):
42
platforms=Utils.to_list(conf.env['MSVC_TARGETS'])or[i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms]
43
desired_versions=conf.env['MSVC_VERSIONS']or[v for v,_ in versions][::-1]
44
versiondict=dict(versions)
45
for version in desired_versions:
47
targets=dict(versiondict[version])
48
for target in platforms:
50
arch,(p1,p2,p3)=targets[target]
51
compiler,revision=version.split()
52
return compiler,revision,p1,p2,p3
53
except KeyError:continue
54
except KeyError:continue
55
conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)')
56
def get_msvc_version(conf,compiler,version,target,vcvars):
57
debug('msvc: get_msvc_version: %r %r %r',compiler,version,target)
58
batfile=conf.bldnode.make_node('waf-print-msvc.bat')
59
batfile.write("""@echo off
64
echo INCLUDE=%%INCLUDE%%
67
sout=conf.cmd_and_log(['cmd','/E:on','/V:on','/C',batfile.abspath()])
68
lines=sout.splitlines()
69
for x in('Setting environment','Setting SDK environment','Intel(R) C++ Compiler','Intel Parallel Studio'):
70
if lines[0].find(x)!=-1:
73
debug('msvc: get_msvc_version: %r %r %r -> not found',compiler,version,target)
74
conf.fatal('msvc: Impossible to find a valid architecture for building (in get_msvc_version)')
75
for line in lines[1:]:
76
if line.startswith('PATH='):
78
MSVC_PATH=path.split(';')
79
elif line.startswith('INCLUDE='):
80
MSVC_INCDIR=[i for i in line[8:].split(';')if i]
81
elif line.startswith('LIB='):
82
MSVC_LIBDIR=[i for i in line[4:].split(';')if i]
84
env.update(os.environ)
86
compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler)
87
cxx=conf.find_program(compiler_name,path_list=MSVC_PATH)
88
cxx=conf.cmd_to_list(cxx)
93
conf.cmd_and_log(cxx+['/help'],env=env)
95
debug('msvc: get_msvc_version: %r %r %r -> failure'%(compiler,version,target))
97
conf.fatal('msvc: cannot run the compiler (in get_msvc_version)')
99
debug('msvc: get_msvc_version: %r %r %r -> OK',compiler,version,target)
101
conf.env[compiler_name]=''
102
return(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR)
103
def gather_wsdk_versions(conf,versions):
104
version_pattern=re.compile('^v..?.?\...?.?')
106
all_versions=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows')
109
all_versions=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows')
115
version=_winreg.EnumKey(all_versions,index)
119
if not version_pattern.match(version):
122
msvc_version=_winreg.OpenKey(all_versions,version)
123
path,type=_winreg.QueryValueEx(msvc_version,'InstallationFolder')
126
if os.path.isfile(os.path.join(path,'bin','SetEnv.cmd')):
128
for target,arch in all_msvc_platforms:
130
targets.append((target,(arch,conf.get_msvc_version('wsdk',version,'/'+target,os.path.join(path,'bin','SetEnv.cmd')))))
131
except conf.errors.ConfigurationError:
133
versions.append(('wsdk '+version[1:],targets))
134
def gather_msvc_versions(conf,versions):
136
ce_sdk=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs')
139
ce_sdk=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs')
143
supported_wince_platforms=[]
147
sdk_device=_winreg.EnumKey(ce_sdk,ce_index)
151
sdk=_winreg.OpenKey(ce_sdk,sdk_device)
152
path,type=_winreg.QueryValueEx(sdk,'SDKRootDir')
154
path,device=os.path.split(path)
156
path,device=os.path.split(path)
157
for arch,compiler in all_wince_platforms:
159
if os.path.isdir(os.path.join(path,device,'Lib',arch)):
160
platforms.append((arch,compiler,os.path.join(path,device,'Include',arch),os.path.join(path,device,'Lib',arch)))
162
supported_wince_platforms.append((device,platforms))
163
version_pattern=re.compile('^..?\...?')
165
for vcver,vcvar in[('VCExpress','Exp'),('VisualStudio','')]:
167
prefix='SOFTWARE\\Wow6432node\\Microsoft\\'+vcver
168
all_versions=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,prefix)
171
prefix='SOFTWARE\\Microsoft\\'+vcver
172
all_versions=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,prefix)
178
version=_winreg.EnumKey(all_versions,index)
182
if not version_pattern.match(version):
184
if version.endswith('Exp'):
185
versionnumber=float(version[:-3])
187
versionnumber=float(version)
188
detected_versions.append((versionnumber,version,prefix+"\\"+version))
191
detected_versions.sort(key=fun)
192
for(v,version,reg)in detected_versions:
194
msvc_version=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,reg+"\\Setup\\VS")
195
path,type=_winreg.QueryValueEx(msvc_version,'ProductDir')
199
for device,platforms in supported_wince_platforms:
201
for platform,compiler,include,lib in platforms:
202
winCEpath=os.path.join(path,'VC','ce')
203
if os.path.isdir(winCEpath):
205
common_bindirs,_1,_2=conf.get_msvc_version('msvc',version,'x86',os.path.join(path,'Common7','Tools','vsvars32.bat'))
206
except conf.errors.ConfigurationError:
209
if os.path.isdir(os.path.join(winCEpath,'lib',platform)):
210
bindirs=[os.path.join(winCEpath,'bin',compiler),os.path.join(winCEpath,'bin','x86_'+compiler)]+common_bindirs
211
incdirs=[include,os.path.join(winCEpath,'include'),os.path.join(winCEpath,'atlmfc','include')]
212
libdirs=[lib,os.path.join(winCEpath,'lib',platform),os.path.join(winCEpath,'atlmfc','lib',platform)]
213
cetargets.append((platform,(platform,(bindirs,incdirs,libdirs))))
214
versions.append((device+' '+version,cetargets))
215
if os.path.isfile(os.path.join(path,'VC','vcvarsall.bat')):
216
for target,realtarget in all_msvc_platforms[::-1]:
218
targets.append((target,(realtarget,conf.get_msvc_version('msvc',version,target,os.path.join(path,'VC','vcvarsall.bat')))))
219
except conf.errors.ConfigurationError:
221
elif os.path.isfile(os.path.join(path,'Common7','Tools','vsvars32.bat')):
223
targets.append(('x86',('x86',conf.get_msvc_version('msvc',version,'x86',os.path.join(path,'Common7','Tools','vsvars32.bat')))))
224
except conf.errors.ConfigurationError:
226
versions.append(('msvc '+version,targets))
229
def gather_icl_versions(conf,versions):
230
version_pattern=re.compile('^...?.?\....?.?')
232
all_versions=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++')
235
all_versions=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Compilers\\C++')
241
version=_winreg.EnumKey(all_versions,index)
245
if not version_pattern.match(version):
248
for target,arch in all_icl_platforms:
250
if target=='intel64':targetDir='EM64T_NATIVE'
251
else:targetDir=target
252
_winreg.OpenKey(all_versions,version+'\\'+targetDir)
253
icl_version=_winreg.OpenKey(all_versions,version)
254
path,type=_winreg.QueryValueEx(icl_version,'ProductDir')
255
if os.path.isfile(os.path.join(path,'bin','iclvars.bat')):
257
targets.append((target,(arch,conf.get_msvc_version('intel',version,target,os.path.join(path,'bin','iclvars.bat')))))
258
except conf.errors.ConfigurationError:
262
for target,arch in all_icl_platforms:
264
icl_version=_winreg.OpenKey(all_versions,version+'\\'+target)
265
path,type=_winreg.QueryValueEx(icl_version,'ProductDir')
266
if os.path.isfile(os.path.join(path,'bin','iclvars.bat')):
268
targets.append((target,(arch,conf.get_msvc_version('intel',version,target,os.path.join(path,'bin','iclvars.bat')))))
269
except conf.errors.ConfigurationError:
274
versions.append(('intel '+major,targets))
275
def get_msvc_versions(conf):
276
if not conf.env['MSVC_INSTALLED_VERSIONS']:
278
conf.gather_icl_versions(lst)
279
conf.gather_wsdk_versions(lst)
280
conf.gather_msvc_versions(lst)
281
conf.env['MSVC_INSTALLED_VERSIONS']=lst
282
return conf.env['MSVC_INSTALLED_VERSIONS']
283
def print_all_msvc_detected(conf):
284
for version,targets in conf.env['MSVC_INSTALLED_VERSIONS']:
286
for target,l in targets:
288
def detect_msvc(conf):
289
versions=get_msvc_versions(conf)
290
return setup_msvc(conf,versions)
291
def find_lt_names_msvc(self,libname,is_static=False):
292
lt_names=['lib%s.la'%libname,'%s.la'%libname,]
293
for path in self.env['LIBPATH']:
295
laf=os.path.join(path,la)
297
if os.path.exists(laf):
298
ltdict=Utils.read_la_file(laf)
300
if ltdict.get('libdir',''):
301
lt_libdir=ltdict['libdir']
302
if not is_static and ltdict.get('library_names',''):
303
dllnames=ltdict['library_names'].split()
304
dll=dllnames[0].lower()
305
dll=re.sub('\.dll$','',dll)
306
return(lt_libdir,dll,False)
307
elif ltdict.get('old_library',''):
308
olib=ltdict['old_library']
309
if os.path.exists(os.path.join(path,olib)):
310
return(path,olib,True)
311
elif lt_libdir!=''and os.path.exists(os.path.join(lt_libdir,olib)):
312
return(lt_libdir,olib,True)
314
return(None,olib,True)
316
raise Errors.WafError('invalid libtool object file: %s'%laf)
317
return(None,None,None)
318
def libname_msvc(self,libname,is_static=False):
320
lib=re.sub('\.lib$','',lib)
321
if lib in g_msvc_systemlibs:
323
lib=re.sub('^lib','',lib)
326
(lt_path,lt_libname,lt_static)=self.find_lt_names_msvc(lib,is_static)
327
if lt_path!=None and lt_libname!=None:
329
return os.path.join(lt_path,lt_libname)
331
_libpaths=[lt_path]+self.env['LIBPATH']
333
_libpaths=self.env['LIBPATH']
334
static_libs=['lib%ss.lib'%lib,'lib%s.lib'%lib,'%ss.lib'%lib,'%s.lib'%lib,]
335
dynamic_libs=['lib%s.dll.lib'%lib,'lib%s.dll.a'%lib,'%s.dll.lib'%lib,'%s.dll.a'%lib,'lib%s_d.lib'%lib,'%s_d.lib'%lib,'%s.lib'%lib,]
338
libnames=dynamic_libs+static_libs
339
for path in _libpaths:
340
for libn in libnames:
341
if os.path.exists(os.path.join(path,libn)):
342
debug('msvc: lib found: %s'%os.path.join(path,libn))
343
return re.sub('\.lib$','',libn)
344
self.fatal("The library %r could not be found"%libname)
345
return re.sub('\.lib$','',libname)
346
def check_lib_msvc(self,libname,is_static=False,uselib_store=None):
347
libn=self.libname_msvc(libname,is_static)
349
uselib_store=libname.upper()
350
if False and is_static:
351
self.env['STLIB_'+uselib_store]=[libn]
353
self.env['LIB_'+uselib_store]=[libn]
354
def check_libs_msvc(self,libnames,is_static=False):
355
for libname in Utils.to_list(libnames):
356
self.check_lib_msvc(libname,is_static)
357
def no_autodetect(conf):
358
conf.eval_rules(detect.replace('autodetect',''))
362
conf.msvc_common_flags()
364
conf.cxx_load_tools()
367
conf.link_add_flags()
368
def autodetect(conf):
370
compiler,version,path,includes,libdirs=detect_msvc(conf)
372
v['INCLUDES']=includes
374
v['MSVC_COMPILER']=compiler
375
def _get_prog_names(conf,compiler):
376
if compiler=='intel':
384
return compiler_name,linker_name,lib_name
386
if sys.platform=='cygwin':
387
conf.fatal('MSVC module does not work under cygwin Python!')
389
compiler,version,path,includes,libdirs=detect_msvc(conf)
391
v['INCLUDES']=includes
393
compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler)
394
v.MSVC_MANIFEST=(compiler=='msvc'and float(version)>=8)or(compiler=='wsdk'and float(version)>=6)or(compiler=='intel'and float(version)>=11)
396
if v['CXX']:cxx=v['CXX']
397
elif'CXX'in conf.environ:cxx=conf.environ['CXX']
398
cxx=conf.find_program(compiler_name,var='CXX',path_list=path)
399
cxx=conf.cmd_to_list(cxx)
400
env=dict(conf.environ)
401
env.update(PATH=';'.join(path))
402
if not conf.cmd_and_log(cxx+['/nologo','/help'],env=env):
403
conf.fatal('the msvc compiler could not be identified')
405
v['CC_NAME']=v['CXX_NAME']='msvc'
406
try:v.prepend_value('INCLUDES',conf.environ['INCLUDE'])
408
try:v.prepend_value('LIBPATH',conf.environ['LIB'])
410
if not v['LINK_CXX']:
411
link=conf.find_program(linker_name,path_list=path)
412
if link:v['LINK_CXX']=link
413
else:conf.fatal('%s was not found (linker)'%linker_name)
416
v['LINK_CC']=v['LINK_CXX']
418
stliblink=conf.find_program(lib_name,path_list=path,var='AR')
419
if not stliblink:return
420
v['ARFLAGS']=['/NOLOGO']
422
mt=conf.find_program('MT',path_list=path,var='MT')
423
v['MTFLAGS']=['/NOLOGO']
425
if not conf.env['WINRC']:
426
warn('Resource compiler not found. Compiling resource file is disabled')
427
def msvc_common_flags(conf):
429
v['DEST_BINFMT']='pe'
430
v.append_value('CFLAGS',['/nologo'])
431
v.append_value('CXXFLAGS',['/nologo'])
432
v['DEFINES_ST']='/D%s'
434
v['CC_TGT_F']=['/c','/Fo']
436
v['CXX_TGT_F']=['/c','/Fo']
437
v['CPPPATH_ST']='/I%s'
438
v['AR_TGT_F']=v['CCLNK_TGT_F']=v['CXXLNK_TGT_F']='/OUT:'
439
v['CFLAGS_CONSOLE']=v['CXXFLAGS_CONSOLE']=['/SUBSYSTEM:CONSOLE']
440
v['CFLAGS_NATIVE']=v['CXXFLAGS_NATIVE']=['/SUBSYSTEM:NATIVE']
441
v['CFLAGS_POSIX']=v['CXXFLAGS_POSIX']=['/SUBSYSTEM:POSIX']
442
v['CFLAGS_WINDOWS']=v['CXXFLAGS_WINDOWS']=['/SUBSYSTEM:WINDOWS']
443
v['CFLAGS_WINDOWSCE']=v['CXXFLAGS_WINDOWSCE']=['/SUBSYSTEM:WINDOWSCE']
444
v['CFLAGS_CRT_MULTITHREADED']=v['CXXFLAGS_CRT_MULTITHREADED']=['/MT']
445
v['CFLAGS_CRT_MULTITHREADED_DLL']=v['CXXFLAGS_CRT_MULTITHREADED_DLL']=['/MD']
446
v['CFLAGS_CRT_MULTITHREADED_DBG']=v['CXXFLAGS_CRT_MULTITHREADED_DBG']=['/MTd']
447
v['CFLAGS_CRT_MULTITHREADED_DLL_DBG']=v['CXXFLAGS_CRT_MULTITHREADED_DLL_DBG']=['/MDd']
449
v['LIBPATH_ST']='/LIBPATH:%s'
450
v['STLIB_ST']='lib%s.lib'
451
v['STLIBPATH_ST']='/LIBPATH:%s'
452
v.append_value('LINKFLAGS',['/NOLOGO'])
453
if v['MSVC_MANIFEST']:
454
v.append_value('LINKFLAGS',['/MANIFEST'])
455
v['CFLAGS_cshlib']=['']
456
v['CXXFLAGS_cxxshlib']=['']
457
v['LINKFLAGS_cshlib']=v['LINKFLAGS_cxxshlib']=['/DLL']
458
v['cshlib_PATTERN']=v['cxxshlib_PATTERN']='%s.dll'
459
v['implib_PATTERN']='%s.lib'
460
v['IMPLIB_ST']='/IMPLIB:%s'
461
v['LINKFLAGS_cstlib']=['']
462
v['cstlib_PATTERN']=v['cxxstlib_PATTERN']='lib%s.lib'
463
v['cprogram_PATTERN']=v['cxxprogram_PATTERN']='%s.exe'
464
def apply_flags_msvc(self):
465
if self.env.CC_NAME!='msvc'or not getattr(self,'link_task',None):
467
is_static=isinstance(self.link_task,ccroot.stlink_task)
468
subsystem=getattr(self,'subsystem','')
470
subsystem='/subsystem:%s'%subsystem
471
flags=is_static and'ARFLAGS'or'LINKFLAGS'
472
self.env.append_value(flags,subsystem)
474
for f in self.env.LINKFLAGS:
478
pdbnode=self.link_task.outputs[0].change_ext('.pdb')
479
dest=self.inst_task.dest
480
except AttributeError:
483
pdbfile=pdbnode.bldpath()
484
self.link_task.outputs.append(pdbnode)
485
self.bld.install_files(dest,[pdbnode],env=self.env)
487
def apply_manifest(self):
488
if self.env.CC_NAME=='msvc'and self.env.MSVC_MANIFEST and getattr(self,'link_task',None):
489
out_node=self.link_task.outputs[0]
490
man_node=out_node.parent.find_or_declare(out_node.name+'.manifest')
491
self.link_task.outputs.append(man_node)
492
self.link_task.do_manifest=True
498
self.do_manifest=False
499
outfile=self.outputs[0].abspath()
501
for out_node in self.outputs:
502
if out_node.name.endswith('.manifest'):
503
manifest=out_node.abspath()
508
if'cprogram'in self.generator.features or'cxxprogram'in self.generator.features:
510
elif'cshlib'in self.generator.features or'cxxshlib'in self.generator.features:
512
debug('msvc: embedding manifest in mode %r'%mode)
514
lst.append(env['MT'])
515
lst.extend(Utils.to_list(env['MTFLAGS']))
516
lst.extend(['-manifest',manifest])
517
lst.append('-outputresource:%s;%s'%(outfile,mode))
519
return self.exec_command(*lst)
520
def quote_response_command(self,flag):
521
if flag.find(' ')>-1:
522
for x in('/LIBPATH:','/IMPLIB:','/OUT:','/I'):
523
if flag.startswith(x):
524
flag='%s"%s"'%(x,flag[len(x):])
529
def exec_response_command(self,cmd,**kw):
532
if sys.platform.startswith('win')and isinstance(cmd,list)and len(' '.join(cmd))>=8192:
534
cmd=[self.quote_response_command(x)for x in cmd]
535
(fd,tmp)=tempfile.mkstemp()
536
os.write(fd,' '.join(cmd[1:]))
538
cmd=[program,'@'+tmp]
539
ret=self.generator.bld.exec_command(cmd,**kw)
544
def exec_command_msvc(self,*k,**kw):
545
if self.env['CC_NAME']=='msvc':
546
if isinstance(k[0],list):
550
if len(a)==3 and a.startswith('/F')or a=='/doc'or a[-1]==':':
557
env.update(PATH=';'.join(self.env['PATH']))
559
bld=self.generator.bld
561
if not kw.get('cwd',None):
563
except AttributeError:
564
bld.cwd=kw['cwd']=bld.variant_dir
565
ret=self.exec_response_command(k[0],**kw)
566
if not ret and getattr(self,'do_manifest',None):
569
for k in'c cxx winrc cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib qxx'.split():
570
cls=Task.classes.get(k,None)
572
cls.exec_command=exec_command_msvc
573
cls.exec_response_command=exec_response_command
574
cls.quote_response_command=quote_response_command
577
conf(get_msvc_version)
578
conf(gather_wsdk_versions)
579
conf(gather_msvc_versions)
580
conf(gather_icl_versions)
581
conf(get_msvc_versions)
582
conf(print_all_msvc_detected)
583
conf(find_lt_names_msvc)
586
conf(check_libs_msvc)
590
conf(msvc_common_flags)
591
after('apply_link')(apply_flags_msvc)
592
feature('c','cxx')(apply_flags_msvc)
593
feature('cprogram','cshlib','cxxprogram','cxxshlib')(apply_manifest)
594
after('apply_link')(apply_manifest)
b'\\ No newline at end of file'