def run(): if len(sys.argv) < 2 or sys.argv[1] in ('--version', '--help'): print('''\ emconfigure is a helper for configure, setting various environment variables so that emcc etc. are used. Typical usage: emconfigure ./configure [FLAGS] (but you can run any command instead of configure)''', file=sys.stderr) return 1 args = sys.argv[1:] if 'cmake' in args: print( 'error: use `emcmake` rather then `emconfigure` for cmake projects', file=sys.stderr) return 1 env = building.get_building_env() # When we configure via a ./configure script, don't do config-time # compilation with emcc, but instead do builds natively with Clang. This # is a heuristic emulation that may or may not work. env['EMMAKEN_JUST_CONFIGURE'] = '1' print('configure: ' + shared.shlex_join(args), file=sys.stderr) try: shared.check_call(args, env=env) return 0 except CalledProcessError as e: return e.returncode
def run(): if len(sys.argv) < 2 or sys.argv[1] in ('--version', '--help'): print('''\ emcmake is a helper for cmake, setting various environment variables so that emcc etc. are used. Typical usage: emcmake cmake [FLAGS] ''', file=sys.stderr) return 1 args = sys.argv[1:] def has_substr(args, substr): return any(substr in s for s in args) # Append the Emscripten toolchain file if the user didn't specify one. if not has_substr(args, '-DCMAKE_TOOLCHAIN_FILE'): args.append('-DCMAKE_TOOLCHAIN_FILE=' + utils.path_from_root( 'cmake', 'Modules', 'Platform', 'Emscripten.cmake')) if not has_substr(args, '-DCMAKE_CROSSCOMPILING_EMULATOR'): node_js = config.NODE_JS[0] args.append(f'-DCMAKE_CROSSCOMPILING_EMULATOR={node_js}') # On Windows specify MinGW Makefiles or ninja if we have them and no other # toolchain was specified, to keep CMake from pulling in a native Visual # Studio, or Unix Makefiles. if utils.WINDOWS and '-G' not in args: if utils.which('mingw32-make'): args += ['-G', 'MinGW Makefiles'] elif utils.which('ninja'): args += ['-G', 'Ninja'] else: print( 'emcmake: no compatible cmake generator found; Please install ninja or mingw32-make, or specify a generator explicitly using -G', file=sys.stderr) return 1 # CMake has a requirement that it wants sh.exe off PATH if MinGW Makefiles # is being used. This happens quite often, so do this automatically on # behalf of the user. See # http://www.cmake.org/Wiki/CMake_MinGW_Compiler_Issues if utils.WINDOWS and 'MinGW Makefiles' in args: env = building.remove_sh_exe_from_path(os.environ) else: env = None print('configure: ' + shared.shlex_join(args), file=sys.stderr) try: shared.check_call(args, env=env) return 0 except CalledProcessError as e: return e.returncode
def run(): if len(sys.argv) < 2 or sys.argv[1] in ('--version', '--help'): print('''\ emcmake is a helper for cmake, setting various environment variables so that emcc etc. are used. Typical usage: emcmake cmake [FLAGS] ''', file=sys.stderr) return 1 args = sys.argv[1:] def has_substr(args, substr): return any(substr in s for s in args) # Append the Emscripten toolchain file if the user didn't specify one. if not has_substr(args, '-DCMAKE_TOOLCHAIN_FILE'): args.append( '-DCMAKE_TOOLCHAIN_FILE=' + utils.path_from_root('cmake/Modules/Platform/Emscripten.cmake')) if not has_substr(args, '-DCMAKE_CROSSCOMPILING_EMULATOR'): node_js = config.NODE_JS[0] args.append(f'-DCMAKE_CROSSCOMPILING_EMULATOR={node_js}') # On Windows specify MinGW Makefiles or ninja if we have them and no other # toolchain was specified, to keep CMake from pulling in a native Visual # Studio, or Unix Makefiles. if utils.WINDOWS and '-G' not in args: if utils.which('mingw32-make'): args += ['-G', 'MinGW Makefiles'] elif utils.which('ninja'): args += ['-G', 'Ninja'] else: print( 'emcmake: no compatible cmake generator found; Please install ninja or mingw32-make, or specify a generator explicitly using -G', file=sys.stderr) return 1 print('configure: ' + shared.shlex_join(args), file=sys.stderr) try: shared.check_call(args) return 0 except CalledProcessError as e: return e.returncode
def run(): if len(sys.argv) < 2 or sys.argv[1] in ('--version', '--help'): print('''\ emcmake is a helper for cmake, setting various environment variables so that emcc etc. are used. Typical usage: emcmake cmake [FLAGS] ''', file=sys.stderr) return 1 args = sys.argv[1:] def has_substr(args, substr): return any(substr in s for s in args) # Append the Emscripten toolchain file if the user didn't specify one. if not has_substr(args, '-DCMAKE_TOOLCHAIN_FILE'): args.append('-DCMAKE_TOOLCHAIN_FILE=' + utils.path_from_root('cmake/Modules/Platform/Emscripten.cmake')) if not has_substr(args, '-DCMAKE_CROSSCOMPILING_EMULATOR'): node_js = config.NODE_JS[0] # In order to allow cmake to run code built with pthreads we need to pass some extra flags to node. # Note that we also need --experimental-wasm-bulk-memory which is true by default and hence not added here # See https://github.com/emscripten-core/emscripten/issues/15522 args.append(f'-DCMAKE_CROSSCOMPILING_EMULATOR={node_js};--experimental-wasm-threads') # On Windows specify MinGW Makefiles or ninja if we have them and no other # toolchain was specified, to keep CMake from pulling in a native Visual # Studio, or Unix Makefiles. if utils.WINDOWS and not any(arg.startswith('-G') for arg in args): if utils.which('mingw32-make'): args += ['-G', 'MinGW Makefiles'] elif utils.which('ninja'): args += ['-G', 'Ninja'] else: print('emcmake: no compatible cmake generator found; Please install ninja or mingw32-make, or specify a generator explicitly using -G', file=sys.stderr) return 1 print('configure: ' + shared.shlex_join(args), file=sys.stderr) try: shared.check_call(args) return 0 except CalledProcessError as e: return e.returncode
def inspect_headers(headers, cpp_opts): code = ['#include <stdio.h>', '#include <stddef.h>'] for header in headers: code.append('#include "' + header['name'] + '"') code.append('int main() {') c_descent('structs', code) for header in headers: for name, struct in header['structs'].items(): gen_inspect_code([name], struct, code) c_ascent(code) c_descent('defines', code) for header in headers: for name, type_ in header['defines'].items(): # Add the necessary python type, if missing. if '%' not in type_: if type_[-1] in ('d', 'i', 'u'): # integer type_ = 'i%' + type_ elif type_[-1] in ('f', 'F', 'e', 'E', 'g', 'G'): # float type_ = 'f%' + type_ elif type_[-1] in ('x', 'X', 'a', 'A', 'c', 's'): # hexadecimal or string type_ = 's%' + type_ c_set(name, type_, name, code) code.append('return 0;') code.append('}') # Write the source code to a temporary file. src_file = tempfile.mkstemp('.c') show('Generating C code... ' + src_file[1]) os.write(src_file[0], shared.asbytes('\n'.join(code))) js_file = tempfile.mkstemp('.js') # Close all unneeded FDs. os.close(src_file[0]) os.close(js_file[0]) # Remove dangerous env modifications env = os.environ.copy() env['EMCC_FORCE_STDLIBS'] = 'libcompiler_rt' env['EMCC_ONLY_FORCED_STDLIBS'] = '1' info = [] # Compile the program. show('Compiling generated code...') # -Oz optimizes enough to avoid warnings on code size/num locals cmd = [shared.EMCC] + cpp_opts + ['-o', js_file[1], src_file[1], '-O0', '-Werror', '-Wno-format', '-I', shared.path_from_root(), '-s', 'BOOTSTRAPPING_STRUCT_INFO=1', '-s', 'WARN_ON_UNDEFINED_SYMBOLS=0', '-s', 'STRICT=1', # Use SINGLE_FILE=1 so there is only a single # file to cleanup. '-s', 'SINGLE_FILE=1'] # Default behavior for emcc is to warn for binaryen version check mismatches # so we should try to match that behavior. cmd += ['-Wno-error=version-check'] # TODO(sbc): Remove this one we remove the test_em_config_env_var test cmd += ['-Wno-deprecated'] if shared.Settings.LTO: cmd += ['-flto=' + shared.Settings.LTO] show(shared.shlex_join(cmd)) try: subprocess.check_call(cmd, env=env) except subprocess.CalledProcessError as e: sys.stderr.write('FAIL: Compilation failed!: %s\n' % e.cmd) sys.exit(1) # Run the compiled program. show('Calling generated program... ' + js_file[1]) info = shared.run_js_tool(js_file[1], stdout=shared.PIPE).splitlines() # Remove all temporary files. os.unlink(src_file[1]) if os.path.exists(js_file[1]): os.unlink(js_file[1]) # Parse the output of the program into a dict. return parse_c_output(info)
def inspect_headers(headers, cflags): code = ['#include <stdio.h>', '#include <stddef.h>'] for header in headers: code.append('#include "' + header['name'] + '"') code.append('int main() {') c_descent('structs', code) for header in headers: for name, struct in header['structs'].items(): gen_inspect_code([name], struct, code) c_ascent(code) c_descent('defines', code) for header in headers: for name, type_ in header['defines'].items(): # Add the necessary python type, if missing. if '%' not in type_: if type_[-1] in ('d', 'i', 'u'): # integer type_ = 'i%' + type_ elif type_[-1] in ('f', 'F', 'e', 'E', 'g', 'G'): # float type_ = 'f%' + type_ elif type_[-1] in ('x', 'X', 'a', 'A', 'c', 's'): # hexadecimal or string type_ = 's%' + type_ c_set(name, type_, name, code) code.append('return 0;') code.append('}') # Write the source code to a temporary file. src_file = tempfile.mkstemp('.c', text=True) show('Generating C code... ' + src_file[1]) os.write(src_file[0], '\n'.join(code).encode()) js_file = tempfile.mkstemp('.js') # Check sanity early on before populating the cache with libcompiler_rt # If we don't do this the parallel build of compiler_rt will run while holding the cache # lock and with EM_EXCLUSIVE_CACHE_ACCESS set causing N processes to race to run sanity checks. # While this is not in itself serious problem it is wasteful and noise on stdout. # For the same reason we run this early in embuilder.py and emcc.py. # TODO(sbc): If we can remove EM_EXCLUSIVE_CACHE_ACCESS then this would not longer be needed. shared.check_sanity() compiler_rt = system_libs.Library.get_usable_variations( )['libcompiler_rt'].get_path() # Close all unneeded FDs. os.close(src_file[0]) os.close(js_file[0]) info = [] # Compile the program. show('Compiling generated code...') if any('libcxxabi' in f for f in cflags): compiler = shared.EMXX else: compiler = shared.EMCC # -Oz optimizes enough to avoid warnings on code size/num locals cmd = [compiler] + cflags + [ '-o', js_file[1], src_file[1], '-O0', '-Werror', '-Wno-format', '-nostdlib', compiler_rt, '-sMEMORY64=' + str(settings.MEMORY64), '-sBOOTSTRAPPING_STRUCT_INFO=1', '-sLLD_REPORT_UNDEFINED=1', '-sSTRICT', # Use SINGLE_FILE=1 so there is only a single # file to cleanup. '-sSINGLE_FILE' ] # Default behavior for emcc is to warn for binaryen version check mismatches # so we should try to match that behavior. cmd += ['-Wno-error=version-check'] # TODO(sbc): Remove this one we remove the test_em_config_env_var test cmd += ['-Wno-deprecated'] if settings.LTO: cmd += ['-flto=' + settings.LTO] show(shared.shlex_join(cmd)) try: subprocess.check_call(cmd, env=system_libs.clean_env()) except subprocess.CalledProcessError as e: sys.stderr.write('FAIL: Compilation failed!: %s\n' % e.cmd) sys.exit(1) # Run the compiled program. show('Calling generated program... ' + js_file[1]) args = [] if settings.MEMORY64: args += ['--experimental-wasm-bigint'] info = shared.run_js_tool(js_file[1], node_args=args, stdout=shared.PIPE).splitlines() if not DEBUG: # Remove all temporary files. os.unlink(src_file[1]) if os.path.exists(js_file[1]): os.unlink(js_file[1]) # Parse the output of the program into a dict. return parse_c_output(info)