diff --git a/test/common.py b/test/common.py index 8f2ba6bdb312c..1b5444cb2288a 100644 --- a/test/common.py +++ b/test/common.py @@ -491,7 +491,7 @@ def require_node_25(self): if not nodejs: self.skipTest('Test requires nodejs to run') if not self.try_require_node_version(25, 0, 0): - if os.getenv('EMTEST_AUTOSKIP') == '1': + if utils.get_env_bool('EMTEST_AUTOSKIP'): self.skipTest('test requires node v25 and current Node.js version is older than this, with EMTEST_AUTOSKIP being set') self.fail('node v25 required to run this test. Use EMTEST_SKIP_NODE_25 to skip') diff --git a/test/runner.py b/test/runner.py index d3d6a7110b51f..7bdde5e96945b 100755 --- a/test/runner.py +++ b/test/runner.py @@ -457,7 +457,7 @@ def flattened_tests(loaded_tests): def run_tests(options, suite): # Run the discovered tests - if os.getenv('CI'): + if utils.get_env_bool('CI'): # output fd must remain open until after testRunner.run() below output = open('out/test-results.xml', 'wb') import xmlrunner # type: ignore # noqa: PLC0415 @@ -552,16 +552,16 @@ def parse_args(): def configure(): browser_common.EMTEST_BROWSER = os.getenv('EMTEST_BROWSER') - browser_common.EMTEST_BROWSER_AUTO_CONFIG = int(os.getenv('EMTEST_BROWSER_AUTO_CONFIG', '1')) - browser_common.EMTEST_HEADLESS = int(os.getenv('EMTEST_HEADLESS', '0')) - common.EMTEST_DETECT_TEMPFILE_LEAKS = int(os.getenv('EMTEST_DETECT_TEMPFILE_LEAKS', '0')) - common.EMTEST_ALL_ENGINES = int(os.getenv('EMTEST_ALL_ENGINES', '0')) - common.EMTEST_SKIP_SLOW = int(os.getenv('EMTEST_SKIP_SLOW', '0')) - common.EMTEST_SKIP_FLAKY = int(os.getenv('EMTEST_SKIP_FLAKY', '0')) - common.EMTEST_RETRY_FLAKY = int(os.getenv('EMTEST_RETRY_FLAKY', '0')) - common.EMTEST_LACKS_NATIVE_CLANG = int(os.getenv('EMTEST_LACKS_NATIVE_CLANG', '0')) - common.EMTEST_REBASELINE = int(os.getenv('EMTEST_REBASELINE', '0')) - common.EMTEST_VERBOSE = int(os.getenv('EMTEST_VERBOSE', '0')) or shared.DEBUG + browser_common.EMTEST_BROWSER_AUTO_CONFIG = utils.get_env_bool('EMTEST_BROWSER_AUTO_CONFIG', '1') + browser_common.EMTEST_HEADLESS = utils.get_env_bool('EMTEST_HEADLESS') + common.EMTEST_DETECT_TEMPFILE_LEAKS = utils.get_env_bool('EMTEST_DETECT_TEMPFILE_LEAKS') + common.EMTEST_ALL_ENGINES = utils.get_env_bool('EMTEST_ALL_ENGINES') + common.EMTEST_SKIP_SLOW = utils.get_env_bool('EMTEST_SKIP_SLOW') + common.EMTEST_SKIP_FLAKY = utils.get_env_bool('EMTEST_SKIP_FLAKY') + common.EMTEST_RETRY_FLAKY = utils.get_env_int('EMTEST_RETRY_FLAKY') + common.EMTEST_LACKS_NATIVE_CLANG = utils.get_env_bool('EMTEST_LACKS_NATIVE_CLANG') + common.EMTEST_REBASELINE = utils.get_env_bool('EMTEST_REBASELINE') + common.EMTEST_VERBOSE = utils.get_env_bool('EMTEST_VERBOSE') or shared.DEBUG if common.EMTEST_VERBOSE: logging.root.setLevel(logging.DEBUG) diff --git a/test/test_browser.py b/test/test_browser.py index bf935ec74a483..46fb9fae67c8e 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -286,7 +286,7 @@ def make_reftest(self, expected): # pngcrush -rem gAMA -rem cHRM -rem iCCP -rem sRGB infile outfile shutil.copy(expected, 'expected.png') create_file('reftest.js', f''' - const reftestRebaseline = {common.EMTEST_REBASELINE}; + const reftestRebaseline = {int(common.EMTEST_REBASELINE)}; ''' + read_file(test_file('reftest.js'))) def reftest(self, filename, reference=None, reference_slack=0, *args, **kwargs): @@ -308,7 +308,7 @@ def reftest(self, filename, reference=None, reference_slack=0, *args, **kwargs): self.run_process('pngcrush -rem gAMA -rem cHRM -rem iCCP -rem sRGB actual.png'.split() + [reference]) def test_sdl1_in_emscripten_nonstrict_mode(self): - if 'EMCC_STRICT' in os.environ and int(os.environ['EMCC_STRICT']): + if utils.get_env_bool('EMCC_STRICT'): self.skipTest('This test requires being run in non-strict mode (EMCC_STRICT env. variable unset)') # TODO: This test is verifying behavior that will be deprecated at some point in the future, remove this test once # system JS libraries are no longer automatically linked to anymore. diff --git a/tools/response_file.py b/tools/response_file.py index 805e8c3f8d949..b33a407723df8 100644 --- a/tools/response_file.py +++ b/tools/response_file.py @@ -9,9 +9,9 @@ import tempfile from . import shared -from .utils import WINDOWS +from .utils import WINDOWS, get_env_int -DEBUG = int(os.environ.get('EMCC_DEBUG', '0')) +DEBUG = get_env_int('EMCC_DEBUG') def create_response_file_contents(args): diff --git a/tools/settings.py b/tools/settings.py index 77f33b0758b3a..169d2719638dd 100644 --- a/tools/settings.py +++ b/tools/settings.py @@ -5,7 +5,6 @@ import copy import difflib -import os import re from typing import Any @@ -300,9 +299,7 @@ def read_js_settings(filename, attrs): self.attrs.update(internal_attrs) self.infer_types() - strict_override = False - if 'EMCC_STRICT' in os.environ: - strict_override = int(os.environ.get('EMCC_STRICT')) + strict_override = utils.get_env_bool('EMCC_STRICT') # Special handling for LEGACY_SETTINGS. See src/setting.js for more # details diff --git a/tools/shared.py b/tools/shared.py index efa6ce35a5942..f4b80ee123f08 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -24,11 +24,20 @@ assert sys.version_info >= (3, 10), f'emscripten requires python 3.10 or above ({sys.executable} {sys.version})' from . import colored_logger +from .utils import ( + exe_path_from_root, + exit_with_error, + get_env_bool, + get_env_int, + memoize, + path_from_root, + safe_ensure_dirs, +) # Configure logging before importing any other local modules so even # log message during import are shown as expected. -DEBUG = int(os.environ.get('EMCC_DEBUG', '0')) -EMCC_LOGGING = int(os.environ.get('EMCC_LOGGING', '1')) +DEBUG = get_env_int('EMCC_DEBUG') +EMCC_LOGGING = get_env_bool('EMCC_LOGGING', '1') log_level = logging.ERROR if DEBUG: log_level = logging.DEBUG @@ -42,10 +51,9 @@ from . import cache, config, diagnostics, filelock, tempfiles, utils from .settings import settings -from .utils import exe_path_from_root, exit_with_error, memoize, path_from_root, safe_ensure_dirs -DEBUG_SAVE = DEBUG or int(os.environ.get('EMCC_DEBUG_SAVE', '0')) -PRINT_SUBPROCS = int(os.getenv('EMCC_VERBOSE', '0')) +DEBUG_SAVE = DEBUG or get_env_bool('EMCC_DEBUG_SAVE') +PRINT_SUBPROCS = get_env_bool('EMCC_VERBOSE') SKIP_SUBPROCS = False # Minimum node version required to run the emscripten compiler. This is @@ -347,7 +355,7 @@ def perform_sanity_checks(quiet=False): llvm_ok = check_llvm() - if os.environ.get('EM_IGNORE_SANITY'): + if utils.get_env_bool('EM_IGNORE_SANITY'): logger.info('EM_IGNORE_SANITY set, ignoring sanity checks') return @@ -374,7 +382,7 @@ def check_sanity(force=False, quiet=False): EM_CONFIG (so, we re-check sanity when the settings are changed). We also re-check sanity and clear the cache when the version changes. """ - if not force and os.environ.get('EMCC_SKIP_SANITY_CHECK') == '1': + if not force and utils.get_env_bool('EMCC_SKIP_SANITY_CHECK'): return # We set EMCC_SKIP_SANITY_CHECK so that any subprocesses that we launch will @@ -391,7 +399,7 @@ def check_sanity(force=False, quiet=False): perform_sanity_checks(quiet) return - if os.environ.get('EM_IGNORE_SANITY'): + if utils.get_env_bool('EM_IGNORE_SANITY'): perform_sanity_checks(quiet) return @@ -498,7 +506,7 @@ def setup_temp_dirs(): global EMSCRIPTEN_TEMP_DIR, CANONICAL_TEMP_DIR, TEMP_DIR EMSCRIPTEN_TEMP_DIR = None - TEMP_DIR = os.environ.get("EMCC_TEMP_DIR", tempfile.gettempdir()) + TEMP_DIR = os.environ.get('EMCC_TEMP_DIR', tempfile.gettempdir()) if not os.path.isdir(TEMP_DIR): exit_with_error(f'The temporary directory `{TEMP_DIR}` does not exist! Please make sure that the path is correct.') diff --git a/tools/system_libs.py b/tools/system_libs.py index 667dbee0f8920..85dfc7b202ff1 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -18,7 +18,7 @@ from . import building, cache, diagnostics, shared, utils from .settings import settings from .toolchain_profiler import ToolchainProfiler -from .utils import read_file +from .utils import get_env_bool, read_file logger = logging.getLogger('system_libs') @@ -37,7 +37,7 @@ # # Setting EMCC_USE_NINJA=2 means that ninja will automatically be run for each library needed at # link time. -USE_NINJA = int(os.environ.get('EMCC_USE_NINJA', '0')) +USE_NINJA = get_env_bool('EMCC_USE_NINJA') # A (fake) deterministic emscripten path to use in __FILE__ macro and debug info # to produce reproducible builds across platforms. @@ -487,7 +487,7 @@ def build_objects(self, build_dir): By default, this builds all the source files returned by `self.get_files()`, with the `cflags` returned by `self.get_cflags()`. """ - batch_inputs = int(os.environ.get('EMCC_BATCH_BUILD', '1')) + batch_inputs = get_env_bool('EMCC_BATCH_BUILD', '1') self.build_dir = build_dir batches = {} commands = [] @@ -1477,7 +1477,7 @@ def can_use(self): # In both cases, the build is not one that is hyper-focused on code size, # and so optz is not that important. return super().can_use() and settings.SHRINK_LEVEL >= 2 and \ - not settings.LINKABLE and not os.environ.get('EMCC_FORCE_STDLIBS') + not settings.LINKABLE and 'EMCC_FORCE_STDLIBS' not in os.environ class libprintf_long_double(libc): @@ -2319,14 +2319,14 @@ def get_libs_to_link(options): # avoids spending time checking for unresolved symbols in your project files, # which can speed up linking, but if you do not have the proper list of # actually needed libraries, errors can occur. - only_forced = os.environ.get('EMCC_ONLY_FORCED_STDLIBS') + only_forced = utils.get_env_bool('EMCC_ONLY_FORCED_STDLIBS') if only_forced: # One of the purposes EMCC_ONLY_FORCED_STDLIBS was to skip the scanning # of the input files for reverse dependencies. diagnostics.warning('deprecated', 'EMCC_ONLY_FORCED_STDLIBS is deprecated. Use `-nostdlib` to avoid linking standard libraries') if force == '1': force_include = [name for name, lib in system_libs_map.items() if not lib.never_force] - elif force is not None: + elif force: force_include = force.split(',') if force_include: logger.debug(f'forcing stdlibs: {force_include}') @@ -2412,8 +2412,7 @@ def add_sanitizer_libs(): if settings.PRINTF_LONG_DOUBLE: add_library('libprintf_long_double') # See comment in libc_optz itself - if settings.SHRINK_LEVEL >= 2 and not settings.LINKABLE and \ - not os.environ.get('EMCC_FORCE_STDLIBS'): + if settings.SHRINK_LEVEL >= 2 and not settings.LINKABLE and not force: add_library('libc_optz') if settings.STANDALONE_WASM: add_library('libstandalonewasm') diff --git a/tools/utils.py b/tools/utils.py index 9e80c400d7522..6d1f3d29a8262 100644 --- a/tools/utils.py +++ b/tools/utils.py @@ -48,6 +48,17 @@ def run_process(cmd, check=True, input=None, *args, **kw): return ret +def get_env_bool(name, default='0'): + env_var = os.getenv(name, default) + assert env_var in {'true', 'false', '1', '0'}, f'invalid environment variable setting {env_var} for {name}' + return env_var in {'1', 'true'} + + +def get_env_int(name, default=0): + env_var = os.getenv(name, default) + return int(env_var) + + def exec(cmd): if WINDOWS: rtn = run_process(cmd, stdin=sys.stdin, check=False).returncode @@ -221,7 +232,7 @@ def get_num_cores(): cpu_count = len(os.sched_getaffinity(0)) else: cpu_count = os.cpu_count() - return int(os.environ.get('EMCC_CORES', cpu_count)) + return get_env_int('EMCC_CORES', cpu_count) memoize = functools.cache