diff options
author | sbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-24 16:44:12 +0000 |
---|---|---|
committer | sbc@chromium.org <sbc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-24 16:44:12 +0000 |
commit | a07e2edee0dc76fd16cbe85f89fc2b5441afc47b (patch) | |
tree | 307655441be46a0cc0b865803799ca1f399276c1 /native_client_sdk | |
parent | 5c65fe817c7420d459b5b817bc1cf05210771e39 (diff) | |
download | chromium_src-a07e2edee0dc76fd16cbe85f89fc2b5441afc47b.zip chromium_src-a07e2edee0dc76fd16cbe85f89fc2b5441afc47b.tar.gz chromium_src-a07e2edee0dc76fd16cbe85f89fc2b5441afc47b.tar.bz2 |
[NaCl SDK] Add sensible defaults to create_nmf.py
create_nmf will now derive a default library path and
objdump location based on its location, or on NACL_SDK_ROOT.
This significantly reduces the number of arguments that
one needs to pass.
BUG=179526
R=binji@chromium.org
Review URL: https://codereview.chromium.org/15255006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202110 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rwxr-xr-x | native_client_sdk/src/tools/create_nmf.py | 82 | ||||
-rw-r--r-- | native_client_sdk/src/tools/nacl_gcc.mk | 10 | ||||
-rwxr-xr-x | native_client_sdk/src/tools/tests/create_nmf_test.py | 33 |
3 files changed, 114 insertions, 11 deletions
diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py index 93f8004..5c9d270 100755 --- a/native_client_sdk/src/tools/create_nmf.py +++ b/native_client_sdk/src/tools/create_nmf.py @@ -14,6 +14,7 @@ import struct import subprocess import sys +import getos import quote if sys.version_info < (2, 6, 0): @@ -23,6 +24,8 @@ if sys.version_info < (2, 6, 0): NeededMatcher = re.compile('^ *NEEDED *([^ ]+)\n$') FormatMatcher = re.compile('^(.+):\\s*file format (.+)\n$') +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + OBJDUMP_ARCH_MAP = { # Names returned by Linux's objdump: 'elf64-x86-64': 'x86-64', @@ -251,7 +254,9 @@ class NmfUtils(object): set(['x86-32/libc.so', 'x86-64/libgcc.so']) ''' if not self.objdump: - raise Error('No objdump executable specified (see --help for more info)') + self.objdump = FindObjdumpExecutable() + if not self.objdump: + raise Error('No objdump executable found (see --help for more info)') DebugPrint('GleanFromObjdump(%s)' % ([self.objdump, '-p'] + files.keys())) proc = subprocess.Popen([self.objdump, '-p'] + files.keys(), stdout=subprocess.PIPE, @@ -519,6 +524,68 @@ def ParseExtraFiles(encoded_list, err): return canonicalized +def GetSDKRoot(): + """Determine current NACL_SDK_ROOT, either via the environment variable + itself, or by attempting to derive it from the location of this script. + """ + sdk_root = os.environ.get('NACL_SDK_ROOT') + if not sdk_root: + sdk_root = os.path.dirname(SCRIPT_DIR) + if not os.path.exists(os.path.join(sdk_root, 'toolchain')): + return None + + return sdk_root + + +def FindObjdumpExecutable(): + """Derive path to objdump executable to use for determining shared + object dependencies. + """ + sdk_root = GetSDKRoot() + if not sdk_root: + return None + + osname = getos.GetPlatform() + toolchain = os.path.join(sdk_root, 'toolchain', '%s_x86_glibc' % osname) + objdump = os.path.join(toolchain, 'bin', 'x86_64-nacl-objdump') + if osname == 'win': + objdump += '.exe' + + if not os.path.exists(objdump): + sys.stderr.write('WARNING: failed to find objdump in default ' + 'location: %s' % objdump) + return None + + return objdump + + +def GetDefaultLibPath(config): + """Derive default library path to use when searching for shared + objects. This currently include the toolchain library folders + as well as the top level SDK lib folder and the naclports lib + folder. We include both 32-bit and 64-bit library paths. + """ + assert(config in ('Debug', 'Release')) + sdk_root = GetSDKRoot() + if not sdk_root: + # TOOD(sbc): output a warning here? We would also need to suppress + # the warning when run from the chromium build. + return [] + + osname = getos.GetPlatform() + libpath = [ + 'toolchain/%s_x86_glibc/x86_64-nacl/lib' % osname, + 'toolchain/%s_x86_glibc/x86_64-nacl/lib32' % osname, + 'lib/glibc_x86_32/%s' % config, + 'lib/glibc_x86_64/%s' % config, + 'ports/lib/glibc_x86_32/%s' % config, + 'ports/lib/glibc_x86_64/%s' % config, + ] + libpath = [os.path.normpath(p) for p in libpath] + libpath = [os.path.join(sdk_root, p) for p in libpath] + return libpath + + def main(argv): parser = optparse.OptionParser( usage='Usage: %prog [options] nexe [extra_libs...]') @@ -526,8 +593,14 @@ def main(argv): help='Write manifest file to FILE (default is stdout)', metavar='FILE') parser.add_option('-D', '--objdump', dest='objdump', - help='Use TOOL as the "objdump" tool to run', + help='Override the default "objdump" tool used to find ' + 'shared object dependencies', metavar='TOOL') + parser.add_option('--no-default-libpath', + help="Don't include the SDK default library paths") + parser.add_option('--debug-libs', action='store_true', + help='Use debug library paths when constructing default ' + 'library path.') parser.add_option('-L', '--library-path', dest='lib_path', action='append', default=[], help='Add DIRECTORY to library search path', @@ -578,6 +651,11 @@ def main(argv): else: path_prefix = [] + if not options.no_default_libpath: + # Add default libraries paths to the end of the search path. + config = options.debug_libs and 'Debug' or 'Release' + options.lib_path += GetDefaultLibPath(config) + nmf = NmfUtils(objdump=options.objdump, main_files=args, lib_path=options.lib_path, diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk index a6f665f..1460637 100644 --- a/native_client_sdk/src/tools/nacl_gcc.mk +++ b/native_client_sdk/src/tools/nacl_gcc.mk @@ -352,15 +352,13 @@ NMF_ARCHES := $(foreach arch,$(ARCHES),_$(arch).nexe) # $2 = Additional create_nmf.py arguments # NMF := python $(NACL_SDK_ROOT)/tools/create_nmf.py -GLIBC_DUMP := $(TC_PATH)/$(OSNAME)_x86_glibc/x86_64-nacl/bin/objdump -GLIBC_PATHS := -L $(TC_PATH)/$(OSNAME)_x86_glibc/x86_64-nacl/lib32 -GLIBC_PATHS += -L $(TC_PATH)/$(OSNAME)_x86_glibc/x86_64-nacl/lib -GLIBC_PATHS += -L$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_64/$(CONFIG) -GLIBC_PATHS += -L$(NACL_SDK_ROOT)/lib/$(TOOLCHAIN)_x86_32/$(CONFIG) +ifeq ($(CONFIG),Debug) +NMF_FLAGS += --debug-libs +endif define NMF_RULE all:$(OUTDIR)/$(1).nmf $(OUTDIR)/$(1).nmf : $(foreach arch,$(NMF_ARCHES),$(OUTDIR)/$(1)$(arch)) $(GLIBC_SO_LIST) - $(call LOG,CREATE_NMF,$$@,$(NMF) -o $$@ $$^ -D $(GLIBC_DUMP) $(GLIBC_PATHS) -s $(OUTDIR) $(2) $(GLIBC_REMAP)) + $(call LOG,CREATE_NMF,$$@,$(NMF) $(NMF_FLAGS) -o $$@ $$^ $(GLIBC_PATHS) -s $(OUTDIR) $(2) $(GLIBC_REMAP)) endef diff --git a/native_client_sdk/src/tools/tests/create_nmf_test.py b/native_client_sdk/src/tools/tests/create_nmf_test.py index e8fec58..fe08f6b 100755 --- a/native_client_sdk/src/tools/tests/create_nmf_test.py +++ b/native_client_sdk/src/tools/tests/create_nmf_test.py @@ -12,11 +12,16 @@ import unittest SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PARENT_DIR = os.path.dirname(SCRIPT_DIR) DATA_DIR = os.path.join(SCRIPT_DIR, 'data') +CHROME_SRC = os.path.dirname(os.path.dirname(os.path.dirname(PARENT_DIR))) +MOCK_DIR = os.path.join(CHROME_SRC, "third_party", "pymock") +# For the mock library +sys.path.append(MOCK_DIR) sys.path.append(PARENT_DIR) -import getos import create_nmf +import getos +import mock class TestIsDynamicElf(unittest.TestCase): @@ -75,13 +80,35 @@ class TestParseElfHeader(unittest.TestCase): self.assertFalse(dynamic) +class TestDefaultLibpath(unittest.TestCase): + def testWithoutNaClSDKRoot(self): + """GetDefaultLibPath wihtout NACL_SDK_ROOT set + + In the absence of NACL_SDK_ROOT GetDefaultLibPath should + return the empty list.""" + with mock.patch.dict('os.environ', clear=True): + paths = create_nmf.GetDefaultLibPath('Debug') + self.assertEqual(paths, []) + + def testHonorNaClSDKRoot(self): + with mock.patch.dict('os.environ', {'NACL_SDK_ROOT': '/dummy/path'}): + paths = create_nmf.GetDefaultLibPath('Debug') + for path in paths: + self.assertTrue(path.startswith('/dummy/path')) + + def testIncludesNaClPorts(self): + with mock.patch.dict('os.environ', {'NACL_SDK_ROOT': '/dummy/path'}): + paths = create_nmf.GetDefaultLibPath('Debug') + self.assertTrue(any(os.path.join('ports', 'lib') in p for p in paths), + "naclports libpath missing: %s" % str(paths)) + + class TestNmfUtils(unittest.TestCase): """Tests for the main NmfUtils class in create_nmf.""" def setUp(self): self.tempdir = None - chrome_src = os.path.dirname(os.path.dirname(os.path.dirname(PARENT_DIR))) - toolchain = os.path.join(chrome_src, 'native_client', 'toolchain') + toolchain = os.path.join(CHROME_SRC, 'native_client', 'toolchain') self.toolchain = os.path.join(toolchain, '%s_x86' % getos.GetPlatform()) self.objdump = os.path.join(self.toolchain, 'bin', 'i686-nacl-objdump') if os.name == 'nt': |