mirror of https://gitlab.com/ita1024/waf.git
Simplify manifest file processing
This commit is contained in:
parent
f18d481e75
commit
98f495bda1
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue