aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemar4
-rwxr-xr-xemcc26
-rw-r--r--tests/openjpeg/CMakeLists.txt2
-rwxr-xr-xtests/runner.py80
-rw-r--r--tools/shared.py47
5 files changed, 123 insertions, 36 deletions
diff --git a/emar b/emar
index 49d995bd..e64cd8b9 100755
--- a/emar
+++ b/emar
@@ -12,11 +12,11 @@ from tools import shared
DEBUG = os.environ.get('EMCC_DEBUG')
-newargs = [shared.LLVM_LINK] + sys.argv[3:] + ['-o='+sys.argv[2]]
+newargs = [shared.LLVM_AR] + sys.argv[1:]
if DEBUG:
print >> sys.stderr, 'emar:', sys.argv, ' ==> ', newargs
if len(newargs) > 2:
- os.execvp(shared.LLVM_LINK, newargs)
+ os.execvp(shared.LLVM_AR, newargs)
diff --git a/emcc b/emcc
index b8e2489c..b59dd36a 100755
--- a/emcc
+++ b/emcc
@@ -239,7 +239,8 @@ if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += EMMAKEN_CFLAGS.split(' ')
# ---------------- Utilities ---------------
SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc')
-BITCODE_SUFFIXES = ('.bc', '.o', '.a', '.dylib', '.so', '.dll')
+BITCODE_SUFFIXES = ('.bc', '.o')
+SHAREDLIB_SUFFIXES = ('.dylib', '.so', '.dll')
ASSEMBLY_SUFFIXES = ('.ll',)
def unsuffixed(name):
@@ -377,7 +378,7 @@ try:
for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params,
# right now we just assume that what is left contains no more |-x OPT| things
arg = newargs[i]
- if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + ASSEMBLY_SUFFIXES): # we already removed -o <target>, so all these should be inputs
+ if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + SHAREDLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
newargs[i] = ''
if os.path.exists(arg):
if arg.endswith(SOURCE_SUFFIXES):
@@ -425,11 +426,14 @@ try:
if DEBUG: print >> sys.stderr, 'emcc: compiling to bitcode'
+ temp_files = []
+
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
for input_file in input_files:
if input_file.endswith(SOURCE_SUFFIXES):
if DEBUG: print >> sys.stderr, 'emcc: compiling source file: ', input_file
output_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args)
Popen([call] + args).communicate() # let compiler frontend print directly, so colors are saved (PIPE kills that)
@@ -439,13 +443,22 @@ try:
else: # bitcode
if input_file.endswith(BITCODE_SUFFIXES):
if DEBUG: print >> sys.stderr, 'emcc: copying bitcode file: ', input_file
- shutil.copyfile(input_file, in_temp(unsuffixed_basename(input_file) + '.o'))
+ temp_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ shutil.copyfile(input_file, temp_file)
+ temp_files.append(temp_file)
+ elif input_file.endswith(SHAREDLIB_SUFFIXES) or shared.Building.is_ar(input_file):
+ if DEBUG: print >> sys.stderr, 'emcc: copying library file: ', input_file
+ temp_file = in_temp(os.path.basename(input_file))
+ shutil.copyfile(input_file, temp_file)
+ temp_files.append(temp_file)
else: #.ll
if not LEAVE_INPUTS_RAW:
# Note that by assembling the .ll file, then disassembling it later, we will
# remove annotations which is a good thing for compilation time
if DEBUG: print >> sys.stderr, 'emcc: assembling assembly file: ', input_file
- shared.Building.llvm_as(input_file, in_temp(unsuffixed_basename(input_file) + '.o'))
+ temp_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ shared.Building.llvm_as(input_file, temp_file)
+ temp_files.append(temp_file)
# If we were just asked to generate bitcode, stop there
if final_suffix not in ['js', 'html']:
@@ -461,11 +474,10 @@ try:
assert not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv)
# We have a specified target (-o <target>), which is not JavaScript or HTML, and
# we have multiple files: Link them TODO: llvm link-time opts?
- ld_args = map(lambda input_file: in_temp(unsuffixed_basename(input_file) + '.o'), input_files) + \
- ['-o', specified_target]
+ ld_args = temp_files + ['-b', specified_target]
#[arg.split('-Wl,')[1] for arg in filter(lambda arg: arg.startswith('-Wl,'), sys.argv)]
if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(ld_args)
- Popen([shared.LLVM_LINK] + ld_args).communicate()
+ Popen([shared.LLVM_LD, '-disable-opt'] + ld_args).communicate()
exit(0)
## Continue on to create JavaScript
diff --git a/tests/openjpeg/CMakeLists.txt b/tests/openjpeg/CMakeLists.txt
index 52150f5f..d8671fed 100644
--- a/tests/openjpeg/CMakeLists.txt
+++ b/tests/openjpeg/CMakeLists.txt
@@ -22,6 +22,8 @@ STRING(TOLOWER ${OPENJPEG_NAMESPACE} OPENJPEG_LIBRARY_NAME)
PROJECT(${OPENJPEG_NAMESPACE} C)
+include(CMakeDetermineSystem)
+
# Do full dependency headers.
INCLUDE_REGULAR_EXPRESSION("^.*$")
diff --git a/tests/runner.py b/tests/runner.py
index ae46634c..069598d1 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -260,11 +260,13 @@ process(sys.argv[1])
if self.library_cache is not None:
if cache and self.library_cache.get(cache_name):
print >> sys.stderr, '<load build from cache> ',
- bc_file = os.path.join(output_dir, 'lib' + name + '.bc')
- f = open(bc_file, 'wb')
- f.write(self.library_cache[cache_name])
- f.close()
- return bc_file
+ generated_libs = []
+ for bc_file in self.library_cache[cache_name]:
+ f = open(bc_file, 'wb')
+ f.write(self.library_cache[cache_name][bc_file])
+ f.close()
+ generated_libs.append(bc_file)
+ return generated_libs
print >> sys.stderr, '<building and saving into cache> ',
@@ -917,6 +919,46 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
'''
self.do_run(src, '*1 2*')
+ def test_multiply_defined_symbols(self):
+ a1 = "int f() { return 1; }"
+ a1_name = os.path.join(self.get_dir(), 'a1.c')
+ open(a1_name, 'w').write(a1)
+ a2 = "void x() {}"
+ a2_name = os.path.join(self.get_dir(), 'a2.c')
+ open(a2_name, 'w').write(a2)
+ b1 = "int f() { return 2; }"
+ b1_name = os.path.join(self.get_dir(), 'b1.c')
+ open(b1_name, 'w').write(b1)
+ b2 = "void y() {}"
+ b2_name = os.path.join(self.get_dir(), 'b2.c')
+ open(b2_name, 'w').write(b2)
+ main = r'''
+ #include <stdio.h>
+ int f();
+ int main() {
+ printf("result: %d\n", f());
+ return 0;
+ }
+ '''
+ main_name = os.path.join(self.get_dir(), 'main.c')
+ open(main_name, 'w').write(main)
+
+ Building.emcc(a1_name)
+ Building.emcc(a2_name)
+ Building.emcc(b1_name)
+ Building.emcc(b2_name)
+ Building.emcc(main_name)
+
+ liba_name = os.path.join(self.get_dir(), 'liba.a')
+ Building.emar('cr', liba_name, [a1_name + '.o', a2_name + '.o'])
+ libb_name = os.path.join(self.get_dir(), 'libb.a')
+ Building.emar('cr', libb_name, [b1_name + '.o', b2_name + '.o'])
+
+ all_name = os.path.join(self.get_dir(), 'all.bc')
+ Building.link([main_name + '.o', liba_name, libb_name], all_name)
+
+ self.do_ll_run(all_name, 'result: 1')
+
def test_if(self):
src = '''
#include <stdio.h>
@@ -4320,7 +4362,7 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(),
open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(),
['font.ttf', 'test!', '150', '120', '25'],
- libraries=[self.get_freetype()],
+ libraries=self.get_freetype(),
includes=[path_from_root('tests', 'freetype', 'include')],
post_build=post)
#build_ll_hook=self.do_autodebug)
@@ -4361,7 +4403,7 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'zlib', 'example.c'), 'r').read(),
open(path_from_root('tests', 'zlib', 'ref.txt'), 'r').read(),
- libraries=[self.get_library('zlib', os.path.join('libz.a'), make_args=['libz.a'])],
+ libraries=self.get_library('zlib', os.path.join('libz.a'), make_args=['libz.a']),
includes=[path_from_root('tests', 'zlib')],
force_c=True)
@@ -4378,10 +4420,10 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'bullet', 'Demos', 'HelloWorld', 'HelloWorld.cpp'), 'r').read(),
[open(path_from_root('tests', 'bullet', 'output.txt'), 'r').read(), # different roundings
open(path_from_root('tests', 'bullet', 'output2.txt'), 'r').read()],
- libraries=[self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletCollision.a'),
- os.path.join('src', '.libs', 'libBulletDynamics.a'),
+ libraries=self.get_library('bullet', [os.path.join('src', '.libs', 'libBulletDynamics.a'),
+ os.path.join('src', '.libs', 'libBulletCollision.a'),
os.path.join('src', '.libs', 'libLinearMath.a')],
- configure_args=['--disable-demos','--disable-dependency-tracking'])],
+ configure_args=['--disable-demos','--disable-dependency-tracking']),
includes=[path_from_root('tests', 'bullet', 'src')],
js_engines=[SPIDERMONKEY_ENGINE]) # V8 issue 1407
@@ -4422,15 +4464,15 @@ def process(filename):
freetype = self.get_freetype()
poppler = self.get_library('poppler',
- [os.path.join('poppler', '.libs', self.get_shared_library_name('libpoppler.so.13')),
- os.path.join('utils', 'pdftoppm.o'),
- os.path.join('utils', 'parseargs.o')],
- configure_args=['--disable-libjpeg', '--disable-libpng', '--disable-poppler-qt', '--disable-poppler-qt4', '--disable-cms'])
+ [os.path.join('utils', 'pdftoppm.o'),
+ os.path.join('utils', 'parseargs.o'),
+ os.path.join('poppler', '.libs', 'libpoppler.a')],
+ configure_args=['--disable-libjpeg', '--disable-libpng', '--disable-poppler-qt', '--disable-poppler-qt4', '--disable-cms', '--disable-cairo-output', '--disable-abiword-output', '--enable-shared=no'])
# Combine libraries
combined = os.path.join(self.get_dir(), 'poppler-combined.bc')
- Building.link([freetype, poppler], combined)
+ Building.link(poppler + freetype, combined)
self.do_ll_run(combined,
map(ord, open(path_from_root('tests', 'poppler', 'ref.ppm'), 'r').read()).__str__().replace(' ', ''),
@@ -4464,11 +4506,11 @@ def process(filename):
shutil.copy(path_from_root('tests', 'openjpeg', 'opj_config.h'), self.get_dir())
lib = self.get_library('openjpeg',
- [os.path.join('bin', self.get_shared_library_name('libopenjpeg.so.1.4.0')),
- os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/index.c.o'.split('/')),
+ [os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/index.c.o'.split('/')),
os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/convert.c.o'.split('/')),
os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/color.c.o'.split('/')),
- os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/getopt.c.o'.split('/'))],
+ os.path.sep.join('codec/CMakeFiles/j2k_to_image.dir/__/common/getopt.c.o'.split('/')),
+ os.path.join('bin', self.get_shared_library_name('libopenjpeg.so.1.4.0'))],
configure=['cmake', '.'],
#configure_args=['--enable-tiff=no', '--enable-jp3d=no', '--enable-png=no'],
make_args=[]) # no -j 2, since parallel builds can fail
@@ -4512,7 +4554,7 @@ def process(filename):
self.do_run(open(path_from_root('tests', 'openjpeg', 'codec', 'j2k_to_image.c'), 'r').read(),
'Successfully generated', # The real test for valid output is in image_compare
'-i image.j2k -o image.raw'.split(' '),
- libraries=[lib],
+ libraries=lib,
includes=[path_from_root('tests', 'openjpeg', 'libopenjpeg'),
path_from_root('tests', 'openjpeg', 'codec'),
path_from_root('tests', 'openjpeg', 'common'),
diff --git a/tools/shared.py b/tools/shared.py
index 7f633318..ba953e19 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -90,6 +90,7 @@ CLANG_CPP=os.path.expanduser(os.path.join(LLVM_ROOT, 'clang++'))
CLANG=CLANG_CPP
LLVM_LINK=os.path.join(LLVM_ROOT, 'llvm-link')
LLVM_LD=os.path.join(LLVM_ROOT, 'llvm-ld')
+LLVM_AR=os.path.join(LLVM_ROOT, 'llvm-ar')
LLVM_OPT=os.path.expanduser(os.path.join(LLVM_ROOT, 'opt'))
LLVM_AS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-as'))
LLVM_DIS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-dis'))
@@ -450,18 +451,18 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
stderr=open(os.path.join(project_dir, 'configure_err'), 'w'), env=env)
Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_'), 'w'),
stderr=open(os.path.join(project_dir, 'make_err'), 'w'), env=env)
- bc_file = os.path.join(project_dir, 'bc.bc')
- Building.link(generated_libs, bc_file)
if cache is not None:
- cache[cache_name] = open(bc_file, 'rb').read()
+ cache[cache_name] = {}
+ for f in generated_libs:
+ cache[cache_name][f] = open(f, 'rb').read()
if old_dir:
os.chdir(old_dir)
- return bc_file
+ return generated_libs
@staticmethod
def link(files, target):
try_delete(target)
- output = Popen([LLVM_LINK] + files + ['-o', target], stdout=PIPE).communicate()[0]
+ output = Popen([LLVM_LD, '-disable-opt'] + files + ['-b', target], stdout=PIPE).communicate()[0]
assert os.path.exists(target) and (output is None or 'Could not open input file' not in output), 'Linking error: ' + output
# Emscripten optimizations that we run on the .ll file
@@ -553,6 +554,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
assert os.path.exists(output_filename), 'emcc could not create output file'
@staticmethod
+ def emar(action, output_filename, filenames, stdout=None, stderr=None, env=None):
+ try_delete(output_filename)
+ Popen([EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate()
+ if 'c' in action:
+ assert os.path.exists(output_filename), 'emar could not create output file'
+
+ @staticmethod
def emscripten(filename, append_ext=True, extra_args=[]):
# Allow usage of emscripten.py without warning
os.environ['EMSCRIPTEN_SUPPRESS_USAGE_WARNING'] = '1'
@@ -732,6 +740,22 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
return filename + '.cc.js'
+ _is_ar_cache = {}
+ @staticmethod
+ def is_ar(filename):
+ try:
+ if Building._is_ar_cache.get(filename):
+ return Building._is_ar_cache[filename]
+ b = open(filename, 'r').read(8)
+ sigcheck = b[0] == '!' and b[1] == '<' and \
+ b[2] == 'a' and b[3] == 'r' and \
+ b[4] == 'c' and b[5] == 'h' and \
+ b[6] == '>' and ord(b[7]) == 10
+ Building._is_ar_cache[filename] = sigcheck
+ return sigcheck
+ except:
+ return False
+
@staticmethod
def is_bitcode(filename):
# checks if a file contains LLVM bitcode
@@ -740,9 +764,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
defs = Building.llvm_nm(filename, stderr=PIPE)
# If no symbols found, it might just be an empty bitcode file, try to dis it
if len(defs.defs) + len(defs.undefs) + len(defs.commons) == 0:
- test_ll = os.path.join(EMSCRIPTEN_TEMP_DIR, 'test.ll')
- Building.llvm_dis(filename, test_ll)
- assert os.path.exists(test_ll)
+ # llvm-nm 3.0 has a bug when reading symbols from ar files
+ # so try to see if we're dealing with an ar file, in which
+ # case we should try to dis it.
+ if not Building.is_ar(filename):
+ test_ll = os.path.join(EMSCRIPTEN_TEMP_DIR, 'test.ll')
+ Building.llvm_dis(filename, test_ll)
+ assert os.path.exists(test_ll)
except:
return False
@@ -750,6 +778,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
b = open(filename, 'r').read(4)
if b[0] == 'B' and b[1] == 'C':
return True
+ # look for ar signature
+ elif Building.is_ar(filename):
+ return True
# on OS X, there is a 20-byte prefix
elif ord(b[0]) == 222 and ord(b[1]) == 192 and ord(b[2]) == 23 and ord(b[3]) == 11:
b = open(filename, 'r').read(24)