| #!/usr/bin/env python3 |
| # Copyright 2026 The Emscripten Authors. All rights reserved. |
| # Emscripten is available under two separate licenses, the MIT license and the |
| # University of Illinois/NCSA Open Source License. Both these licenses can be |
| # found in the LICENSE file. |
| |
| import os |
| import sys |
| import shutil |
| import subprocess |
| |
| |
| script_dir = os.path.abspath(os.path.dirname(__file__)) |
| emscripten_root = os.path.dirname(os.path.dirname(script_dir)) |
| default_llvm_dir = os.path.join(os.path.dirname(emscripten_root), 'llvm-project') |
| |
| # system/lib/openmp (to be updated) |
| local_root = os.path.join(script_dir, 'openmp') |
| local_src = os.path.join(local_root, 'src') |
| local_include = os.path.join(local_root, 'include') |
| local_prebuilt = os.path.join(local_root, 'prebuilt') |
| |
| # Files to ignore during copy_tree |
| excludes = [ |
| 'doc', |
| 'build', |
| 'tests', |
| 'CMakeFiles', |
| 'libgomp.a', |
| 'libiomp5.a', |
| 'libomp.a', |
| ] |
| |
| |
| def clean_dir(dirname): |
| for f in os.listdir(dirname): |
| full = os.path.join(dirname, f) |
| if os.path.isdir(full): |
| shutil.rmtree(full) |
| else: |
| os.remove(full) |
| |
| |
| def copy_tree(upstream_dir, local_dir): |
| for f in os.listdir(upstream_dir): |
| full = os.path.join(upstream_dir, f) |
| if f not in excludes: |
| if os.path.isdir(full): |
| if not os.path.exists(os.path.join(local_dir, f)): |
| os.makedirs(os.path.join(local_dir, f)) |
| copy_tree(full, os.path.join(local_dir, f)) |
| else: |
| shutil.copy2(full, os.path.join(local_dir, f)) |
| |
| |
| def main(): |
| if len(sys.argv) > 1: |
| llvm_dir = os.path.join(os.path.abspath(sys.argv[1])) |
| else: |
| llvm_dir = default_llvm_dir |
| |
| # Output directory for build |
| output_dir = os.path.join(emscripten_root, 'out') |
| build_dir = os.path.join(output_dir, 'build_openmp') |
| |
| # LLVM/OpenMP folder containing latest version |
| upstream_runtimes = os.path.join(llvm_dir, 'runtimes/') |
| upstream_root = os.path.join(llvm_dir, 'openmp/') |
| upstream_runtime_root = os.path.join(upstream_root, 'runtime/src') |
| assert os.path.exists(upstream_runtime_root) |
| |
| # Build output paths |
| upstream_build_src = os.path.join(build_dir, 'openmp/runtime/src') # contains various *.a and generated *.h |
| |
| # Remove old version |
| clean_dir(local_root) |
| os.mkdir(local_src) |
| os.mkdir(local_include) |
| os.mkdir(local_prebuilt) |
| |
| # Update source |
| copy_tree(upstream_runtime_root, local_src) |
| |
| # Generates header files for OpenMP library build |
| subprocess.run( |
| [ |
| 'emcmake', |
| 'cmake', |
| '-S', |
| f'{upstream_runtimes}', |
| '-B', |
| f'{build_dir}', |
| '-G', |
| 'Ninja', |
| '-DLLVM_ENABLE_RUNTIMES=openmp', |
| '-DLLVM_DEFAULT_TARGET_TRIPLE=wasm32-unknown-emscripten', |
| '-DOPENMP_ENABLE_LIBOMPTARGET=OFF', |
| '-DLIBOMP_HAVE_OMPT_SUPPORT=OFF', |
| '-DLIBOMP_OMPT_SUPPORT=OFF', |
| '-DLIBOMP_OMPD_SUPPORT=OFF', |
| '-DLIBOMP_USE_DEBUGGER=OFF', |
| '-DLIBOMP_FORTRAN_MODULES=OFF', |
| '-DLIBOMP_ENABLE_SHARED=OFF', |
| '-DLIBOMP_ARCH=wasm32', |
| '-DOPENMP_ENABLE_LIBOMPTARGET_PROFILING=OFF', |
| ] |
| ) |
| subprocess.run(['cmake', '--build', '.'], cwd=build_dir) |
| |
| # Update license file |
| shutil.copy2(os.path.join(upstream_root, 'LICENSE.TXT'), local_root) |
| |
| # Update include headers |
| header_files = ['omp.h', 'ompx.h'] |
| for file in header_files: |
| shutil.copy2(os.path.join(upstream_build_src, file), local_include) |
| |
| # Update generated header files |
| built_files = ['kmp_config.h', 'kmp_i18n_id.inc', 'kmp_i18n_default.inc'] |
| for file in built_files: |
| shutil.copy2(os.path.join(upstream_build_src, file), local_prebuilt) |
| |
| |
| if __name__ == '__main__': |
| main() |