diff --git a/emsdk.py b/emsdk.py index 90b4c55..e83b2c8 100644 --- a/emsdk.py +++ b/emsdk.py @@ -1402,6 +1402,8 @@ def emscripten_npm_install(tool, directory): env = os.environ.copy() env["PATH"] = node_path + os.pathsep + env["PATH"] print('Running post-install step: npm ci ...') + # Do a --no-optional install to avoid bloating disk size: + # https://github.com/emscripten-core/emscripten/issues/12406 try: subprocess.check_output( [npm, 'ci', '--production', '--no-optional'], @@ -1411,6 +1413,66 @@ def emscripten_npm_install(tool, directory): errlog('Error running %s:\n%s' % (e.cmd, e.output)) return False + # Manually install the appropriate native Closure Compiler package + # This is currently needed because npm ci would install the packages + # for Closure for all platforms, adding 180MB to the download size + # There are two problems here: + # 1. npm ci does not consider the platform of optional dependencies + # https://github.com/npm/cli/issues/558 + # 2. A bug with the native compiler has bloated the packages from + # 30MB to almost 300MB + # https://github.com/google/closure-compiler-npm/issues/186 + # If either of these bugs are fixed then we can remove this exception + # See also https://github.com/google/closure-compiler/issues/3925 + closure_compiler_native = '' + if LINUX and ARCH in ('x86', 'x86_64'): + closure_compiler_native = 'google-closure-compiler-linux' + if MACOS and ARCH in ('x86', 'x86_64'): + closure_compiler_native = 'google-closure-compiler-osx' + if WINDOWS and ARCH == 'x86_64': + closure_compiler_native = 'google-closure-compiler-windows' + + if closure_compiler_native: + # Check which version of native Closure Compiler we want to install via npm. + # (npm install command has this requirement that we must explicitly tell the pinned version) + try: + closure_version = json.load(open(os.path.join(directory, 'package.json')))['dependencies']['google-closure-compiler'] + except KeyError as e: + # The target version of Emscripten does not (did not) have a package.json that would contain google-closure-compiler. (fastcomp) + # Skip manual native google-closure-compiler installation there. + print(str(e)) + print('Emscripten version does not have a npm package.json with google-closure-compiler dependency, skipping native google-closure-compiler install step') + return True + + closure_compiler_native += '@' + closure_version + print('Running post-install step: npm install', closure_compiler_native) + try: + subprocess.check_output( + [npm, 'install', '--production', '--no-optional', closure_compiler_native], + cwd=directory, stderr=subprocess.STDOUT, env=env, + universal_newlines=True) + + # Installation of native Closure compiler was successful, so remove import of Java Closure Compiler module to avoid + # a Java dependency. + compiler_filename = os.path.join(directory, 'node_modules', 'google-closure-compiler', 'lib', 'node', 'closure-compiler.js') + if os.path.isfile(compiler_filename): + old_js = open(compiler_filename, 'r').read() + new_js = old_js.replace("require('google-closure-compiler-java')", "''/*require('google-closure-compiler-java') XXX Removed by Emsdk*/") + if old_js == new_js: + raise Exception('Failed to patch google-closure-compiler-java dependency away!') + open(compiler_filename, 'w').write(new_js) + + # Now that we succeeded to install the native version and patch away the Java dependency, delete the Java version + # since that takes up ~12.5MB of installation space that is no longer needed. + # This process is currently a little bit hacky, see https://github.com/google/closure-compiler/issues/3926 + remove_tree(os.path.join(directory, 'node_modules', 'google-closure-compiler-java')) + print('Removed google-closure-compiler-java dependency.') + else: + errlog('Failed to patch away google-closure-compiler Java dependency. ' + compiler_filename + ' does not exist.') + except subprocess.CalledProcessError as e: + errlog('Error running %s:\n%s' % (e.cmd, e.output)) + return False + print('Done running: npm ci') return True