Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion tools/building.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,33 @@ def get_command_with_possible_response_file(cmd):
return cmd

logger.debug('using response file for %s' % cmd[0])
filename = response_file.create_response_file(cmd[1:], shared.TEMP_DIR)
filename = create_response_file(cmd[1:], shared.TEMP_DIR)
new_cmd = [cmd[0], "@" + filename]
return new_cmd


def create_response_file(args, directory):
"""Routes the given cmdline param list in args into a new response file and
returns the filename to it.
"""
# Backslashes and other special chars need to be escaped in the response file.
contents = response_file.create_response_file_contents(args)

response_fd, response_filename = tempfile.mkstemp(prefix='emscripten_', suffix='.rsp.utf-8', dir=directory, text=True)

with os.fdopen(response_fd, 'w', encoding='utf-8') as f:
f.write(contents)

if DEBUG:
logging.warning(f'Creating response file {response_filename} with following contents: {contents}')

# Register the created .rsp file to be automatically cleaned up once this
# process finishes, so that caller does not have to remember to do it.
shared.get_temp_files().note(response_filename)

return response_filename


def emar(action, output_filename, filenames, stdout=None, stderr=None, env=None):
utils.delete_file(output_filename)
cmd = [EMAR, action, output_filename] + filenames
Expand Down
5 changes: 4 additions & 1 deletion tools/file_packager.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
__rootdir__ = os.path.dirname(__scriptdir__)
sys.path.insert(0, __rootdir__)

from tools import diagnostics, js_manipulation, shared, utils
# Do not import shared.py globally so that this command can run without setting up LLVM_ROOT unless the user explicitly specifies flags that depend on it.
from tools import diagnostics, js_manipulation, utils
from tools.response_file import substitute_response_files

DEBUG = os.environ.get('EMCC_DEBUG')
Expand Down Expand Up @@ -252,6 +253,7 @@ def escape(c):


def generate_object_file(data_files):
from tools import shared
embed_files = [f for f in data_files if f.mode == 'embed']
assert embed_files

