Skip to content

Commit

Permalink
Cleanup scons support and remove config file parsing (emscripten-core…
Browse files Browse the repository at this point in the history
…#7249)

This change is precursor to removing EMSCRIPTEN_ROOT from
the emscripten config file. Now scons requires EMSCRIPTEN_ROOT
to be set explicitly in the environment.

The rational for this change is that having the EMSCRIPTEN_ROOT
set in the config can leave is in a contradictory state.  e.g.
when emcc runs from location X but the config file says EMSCRIPTEN_ROOT
is location Y.  In most cases it is the tool entry point that dictates
the root directory.

The only exception was scons which was trying to imply the root
based on the config.

Also importantly this change removes the `exec` of the config file from
scons which should allow is to be more strict in how we parse and
evaluate the config file in `tools/shared.py` since it will hopefully
soon be the only consumer.
  • Loading branch information
sbc100 authored Oct 10, 2018
1 parent bcc63a6 commit 029adc4
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 50 deletions.
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ignore = E111,E114,E501,E261,E266,E121,E402,E241
# exclude = ./third_party/,emmaken.py,./tools/scons/,./tools/ports/,./tests/
filename =
*/emcc.py
*/emscons.py
*/emscripten.py
*/tools/shared.py
*/tools/response_file.py
Expand Down
23 changes: 7 additions & 16 deletions emscons
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
#!/usr/bin/env python2
#!/usr/bin/env python

'''
Wrapping the scons invocation, EMSCRIPTEN_TOOL_PATH is set in the process
environment, and can be used to locate the emscripten SCons Tool.
Example:
# Load emscripten Tool
my_env = Environment(tools=['emscripten'], toolpath=[os.environ['EMSCRIPTEN_TOOL_PATH']])
'''
# This script should work in python 2 *or* 3. It loads the main code using
# python_selector, which may pick a different version.

import os, subprocess, sys
from tools import shared
from tools import python_selector

tool_path = os.path.join(shared.path_from_root('tools'), 'scons', 'site_scons', 'site_tools', 'emscripten')

env = os.environ.copy()
env[ 'EMSCRIPTEN_TOOL_PATH' ] = tool_path

exit(subprocess.call(sys.argv[1:], env=env))
import sys

if __name__ == '__main__':
python_selector.run(__file__)
21 changes: 21 additions & 0 deletions emscons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python2
"""Wrapping the scons invocation, EMSCRIPTEN_TOOL_PATH is set in the process
environment, and can be used to locate the emscripten SCons Tool.
Example:
# Load emscripten Tool
my_env = Environment(tools=['emscripten'], toolpath=[os.environ['EMSCRIPTEN_TOOL_PATH']])
"""

import os
import subprocess
import sys
from tools import shared

tool_path = os.path.join(shared.path_from_root('tools'), 'scons', 'site_scons', 'site_tools', 'emscripten')

env = os.environ.copy()
env['EMSCRIPTEN_TOOL_PATH'] = tool_path

sys.exit(subprocess.call(sys.argv[1:], env=env))
10 changes: 10 additions & 0 deletions tests/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ def env_modify(updates):
os.environ.update(old_env)


# Decorator version of env_modify
def with_env_modify(updates):
def decorated(f):
def modified(self):
with env_modify(updates):
return f(self)
return modified
return decorated


@contextlib.contextmanager
def chdir(dir):
"""A context manager that performs actions in the given directory."""
Expand Down
4 changes: 2 additions & 2 deletions tests/scons/SConstruct
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
env = Environment()
import os
env = Environment(toolpath=[os.environ.get('EMSCRIPTEN_TOOL_PATH')])
env.Tool('emscripten')
env.Append(CXXFLAGS='-std=c++11')
env.Program('scons_integration', ['integration.cpp', 'other.c'])

37 changes: 25 additions & 12 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@
from tools.shared import EMCC, EMXX, EMAR, EMRANLIB, PYTHON, FILE_PACKAGER, WINDOWS, MACOS, LLVM_ROOT, EMCONFIG, TEMP_DIR, EM_BUILD_VERBOSE
from tools.shared import CLANG, CLANG_CC, CLANG_CPP, LLVM_AR
from tools.shared import COMPILER_ENGINE, NODE_JS, SPIDERMONKEY_ENGINE, JS_ENGINES, V8_ENGINE
from runner import RunnerCore, path_from_root, get_zlib_library, no_wasm_backend, needs_dlfcn, env_modify, no_windows
from runner import RunnerCore, path_from_root, get_zlib_library, no_wasm_backend, needs_dlfcn, env_modify, no_windows, chdir, with_env_modify
from tools import jsrun, shared
import tools.line_endings
import tools.js_optimizer
import tools.tempfiles
import tools.duplicate_function_eliminator

scons_path = Building.which('scons')


class temp_directory(object):
def __enter__(self):
Expand Down Expand Up @@ -2260,17 +2262,28 @@ def test_debuginfo(self):
else:
self.assertIn('strip-debug', opts)

def test_scons(self): # also incidentally tests c++11 integration in llvm 3.1
scons_path = Building.which('scons')
if not scons_path:
self.skipTest('Skipping other.test_scons: The tool "scons" was not found in PATH!')
try_delete(os.path.join(self.get_dir(), 'test'))
shutil.copytree(path_from_root('tests', 'scons'), os.path.join(self.get_dir(), 'test'))
shutil.copytree(path_from_root('tools', 'scons', 'site_scons'), os.path.join(self.get_dir(), 'test', 'site_scons'))
os.chdir(os.path.join(self.get_dir(), 'test'))
run_process(['scons'])
output = run_js('scons_integration.js', assert_returncode=5)
assert 'If you see this - the world is all right!' in output
@unittest.skipIf(not scons_path, 'scons not found in PATH')
@with_env_modify({'EMSCRIPTEN_ROOT': path_from_root()})
def test_scons(self):
# this test copies the site_scons directory alongside the test
shutil.copytree(path_from_root('tests', 'scons'), 'test')
shutil.copytree(path_from_root('tools', 'scons', 'site_scons'), os.path.join('test', 'site_scons'))
with chdir('test'):
run_process(['scons'])
output = run_js('scons_integration.js', assert_returncode=5)
self.assertContained('If you see this - the world is all right!', output)

@unittest.skipIf(not scons_path, 'scons not found in PATH')
@with_env_modify({'EMSCRIPTEN_TOOLPATH': path_from_root('tools', 'scons', 'site_scons'),
'EMSCRIPTEN_ROOT': path_from_root()})
def test_emscons(self):
# uses the emscons wrapper which requires EMSCRIPTEN_TOOLPATH to find
# site_scons
shutil.copytree(path_from_root('tests', 'scons'), 'test')
with chdir('test'):
run_process([path_from_root('emscons'), 'scons'])
output = run_js('scons_integration.js', assert_returncode=5)
self.assertContained('If you see this - the world is all right!', output)

def test_embind(self):
environ = os.environ.copy()
Expand Down
24 changes: 4 additions & 20 deletions tools/scons/site_scons/site_tools/emscripten/emscripten.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,25 @@

from __future__ import print_function
import os
import sys


def generate(env, emscripten_path=None, **kw):
""" SCons tool entry point """

# Try to find emscripten
# Use same method as Emscripten's shared.py
EM_CONFIG = os.environ.get('EM_CONFIG')
if not EM_CONFIG:
EM_CONFIG = os.path.expanduser('~/.emscripten')

if emscripten_path is None:

CONFIG_FILE = os.path.expanduser(EM_CONFIG)
try:
exec(open(CONFIG_FILE, 'r').read())
except Exception, e:
print('Error in evaluating %s (at %s): %s' % (EM_CONFIG, CONFIG_FILE, str(e)), file=sys.stderr)
sys.exit(1)

emscripten_path = EMSCRIPTEN_ROOT # noqa

env['EMSCRIPTEN_ROOT'] = emscripten_path
emscripten_path = os.environ.get('EMSCRIPTEN_ROOT')
if not emscripten_path:
raise 'Unable to find emscripten. Please set EMSCRIPTEN_ROOT'

# SCons does not by default invoke the compiler with the
# environment variabls from the parent calling process,
# so manually route all environment variables referenced
# by Emscripten to the child.
env['ENV']['EM_CONFIG'] = EM_CONFIG
for var in ['EM_CACHE', 'EMCC_DEBUG', 'EMSCRIPTEN_NATIVE_OPTIMIZER', 'EMTEST_BROWSER',
'EMMAKEN_JUST_CONFIGURE', 'EMCC_CFLAGS', 'EMCC_LEAVE_INPUTS_RAW', 'EMCC_TEMP_DIR',
'EMCC_AUTODEBUG', 'EMMAKEN_JUST_CONFIGURE_RECURSE', 'EMCONFIGURE_JS', 'CONFIGURE_CC',
'EMMAKEN_COMPILER', 'EMMAKEN_CFLAGS', 'EMCC_FAST_COMPILER', 'EMCC_JSOPT_BLACKLIST',
'MOZ_DISABLE_AUTO_SAFE_MODE', 'EMSCRIPTEN_TOOL_PATH', 'EMCC_STDERR_FILE',
'MOZ_DISABLE_AUTO_SAFE_MODE', 'EMCC_STDERR_FILE',
'EMSCRIPTEN_SUPPRESS_USAGE_WARNING', 'EM_SAVE_DIR', 'NODE_PATH', 'EMCC_JSOPT_MIN_CHUNK_SIZE',
'EMCC_JSOPT_MAX_CHUNK_SIZE', 'EMCC_SAVE_OPT_TEMP', 'EMCC_CORES', 'EMCC_NO_OPT_SORT',
'EMCC_BUILD_DIR', 'EM_POPEN_WORKAROUND', 'EMCC_DEBUG_SAVE', 'EMCC_SKIP_SANITY_CHECK',
Expand Down

0 comments on commit 029adc4

Please sign in to comment.