From 2f9a0bee9b2b50f08a57e0eed8ab795b0ec0bc7a Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 28 Dec 2013 10:22:08 -0500 Subject: [PATCH] Add dsymutil and strip support for executable and shared library builders (bug 5997 part 10, r=ds). --- ambuild2/frontend/amb2/gen.py | 13 +--- ambuild2/frontend/base_gen.py | 5 +- ambuild2/frontend/cpp.py | 92 ++++++++++++++++++++--------- scripts/ambuild_dsymutil_wrapper.sh | 26 ++++++++ setup.py | 2 + tests/dsymutil/AMBuildScript | 10 ++++ tests/dsymutil/configure.py | 6 ++ tests/dsymutil/main.cpp | 7 +++ 8 files changed, 121 insertions(+), 40 deletions(-) create mode 100755 scripts/ambuild_dsymutil_wrapper.sh create mode 100644 tests/dsymutil/AMBuildScript create mode 100644 tests/dsymutil/configure.py create mode 100644 tests/dsymutil/main.cpp diff --git a/ambuild2/frontend/amb2/gen.py b/ambuild2/frontend/amb2/gen.py index e5abd6df..db8bcc08 100644 --- a/ambuild2/frontend/amb2/gen.py +++ b/ambuild2/frontend/amb2/gen.py @@ -510,20 +510,13 @@ def addCxxTasks(self, cx, binary): ) inputs.append(rcNode) - outputs = [binary.outputFile] - if binary.pdbFile: - outputs.append(binary.pdbFile) - - linkCmd, binNodes = self.addCommand( + output_file, debug_file = binary.link( context = cx, - node_type = nodetypes.Command, folder = folder_node, - data = binary.argv, - inputs = inputs, - outputs = outputs + inputs = inputs ) - return CppNodes(binNodes[0], binNodes[1:]) + return CppNodes(output_file, debug_file) def addFileOp(self, cmd, context, source, output_path): # Try to detect if our output_path is actually a folder, via trailing diff --git a/ambuild2/frontend/base_gen.py b/ambuild2/frontend/base_gen.py index 4bda344d..24080cc9 100644 --- a/ambuild2/frontend/base_gen.py +++ b/ambuild2/frontend/base_gen.py @@ -122,12 +122,13 @@ def AddFolder(self, folder): def AddCopy(self, source, output_path): return self.generator.addCopy(self, source, output_path) - def AddCommand(self, inputs, argv, outputs, dep_type=None, weak_inputs=[]): + def AddCommand(self, inputs, argv, outputs, folder=-1, dep_type=None, weak_inputs=[]): return self.generator.addShellCommand( self, inputs, argv, outputs, + folder = folder, dep_type = dep_type, weak_inputs = weak_inputs ) @@ -243,7 +244,7 @@ def addFolder(self, context, folder): def addCopy(self, context, source, output_path): raise Exception('Must be implemented!') - def addShellCommand(self, context, inputs, argv, outputs, dep_type=None, weak_inputs=[]): + def addShellCommand(self, context, inputs, argv, outputs, folder=-1, dep_type=None, weak_inputs=[]): raise Exception('Must be implemented!') def addConfigureFile(self, context, path): diff --git a/ambuild2/frontend/cpp.py b/ambuild2/frontend/cpp.py index 15fef41b..fd06fb11 100644 --- a/ambuild2/frontend/cpp.py +++ b/ambuild2/frontend/cpp.py @@ -26,12 +26,13 @@ def __init__(self, name, version, behavior, command, objSuffix): self.behavior = behavior self.command = command self.objSuffix = objSuffix + self.debuginfo_argv = [] class MSVC(Vendor): def __init__(self, command, version): super(MSVC, self).__init__('msvc', version, 'msvc', command, '.obj') self.definePrefix = '/D' - self.pdbSuffix = '.pdb' + self.debuginfo_argv = ['/Zi'] @staticmethod def IncludePath(outputPath, includePath): @@ -63,7 +64,6 @@ def __init__(self, name, command, version): self.majorVersion = int(parts[0]) self.minorVersion = int(parts[1]) self.definePrefix = '-D' - self.pdbSuffix = None def formatInclude(self, outputPath, includePath): return ['-I', os.path.normpath(includePath)] @@ -74,17 +74,18 @@ def objectArgs(self, sourceFile, objFile): class GCC(CompatGCC): def __init__(self, command, version): super(GCC, self).__init__('gcc', command, version) + self.debuginfo_argv = ['-g3', '-ggdb3'] class Clang(CompatGCC): def __init__(self, command, version): super(Clang, self).__init__('clang', command, version) + self.debuginfo_argv = ['-g3'] class SunPro(Vendor): def __init__(self, command, version): super(SunPro, self).__init__('sun', version, 'sun', command, '.o') - parts = version.split('.') self.definePrefix = '-D' - self.pdbSuffix = None + self.debuginfo_argv = ['-g3'] def formatInclude(self, outputPath, includePath): return ['-I', os.path.normpath(includePath)] @@ -272,6 +273,7 @@ class Compiler(object): def __init__(self, cc, cxx): self.cc = cc self.cxx = cxx + self.debuginfo = True for attr in Compiler.attrs: setattr(self, attr, []) @@ -279,6 +281,7 @@ def clone(self): cc = Compiler(self.cc, self.cxx) cc.cc = self.cc cc.cxx = self.cxx + cc.debuginfo = self.debuginfo for attr in Compiler.attrs: setattr(cc, attr, copy.copy(getattr(self, attr))) return cc @@ -302,6 +305,8 @@ class CCommandEnv(object): def __init__(self, outputPath, config, compiler): args = compiler.command.split(' ') args += config.cflags + if config.debuginfo: + args += compiler.debuginfo_argv if compiler == config.cxx: args += config.cxxflags args += [compiler.definePrefix + define for define in config.defines] @@ -442,7 +447,40 @@ def finish(self, cx): self.linker_ = self.compiler.cc files = [out.outputFile for out in self.objects + self.resources] - self.argv, self.pdbFile = self.generateBinary(cx, files) + self.argv = self.generateBinary(cx, files) + self.linker_outputs = [self.outputFile] + self.debug_entry = None + + if self.compiler.debuginfo and not isinstance(self, StaticLibrary): + if isinstance(self.linker_, MSVC): + self.linker_outputs += [self.name_ + '.pdb'] + elif cx.target_platform is 'mac': + bundle_folder = os.path.join(self.localFolder, self.outputFile + '.dSYM') + bundle_entry = cx.AddFolder(bundle_folder) + bundle_layout = [ + 'Contents', + 'Contents/Resources', + 'Contents/Resources/DWARF', + ] + for folder in bundle_layout: + cx.AddFolder(os.path.join(bundle_folder, folder)) + self.linker_outputs += [ + self.outputFile + '.dSYM/Contents/Info.plist', + self.outputFile + '.dSYM/Contents/Resources/DWARF/' + self.outputFile + ] + self.debug_entry = bundle_entry + self.argv = ['ambuild_dsymutil_wrapper.sh', self.outputFile] + self.argv + + def link(self, context, folder, inputs): + ignore, outputs = context.AddCommand( + inputs = inputs, + argv = self.argv, + outputs = self.linker_outputs, + folder = folder + ) + if not self.debug_entry and self.compiler.debuginfo: + self.debug_entry = outputs[-1] + return outputs[0], self.debug_entry class Program(BinaryBuilder): def __init__(self, compiler, name): @@ -455,20 +493,19 @@ def generateBinary(self, cx, files): if isinstance(self.linker_, MSVC): argv.append('/link') - argv.extend(self.linkFlags(cx)) - if isinstance(self.linker_, MSVC): - argv.append('/OUT:' + self.outputFile) - argv.append('/DEBUG') + argv.extend(self.linkFlags(cx)) argv.append('/nologo') - argv.append('/PDB:"' + self.name_ + '.pdb"') + argv += [ + '/OUT:' + self.outputFile, + '/nologo', + ] + if self.compiler.debuginfo: + argv += ['/DEBUG', '/PDB:"' + self.name_ + '.pdb"'] else: + argv.extend(self.linkFlags(cx)) argv.extend(['-o', self.outputFile]) - pdbFile = None - if self.linker_.pdbSuffix: - pdbFile = self.name_ + self.linker_.pdbSuffix - - return argv, pdbFile + return argv class Library(BinaryBuilder): def __init__(self, compiler, name): @@ -481,25 +518,24 @@ def generateBinary(self, cx, files): if isinstance(self.linker_, MSVC): argv.append('/link') - argv.extend(self.linkFlags(cx)) - if isinstance(self.linker_, MSVC): - argv.append('/OUT:' + self.outputFile) - argv.append('/DEBUG') - argv.append('/nologo') - argv.append('/DLL') - argv.append('/PDB:"' + self.name_ + '.pdb"') + argv.extend(self.linkFlags(cx)) + argv += [ + '/OUT:' + self.outputFile, + '/DEBUG', + '/nologo', + '/DLL', + ] + if self.compiler.debuginfo: + argv += ['/DEBUG', '/PDB:"' + self.name_ + '.pdb"'] elif isinstance(self.linker_, CompatGCC): + argv.extend(self.linkFlags(cx)) if util.IsMac(): argv.append('-dynamiclib') else: argv.append('-shared') argv.extend(['-o', self.outputFile]) - pdbFile = None - if self.linker_.pdbSuffix: - pdbFile = self.name_ + self.linker_.pdbSuffix - - return argv, pdbFile + return argv class StaticLibrary(BinaryBuilder): def __init__(self, compiler, name): @@ -512,4 +548,4 @@ def generateBinary(self, cx, files): else: argv = ['ar', 'rcs', self.outputFile] argv += files - return argv, None + return argv diff --git a/scripts/ambuild_dsymutil_wrapper.sh b/scripts/ambuild_dsymutil_wrapper.sh new file mode 100755 index 00000000..2cc0fb02 --- /dev/null +++ b/scripts/ambuild_dsymutil_wrapper.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +if [ $# -lt 3 ]; then + echo "Usage: <...linker args>"; + exit 1; +fi + +LD_FILE=$1 +LD_EXEC=$2 + +shift; +shift; + +$LD_EXEC $@ +if [ $? -ne 0 ]; then + exit $? +fi +dsymutil $LD_FILE +if [ $? -ne 0 ]; then + exit $? +fi +strip -S $LD_FILE +if [ $? -ne 0 ]; then + exit $? +fi + diff --git a/setup.py b/setup.py index 0b3408fe..8f197c4a 100755 --- a/setup.py +++ b/setup.py @@ -9,6 +9,8 @@ if sys.platform == 'win32': scripts.append('scripts/ambuild.bat') +elif sys.platform == 'darwin': + scripts.append('scripts/ambuild_dsymutil_wrapper.sh') setup( name = 'AMBuild', diff --git a/tests/dsymutil/AMBuildScript b/tests/dsymutil/AMBuildScript new file mode 100644 index 00000000..de0c9b50 --- /dev/null +++ b/tests/dsymutil/AMBuildScript @@ -0,0 +1,10 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +builder.DetectCompilers() + +program = builder.compiler.Program("hello") +program.sources = [ + 'main.cpp' +] +builder.Add(program) diff --git a/tests/dsymutil/configure.py b/tests/dsymutil/configure.py new file mode 100644 index 00000000..7f40307e --- /dev/null +++ b/tests/dsymutil/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/dsymutil/main.cpp b/tests/dsymutil/main.cpp new file mode 100644 index 00000000..a8cf84fa --- /dev/null +++ b/tests/dsymutil/main.cpp @@ -0,0 +1,7 @@ +#include + +int main() +{ + return printf("hello!\n"); +} +