Expand Down Expand Up @@ -727,6 +729,7 @@ def generate_preload_js(data_target, data_files, metadata):
js_manipulation.escape_for_js_string(data_target))
else:
# LZ4FS usage
from tools import shared
temp = data_target + '.orig'
shutil.move(data_target, temp)
meta = shared.run_js_tool(utils.path_from_root('tools/lz4-compress.mjs'),
Expand Down
33 changes: 2 additions & 31 deletions tools/js_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import re

from . import shared, utils
# Do not import shared.py so that file_packager.py can run without setting up LLVM_ROOT.
from . import utils
from .settings import settings

emscripten_license = '''\
Expand All @@ -28,36 +29,6 @@
emscripten_license_regex = r'\/\*\*?(\s*\*?\s*@license)?(\s*\*?\s*Copyright \d+ The Emscripten Authors\s*\*?\s*SPDX-License-Identifier: MIT)+\s*\*\/\s*'


def add_files_pre_js(pre_js_list, files_pre_js):
# the normal thing is to just combine the pre-js content
filename = shared.get_temp_files().get('.js').name
utils.write_file(filename, files_pre_js)
pre_js_list.insert(0, filename)
if not settings.ASSERTIONS:
return

# if a user pre-js tramples the file code's changes to Module.preRun
# that could be confusing. show a clear error at runtime if assertions are
# enabled
pre = shared.get_temp_files().get('.js').name
post = shared.get_temp_files().get('.js').name
utils.write_file(pre, '''
// All the pre-js content up to here must remain later on, we need to run
// it.
if ((typeof ENVIRONMENT_IS_WASM_WORKER != 'undefined' && ENVIRONMENT_IS_WASM_WORKER) || (typeof ENVIRONMENT_IS_PTHREAD != 'undefined' && ENVIRONMENT_IS_PTHREAD) || (typeof ENVIRONMENT_IS_AUDIO_WORKLET != 'undefined' && ENVIRONMENT_IS_AUDIO_WORKLET)) Module['preRun'] = [];
var necessaryPreJSTasks = Module['preRun'].slice();
''')
utils.write_file(post, '''
if (!Module['preRun']) throw 'Module.preRun should exist because file support used it; did a pre-js delete it?';
necessaryPreJSTasks.forEach((task) => {
if (Module['preRun'].indexOf(task) < 0) throw 'All preRun tasks that exist before user pre-js code should remain after; did you replace Module or modify Module.preRun?';
});
''')

pre_js_list.insert(1, pre)
pre_js_list.append(post)


def handle_license(js_target):
# ensure we emit the license if and only if we need to, and exactly once
js = utils.read_file(js_target)
Expand Down
32 changes: 31 additions & 1 deletion tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -3008,7 +3008,7 @@ def package_files(options, target):
if options.preload_files:
# Preloading files uses --pre-js code that runs before the module is loaded.
file_code = shared.check_call(cmd, stdout=PIPE).stdout
js_manipulation.add_files_pre_js(settings.PRE_JS_FILES, file_code)
add_files_pre_js(settings.PRE_JS_FILES, file_code)
else:
# Otherwise, we are embedding files, which does not require --pre-js code,
# and instead relies on a static constructor to populate the filesystem.
Expand All @@ -3017,6 +3017,36 @@ def package_files(options, target):
return rtn


def add_files_pre_js(pre_js_list, files_pre_js):
# the normal thing is to just combine the pre-js content
filename = shared.get_temp_files().get('.js').name
utils.write_file(filename, files_pre_js)
pre_js_list.insert(0, filename)
if not settings.ASSERTIONS:
return

# if a user pre-js tramples the file code's changes to Module.preRun
# that could be confusing. show a clear error at runtime if assertions are
# enabled
pre = shared.get_temp_files().get('.js').name
post = shared.get_temp_files().get('.js').name
utils.write_file(pre, '''
// All the pre-js content up to here must remain later on, we need to run
// it.
if ((typeof ENVIRONMENT_IS_WASM_WORKER != 'undefined' && ENVIRONMENT_IS_WASM_WORKER) || (typeof ENVIRONMENT_IS_PTHREAD != 'undefined' && ENVIRONMENT_IS_PTHREAD) || (typeof ENVIRONMENT_IS_AUDIO_WORKLET != 'undefined' && ENVIRONMENT_IS_AUDIO_WORKLET)) Module['preRun'] = [];
var necessaryPreJSTasks = Module['preRun'].slice();
''')
utils.write_file(post, '''
if (!Module['preRun']) throw 'Module.preRun should exist because file support used it; did a pre-js delete it?';
necessaryPreJSTasks.forEach((task) => {
if (Module['preRun'].indexOf(task) < 0) throw 'All preRun tasks that exist before user pre-js code should remain after; did you replace Module or modify Module.preRun?';
});
''')

pre_js_list.insert(1, pre)
pre_js_list.append(post)


@ToolchainProfiler.profile_block('calculate linker inputs')
def phase_calculate_linker_inputs(options, linker_args):
using_lld = not (options.oformat == OFormat.OBJECT and settings.LTO)
Expand Down
24 changes: 1 addition & 23 deletions tools/response_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import shlex
import tempfile

from . import shared
# Do not import shared.py so that file_packager.py can run without setting up LLVM_ROOT.
from .utils import WINDOWS

DEBUG = int(os.environ.get('EMCC_DEBUG', '0'))
Expand Down Expand Up @@ -39,28 +39,6 @@ def escape(arg):
return contents


def create_response_file(args, directory):
"""Routes the given cmdline param list in args into a new response file and
returns the filename to it.
"""
# Backslashes and other special chars need to be escaped in the response file.
contents = create_response_file_contents(args)

response_fd, response_filename = tempfile.mkstemp(prefix='emscripten_', suffix='.rsp.utf-8', dir=directory, text=True)

with os.fdopen(response_fd, 'w', encoding='utf-8') as f:
f.write(contents)

if DEBUG:
logging.warning(f'Creating response file {response_filename} with following contents: {contents}')

# Register the created .rsp file to be automatically cleaned up once this
# process finishes, so that caller does not have to remember to do it.
shared.get_temp_files().note(response_filename)

return response_filename


def expand_response_file(arg):
"""Reads a response file, and returns the list of cmdline params found in the
file.
Expand Down
Loading