diff --git a/ChangeLog b/ChangeLog index 26d8efb4..5b471ef9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 + diff --git a/waflib/Tools/ccroot.py b/waflib/Tools/ccroot.py index 700873f0..2e970559 100644 --- a/waflib/Tools/ccroot.py +++ b/waflib/Tools/ccroot.py @@ -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. diff --git a/waflib/Tools/ifort.py b/waflib/Tools/ifort.py index e03774f6..35a87c7d 100644 --- a/waflib/Tools/ifort.py +++ b/waflib/Tools/ifort.py @@ -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 diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py index d80a3eee..0e2d9784 100644 --- a/waflib/Tools/msvc.py +++ b/waflib/Tools/msvc.py @@ -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