Simplify manifest file processing

This commit is contained in:
Thomas Nagy 2016-06-16 21:39:50 +02:00
parent f18d481e75
commit 98f495bda1
No known key found for this signature in database
GPG Key ID: 67A565EDFDF90E64
4 changed files with 47 additions and 148 deletions

View File

@ -53,3 +53,5 @@ NEW IN WAF 1.9
that case all mappings/precedences must be present. These features were not used in Waf 1.8.
- Do not truncate the _task suffix from Task class names
- Task.exec_command will use @argfile when command-line limits are exceeded
- Task.exec_command will add tsk.env.PATH to the child process environment

View File

@ -8,7 +8,7 @@ as C/C++/D/Assembly/Go (this support module is almost never used alone).
"""
import os, re
from waflib import Task, Utils, Node, Errors
from waflib import Task, Utils, Node, Errors, Logs
from waflib.TaskGen import after_method, before_method, feature, taskgen_method, extension
from waflib.Tools import c_aliases, c_preproc, c_config, c_osx, c_tests
from waflib.Configure import conf
@ -172,6 +172,48 @@ class link_task(Task.Task):
target = base.find_or_declare(tmp)
self.set_outputs(target)
def exec_command(self, *k, **kw):
ret = super(link_task, self).exec_command(*k, **kw)
if not ret and self.env.DO_MANIFEST:
ret = self.exec_mf()
return ret
def exec_mf(self):
"""
Create manifest files for VS-like compilers (msvc, ifort, ...)
"""
if not self.env.MT:
return 0
manifest = None
for out_node in self.outputs:
if out_node.name.endswith('.manifest'):
manifest = out_node.abspath()
break
else:
# Should never get here. If we do, it means the manifest file was
# never added to the outputs list, thus we don't have a manifest file
# to embed, so we just return.
return 0
# embedding mode. Different for EXE's and DLL's.
# see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx
mode = ''
for x in Utils.to_list(self.generator.features):
if x in ('cprogram', 'cxxprogram', 'fcprogram', 'fcprogram_test'):
mode = 1
elif x in ('cshlib', 'cxxshlib', 'fcshlib'):
mode = 2
Logs.debug('msvc: embedding manifest in mode %r', mode)
lst = [] + self.env.MT
lst.extend(Utils.to_list(self.env.MTFLAGS))
lst.extend(['-manifest', manifest])
lst.append('-outputresource:%s;%s' % (self.outputs[0].abspath(), mode))
return super(link_task, self).exec_command(lst)
class stlink_task(link_task):
"""
Base for static link tasks, which use *ar* most of the time.

View File

@ -395,8 +395,6 @@ def apply_flags_ifort(self):
break
# split the manifest file processing from the link task, like for the rc processing
@feature('fcprogram', 'fcshlib', 'fcprogram_test')
@after_method('apply_link')
def apply_manifest_ifort(self):
@ -408,75 +406,5 @@ def apply_manifest_ifort(self):
out_node = self.link_task.outputs[0]
man_node = out_node.parent.find_or_declare(out_node.name + '.manifest')
self.link_task.outputs.append(man_node)
self.link_task.do_manifest = True
def exec_mf(self):
"""
Create the manifest file
"""
env = self.env
mtool = env['MT']
if not mtool:
return 0
self.do_manifest = False
outfile = self.outputs[0].abspath()
manifest = None
for out_node in self.outputs:
if out_node.name.endswith('.manifest'):
manifest = out_node.abspath()
break
if manifest is None:
# Should never get here. If we do, it means the manifest file was
# never added to the outputs list, thus we don't have a manifest file
# to embed, so we just return.
return 0
# embedding mode. Different for EXE's and DLL's.
# see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx
mode = ''
if 'fcprogram' in self.generator.features or 'fcprogram_test' in self.generator.features:
mode = '1'
elif 'fcshlib' in self.generator.features:
mode = '2'
Logs.debug('ifort: embedding manifest in mode %r', mode)
lst = [] + mtool
lst.extend(Utils.to_list(env['MTFLAGS']))
lst.extend(['-manifest', manifest])
lst.append('-outputresource:%s;%s' % (outfile, mode))
return super(self.__class__, self).exec_command(lst)
def wrap_class(class_name):
"""
Manifest file processing and @response file workaround for command-line length limits on Windows systems
The indicated task class is replaced by a subclass to prevent conflicts in case the class is wrapped more than once
"""
cls = Task.classes.get(class_name)
if not cls:
return None
derived_class = type(class_name, (cls,), {})
def exec_command(self, *k, **kw):
ret = super(self.__class__, self).exec_command(*k, **kw)
if not ret and self.env.IFORT_WIN32 and getattr(self, 'do_manifest', None):
ret = self.exec_mf()
return ret
derived_class.exec_command = exec_command
derived_class.exec_mf = exec_mf
if hasattr(cls, 'hcode'):
derived_class.hcode = cls.hcode
return derived_class
for k in 'fcprogram fcprogram_test fcshlib fcstlib'.split():
wrap_class(k)
self.env.DO_MANIFEST = True

View File

@ -923,8 +923,6 @@ def apply_flags_msvc(self):
install_to=self.install_task.install_to, install_from=pdbnode)
break
# split the manifest file processing from the link task, like for the rc processing
@feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib')
@after_method('apply_link')
def apply_manifest(self):
@ -934,82 +932,11 @@ def apply_manifest(self):
the manifest file, the binaries are unusable.
See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx
"""
if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None):
out_node = self.link_task.outputs[0]
man_node = out_node.parent.find_or_declare(out_node.name + '.manifest')
self.link_task.outputs.append(man_node)
self.link_task.do_manifest = True
def exec_mf(self):
"""
Create the manifest file
"""
env = self.env
mtool = env['MT']
if not mtool:
return 0
self.do_manifest = False
outfile = self.outputs[0].abspath()
manifest = None
for out_node in self.outputs:
if out_node.name.endswith('.manifest'):
manifest = out_node.abspath()
break
if manifest is None:
# Should never get here. If we do, it means the manifest file was
# never added to the outputs list, thus we don't have a manifest file
# to embed, so we just return.
return 0
# embedding mode. Different for EXE's and DLL's.
# see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx
mode = ''
if 'cprogram' in self.generator.features or 'cxxprogram' in self.generator.features:
mode = '1'
elif 'cshlib' in self.generator.features or 'cxxshlib' in self.generator.features:
mode = '2'
Logs.debug('msvc: embedding manifest in mode %r', mode)
lst = [] + mtool
lst.extend(Utils.to_list(env['MTFLAGS']))
lst.extend(['-manifest', manifest])
lst.append('-outputresource:%s;%s' % (outfile, mode))
return super(self.__class__, self).exec_command(lst)
def wrap_class(class_name):
"""
Manifest file processing and @response file workaround for command-line length limits on Windows systems
The indicated task class is replaced by a subclass to prevent conflicts in case the class is wrapped more than once
"""
cls = Task.classes.get(class_name)
if not cls:
return None
derived_class = type(class_name, (cls,), {})
def exec_command(self, *k, **kw):
ret = super(self.__class__, self).exec_command(*k, **kw)
if not ret and self.env.CC_NAME == 'msvc' and getattr(self, 'do_manifest', None):
ret = self.exec_mf()
return ret
derived_class.exec_command = exec_command
derived_class.exec_mf = exec_mf
if hasattr(cls, 'hcode'):
derived_class.hcode = cls.hcode
return derived_class
for k in 'cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split():
wrap_class(k)
self.env.DO_MANIFEST = True
def make_winapp(self, family):
append = self.env.append_unique