profile = get_option('feature_profile') allow_preinstalled = get_option('allow_preinstalled') dependency_prefix = get_option('dependency_prefix') wheel_carries_native_bundle = get_option('build_python') and get_option('python_install_native') effective_allow_preinstalled = allow_preinstalled and not wheel_carries_native_bundle is_wasm = host_machine.system() == 'emscripten' is_windows = host_machine.system() == 'windows' can_build_posix_mpi = not meson.is_cross_build() and not is_windows and not is_wasm nvcc_program = find_program('nvcc', required: false) hipcc_program = find_program('hipcc', required: false) dependency_has_nvcc = dependency_prefix != '' and fs.exists(dependency_prefix / 'bin' / 'nvcc') dependency_has_hipcc = dependency_prefix != '' and fs.exists(dependency_prefix / 'bin' / 'hipcc') cuda_toolkit_available = nvcc_program.found() or dependency_has_nvcc hip_toolkit_available = hipcc_program.found() or dependency_has_hipcc openmp_dep = dependency('openmp', required: false) bundled_compiler_openmp = cpp.get_id() == 'gcc' and openmp_dep.found() usable_openmp = openmp_dep.found() and ( effective_allow_preinstalled or dependency_prefix != '' or bundled_compiler_openmp ) simd_arch_supported = host_machine.cpu_family() in ['x86', 'x86_64'] if host_machine.cpu_family() in ['aarch64', 'arm'] simd_arch_supported = cpp.compiles(''' #ifndef __ARM_FEATURE_SVE #error SVE is required by MFEM's ARM SIMD specialization #endif int main() { return 0; } ''', name: 'MFEM ARM SVE SIMD support') elif host_machine.cpu_family() in ['ppc', 'ppc64'] simd_arch_supported = cpp.compiles(''' #ifndef __VSX__ #error VSX is required by MFEM's Power SIMD specialization #endif int main() { return 0; } ''', name: 'MFEM Power VSX SIMD support') endif mfem_feature_names = [ 'mpi', 'metis', 'exceptions', 'zlib', 'libunwind', 'lapack', 'thread_safe', 'openmp', 'legacy_openmp', 'memalloc', 'sundials', 'suitesparse', 'superlu', 'superlu5', 'mumps', 'strumpack', 'cudss', 'ginkgo', 'amgx', 'magma', 'gnutls', 'gslib', 'hdf5', 'netcdf', 'petsc', 'slepc', 'mpfr', 'sidre', 'fms', 'conduit', 'pumi', 'hiop', 'cuda', 'hip', 'occa', 'raja', 'ceed', 'umpire', 'simd', 'adios2', 'caliper', 'algoim', 'mkl_cpardiso', 'mkl_pardiso', 'adforward', 'codipack', 'benchmark', 'parelag', 'tribol', 'enzyme', 'moonolith', 'simmetrix', ] mfem_cmake_names = [ 'MFEM_USE_MPI', 'MFEM_USE_METIS', 'MFEM_USE_EXCEPTIONS', 'MFEM_USE_ZLIB', 'MFEM_USE_LIBUNWIND', 'MFEM_USE_LAPACK', 'MFEM_THREAD_SAFE', 'MFEM_USE_OPENMP', 'MFEM_USE_LEGACY_OPENMP', 'MFEM_USE_MEMALLOC', 'MFEM_USE_SUNDIALS', 'MFEM_USE_SUITESPARSE', 'MFEM_USE_SUPERLU', 'MFEM_USE_SUPERLU5', 'MFEM_USE_MUMPS', 'MFEM_USE_STRUMPACK', 'MFEM_USE_CUDSS', 'MFEM_USE_GINKGO', 'MFEM_USE_AMGX', 'MFEM_USE_MAGMA', 'MFEM_USE_GNUTLS', 'MFEM_USE_GSLIB', 'MFEM_USE_HDF5', 'MFEM_USE_NETCDF', 'MFEM_USE_PETSC', 'MFEM_USE_SLEPC', 'MFEM_USE_MPFR', 'MFEM_USE_SIDRE', 'MFEM_USE_FMS', 'MFEM_USE_CONDUIT', 'MFEM_USE_PUMI', 'MFEM_USE_HIOP', 'MFEM_USE_CUDA', 'MFEM_USE_HIP', 'MFEM_USE_OCCA', 'MFEM_USE_RAJA', 'MFEM_USE_CEED', 'MFEM_USE_UMPIRE', 'MFEM_USE_SIMD', 'MFEM_USE_ADIOS2', 'MFEM_USE_CALIPER', 'MFEM_USE_ALGOIM', 'MFEM_USE_MKL_CPARDISO', 'MFEM_USE_MKL_PARDISO', 'MFEM_USE_ADFORWARD', 'MFEM_USE_CODIPACK', 'MFEM_USE_BENCHMARK', 'MFEM_USE_PARELAG', 'MFEM_USE_TRIBOL', 'MFEM_USE_ENZYME', 'MFEM_USE_MOONOLITH', 'MFEM_USE_SIMMETRIX', ] source_capable = { 'mpi': can_build_posix_mpi, 'metis': not is_windows and not is_wasm, 'exceptions': true, 'zlib': true, 'thread_safe': true, 'openmp': bundled_compiler_openmp, 'legacy_openmp': bundled_compiler_openmp, 'memalloc': true, 'sundials': not is_windows and not is_wasm, 'gslib': not is_windows and not is_wasm, 'fms': not is_windows, 'ceed': not is_windows, 'algoim': not meson.is_cross_build() and not is_windows and not is_wasm, 'cuda': cuda_toolkit_available and not is_wasm and not host_machine.system() == 'darwin', 'hip': hip_toolkit_available and not is_wasm and not host_machine.system() == 'darwin', 'simd': simd_arch_supported and not is_wasm, } single_precision_conflicts = [ 'sundials', 'suitesparse', 'superlu', 'strumpack', 'ginkgo', 'amgx', 'slepc', 'pumi', 'simmetrix', 'gslib', 'algoim', 'ceed', 'tribol', 'moonolith', ] cuda_option = get_option('mfem_cuda') hip_option = get_option('mfem_hip') profile_cuda = false profile_hip = false if cuda_option.enabled() and hip_option.enabled() profile_cuda = true profile_hip = true elif cuda_option.enabled() profile_cuda = true elif hip_option.enabled() profile_hip = true else profile_cuda = cuda_option.auto() and source_capable.get('cuda') profile_hip = hip_option.auto() and not profile_cuda and source_capable.get('hip') endif portable_defaults = { 'mpi': can_build_posix_mpi, 'metis': can_build_posix_mpi, 'exceptions': true, 'zlib': true, 'thread_safe': true, 'openmp': usable_openmp, 'memalloc': true, 'sundials': not is_windows and not is_wasm, 'gslib': not is_windows and not is_wasm, 'fms': not is_windows, 'ceed': not is_windows, 'algoim': source_capable.get('algoim'), 'cuda': profile_cuda, 'hip': profile_hip, 'simd': simd_arch_supported and not is_wasm, } full_cuda = false full_hip = false if profile == 'full' full_cuda = profile_cuda full_hip = profile_hip endif mfem_features = {} mfem_feature_states = [] foreach feature_name : mfem_feature_names feature_opt = get_option('mfem_' + feature_name) feature_on = feature_opt.enabled() if feature_opt.auto() if profile == 'portable' feature_on = portable_defaults.get(feature_name, false) elif profile == 'full' feature_on = true if feature_name == 'legacy_openmp' or feature_name == 'superlu5' feature_on = false elif feature_name == 'openmp' feature_on = usable_openmp elif feature_name == 'cuda' feature_on = full_cuda elif feature_name == 'hip' feature_on = full_hip elif feature_name == 'cudss' or feature_name == 'amgx' feature_on = full_cuda elif feature_name == 'magma' feature_on = full_cuda or full_hip elif feature_name == 'simd' feature_on = simd_arch_supported and not is_wasm elif feature_name == 'enzyme' feature_on = cpp.get_id() == 'clang' and not full_cuda elif feature_name in ['benchmark', 'parelag', 'tribol'] feature_on = false endif endif endif if ( feature_opt.auto() and get_option('mfem_precision') == 'single' and feature_name in single_precision_conflicts ) feature_on = false endif if ( feature_on and feature_name not in ['cuda', 'hip', 'openmp', 'simd'] and not effective_allow_preinstalled and dependency_prefix == '' and not source_capable.get(feature_name, false) ) error( 'Selected feature mfem_' + feature_name + ' has no bundled source provider. ' + 'Supply -Ddependency_prefix=/path/to/a/hermetic/prefix or enable preinstalled dependencies.' ) endif mfem_features += {feature_name: feature_on} mfem_feature_states += [feature_on] endforeach foreach build_only_feature : ['benchmark', 'parelag', 'tribol'] if get_option('mfem_' + build_only_feature).enabled() error( 'mfem_' + build_only_feature + ' is an upstream non-installed ' + 'benchmark/miniapp build switch, not an MFEM library capability. ' + 'Build that program in a separate consumer project against this SDK.' ) endif endforeach mfem_has_mpi = mfem_features.get('mpi') mfem_has_metis = mfem_features.get('metis') mfem_has_cuda = mfem_features.get('cuda') mfem_has_hip = mfem_features.get('hip') mfem_has_openmp = mfem_features.get('openmp') mfem_has_gslib = mfem_features.get('gslib') mfem_has_zlib = mfem_features.get('zlib') mfem_has_sundials = mfem_features.get('sundials') if get_option('mfem_mpi').enabled() and not can_build_posix_mpi and not allow_preinstalled and dependency_prefix == '' error('The bundled MPI provider needs a native POSIX build. For cross/Windows builds, provide an MPI prefix or use -Dmfem_mpi=disabled.') endif if get_option('mfem_cuda').enabled() and not source_capable.get('cuda') error('CUDA was forced on, but nvcc and a supported non-macOS CUDA host were not found.') endif if get_option('mfem_hip').enabled() and not source_capable.get('hip') error('HIP was forced on, but hipcc was not found.') endif if get_option('mfem_openmp').enabled() and not usable_openmp error('OpenMP was forced on, but no permitted OpenMP runtime was found for the selected compiler.') endif if get_option('mfem_simd').enabled() and not simd_arch_supported error('SIMD was forced on, but MFEM has no intrinsic specialization for this target/compiler.') endif if get_option('mfem_enzyme').enabled() and cpp.get_id() != 'clang' error('Enzyme was forced on, but Enzyme requires a matching Clang/LLVM compiler toolchain.') endif if mfem_has_cuda and mfem_has_hip error('MFEM CUDA and HIP backends are mutually exclusive.') endif if mfem_features.get('enzyme') and mfem_has_cuda error('The bundled CUDA route uses nvcc and cannot be combined with Enzyme; use a dedicated clang-CUDA toolchain or disable one feature.') endif if mfem_features.get('cudss') and not mfem_has_cuda error('cuDSS requires -Dmfem_cuda=enabled (or an auto-detected CUDA toolkit).') endif if mfem_features.get('amgx') and not mfem_has_cuda error('AmgX requires the CUDA backend.') endif if mfem_features.get('magma') and not (mfem_has_cuda or mfem_has_hip) error('MAGMA requires either the CUDA or HIP backend.') endif if mfem_features.get('slepc') and not mfem_features.get('petsc') error('SLEPc requires PETSc.') endif if mfem_features.get('adforward') and not mfem_features.get('codipack') error('Forward-mode automatic differentiation requires CoDiPack.') endif if mfem_features.get('superlu5') and not mfem_features.get('superlu') error('The SuperLU 5 compatibility option requires SuperLU_DIST.') endif if mfem_features.get('simmetrix') and not mfem_features.get('pumi') error('Simmetrix integration requires PUMI.') endif foreach mpi_feature : ['superlu', 'mumps', 'strumpack', 'petsc', 'slepc', 'pumi', 'mkl_cpardiso', 'tribol'] if mfem_features.get(mpi_feature) and not mfem_has_mpi error('MFEM feature ' + mpi_feature + ' requires MPI/Hypre.') endif endforeach if mfem_features.get('legacy_openmp') and ( mfem_has_openmp or mfem_has_cuda or mfem_features.get('raja') or mfem_features.get('occa')) error('Legacy OpenMP cannot be combined with OpenMP, CUDA, RAJA, or OCCA.') endif if mfem_features.get('legacy_openmp') and not mfem_features.get('thread_safe') error('Legacy OpenMP requires MFEM thread-safe mode.') endif if get_option('mfem_precision') == 'single' foreach single_conflict : single_precision_conflicts if mfem_features.get(single_conflict) error('Single precision is incompatible with MFEM feature ' + single_conflict + '.') endif endforeach endif mfem_consumer_cpp_std = ( mfem_features.get('raja') or mfem_features.get('umpire') ) ? 'c++20' : 'c++17' system_mfem = disabler() mfem_provider = 'source bundle' if effective_allow_preinstalled system_candidate = dependency('mfem', version: '>=4.10', required: false, allow_fallback: false) if system_candidate.found() system_compatible = true foreach i : range(mfem_feature_names.length()) if mfem_feature_states[i] feature_macro = mfem_cmake_names[i] macro_ok = cpp.compiles( '#include \n#ifndef ' + feature_macro + '\n#error missing\n#endif\nint main(){return 0;}', dependencies: system_candidate, name: 'system MFEM provides ' + feature_macro, ) system_compatible = system_compatible and macro_ok endif endforeach precision_macro = get_option('mfem_precision') == 'single' ? 'MFEM_USE_SINGLE' : 'MFEM_USE_DOUBLE' system_compatible = system_compatible and cpp.compiles( '#include \n#ifndef ' + precision_macro + '\n#error precision mismatch\n#endif\nint main(){return 0;}', dependencies: system_candidate, name: 'system MFEM uses requested precision', ) foreach i : range(mfem_feature_names.length()) feature_opt = get_option('mfem_' + mfem_feature_names[i]) feature_macro = mfem_cmake_names[i] if feature_opt.disabled() macro_absent = cpp.compiles( '#include \n#ifdef ' + feature_macro + '\n#error explicitly disabled\n#endif\nint main(){return 0;}', dependencies: system_candidate, name: 'system MFEM omits disabled ' + feature_macro, ) system_compatible = system_compatible and macro_absent endif endforeach if system_compatible system_mfem = system_candidate mfem_provider = 'system' else message('The system MFEM does not satisfy the selected feature set; using the pinned source bundle.') endif endif endif uses_unmodelled_system_tpl = false foreach feature_name : mfem_feature_names if ( mfem_features.get(feature_name) and feature_name != 'openmp' and not source_capable.get(feature_name, false) ) uses_unmodelled_system_tpl = true endif endforeach if ( not system_mfem.found() and effective_allow_preinstalled and dependency_prefix == '' and uses_unmodelled_system_tpl ) error( 'The selected features need external TPLs, but no complete compatible system MFEM was found. ' + 'Provide one coherent -Ddependency_prefix=/path/to/tpls so the source MFEM usage interface remains reproducible.' ) endif if not system_mfem.found() and is_windows error( 'The source fallback currently targets POSIX and Emscripten toolchains. ' + 'On Windows, provide a complete compatible MFEM installation and use -Dallow_preinstalled=true.' ) endif mfem_runtime_prefix = '' mfem_build_target = [] mpi_launcher_from_dependency = false if system_mfem.found() mfem_dep = system_mfem else mfem_source = subproject('mfem').get_variable('mfem_source_dir') mpich_source = '' hypre_source = '' metis_source = '' gslib_source = '' zlib_source = '' sundials_source = '' libceed_source = '' fms_source = '' algoim_source = '' blitz_source = '' dependency_has_mpi = dependency_prefix != '' and ( fs.exists(dependency_prefix / 'bin' / 'mpicc') and fs.exists(dependency_prefix / 'bin' / 'mpicxx') ) dependency_has_hypre = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'HYPRE_config.h' ) dependency_has_metis = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'metis.h' ) dependency_has_gslib = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'gslib' / 'gslib.h' ) dependency_has_zlib = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'zlib.h' ) dependency_has_sundials = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'sundials' / 'sundials_config.h' ) dependency_has_ceed = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'ceed.h' ) dependency_has_fms = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'fms.h' ) dependency_has_algoim = dependency_prefix != '' and fs.exists( dependency_prefix / 'include' / 'algoim_quad.hpp' ) and fs.exists(dependency_prefix / 'include' / 'blitz' / 'array.h') build_mpi_from_source = mfem_has_mpi and can_build_posix_mpi and not dependency_has_mpi mpi_launcher_from_dependency = mfem_has_mpi and dependency_has_mpi if build_mpi_from_source mpich_source = subproject('mpich').get_variable('mpich_source_dir') endif if mfem_has_mpi and (build_mpi_from_source or not dependency_has_hypre) hypre_source = subproject('hypre').get_variable('hypre_source_dir') endif if mfem_has_metis and not dependency_has_metis metis_source = subproject('metis').get_variable('metis_source_dir') endif if mfem_has_gslib and (build_mpi_from_source or not dependency_has_gslib) gslib_source = subproject('gslib').get_variable('gslib_source_dir') endif if mfem_has_zlib and not dependency_has_zlib zlib_source = subproject('zlib').get_variable('zlib_source_dir') endif if mfem_has_sundials and (build_mpi_from_source or not dependency_has_sundials) sundials_source = subproject('sundials').get_variable('sundials_source_dir') endif if mfem_features.get('ceed') and not dependency_has_ceed libceed_source = subproject('libceed').get_variable('libceed_source_dir') endif if mfem_features.get('fms') and not dependency_has_fms fms_source = subproject('fms').get_variable('fms_source_dir') endif if mfem_features.get('algoim') and not dependency_has_algoim algoim_source = subproject('algoim').get_variable('algoim_source_dir') blitz_source = subproject('blitz').get_variable('blitz_source_dir') endif bundle_is_python_package = get_option('build_python') and get_option('python_install_native') bundle_output_name = bundle_is_python_package ? 'meson_mfem_template' : 'mfem-prefix' mfem_runtime_prefix = meson.current_build_dir() / bundle_output_name bundle_work_dir = meson.current_build_dir() / '_bundle' / 'work' bundle_builder = files('../../tools/build_mfem_bundle.py') bundle_auxiliary_files = files('../../tools/ceed_jit_source_root_relocatable.c') cc_command = cc.cmd_array() cxx_command = cpp.cmd_array() known_compiler_launchers = ['ccache', 'sccache', 'distcc'] cc_executable = '' cc_launchers = [] cc_fixed_args = [] foreach command_part : cc_command if cc_executable == '' and fs.name(command_part) in known_compiler_launchers cc_launchers += [command_part] elif cc_executable == '' cc_executable = command_part else cc_fixed_args += [command_part] endif endforeach cxx_executable = '' cxx_launchers = [] cxx_fixed_args = [] foreach command_part : cxx_command if cxx_executable == '' and fs.name(command_part) in known_compiler_launchers cxx_launchers += [command_part] elif cxx_executable == '' cxx_executable = command_part else cxx_fixed_args += [command_part] endif endforeach if cc_executable == '' or cxx_executable == '' error('Could not identify the C/C++ compiler executables in Meson compiler commands.') endif bundle_command = [ python_build, bundle_builder, '--source', mfem_source, '--work-dir', bundle_work_dir, '--prefix', '@OUTPUT@', '--cmake', cmake_program, '--cc', cc_executable, '--cxx', cxx_executable, '--buildtype', get_option('buildtype'), '--jobs', get_option('jobs').to_string(), '--host-system', host_machine.system(), '--cross-build', meson.is_cross_build() ? 'true' : 'false', '--library-kind', is_wasm ? 'static' : 'shared', '--cuda-arch', get_option('mfem_cuda_arch'), '--hip-arch', get_option('mfem_hip_arch'), '--precision', get_option('mfem_precision'), '--dependency-prefix', dependency_prefix, '--allow-system', effective_allow_preinstalled ? 'true' : 'false', '--vendor-dependency-prefix', wheel_carries_native_bundle ? 'true' : 'false', ] foreach compiler_launcher : cc_launchers bundle_command += ['--cc-launcher=' + compiler_launcher] endforeach foreach compiler_launcher : cxx_launchers bundle_command += ['--cxx-launcher=' + compiler_launcher] endforeach foreach c_arg : cc_fixed_args bundle_command += ['--c-arg=' + c_arg] endforeach foreach c_arg : get_option('c_args') bundle_command += ['--c-arg=' + c_arg] endforeach foreach c_arg : platform_c_args bundle_command += ['--c-arg=' + c_arg] endforeach foreach cpp_arg : get_option('cpp_args') bundle_command += ['--cxx-arg=' + cpp_arg] endforeach foreach cpp_arg : cxx_fixed_args bundle_command += ['--cxx-arg=' + cpp_arg] endforeach foreach cpp_arg : platform_cpp_args bundle_command += ['--cxx-arg=' + cpp_arg] endforeach foreach c_link_arg : get_option('c_link_args') bundle_command += ['--c-link-arg=' + c_link_arg] endforeach foreach cpp_link_arg : get_option('cpp_link_args') bundle_command += ['--cxx-link-arg=' + cpp_link_arg] endforeach foreach platform_link_arg : platform_link_args bundle_command += ['--c-link-arg=' + platform_link_arg] bundle_command += ['--cxx-link-arg=' + platform_link_arg] endforeach foreach i : range(mfem_feature_names.length()) bundle_command += [ '--feature', mfem_feature_names[i] + '=' + (mfem_feature_states[i] ? 'ON' : 'OFF'), ] endforeach foreach source_pair : [ ['mpich', mpich_source], ['hypre', hypre_source], ['metis', metis_source], ['gslib', gslib_source], ['zlib', zlib_source], ['sundials', sundials_source], ['libceed', libceed_source], ['fms', fms_source], ['algoim', algoim_source], ['blitz', blitz_source], ] if source_pair[1] != '' bundle_command += ['--' + source_pair[0] + '-source', source_pair[1]] endif endforeach if bundle_is_python_package and get_option('install_mfem') mfem_build_target = custom_target( 'mfem-source-bundle', output: bundle_output_name, command: bundle_command, depend_files: bundle_auxiliary_files, build_by_default: true, build_always_stale: dependency_prefix != '', console: true, install: true, install_dir: python_build.get_install_dir(), install_tag: 'python-native', ) else mfem_build_target = custom_target( 'mfem-source-bundle', output: bundle_output_name, command: bundle_command, depend_files: bundle_auxiliary_files, build_by_default: true, build_always_stale: dependency_prefix != '', console: true, ) endif bundle_compile_args = ['-I' + mfem_runtime_prefix / 'include'] bundle_link_args = [ '-L' + mfem_runtime_prefix / 'lib', '-L' + mfem_runtime_prefix / 'lib64', ] if dependency_prefix != '' and not wheel_carries_native_bundle bundle_compile_args += ['-I' + dependency_prefix / 'include'] bundle_link_args += [ '-L' + dependency_prefix / 'lib', '-L' + dependency_prefix / 'lib64', ] endif bundle_link_args += ['-lmfem'] if mfem_has_mpi bundle_link_args += ['-lHYPRE', '-lmpi'] endif if mfem_has_metis bundle_link_args += ['-lmetis'] endif if mfem_has_gslib bundle_link_args += ['-lgs'] endif if mfem_has_zlib bundle_link_args += ['-lz'] endif if mfem_has_sundials bundle_link_args += [ '-lsundials_nvecserial', '-lsundials_cvodes', '-lsundials_arkode', '-lsundials_kinsol', '-lsundials_core', ] if mfem_has_mpi bundle_link_args += [ '-lsundials_nvecparallel', '-lsundials_nvecmpiplusx', ] endif endif if mfem_features.get('ceed') bundle_link_args += ['-lceed'] endif if mfem_features.get('fms') bundle_link_args += ['-lfms'] endif if mfem_features.get('algoim') bundle_link_args += ['-lblitz'] endif mfem_dep_parts = [] if mfem_has_openmp or mfem_features.get('legacy_openmp') mfem_dep_parts += [openmp_dep] endif mfem_dep = declare_dependency( compile_args: bundle_compile_args, link_args: bundle_link_args, dependencies: mfem_dep_parts, sources: mfem_build_target, version: '4.10', variables: { 'prefix': mfem_runtime_prefix, 'includedir': mfem_runtime_prefix / 'include', 'libdir': mfem_runtime_prefix / 'lib', }, ) if get_option('install_mfem') and not bundle_is_python_package install_bundle = files('../../tools/install_bundle.py') meson.add_install_script( python_build, install_bundle, '--source', mfem_runtime_prefix, '--destination', get_option('prefix'), install_tag: 'runtime', ) endif endif if get_option('build_python') and not get_option('python_install_native') and not system_mfem.found() error('A source-built Python extension requires -Dpython_install_native=true so its runtime libraries are included in the wheel.') endif if get_option('build_python') and get_option('python_install_native') and not get_option('install_mfem') error('A self-contained Python wheel requires -Dinstall_mfem=true so the native bundle is installed.') endif meson.override_dependency('mfem', mfem_dep)