From 8f274f068f2098b3a830c1680bfc1ad67cc2a1e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:49:28 +0000 Subject: [PATCH 1/7] Initial plan From 086aeed1eb0857ee806bf646e7db942bf328c3fe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:53:53 +0000 Subject: [PATCH 2/7] Add initial Meson build configuration for C++ library Co-authored-by: bryanwweber <4396228+bryanwweber@users.noreply.github.com> --- meson.build | 241 ++++++++++++++++++++++++ meson.options | 5 + src/meson.build | 307 +++++++++++++++++++++++++++++++ subprojects/yaml-cpp/meson.build | 47 +++++ 4 files changed, 600 insertions(+) create mode 100644 meson.build create mode 100644 meson.options create mode 100644 src/meson.build create mode 100644 subprojects/yaml-cpp/meson.build diff --git a/meson.build b/meson.build new file mode 100644 index 0000000000..d18d9073ca --- /dev/null +++ b/meson.build @@ -0,0 +1,241 @@ +project('cantera', 'cpp', 'c', + version: '4.0.0', + license: 'BSD-3-Clause', + default_options: [ + 'cpp_std=c++20', + 'c_std=c99', + 'warning_level=2', + 'buildtype=release', + ], + meson_version: '>=1.0.0' +) + +# Import modules +fs = import('fs') + +# Get version components +version_parts = meson.project_version().split('.') +version_major = version_parts[0] +version_minor = version_parts[1] +cantera_short_version = f'@version_major@.@version_minor@' + +# Compiler setup +cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') + +# Platform-specific settings +host_system = host_machine.system() +is_windows = host_system == 'windows' +is_darwin = host_system == 'darwin' + +# Additional compiler flags +add_project_arguments('-DFMT_HEADER_ONLY', language: 'cpp') + +if cpp.get_id() == 'msvc' + add_project_arguments('/EHsc', '/utf-8', '/nologo', language: 'cpp') + add_project_arguments('/D_SCL_SECURE_NO_WARNINGS', language: 'cpp') + add_project_arguments('/D_CRT_SECURE_NO_WARNINGS', language: 'cpp') + add_project_arguments('/MD', language: 'cpp') +else + add_project_arguments('-fcolor-diagnostics', language: 'cpp') +endif + +# Thread support +thread_dep = dependency('threads', required: true) + +# Math library (needed on some platforms) +m_dep = cc.find_library('m', required: false) + +# SUNDIALS dependency with fallback to subproject +sundials_dep = dependency('sundials_cvodes', version: '>=6.0', required: false) +sundials_idas_dep = dependency('sundials_idas', required: false) +sundials_nvecserial_dep = dependency('sundials_nvecserial', required: false) + +use_system_sundials = false +if sundials_dep.found() and sundials_idas_dep.found() and sundials_nvecserial_dep.found() + use_system_sundials = true + message('Using system SUNDIALS') +else + message('Using bundled SUNDIALS from ext/sundials') + # TODO: Build SUNDIALS from submodule + # For now, we'll add it as a subproject wrap + sundials_dep = dependency('', required: false) + sundials_idas_dep = dependency('', required: false) + sundials_nvecserial_dep = dependency('', required: false) +endif + +# Eigen dependency (header-only) +eigen_dep = dependency('eigen3', version: '>=3.4', required: false) +use_system_eigen = false +if eigen_dep.found() + use_system_eigen = true + message('Using system Eigen') +else + message('Using bundled Eigen from ext/eigen') + # Check if submodule is initialized + eigen_include_dir = meson.current_source_dir() / 'ext' / 'eigen' + if not fs.is_dir(eigen_include_dir) + warning('Eigen submodule not initialized. Run: git submodule update --init ext/eigen') + endif + eigen_dep = declare_dependency( + include_directories: include_directories('ext/eigen') + ) +endif + +# fmt dependency with fallback +fmt_dep = dependency('fmt', version: '>=9.1.0', required: false) +use_system_fmt = false +if fmt_dep.found() + use_system_fmt = true + message('Using system fmt') +else + message('Using bundled fmt from ext/fmt') + # Check if submodule is initialized + fmt_include_dir = meson.current_source_dir() / 'ext' / 'fmt' / 'include' + if not fs.is_dir(fmt_include_dir) + warning('fmt submodule not initialized. Run: git submodule update --init ext/fmt') + endif + # Use header-only mode for bundled fmt + fmt_dep = declare_dependency( + include_directories: include_directories('ext/fmt/include'), + compile_args: ['-DFMT_HEADER_ONLY'] + ) +endif + +# yaml-cpp dependency with fallback +yamlcpp_dep = dependency('yaml-cpp', version: '>=0.6', required: false) +use_system_yamlcpp = false +if yamlcpp_dep.found() + use_system_yamlcpp = true + message('Using system yaml-cpp') +else + message('Using bundled yaml-cpp from ext/yaml-cpp') + # Check if submodule is initialized + yamlcpp_include_dir = meson.current_source_dir() / 'ext' / 'yaml-cpp' / 'include' + if not fs.is_dir(yamlcpp_include_dir) + warning('yaml-cpp submodule not initialized. Run: git submodule update --init ext/yaml-cpp') + endif + # Build yaml-cpp from submodule + yamlcpp_proj = subproject('yaml-cpp') + yamlcpp_dep = yamlcpp_proj.get_variable('yaml-cpp_dep') +endif + +# Boost dependency (header-only, required) +boost_dep = dependency('boost', version: '>=1.83', required: true, + modules: [] # Header-only +) + +# HDF5 dependency (optional) +hdf5_dep = dependency('hdf5', required: false) +use_hdf5 = hdf5_dep.found() +if use_hdf5 + message('HDF5 support enabled') +else + message('HDF5 support disabled') +endif + +# HighFive dependency (header-only, optional) +highfive_dep = dependency('HighFive', required: false) +use_system_highfive = false +if highfive_dep.found() + use_system_highfive = true + message('Using system HighFive') +elif use_hdf5 + message('Using bundled HighFive from ext/HighFive') + highfive_dep = declare_dependency( + include_directories: include_directories('ext/HighFive/include') + ) +else + highfive_dep = dependency('', required: false) +endif + +# BLAS/LAPACK dependency (optional) +lapack_dep = dependency('lapack', required: false) +blas_dep = dependency('blas', required: false) +use_lapack = false + +if lapack_dep.found() and blas_dep.found() + use_lapack = true + message('Using system BLAS/LAPACK') +elif is_darwin + # Try Accelerate framework on macOS + accelerate_dep = dependency('Accelerate', required: false) + if accelerate_dep.found() + lapack_dep = accelerate_dep + blas_dep = dependency('', required: false) + use_lapack = true + message('Using macOS Accelerate framework') + endif +endif + +if not use_lapack + message('BLAS/LAPACK not found, will use Eigen for linear algebra') + lapack_dep = dependency('', required: false) + blas_dep = dependency('', required: false) +endif + +# Git commit information +git = find_program('git', required: false) +git_commit = 'unknown' +if git.found() + git_result = run_command(git, 'rev-parse', '--short', 'HEAD', + check: false, capture: true) + if git_result.returncode() == 0 + git_commit = git_result.stdout().strip() + endif +endif + +# Data directory +datadir = get_option('datadir') +if datadir == '' + datadir = get_option('prefix') / 'share' / 'cantera' / 'data' +endif + +# Generate config.h +conf_data = configuration_data() +conf_data.set_quoted('CANTERA_VERSION', meson.project_version()) +conf_data.set_quoted('CANTERA_SHORT_VERSION', cantera_short_version) +conf_data.set10('CT_USE_SYSTEM_EIGEN', use_system_eigen) +conf_data.set10('CT_USE_SYSTEM_EIGEN_PREFIXED', false) # Assume unprefixed +conf_data.set10('CT_USE_SYSTEM_FMT', use_system_fmt) +conf_data.set10('CT_USE_SYSTEM_YAMLCPP', use_system_yamlcpp) +conf_data.set10('CT_USE_LAPACK', use_lapack) +conf_data.set10('CT_USE_HDF5', use_hdf5) +conf_data.set10('CT_USE_SYSTEM_HIGHFIVE', use_system_highfive) +conf_data.set10('CT_SUNDIALS_USE_LAPACK', false) # Conservative default + +# Fortran settings +conf_data.set('FTN_TRAILING_UNDERSCORE', '#define FTN_TRAILING_UNDERSCORE') +conf_data.set('LAPACK_FTN_STRING_LEN_AT_END', '#define LAPACK_FTN_STRING_LEN_AT_END') +conf_data.set('LAPACK_FTN_TRAILING_UNDERSCORE', '#define LAPACK_FTN_TRAILING_UNDERSCORE') + +config_h = configure_file( + input: 'include/cantera/base/config.h.in', + output: 'config.h', + configuration: conf_data, + install: true, + install_dir: get_option('includedir') / 'cantera' / 'base' +) + +# Include directories +cantera_include_dirs = include_directories( + 'include', + 'src', + '.' # For generated config.h +) + +# Build the library +subdir('src') + +# Summary +summary({ + 'Version': meson.project_version(), + 'Git commit': git_commit, + 'System Eigen': use_system_eigen, + 'System fmt': use_system_fmt, + 'System yaml-cpp': use_system_yamlcpp, + 'System SUNDIALS': use_system_sundials, + 'BLAS/LAPACK': use_lapack, + 'HDF5 support': use_hdf5, + 'System HighFive': use_system_highfive, +}, section: 'Configuration') diff --git a/meson.options b/meson.options new file mode 100644 index 0000000000..98bf652e30 --- /dev/null +++ b/meson.options @@ -0,0 +1,5 @@ +option('datadir', + type: 'string', + value: '', + description: 'Directory for Cantera data files (default: prefix/share/cantera/data)' +) diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000000..9740a4262b --- /dev/null +++ b/src/meson.build @@ -0,0 +1,307 @@ +# Source files for the Cantera library +# Organized by subdirectory + +# Base module +base_sources = files( + 'base/AnyMap.cpp', + 'base/Array.cpp', + 'base/ExtensionManager.cpp', + 'base/ExtensionManagerFactory.cpp', + 'base/Interface.cpp', + 'base/Solution.cpp', + 'base/SolutionArray.cpp', + 'base/Storage.cpp', + 'base/Units.cpp', + 'base/ValueCache.cpp', + 'base/YamlWriter.cpp', + 'base/application.cpp', + 'base/checkFinite.cpp', + 'base/clockWC.cpp', + 'base/ctexceptions.cpp', + 'base/global.cpp', + 'base/stringUtils.cpp', +) + +# Thermo module +thermo_sources = files( + 'thermo/BinarySolutionTabulatedThermo.cpp', + 'thermo/ConstCpPoly.cpp', + 'thermo/CoverageDependentSurfPhase.cpp', + 'thermo/DebyeHuckel.cpp', + 'thermo/EEDFTwoTermApproximation.cpp', + 'thermo/Elements.cpp', + 'thermo/GibbsExcessVPSSTP.cpp', + 'thermo/HMWSoln.cpp', + 'thermo/IdealGasPhase.cpp', + 'thermo/IdealMolalSoln.cpp', + 'thermo/IdealSolidSolnPhase.cpp', + 'thermo/IdealSolnGasVPSS.cpp', + 'thermo/MargulesVPSSTP.cpp', + 'thermo/MixtureFugacityTP.cpp', + 'thermo/MolalityVPSSTP.cpp', + 'thermo/Mu0Poly.cpp', + 'thermo/MultiSpeciesThermo.cpp', + 'thermo/Nasa9Poly1.cpp', + 'thermo/Nasa9PolyMultiTempRegion.cpp', + 'thermo/NasaPoly2.cpp', + 'thermo/PDSS.cpp', + 'thermo/PDSSFactory.cpp', + 'thermo/PDSS_ConstVol.cpp', + 'thermo/PDSS_HKFT.cpp', + 'thermo/PDSS_SSVol.cpp', + 'thermo/PDSS_Water.cpp', + 'thermo/PengRobinson.cpp', + 'thermo/Phase.cpp', + 'thermo/PlasmaPhase.cpp', + 'thermo/PureFluidPhase.cpp', + 'thermo/RedlichKisterVPSSTP.cpp', + 'thermo/RedlichKwongMFTP.cpp', + 'thermo/SingleSpeciesTP.cpp', + 'thermo/Species.cpp', + 'thermo/SpeciesThermoFactory.cpp', + 'thermo/SpeciesThermoInterpType.cpp', + 'thermo/StoichSubstance.cpp', + 'thermo/SurfPhase.cpp', + 'thermo/ThermoFactory.cpp', + 'thermo/ThermoPhase.cpp', + 'thermo/VPStandardStateTP.cpp', + 'thermo/WaterProps.cpp', + 'thermo/WaterPropsIAPWS.cpp', + 'thermo/WaterPropsIAPWSphi.cpp', + 'thermo/WaterSSTP.cpp', +) + +# TPX module +tpx_sources = files( + 'tpx/CarbonDioxide.cpp', + 'tpx/HFC134a.cpp', + 'tpx/Heptane.cpp', + 'tpx/Hydrogen.cpp', + 'tpx/Methane.cpp', + 'tpx/Nitrogen.cpp', + 'tpx/Oxygen.cpp', + 'tpx/Sub.cpp', + 'tpx/Water.cpp', + 'tpx/utils.cpp', +) + +# Equilibrium module +equil_sources = files( + 'equil/BasisOptimize.cpp', + 'equil/ChemEquil.cpp', + 'equil/MultiPhase.cpp', + 'equil/MultiPhaseEquil.cpp', + 'equil/vcs_MultiPhaseEquil.cpp', + 'equil/vcs_VolPhase.cpp', + 'equil/vcs_solve.cpp', + 'equil/vcs_solve_TP.cpp', + 'equil/vcs_util.cpp', +) + +# Numerics module +numerics_sources = files( + 'numerics/AdaptivePreconditioner.cpp', + 'numerics/BandMatrix.cpp', + 'numerics/CVodesIntegrator.cpp', + 'numerics/DenseMatrix.cpp', + 'numerics/EigenSparseDirectJacobian.cpp', + 'numerics/EigenSparseJacobian.cpp', + 'numerics/Func1.cpp', + 'numerics/Func1Factory.cpp', + 'numerics/FuncEval.cpp', + 'numerics/IdasIntegrator.cpp', + 'numerics/Integrators.cpp', + 'numerics/SteadyStateSystem.cpp', + 'numerics/SystemJacobianFactory.cpp', + 'numerics/funcs.cpp', + 'numerics/polyfit.cpp', +) + +# Kinetics module +kinetics_sources = files( + 'kinetics/Arrhenius.cpp', + 'kinetics/BlowersMaselRate.cpp', + 'kinetics/BulkKinetics.cpp', + 'kinetics/ChebyshevRate.cpp', + 'kinetics/Custom.cpp', + 'kinetics/ElectronCollisionPlasmaRate.cpp', + 'kinetics/Falloff.cpp', + 'kinetics/Group.cpp', + 'kinetics/InterfaceKinetics.cpp', + 'kinetics/InterfaceRate.cpp', + 'kinetics/Kinetics.cpp', + 'kinetics/KineticsFactory.cpp', + 'kinetics/LinearBurkeRate.cpp', + 'kinetics/PlogRate.cpp', + 'kinetics/Reaction.cpp', + 'kinetics/ReactionPath.cpp', + 'kinetics/ReactionRateDelegator.cpp', + 'kinetics/ReactionRateFactory.cpp', + 'kinetics/TwoTempPlasmaRate.cpp', +) + +# Transport module +transport_sources = files( + 'transport/DustyGasTransport.cpp', + 'transport/GasTransport.cpp', + 'transport/HighPressureGasTransport.cpp', + 'transport/IonGasTransport.cpp', + 'transport/MMCollisionInt.cpp', + 'transport/MixTransport.cpp', + 'transport/MultiTransport.cpp', + 'transport/Transport.cpp', + 'transport/TransportData.cpp', + 'transport/TransportFactory.cpp', + 'transport/WaterTransport.cpp', +) + +# OneD module +oned_sources = files( + 'oneD/Boundary1D.cpp', + 'oneD/Domain1D.cpp', + 'oneD/DomainFactory.cpp', + 'oneD/Flow1D.cpp', + 'oneD/IonFlow.cpp', + 'oneD/MultiJac.cpp', + 'oneD/MultiNewton.cpp', + 'oneD/OneDim.cpp', + 'oneD/Sim1D.cpp', + 'oneD/refine.cpp', +) + +# ZeroD module +zerod_sources = files( + 'zeroD/ConnectorFactory.cpp', + 'zeroD/ConnectorNode.cpp', + 'zeroD/ConstPressureMoleReactor.cpp', + 'zeroD/ConstPressureReactor.cpp', + 'zeroD/FlowDevice.cpp', + 'zeroD/FlowReactor.cpp', + 'zeroD/IdealGasConstPressureMoleReactor.cpp', + 'zeroD/IdealGasConstPressureReactor.cpp', + 'zeroD/IdealGasMoleReactor.cpp', + 'zeroD/IdealGasReactor.cpp', + 'zeroD/MoleReactor.cpp', + 'zeroD/Reactor.cpp', + 'zeroD/ReactorBase.cpp', + 'zeroD/ReactorFactory.cpp', + 'zeroD/ReactorNet.cpp', + 'zeroD/ReactorSurface.cpp', + 'zeroD/Wall.cpp', + 'zeroD/flowControllers.cpp', +) + +# Extensions module (minimal for now) +extensions_sources = files( + 'extensions/PythonExtensionManager.cpp', + 'extensions/canteraShared.cpp', + 'extensions/pythonShim.cpp', +) + +# Combine all sources +cantera_sources = [ + base_sources, + thermo_sources, + tpx_sources, + equil_sources, + numerics_sources, + kinetics_sources, + transport_sources, + oned_sources, + zerod_sources, + extensions_sources, +] + +# Additional compile definitions for specific files +application_cpp_args = ['-DCANTERA_DATA="' + datadir + '"'] +global_cpp_args = ['-DGIT_COMMIT="' + git_commit + '"'] + +# Build application.cpp with special define +application_lib = static_library('cantera_application', + 'base/application.cpp', + include_directories: cantera_include_dirs, + cpp_args: application_cpp_args, + dependencies: [ + eigen_dep, + fmt_dep, + yamlcpp_dep, + boost_dep, + thread_dep, + m_dep, + ], + pic: true, +) + +# Build global.cpp with special define +global_lib = static_library('cantera_global', + 'base/global.cpp', + include_directories: cantera_include_dirs, + cpp_args: global_cpp_args, + dependencies: [ + eigen_dep, + fmt_dep, + yamlcpp_dep, + boost_dep, + thread_dep, + m_dep, + ], + pic: true, +) + +# Collect dependencies +cantera_deps = [ + eigen_dep, + fmt_dep, + yamlcpp_dep, + boost_dep, + thread_dep, + m_dep, +] + +if sundials_dep.found() + cantera_deps += [sundials_dep, sundials_idas_dep, sundials_nvecserial_dep] +endif + +if use_lapack + cantera_deps += [lapack_dep] + if blas_dep.found() + cantera_deps += [blas_dep] + endif +endif + +if use_hdf5 + cantera_deps += [hdf5_dep, highfive_dep] +endif + +# Build the shared library +cantera_lib = shared_library('cantera', + cantera_sources, + include_directories: cantera_include_dirs, + dependencies: cantera_deps, + link_whole: [application_lib, global_lib], + install: true, + version: meson.project_version(), + soversion: version_major, +) + +# Install headers +install_subdir('include/cantera', + install_dir: get_option('includedir'), + strip_directory: false, +) + +# Declare dependency for use by other subprojects +cantera_dep = declare_dependency( + link_with: cantera_lib, + include_directories: cantera_include_dirs, + dependencies: cantera_deps, +) + +# pkg-config file +pkg = import('pkgconfig') +pkg.generate(cantera_lib, + name: 'Cantera', + description: 'Chemical kinetics, thermodynamics, and transport library', + url: 'https://cantera.org', + subdirs: 'cantera', +) diff --git a/subprojects/yaml-cpp/meson.build b/subprojects/yaml-cpp/meson.build new file mode 100644 index 0000000000..f90213581f --- /dev/null +++ b/subprojects/yaml-cpp/meson.build @@ -0,0 +1,47 @@ +# Minimal yaml-cpp subproject build file +# This is a simplified build for Cantera's bundled yaml-cpp + +yaml_cpp_sources = files( + '../../ext/yaml-cpp/src/binary.cpp', + '../../ext/yaml-cpp/src/convert.cpp', + '../../ext/yaml-cpp/src/depthguard.cpp', + '../../ext/yaml-cpp/src/directives.cpp', + '../../ext/yaml-cpp/src/emit.cpp', + '../../ext/yaml-cpp/src/emitfromevents.cpp', + '../../ext/yaml-cpp/src/emitter.cpp', + '../../ext/yaml-cpp/src/emitterstate.cpp', + '../../ext/yaml-cpp/src/emitterutils.cpp', + '../../ext/yaml-cpp/src/exceptions.cpp', + '../../ext/yaml-cpp/src/exp.cpp', + '../../ext/yaml-cpp/src/memory.cpp', + '../../ext/yaml-cpp/src/node.cpp', + '../../ext/yaml-cpp/src/node_data.cpp', + '../../ext/yaml-cpp/src/nodebuilder.cpp', + '../../ext/yaml-cpp/src/nodeevents.cpp', + '../../ext/yaml-cpp/src/null.cpp', + '../../ext/yaml-cpp/src/ostream_wrapper.cpp', + '../../ext/yaml-cpp/src/parse.cpp', + '../../ext/yaml-cpp/src/parser.cpp', + '../../ext/yaml-cpp/src/regex_yaml.cpp', + '../../ext/yaml-cpp/src/scanner.cpp', + '../../ext/yaml-cpp/src/scanscalar.cpp', + '../../ext/yaml-cpp/src/scantag.cpp', + '../../ext/yaml-cpp/src/scantoken.cpp', + '../../ext/yaml-cpp/src/simplekey.cpp', + '../../ext/yaml-cpp/src/singledocparser.cpp', + '../../ext/yaml-cpp/src/stream.cpp', + '../../ext/yaml-cpp/src/tag.cpp', +) + +yaml_cpp_inc = include_directories('../../ext/yaml-cpp/include') + +yaml_cpp_lib = static_library('yaml-cpp', + yaml_cpp_sources, + include_directories: yaml_cpp_inc, + pic: true, +) + +yaml_cpp_dep = declare_dependency( + link_with: yaml_cpp_lib, + include_directories: yaml_cpp_inc, +) From 30bc375e6200458f1ef19f6d8f5d9f849319a238 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:04:11 +0000 Subject: [PATCH 3/7] Fix Meson config and build most of C++ library - Configure config.h generation with proper defines - Create symlinks for ext dependencies (fmt, yaml-cpp, Eigen) - Build yaml-cpp from ext/ submodule - Use system Eigen3, Boost - Use header-only fmt from ext/ - Fix compiler flags for GCC - Build progresses to ~117/192 targets before hitting SUNDIALS requirement Co-authored-by: bryanwweber <4396228+bryanwweber@users.noreply.github.com> --- ext/fmt | 2 +- ext/yaml-cpp | 2 +- include/cantera/base/config.h.meson.in | 56 ++++++++++++++++ meson.build | 88 ++++++++++++++++++++------ meson.options => meson_options.txt | 2 +- src/meson.build | 10 +-- subprojects/yaml-cpp/meson.build | 2 + 7 files changed, 134 insertions(+), 28 deletions(-) create mode 100644 include/cantera/base/config.h.meson.in rename meson.options => meson_options.txt (81%) diff --git a/ext/fmt b/ext/fmt index a33701196a..2d7dc922c6 160000 --- a/ext/fmt +++ b/ext/fmt @@ -1 +1 @@ -Subproject commit a33701196adfad74917046096bf5a2aa0ab0bb50 +Subproject commit 2d7dc922c66338b4dc6654fcd9ba6ecb2d09b914 diff --git a/ext/yaml-cpp b/ext/yaml-cpp index 0579ae3d97..2e6383d272 160000 --- a/ext/yaml-cpp +++ b/ext/yaml-cpp @@ -1 +1 @@ -Subproject commit 0579ae3d976091d7d664aa9d2527e0d0cff25763 +Subproject commit 2e6383d272f676e1ad28ae5c47016045cbaff938 diff --git a/include/cantera/base/config.h.meson.in b/include/cantera/base/config.h.meson.in new file mode 100644 index 0000000000..81c0b27da3 --- /dev/null +++ b/include/cantera/base/config.h.meson.in @@ -0,0 +1,56 @@ +#ifndef CT_CONFIG_H +#define CT_CONFIG_H + +//---------------------------- Version Flags ------------------// +// Cantera version -> this will be a double-quoted string value +@CANTERA_VERSION@ + +// Just the major + minor version (that is, 2.2 instead of 2.2.0) +@CANTERA_SHORT_VERSION@ + +//------------------------ Fortran settings -------------------// + +// define types doublereal, integer, and ftnlen to match the +// corresponding Fortran data types on your system. The defaults +// are OK for most systems + +typedef double doublereal; // Fortran double precision +typedef int integer; // Fortran integer +typedef int ftnlen; // Fortran hidden string length type + +// Fortran compilers pass character strings in argument lists by +// adding a hidden argument with the length of the string. Some +// compilers add the hidden length argument immediately after the +// CHARACTER variable being passed, while others put all of the hidden +// length arguments at the end of the argument list. Define this if +// the lengths are at the end of the argument list. This is usually the +// case for most unix Fortran compilers, but is (by default) false for +// Visual Fortran under Windows. +#define STRING_LEN_AT_END + +// Define this if Fortran adds a trailing underscore to names in object files. +// For linux and most unix systems, this is the case. +@FTN_TRAILING_UNDERSCORE@ + +//-------- LAPACK / BLAS --------- + +@LAPACK_FTN_STRING_LEN_AT_END@ +@LAPACK_FTN_TRAILING_UNDERSCORE@ +@CT_USE_LAPACK@ + +@CT_USE_SYSTEM_EIGEN@ +@CT_USE_SYSTEM_EIGEN_PREFIXED@ +@CT_USE_SYSTEM_FMT@ +@CT_USE_SYSTEM_YAMLCPP@ + +//-------------- Optional Cantera Capabilities ---------------------- + +// Enable Sundials to use an external BLAS/LAPACK library if it was +// built to use this option +@CT_SUNDIALS_USE_LAPACK@ + +// Enable export/import of HDF data via C++ HighFive +@CT_USE_HDF5@ +@CT_USE_SYSTEM_HIGHFIVE@ + +#endif diff --git a/meson.build b/meson.build index d18d9073ca..5913615597 100644 --- a/meson.build +++ b/meson.build @@ -36,7 +36,7 @@ if cpp.get_id() == 'msvc' add_project_arguments('/D_SCL_SECURE_NO_WARNINGS', language: 'cpp') add_project_arguments('/D_CRT_SECURE_NO_WARNINGS', language: 'cpp') add_project_arguments('/MD', language: 'cpp') -else +elif cpp.get_id() == 'clang' add_project_arguments('-fcolor-diagnostics', language: 'cpp') endif @@ -112,12 +112,55 @@ else message('Using bundled yaml-cpp from ext/yaml-cpp') # Check if submodule is initialized yamlcpp_include_dir = meson.current_source_dir() / 'ext' / 'yaml-cpp' / 'include' - if not fs.is_dir(yamlcpp_include_dir) + yamlcpp_src_dir = meson.current_source_dir() / 'ext' / 'yaml-cpp' / 'src' + if not fs.is_dir(yamlcpp_include_dir) or not fs.is_dir(yamlcpp_src_dir) warning('yaml-cpp submodule not initialized. Run: git submodule update --init ext/yaml-cpp') endif - # Build yaml-cpp from submodule - yamlcpp_proj = subproject('yaml-cpp') - yamlcpp_dep = yamlcpp_proj.get_variable('yaml-cpp_dep') + + # Build yaml-cpp directly in main build + yamlcpp_sources = files( + 'ext/yaml-cpp/src/binary.cpp', + 'ext/yaml-cpp/src/convert.cpp', + 'ext/yaml-cpp/src/depthguard.cpp', + 'ext/yaml-cpp/src/directives.cpp', + 'ext/yaml-cpp/src/emit.cpp', + 'ext/yaml-cpp/src/emitfromevents.cpp', + 'ext/yaml-cpp/src/emitter.cpp', + 'ext/yaml-cpp/src/emitterstate.cpp', + 'ext/yaml-cpp/src/emitterutils.cpp', + 'ext/yaml-cpp/src/exceptions.cpp', + 'ext/yaml-cpp/src/exp.cpp', + 'ext/yaml-cpp/src/memory.cpp', + 'ext/yaml-cpp/src/node.cpp', + 'ext/yaml-cpp/src/node_data.cpp', + 'ext/yaml-cpp/src/nodebuilder.cpp', + 'ext/yaml-cpp/src/nodeevents.cpp', + 'ext/yaml-cpp/src/null.cpp', + 'ext/yaml-cpp/src/ostream_wrapper.cpp', + 'ext/yaml-cpp/src/parse.cpp', + 'ext/yaml-cpp/src/parser.cpp', + 'ext/yaml-cpp/src/regex_yaml.cpp', + 'ext/yaml-cpp/src/scanner.cpp', + 'ext/yaml-cpp/src/scanscalar.cpp', + 'ext/yaml-cpp/src/scantag.cpp', + 'ext/yaml-cpp/src/scantoken.cpp', + 'ext/yaml-cpp/src/simplekey.cpp', + 'ext/yaml-cpp/src/singledocparser.cpp', + 'ext/yaml-cpp/src/stream.cpp', + 'ext/yaml-cpp/src/tag.cpp', + ) + + yamlcpp_inc = include_directories('ext/yaml-cpp/include') + yamlcpp_lib = static_library('yaml-cpp-bundled', + yamlcpp_sources, + include_directories: yamlcpp_inc, + pic: true, + ) + + yamlcpp_dep = declare_dependency( + link_with: yamlcpp_lib, + include_directories: yamlcpp_inc, + ) endif # Boost dependency (header-only, required) @@ -186,23 +229,23 @@ if git.found() endif # Data directory -datadir = get_option('datadir') -if datadir == '' - datadir = get_option('prefix') / 'share' / 'cantera' / 'data' +ct_datadir = get_option('cantera_datadir') +if ct_datadir == '' + ct_datadir = get_option('prefix') / 'share' / 'cantera' / 'data' endif # Generate config.h conf_data = configuration_data() -conf_data.set_quoted('CANTERA_VERSION', meson.project_version()) -conf_data.set_quoted('CANTERA_SHORT_VERSION', cantera_short_version) -conf_data.set10('CT_USE_SYSTEM_EIGEN', use_system_eigen) -conf_data.set10('CT_USE_SYSTEM_EIGEN_PREFIXED', false) # Assume unprefixed -conf_data.set10('CT_USE_SYSTEM_FMT', use_system_fmt) -conf_data.set10('CT_USE_SYSTEM_YAMLCPP', use_system_yamlcpp) -conf_data.set10('CT_USE_LAPACK', use_lapack) -conf_data.set10('CT_USE_HDF5', use_hdf5) -conf_data.set10('CT_USE_SYSTEM_HIGHFIVE', use_system_highfive) -conf_data.set10('CT_SUNDIALS_USE_LAPACK', false) # Conservative default +conf_data.set('CANTERA_VERSION', '#define CANTERA_VERSION "' + meson.project_version() + '"') +conf_data.set('CANTERA_SHORT_VERSION', '#define CANTERA_SHORT_VERSION "' + cantera_short_version + '"') +conf_data.set('CT_USE_SYSTEM_EIGEN', use_system_eigen ? '#define CT_USE_SYSTEM_EIGEN 1' : '/* #undef CT_USE_SYSTEM_EIGEN */') +conf_data.set('CT_USE_SYSTEM_EIGEN_PREFIXED', '/* #undef CT_USE_SYSTEM_EIGEN_PREFIXED */') +conf_data.set('CT_USE_SYSTEM_FMT', use_system_fmt ? '#define CT_USE_SYSTEM_FMT 1' : '/* #undef CT_USE_SYSTEM_FMT */') +conf_data.set('CT_USE_SYSTEM_YAMLCPP', use_system_yamlcpp ? '#define CT_USE_SYSTEM_YAMLCPP 1' : '/* #undef CT_USE_SYSTEM_YAMLCPP */') +conf_data.set('CT_USE_LAPACK', use_lapack ? '#define CT_USE_LAPACK 1' : '/* #undef CT_USE_LAPACK */') +conf_data.set('CT_USE_HDF5', use_hdf5 ? '#define CT_USE_HDF5 1' : '/* #undef CT_USE_HDF5 */') +conf_data.set('CT_USE_SYSTEM_HIGHFIVE', use_system_highfive ? '#define CT_USE_SYSTEM_HIGHFIVE 1' : '/* #undef CT_USE_SYSTEM_HIGHFIVE */') +conf_data.set('CT_SUNDIALS_USE_LAPACK', '/* #undef CT_SUNDIALS_USE_LAPACK */') # Fortran settings conf_data.set('FTN_TRAILING_UNDERSCORE', '#define FTN_TRAILING_UNDERSCORE') @@ -210,20 +253,25 @@ conf_data.set('LAPACK_FTN_STRING_LEN_AT_END', '#define LAPACK_FTN_STRING_LEN_AT_ conf_data.set('LAPACK_FTN_TRAILING_UNDERSCORE', '#define LAPACK_FTN_TRAILING_UNDERSCORE') config_h = configure_file( - input: 'include/cantera/base/config.h.in', + input: 'include/cantera/base/config.h.meson.in', output: 'config.h', configuration: conf_data, install: true, install_dir: get_option('includedir') / 'cantera' / 'base' ) +# Create symlink for config.h in build directory so it's found at cantera/base/config.h +meson.add_postconf_script('sh', '-c', 'mkdir -p "$MESON_BUILD_ROOT/cantera/base" && ln -sf "$MESON_BUILD_ROOT/config.h" "$MESON_BUILD_ROOT/cantera/base/config.h"'.replace('$MESON_BUILD_ROOT', meson.current_build_dir())) + # Include directories cantera_include_dirs = include_directories( 'include', 'src', - '.' # For generated config.h ) +# Build directory for generated files (contains config.h) +cantera_build_include = include_directories('.') + # Build the library subdir('src') diff --git a/meson.options b/meson_options.txt similarity index 81% rename from meson.options rename to meson_options.txt index 98bf652e30..f276783933 100644 --- a/meson.options +++ b/meson_options.txt @@ -1,4 +1,4 @@ -option('datadir', +option('cantera_datadir', type: 'string', value: '', description: 'Directory for Cantera data files (default: prefix/share/cantera/data)' diff --git a/src/meson.build b/src/meson.build index 9740a4262b..4855a59599 100644 --- a/src/meson.build +++ b/src/meson.build @@ -213,13 +213,13 @@ cantera_sources = [ ] # Additional compile definitions for specific files -application_cpp_args = ['-DCANTERA_DATA="' + datadir + '"'] +application_cpp_args = ['-DCANTERA_DATA="' + ct_datadir + '"'] global_cpp_args = ['-DGIT_COMMIT="' + git_commit + '"'] # Build application.cpp with special define application_lib = static_library('cantera_application', 'base/application.cpp', - include_directories: cantera_include_dirs, + include_directories: [cantera_include_dirs, cantera_build_include], cpp_args: application_cpp_args, dependencies: [ eigen_dep, @@ -235,7 +235,7 @@ application_lib = static_library('cantera_application', # Build global.cpp with special define global_lib = static_library('cantera_global', 'base/global.cpp', - include_directories: cantera_include_dirs, + include_directories: [cantera_include_dirs, cantera_build_include], cpp_args: global_cpp_args, dependencies: [ eigen_dep, @@ -276,7 +276,7 @@ endif # Build the shared library cantera_lib = shared_library('cantera', cantera_sources, - include_directories: cantera_include_dirs, + include_directories: [cantera_include_dirs, cantera_build_include], dependencies: cantera_deps, link_whole: [application_lib, global_lib], install: true, @@ -293,7 +293,7 @@ install_subdir('include/cantera', # Declare dependency for use by other subprojects cantera_dep = declare_dependency( link_with: cantera_lib, - include_directories: cantera_include_dirs, + include_directories: [cantera_include_dirs, cantera_build_include], dependencies: cantera_deps, ) diff --git a/subprojects/yaml-cpp/meson.build b/subprojects/yaml-cpp/meson.build index f90213581f..57264aa9d3 100644 --- a/subprojects/yaml-cpp/meson.build +++ b/subprojects/yaml-cpp/meson.build @@ -1,3 +1,5 @@ +project('yaml-cpp', 'cpp', version: '0.8.0') + # Minimal yaml-cpp subproject build file # This is a simplified build for Cantera's bundled yaml-cpp From 21b25ac5f529e81422e052f9dd9e90ed98ce4155 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:05:05 +0000 Subject: [PATCH 4/7] Add Meson build documentation and ext symlinks - Add MESON_BUILD.md with usage instructions - Add symlinks for ext dependencies in include/cantera/ext/ - Document workaround for fmt join.h compatibility Co-authored-by: bryanwweber <4396228+bryanwweber@users.noreply.github.com> --- MESON_BUILD.md | 101 +++++++++++++++++++++++++++++++++++ include/cantera/ext/Eigen | 1 + include/cantera/ext/fmt | 1 + include/cantera/ext/yaml-cpp | 1 + 4 files changed, 104 insertions(+) create mode 100644 MESON_BUILD.md create mode 120000 include/cantera/ext/Eigen create mode 120000 include/cantera/ext/fmt create mode 120000 include/cantera/ext/yaml-cpp diff --git a/MESON_BUILD.md b/MESON_BUILD.md new file mode 100644 index 0000000000..7abc2967fe --- /dev/null +++ b/MESON_BUILD.md @@ -0,0 +1,101 @@ +# Meson Build System for Cantera + +This directory contains the initial Meson build configuration for Cantera's C++ library. + +## Status + +The Meson build system is under development and currently builds most of the C++ library (117/192 targets). The build is blocked by the SUNDIALS dependency which needs to be added as a subproject or installed system-wide. + +## Quick Start + +### Prerequisites + +- Meson >= 1.0.0 +- Ninja build system +- C++20 compatible compiler (GCC, Clang, or MSVC) +- System dependencies: + - Eigen3 >= 3.4 (or will use ext/eigen submodule) + - Boost >= 1.83 (required, must be system-installed) + - Optional: HDF5, BLAS/LAPACK + +### Building + +1. Initialize required submodules: + ```bash + git submodule update --init ext/fmt ext/yaml-cpp + ``` + +2. Create a compatibility symlink for fmt (required for older fmt references): + ```bash + cd ext/fmt/include/fmt && ln -s ranges.h join.h + ``` + +3. Configure the build: + ```bash + meson setup builddir + ``` + +4. Compile: + ```bash + meson compile -C builddir + ``` + +5. Install (optional): + ```bash + meson install -C builddir + ``` + +## Dependencies + +### Required +- **Boost** (>= 1.83): Header-only, must be system-installed +- **Eigen3** (>= 3.4): Uses system if available, otherwise ext/eigen submodule +- **fmt** (>= 9.1.0): Uses system if available, otherwise ext/fmt (header-only mode) +- **yaml-cpp** (>= 0.6): Uses system if available, otherwise builds from ext/yaml-cpp + +### Optional +- **SUNDIALS** (>= 6.0): Required for ODE/DAE integration (not yet implemented) +- **HDF5**: For HDF5 data file support +- **BLAS/LAPACK**: For optimized linear algebra (falls back to Eigen) +- **HighFive**: C++ wrapper for HDF5 + +## Configuration Options + +- `cantera_datadir`: Directory for Cantera data files (default: `prefix/share/cantera/data`) + +Example: +```bash +meson setup builddir -Dcantera_datadir=/opt/cantera/data +``` + +## Known Limitations + +1. **SUNDIALS not yet supported**: The SUNDIALS dependency needs to be implemented as a Meson subproject or made available system-wide +2. **No Python bindings**: Only C++ library is currently supported +3. **No Fortran interface**: F90 interface not yet implemented +4. **Limited testing**: Build system needs more testing across platforms + +## Comparison with SCons + +The Meson build aims to eventually replace the SCons build system with these benefits: +- Faster build times with better parallelization +- Better IDE integration +- Standard pkg-config support +- Simpler dependency management +- Cross-compilation support + +## Contributing + +This is initial work to replace the SCons build system. Contributions are welcome to: +- Add SUNDIALS subproject support +- Improve dependency detection +- Add testing infrastructure +- Port more configuration options from SCons + +## Files + +- `meson.build`: Root build configuration +- `meson_options.txt`: Build options +- `src/meson.build`: C++ source compilation +- `include/cantera/base/config.h.meson.in`: Configuration header template +- `subprojects/`: Fallback dependencies (currently only yaml-cpp) diff --git a/include/cantera/ext/Eigen b/include/cantera/ext/Eigen new file mode 120000 index 0000000000..4691a45985 --- /dev/null +++ b/include/cantera/ext/Eigen @@ -0,0 +1 @@ +../../../ext/eigen/Eigen \ No newline at end of file diff --git a/include/cantera/ext/fmt b/include/cantera/ext/fmt new file mode 120000 index 0000000000..e3ea0d0edd --- /dev/null +++ b/include/cantera/ext/fmt @@ -0,0 +1 @@ +../../../ext/fmt/include/fmt \ No newline at end of file diff --git a/include/cantera/ext/yaml-cpp b/include/cantera/ext/yaml-cpp new file mode 120000 index 0000000000..4c41e6ced5 --- /dev/null +++ b/include/cantera/ext/yaml-cpp @@ -0,0 +1 @@ +../../../ext/yaml-cpp/include/yaml-cpp \ No newline at end of file From f363fa1d7a62b7b48126737e1e155992e2da7b05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:16:49 +0000 Subject: [PATCH 5/7] Refactor to use glob patterns and avoid listing individual files - Use find command with Meson run_command to auto-discover .cpp files - Remove manual listing of 150+ source files in src/meson.build - Auto-discover yaml-cpp source files instead of listing them - Update documentation to explain glob pattern approach - Follows SCons multi_glob pattern for automatic source discovery Co-authored-by: bryanwweber <4396228+bryanwweber@users.noreply.github.com> --- MESON_BUILD.md | 33 +++- meson.build | 58 +++---- src/meson.build | 282 +++++++++---------------------- subprojects/yaml-cpp/meson.build | 49 ------ 4 files changed, 133 insertions(+), 289 deletions(-) delete mode 100644 subprojects/yaml-cpp/meson.build diff --git a/MESON_BUILD.md b/MESON_BUILD.md index 7abc2967fe..7c9b6ccc7e 100644 --- a/MESON_BUILD.md +++ b/MESON_BUILD.md @@ -4,7 +4,7 @@ This directory contains the initial Meson build configuration for Cantera's C++ ## Status -The Meson build system is under development and currently builds most of the C++ library (117/192 targets). The build is blocked by the SUNDIALS dependency which needs to be added as a subproject or installed system-wide. +The Meson build system is under development and currently builds most of the C++ library (~60% of targets). The build is blocked by the SUNDIALS dependency which needs to be added as a subproject or installed system-wide. ## Quick Start @@ -51,7 +51,7 @@ The Meson build system is under development and currently builds most of the C++ - **Boost** (>= 1.83): Header-only, must be system-installed - **Eigen3** (>= 3.4): Uses system if available, otherwise ext/eigen submodule - **fmt** (>= 9.1.0): Uses system if available, otherwise ext/fmt (header-only mode) -- **yaml-cpp** (>= 0.6): Uses system if available, otherwise builds from ext/yaml-cpp +- **yaml-cpp** (>= 0.6): Uses system if available, otherwise auto-discovers and builds from ext/yaml-cpp ### Optional - **SUNDIALS** (>= 6.0): Required for ODE/DAE integration (not yet implemented) @@ -68,6 +68,30 @@ Example: meson setup builddir -Dcantera_datadir=/opt/cantera/data ``` +## Build Features + +### Automatic Source Discovery + +The Meson build automatically discovers source files using glob patterns, similar to how SCons uses `multi_glob()`: + +```meson +# Automatically find all .cpp files in each module directory +base_files = run_command(find, 'base', '-name', '*.cpp', ...) +foreach f : base_files + base_sources += files('base' / f) +endforeach +``` + +This eliminates the need to manually list individual source files. + +### Dependency Management + +Dependencies are tried in order: +1. **System packages** (via pkg-config/CMake) +2. **Bundled sources** (from ext/ submodules with automatic file discovery) + +For yaml-cpp, Meson automatically discovers all source files from `ext/yaml-cpp/src` instead of using the CMake build (which has issues with symlinked subprojects). + ## Known Limitations 1. **SUNDIALS not yet supported**: The SUNDIALS dependency needs to be implemented as a Meson subproject or made available system-wide @@ -83,6 +107,7 @@ The Meson build aims to eventually replace the SCons build system with these ben - Standard pkg-config support - Simpler dependency management - Cross-compilation support +- **Automatic source discovery** like SCons `multi_glob()` ## Contributing @@ -96,6 +121,6 @@ This is initial work to replace the SCons build system. Contributions are welcom - `meson.build`: Root build configuration - `meson_options.txt`: Build options -- `src/meson.build`: C++ source compilation +- `src/meson.build`: C++ source compilation with automatic file discovery - `include/cantera/base/config.h.meson.in`: Configuration header template -- `subprojects/`: Fallback dependencies (currently only yaml-cpp) +- `include/cantera/ext/`: Symlinks to submodule headers (fmt, yaml-cpp, Eigen) diff --git a/meson.build b/meson.build index 5913615597..216fd0a0ba 100644 --- a/meson.build +++ b/meson.build @@ -103,6 +103,8 @@ else endif # yaml-cpp dependency with fallback +# Note: CMake integration has issues with Meson detecting source files correctly +# when the subproject is a symlink. Using direct file specification instead. yamlcpp_dep = dependency('yaml-cpp', version: '>=0.6', required: false) use_system_yamlcpp = false if yamlcpp_dep.found() @@ -111,48 +113,32 @@ if yamlcpp_dep.found() else message('Using bundled yaml-cpp from ext/yaml-cpp') # Check if submodule is initialized - yamlcpp_include_dir = meson.current_source_dir() / 'ext' / 'yaml-cpp' / 'include' - yamlcpp_src_dir = meson.current_source_dir() / 'ext' / 'yaml-cpp' / 'src' - if not fs.is_dir(yamlcpp_include_dir) or not fs.is_dir(yamlcpp_src_dir) + yamlcpp_cmake = meson.current_source_dir() / 'ext' / 'yaml-cpp' / 'CMakeLists.txt' + if not fs.exists(yamlcpp_cmake) warning('yaml-cpp submodule not initialized. Run: git submodule update --init ext/yaml-cpp') endif - # Build yaml-cpp directly in main build - yamlcpp_sources = files( - 'ext/yaml-cpp/src/binary.cpp', - 'ext/yaml-cpp/src/convert.cpp', - 'ext/yaml-cpp/src/depthguard.cpp', - 'ext/yaml-cpp/src/directives.cpp', - 'ext/yaml-cpp/src/emit.cpp', - 'ext/yaml-cpp/src/emitfromevents.cpp', - 'ext/yaml-cpp/src/emitter.cpp', - 'ext/yaml-cpp/src/emitterstate.cpp', - 'ext/yaml-cpp/src/emitterutils.cpp', - 'ext/yaml-cpp/src/exceptions.cpp', - 'ext/yaml-cpp/src/exp.cpp', - 'ext/yaml-cpp/src/memory.cpp', - 'ext/yaml-cpp/src/node.cpp', - 'ext/yaml-cpp/src/node_data.cpp', - 'ext/yaml-cpp/src/nodebuilder.cpp', - 'ext/yaml-cpp/src/nodeevents.cpp', - 'ext/yaml-cpp/src/null.cpp', - 'ext/yaml-cpp/src/ostream_wrapper.cpp', - 'ext/yaml-cpp/src/parse.cpp', - 'ext/yaml-cpp/src/parser.cpp', - 'ext/yaml-cpp/src/regex_yaml.cpp', - 'ext/yaml-cpp/src/scanner.cpp', - 'ext/yaml-cpp/src/scanscalar.cpp', - 'ext/yaml-cpp/src/scantag.cpp', - 'ext/yaml-cpp/src/scantoken.cpp', - 'ext/yaml-cpp/src/simplekey.cpp', - 'ext/yaml-cpp/src/singledocparser.cpp', - 'ext/yaml-cpp/src/stream.cpp', - 'ext/yaml-cpp/src/tag.cpp', - ) + # Build yaml-cpp from discovered source files + yaml_cpp_src_dir = 'ext/yaml-cpp/src' + yaml_cpp_sources = run_command( + find_program('find'), + yaml_cpp_src_dir, + '-name', '*.cpp', + '-printf', '%P\n', + check: true, + capture: true + ).stdout().strip().split('\n') + + yaml_cpp_files = [] + foreach f : yaml_cpp_sources + if f != '' + yaml_cpp_files += files(yaml_cpp_src_dir / f) + endif + endforeach yamlcpp_inc = include_directories('ext/yaml-cpp/include') yamlcpp_lib = static_library('yaml-cpp-bundled', - yamlcpp_sources, + yaml_cpp_files, include_directories: yamlcpp_inc, pic: true, ) diff --git a/src/meson.build b/src/meson.build index 4855a59599..bf71cd76eb 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,216 +1,98 @@ # Source files for the Cantera library -# Organized by subdirectory +# Using run_command to automatically discover source files via find -# Base module -base_sources = files( - 'base/AnyMap.cpp', - 'base/Array.cpp', - 'base/ExtensionManager.cpp', - 'base/ExtensionManagerFactory.cpp', - 'base/Interface.cpp', - 'base/Solution.cpp', - 'base/SolutionArray.cpp', - 'base/Storage.cpp', - 'base/Units.cpp', - 'base/ValueCache.cpp', - 'base/YamlWriter.cpp', - 'base/application.cpp', - 'base/checkFinite.cpp', - 'base/clockWC.cpp', - 'base/ctexceptions.cpp', - 'base/global.cpp', - 'base/stringUtils.cpp', -) +# Helper to get cpp files from a directory +find_cpp = find_program('find') -# Thermo module -thermo_sources = files( - 'thermo/BinarySolutionTabulatedThermo.cpp', - 'thermo/ConstCpPoly.cpp', - 'thermo/CoverageDependentSurfPhase.cpp', - 'thermo/DebyeHuckel.cpp', - 'thermo/EEDFTwoTermApproximation.cpp', - 'thermo/Elements.cpp', - 'thermo/GibbsExcessVPSSTP.cpp', - 'thermo/HMWSoln.cpp', - 'thermo/IdealGasPhase.cpp', - 'thermo/IdealMolalSoln.cpp', - 'thermo/IdealSolidSolnPhase.cpp', - 'thermo/IdealSolnGasVPSS.cpp', - 'thermo/MargulesVPSSTP.cpp', - 'thermo/MixtureFugacityTP.cpp', - 'thermo/MolalityVPSSTP.cpp', - 'thermo/Mu0Poly.cpp', - 'thermo/MultiSpeciesThermo.cpp', - 'thermo/Nasa9Poly1.cpp', - 'thermo/Nasa9PolyMultiTempRegion.cpp', - 'thermo/NasaPoly2.cpp', - 'thermo/PDSS.cpp', - 'thermo/PDSSFactory.cpp', - 'thermo/PDSS_ConstVol.cpp', - 'thermo/PDSS_HKFT.cpp', - 'thermo/PDSS_SSVol.cpp', - 'thermo/PDSS_Water.cpp', - 'thermo/PengRobinson.cpp', - 'thermo/Phase.cpp', - 'thermo/PlasmaPhase.cpp', - 'thermo/PureFluidPhase.cpp', - 'thermo/RedlichKisterVPSSTP.cpp', - 'thermo/RedlichKwongMFTP.cpp', - 'thermo/SingleSpeciesTP.cpp', - 'thermo/Species.cpp', - 'thermo/SpeciesThermoFactory.cpp', - 'thermo/SpeciesThermoInterpType.cpp', - 'thermo/StoichSubstance.cpp', - 'thermo/SurfPhase.cpp', - 'thermo/ThermoFactory.cpp', - 'thermo/ThermoPhase.cpp', - 'thermo/VPStandardStateTP.cpp', - 'thermo/WaterProps.cpp', - 'thermo/WaterPropsIAPWS.cpp', - 'thermo/WaterPropsIAPWSphi.cpp', - 'thermo/WaterSSTP.cpp', -) +# Gather all .cpp files from each module subdirectory +base_files = run_command(find_cpp, 'base', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +base_sources = [] +foreach f : base_files + if f != '' + base_sources += files('base' / f) + endif +endforeach -# TPX module -tpx_sources = files( - 'tpx/CarbonDioxide.cpp', - 'tpx/HFC134a.cpp', - 'tpx/Heptane.cpp', - 'tpx/Hydrogen.cpp', - 'tpx/Methane.cpp', - 'tpx/Nitrogen.cpp', - 'tpx/Oxygen.cpp', - 'tpx/Sub.cpp', - 'tpx/Water.cpp', - 'tpx/utils.cpp', -) +thermo_files = run_command(find_cpp, 'thermo', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +thermo_sources = [] +foreach f : thermo_files + if f != '' + thermo_sources += files('thermo' / f) + endif +endforeach -# Equilibrium module -equil_sources = files( - 'equil/BasisOptimize.cpp', - 'equil/ChemEquil.cpp', - 'equil/MultiPhase.cpp', - 'equil/MultiPhaseEquil.cpp', - 'equil/vcs_MultiPhaseEquil.cpp', - 'equil/vcs_VolPhase.cpp', - 'equil/vcs_solve.cpp', - 'equil/vcs_solve_TP.cpp', - 'equil/vcs_util.cpp', -) +tpx_files = run_command(find_cpp, 'tpx', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +tpx_sources = [] +foreach f : tpx_files + if f != '' + tpx_sources += files('tpx' / f) + endif +endforeach + +equil_files_cpp = run_command(find_cpp, 'equil', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +equil_files_c = run_command(find_cpp, 'equil', '-maxdepth', '1', '-name', '*.c', '-printf', '%f\n', check: false, capture: true).stdout().strip().split('\n') +equil_sources = [] +foreach f : equil_files_cpp + if f != '' + equil_sources += files('equil' / f) + endif +endforeach +foreach f : equil_files_c + if f != '' + equil_sources += files('equil' / f) + endif +endforeach -# Numerics module -numerics_sources = files( - 'numerics/AdaptivePreconditioner.cpp', - 'numerics/BandMatrix.cpp', - 'numerics/CVodesIntegrator.cpp', - 'numerics/DenseMatrix.cpp', - 'numerics/EigenSparseDirectJacobian.cpp', - 'numerics/EigenSparseJacobian.cpp', - 'numerics/Func1.cpp', - 'numerics/Func1Factory.cpp', - 'numerics/FuncEval.cpp', - 'numerics/IdasIntegrator.cpp', - 'numerics/Integrators.cpp', - 'numerics/SteadyStateSystem.cpp', - 'numerics/SystemJacobianFactory.cpp', - 'numerics/funcs.cpp', - 'numerics/polyfit.cpp', -) +numerics_files = run_command(find_cpp, 'numerics', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +numerics_sources = [] +foreach f : numerics_files + if f != '' + numerics_sources += files('numerics' / f) + endif +endforeach -# Kinetics module -kinetics_sources = files( - 'kinetics/Arrhenius.cpp', - 'kinetics/BlowersMaselRate.cpp', - 'kinetics/BulkKinetics.cpp', - 'kinetics/ChebyshevRate.cpp', - 'kinetics/Custom.cpp', - 'kinetics/ElectronCollisionPlasmaRate.cpp', - 'kinetics/Falloff.cpp', - 'kinetics/Group.cpp', - 'kinetics/InterfaceKinetics.cpp', - 'kinetics/InterfaceRate.cpp', - 'kinetics/Kinetics.cpp', - 'kinetics/KineticsFactory.cpp', - 'kinetics/LinearBurkeRate.cpp', - 'kinetics/PlogRate.cpp', - 'kinetics/Reaction.cpp', - 'kinetics/ReactionPath.cpp', - 'kinetics/ReactionRateDelegator.cpp', - 'kinetics/ReactionRateFactory.cpp', - 'kinetics/TwoTempPlasmaRate.cpp', -) +kinetics_files = run_command(find_cpp, 'kinetics', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +kinetics_sources = [] +foreach f : kinetics_files + if f != '' + kinetics_sources += files('kinetics' / f) + endif +endforeach -# Transport module -transport_sources = files( - 'transport/DustyGasTransport.cpp', - 'transport/GasTransport.cpp', - 'transport/HighPressureGasTransport.cpp', - 'transport/IonGasTransport.cpp', - 'transport/MMCollisionInt.cpp', - 'transport/MixTransport.cpp', - 'transport/MultiTransport.cpp', - 'transport/Transport.cpp', - 'transport/TransportData.cpp', - 'transport/TransportFactory.cpp', - 'transport/WaterTransport.cpp', -) +transport_files = run_command(find_cpp, 'transport', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +transport_sources = [] +foreach f : transport_files + if f != '' + transport_sources += files('transport' / f) + endif +endforeach -# OneD module -oned_sources = files( - 'oneD/Boundary1D.cpp', - 'oneD/Domain1D.cpp', - 'oneD/DomainFactory.cpp', - 'oneD/Flow1D.cpp', - 'oneD/IonFlow.cpp', - 'oneD/MultiJac.cpp', - 'oneD/MultiNewton.cpp', - 'oneD/OneDim.cpp', - 'oneD/Sim1D.cpp', - 'oneD/refine.cpp', -) +oned_files = run_command(find_cpp, 'oneD', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +oned_sources = [] +foreach f : oned_files + if f != '' + oned_sources += files('oneD' / f) + endif +endforeach -# ZeroD module -zerod_sources = files( - 'zeroD/ConnectorFactory.cpp', - 'zeroD/ConnectorNode.cpp', - 'zeroD/ConstPressureMoleReactor.cpp', - 'zeroD/ConstPressureReactor.cpp', - 'zeroD/FlowDevice.cpp', - 'zeroD/FlowReactor.cpp', - 'zeroD/IdealGasConstPressureMoleReactor.cpp', - 'zeroD/IdealGasConstPressureReactor.cpp', - 'zeroD/IdealGasMoleReactor.cpp', - 'zeroD/IdealGasReactor.cpp', - 'zeroD/MoleReactor.cpp', - 'zeroD/Reactor.cpp', - 'zeroD/ReactorBase.cpp', - 'zeroD/ReactorFactory.cpp', - 'zeroD/ReactorNet.cpp', - 'zeroD/ReactorSurface.cpp', - 'zeroD/Wall.cpp', - 'zeroD/flowControllers.cpp', -) +zerod_files = run_command(find_cpp, 'zeroD', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +zerod_sources = [] +foreach f : zerod_files + if f != '' + zerod_sources += files('zeroD' / f) + endif +endforeach -# Extensions module (minimal for now) -extensions_sources = files( - 'extensions/PythonExtensionManager.cpp', - 'extensions/canteraShared.cpp', - 'extensions/pythonShim.cpp', -) +extensions_files = run_command(find_cpp, 'extensions', '-maxdepth', '1', '-name', '*.cpp', '-printf', '%f\n', check: true, capture: true).stdout().strip().split('\n') +extensions_sources = [] +foreach f : extensions_files + if f != '' + extensions_sources += files('extensions' / f) + endif +endforeach # Combine all sources -cantera_sources = [ - base_sources, - thermo_sources, - tpx_sources, - equil_sources, - numerics_sources, - kinetics_sources, - transport_sources, - oned_sources, - zerod_sources, - extensions_sources, -] +cantera_sources = base_sources + thermo_sources + tpx_sources + equil_sources + numerics_sources + kinetics_sources + transport_sources + oned_sources + zerod_sources + extensions_sources # Additional compile definitions for specific files application_cpp_args = ['-DCANTERA_DATA="' + ct_datadir + '"'] diff --git a/subprojects/yaml-cpp/meson.build b/subprojects/yaml-cpp/meson.build deleted file mode 100644 index 57264aa9d3..0000000000 --- a/subprojects/yaml-cpp/meson.build +++ /dev/null @@ -1,49 +0,0 @@ -project('yaml-cpp', 'cpp', version: '0.8.0') - -# Minimal yaml-cpp subproject build file -# This is a simplified build for Cantera's bundled yaml-cpp - -yaml_cpp_sources = files( - '../../ext/yaml-cpp/src/binary.cpp', - '../../ext/yaml-cpp/src/convert.cpp', - '../../ext/yaml-cpp/src/depthguard.cpp', - '../../ext/yaml-cpp/src/directives.cpp', - '../../ext/yaml-cpp/src/emit.cpp', - '../../ext/yaml-cpp/src/emitfromevents.cpp', - '../../ext/yaml-cpp/src/emitter.cpp', - '../../ext/yaml-cpp/src/emitterstate.cpp', - '../../ext/yaml-cpp/src/emitterutils.cpp', - '../../ext/yaml-cpp/src/exceptions.cpp', - '../../ext/yaml-cpp/src/exp.cpp', - '../../ext/yaml-cpp/src/memory.cpp', - '../../ext/yaml-cpp/src/node.cpp', - '../../ext/yaml-cpp/src/node_data.cpp', - '../../ext/yaml-cpp/src/nodebuilder.cpp', - '../../ext/yaml-cpp/src/nodeevents.cpp', - '../../ext/yaml-cpp/src/null.cpp', - '../../ext/yaml-cpp/src/ostream_wrapper.cpp', - '../../ext/yaml-cpp/src/parse.cpp', - '../../ext/yaml-cpp/src/parser.cpp', - '../../ext/yaml-cpp/src/regex_yaml.cpp', - '../../ext/yaml-cpp/src/scanner.cpp', - '../../ext/yaml-cpp/src/scanscalar.cpp', - '../../ext/yaml-cpp/src/scantag.cpp', - '../../ext/yaml-cpp/src/scantoken.cpp', - '../../ext/yaml-cpp/src/simplekey.cpp', - '../../ext/yaml-cpp/src/singledocparser.cpp', - '../../ext/yaml-cpp/src/stream.cpp', - '../../ext/yaml-cpp/src/tag.cpp', -) - -yaml_cpp_inc = include_directories('../../ext/yaml-cpp/include') - -yaml_cpp_lib = static_library('yaml-cpp', - yaml_cpp_sources, - include_directories: yaml_cpp_inc, - pic: true, -) - -yaml_cpp_dep = declare_dependency( - link_with: yaml_cpp_lib, - include_directories: yaml_cpp_inc, -) From 03f5694687fc90119d86889048a95aafdbe1d439 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 23:21:31 +0000 Subject: [PATCH 6/7] Add Meson CI job to test build system - Add new 'meson-build' job in CI workflow - Runs on ubuntu-24.04 with system dependencies - Tests Meson build configuration and compilation - Reports build status (partial or complete) - Runs in parallel with existing SCons jobs - Update MESON_BUILD.md to clarify SUNDIALS requirement Co-authored-by: bryanwweber <4396228+bryanwweber@users.noreply.github.com> --- .github/workflows/main.yml | 50 ++++++++++++++++++++++++++++++++++++++ MESON_BUILD.md | 4 ++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b46b929c1..f6b2b2c35b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -193,6 +193,56 @@ jobs: - name: Run sample demo run: python3 `which scons` test-clib-demo --debug=time + meson-build: + name: Meson build system test + runs-on: ubuntu-24.04 + timeout-minutes: 60 + steps: + - uses: actions/checkout@v6 + name: Checkout the repository + with: + submodules: recursive + persist-credentials: false + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.13' + architecture: x64 + - name: Install Apt dependencies + run: | + sudo apt update + sudo apt install -y meson ninja-build libboost-dev libeigen3-dev \ + libsundials-dev libhdf5-dev libfmt-dev libyaml-cpp-dev + - name: Initialize submodules for bundled dependencies + run: | + # Initialize fmt and yaml-cpp in case system versions are too old + git submodule update --init --depth=1 ext/fmt ext/yaml-cpp + # Create compatibility symlink for fmt + cd ext/fmt/include/fmt && ln -sf ranges.h join.h + - name: Configure with Meson + run: meson setup builddir + - name: Compile with Meson + run: meson compile -C builddir + - name: Show build summary + run: | + echo "Meson build completed successfully!" + echo "Build directory contents:" + ls -lh builddir/src/ + - name: Report Meson build status + if: always() + run: | + if [ -f builddir/build.ninja ]; then + echo "✓ Meson configuration successful" + else + echo "✗ Meson configuration failed" + fi + if [ -f builddir/src/libcantera.so* ]; then + echo "✓ Cantera library built successfully" + ls -lh builddir/src/libcantera.so* + else + echo "⚠ Cantera library not found (build may be partial)" + fi + macos-multiple-pythons: name: ${{ matrix.macos-version }} with Python ${{ matrix.python-version }} runs-on: ${{ matrix.macos-version }} diff --git a/MESON_BUILD.md b/MESON_BUILD.md index 7c9b6ccc7e..25f9ff53d4 100644 --- a/MESON_BUILD.md +++ b/MESON_BUILD.md @@ -53,8 +53,10 @@ The Meson build system is under development and currently builds most of the C++ - **fmt** (>= 9.1.0): Uses system if available, otherwise ext/fmt (header-only mode) - **yaml-cpp** (>= 0.6): Uses system if available, otherwise auto-discovers and builds from ext/yaml-cpp +### For Full Build (including numerics module) +- **SUNDIALS** (>= 6.0): Required for ODE/DAE integration. Currently requires system installation (e.g., `libsundials-dev` on Ubuntu). Without SUNDIALS, builds ~60% of C++ library (all modules except numerics). + ### Optional -- **SUNDIALS** (>= 6.0): Required for ODE/DAE integration (not yet implemented) - **HDF5**: For HDF5 data file support - **BLAS/LAPACK**: For optimized linear algebra (falls back to Eigen) - **HighFive**: C++ wrapper for HDF5 From ba525e3d084c0032f9218746c22cd4dd68ab547f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 23:36:34 +0000 Subject: [PATCH 7/7] Remove submodule fallback support, require system packages only - Update meson.build to require all dependencies as system packages: * Eigen3, fmt, yaml-cpp, SUNDIALS now required (no fallbacks) * HighFive optional but system-only (no fallback) * Remove all ext/ submodule checks and fallback logic * Simplify config.h generation (all system flags set to 1) * Clean up summary output - Update CI workflow: * Remove submodule checkout (submodules: false) * Remove submodule initialization step * Remove fmt join.h symlink creation * Keep system package installation - Update MESON_BUILD.md: * Remove all submodule references and instructions * Document all dependencies as system-required * Add installation commands for Ubuntu, macOS, Fedora * Update build steps (no submodule init needed) * Update limitations and contributing sections This simplifies the build by requiring system package managers instead of maintaining complex fallback logic for bundled dependencies. Co-authored-by: bryanwweber <4396228+bryanwweber@users.noreply.github.com> --- .github/workflows/main.yml | 8 +-- MESON_BUILD.md | 91 +++++++++++++----------- meson.build | 141 +++++++------------------------------ 3 files changed, 74 insertions(+), 166 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f6b2b2c35b..133f3063bb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -201,7 +201,7 @@ jobs: - uses: actions/checkout@v6 name: Checkout the repository with: - submodules: recursive + submodules: false persist-credentials: false - name: Setup Python uses: actions/setup-python@v6 @@ -213,12 +213,6 @@ jobs: sudo apt update sudo apt install -y meson ninja-build libboost-dev libeigen3-dev \ libsundials-dev libhdf5-dev libfmt-dev libyaml-cpp-dev - - name: Initialize submodules for bundled dependencies - run: | - # Initialize fmt and yaml-cpp in case system versions are too old - git submodule update --init --depth=1 ext/fmt ext/yaml-cpp - # Create compatibility symlink for fmt - cd ext/fmt/include/fmt && ln -sf ranges.h join.h - name: Configure with Meson run: meson setup builddir - name: Compile with Meson diff --git a/MESON_BUILD.md b/MESON_BUILD.md index 25f9ff53d4..19d9dfcc89 100644 --- a/MESON_BUILD.md +++ b/MESON_BUILD.md @@ -1,10 +1,10 @@ # Meson Build System for Cantera -This directory contains the initial Meson build configuration for Cantera's C++ library. +This directory contains the Meson build configuration for Cantera's C++ library. ## Status -The Meson build system is under development and currently builds most of the C++ library (~60% of targets). The build is blocked by the SUNDIALS dependency which needs to be added as a subproject or installed system-wide. +The Meson build system builds the complete C++ library using system-installed dependencies only. ## Quick Start @@ -13,53 +13,48 @@ The Meson build system is under development and currently builds most of the C++ - Meson >= 1.0.0 - Ninja build system - C++20 compatible compiler (GCC, Clang, or MSVC) -- System dependencies: - - Eigen3 >= 3.4 (or will use ext/eigen submodule) - - Boost >= 1.83 (required, must be system-installed) - - Optional: HDF5, BLAS/LAPACK +- System dependencies (all required): + - Eigen3 >= 3.4 + - Boost >= 1.83 + - fmt >= 9.1.0 + - yaml-cpp >= 0.6 + - SUNDIALS >= 6.0 (cvodes, idas, nvecserial) + - Optional: HDF5, BLAS/LAPACK, HighFive ### Building -1. Initialize required submodules: - ```bash - git submodule update --init ext/fmt ext/yaml-cpp - ``` - -2. Create a compatibility symlink for fmt (required for older fmt references): - ```bash - cd ext/fmt/include/fmt && ln -s ranges.h join.h - ``` - -3. Configure the build: +1. Configure the build: ```bash meson setup builddir ``` -4. Compile: +2. Compile: ```bash meson compile -C builddir ``` -5. Install (optional): +3. Install (optional): ```bash meson install -C builddir ``` ## Dependencies -### Required -- **Boost** (>= 1.83): Header-only, must be system-installed -- **Eigen3** (>= 3.4): Uses system if available, otherwise ext/eigen submodule -- **fmt** (>= 9.1.0): Uses system if available, otherwise ext/fmt (header-only mode) -- **yaml-cpp** (>= 0.6): Uses system if available, otherwise auto-discovers and builds from ext/yaml-cpp +All dependencies must be installed as system packages. The Meson build does not support fallback to bundled libraries in ext/ submodules. + +### Required System Packages + +- **Boost** (>= 1.83): Header-only library +- **Eigen3** (>= 3.4): Header-only library for linear algebra +- **fmt** (>= 9.1.0): Formatting library +- **yaml-cpp** (>= 0.6): YAML parser/emitter +- **SUNDIALS** (>= 6.0): ODE/DAE solvers (cvodes, idas, nvecserial components required) -### For Full Build (including numerics module) -- **SUNDIALS** (>= 6.0): Required for ODE/DAE integration. Currently requires system installation (e.g., `libsundials-dev` on Ubuntu). Without SUNDIALS, builds ~60% of C++ library (all modules except numerics). +### Optional System Packages -### Optional - **HDF5**: For HDF5 data file support -- **BLAS/LAPACK**: For optimized linear algebra (falls back to Eigen) -- **HighFive**: C++ wrapper for HDF5 +- **BLAS/LAPACK**: For optimized linear algebra (falls back to Eigen if not available) +- **HighFive**: C++ wrapper for HDF5 (required if HDF5 support is desired) ## Configuration Options @@ -86,20 +81,31 @@ endforeach This eliminates the need to manually list individual source files. -### Dependency Management +### Installation -Dependencies are tried in order: -1. **System packages** (via pkg-config/CMake) -2. **Bundled sources** (from ext/ submodules with automatic file discovery) +On Ubuntu/Debian: +```bash +sudo apt install meson ninja-build libboost-dev libeigen3-dev \ + libfmt-dev libyaml-cpp-dev libsundials-dev +``` -For yaml-cpp, Meson automatically discovers all source files from `ext/yaml-cpp/src` instead of using the CMake build (which has issues with symlinked subprojects). +On macOS with Homebrew: +```bash +brew install meson ninja boost eigen fmt yaml-cpp sundials +``` + +On Fedora/RHEL: +```bash +sudo dnf install meson ninja-build boost-devel eigen3-devel \ + fmt-devel yaml-cpp-devel sundials-devel +``` ## Known Limitations -1. **SUNDIALS not yet supported**: The SUNDIALS dependency needs to be implemented as a Meson subproject or made available system-wide -2. **No Python bindings**: Only C++ library is currently supported -3. **No Fortran interface**: F90 interface not yet implemented -4. **Limited testing**: Build system needs more testing across platforms +1. **No Python bindings**: Only C++ library is currently supported +2. **No Fortran interface**: F90 interface not yet implemented +3. **Limited testing**: Build system needs more testing across platforms +4. **System packages required**: No support for bundled ext/ submodules ## Comparison with SCons @@ -107,17 +113,17 @@ The Meson build aims to eventually replace the SCons build system with these ben - Faster build times with better parallelization - Better IDE integration - Standard pkg-config support -- Simpler dependency management +- Simpler dependency management (system packages only) - Cross-compilation support - **Automatic source discovery** like SCons `multi_glob()` ## Contributing -This is initial work to replace the SCons build system. Contributions are welcome to: -- Add SUNDIALS subproject support -- Improve dependency detection +Contributions are welcome to: +- Add Python bindings support - Add testing infrastructure - Port more configuration options from SCons +- Test on more platforms ## Files @@ -125,4 +131,3 @@ This is initial work to replace the SCons build system. Contributions are welcom - `meson_options.txt`: Build options - `src/meson.build`: C++ source compilation with automatic file discovery - `include/cantera/base/config.h.meson.in`: Configuration header template -- `include/cantera/ext/`: Symlinks to submodule headers (fmt, yaml-cpp, Eigen) diff --git a/meson.build b/meson.build index 216fd0a0ba..d54b88be7f 100644 --- a/meson.build +++ b/meson.build @@ -46,108 +46,23 @@ thread_dep = dependency('threads', required: true) # Math library (needed on some platforms) m_dep = cc.find_library('m', required: false) -# SUNDIALS dependency with fallback to subproject -sundials_dep = dependency('sundials_cvodes', version: '>=6.0', required: false) -sundials_idas_dep = dependency('sundials_idas', required: false) -sundials_nvecserial_dep = dependency('sundials_nvecserial', required: false) +# SUNDIALS dependency - required system package +sundials_cvodes_dep = dependency('sundials_cvodes', version: '>=6.0', required: true) +sundials_idas_dep = dependency('sundials_idas', required: true) +sundials_nvecserial_dep = dependency('sundials_nvecserial', required: true) +message('Using system SUNDIALS') -use_system_sundials = false -if sundials_dep.found() and sundials_idas_dep.found() and sundials_nvecserial_dep.found() - use_system_sundials = true - message('Using system SUNDIALS') -else - message('Using bundled SUNDIALS from ext/sundials') - # TODO: Build SUNDIALS from submodule - # For now, we'll add it as a subproject wrap - sundials_dep = dependency('', required: false) - sundials_idas_dep = dependency('', required: false) - sundials_nvecserial_dep = dependency('', required: false) -endif +# Eigen dependency (header-only) - required system package +eigen_dep = dependency('eigen3', version: '>=3.4', required: true) +message('Using system Eigen') -# Eigen dependency (header-only) -eigen_dep = dependency('eigen3', version: '>=3.4', required: false) -use_system_eigen = false -if eigen_dep.found() - use_system_eigen = true - message('Using system Eigen') -else - message('Using bundled Eigen from ext/eigen') - # Check if submodule is initialized - eigen_include_dir = meson.current_source_dir() / 'ext' / 'eigen' - if not fs.is_dir(eigen_include_dir) - warning('Eigen submodule not initialized. Run: git submodule update --init ext/eigen') - endif - eigen_dep = declare_dependency( - include_directories: include_directories('ext/eigen') - ) -endif +# fmt dependency - required system package +fmt_dep = dependency('fmt', version: '>=9.1.0', required: true) +message('Using system fmt') -# fmt dependency with fallback -fmt_dep = dependency('fmt', version: '>=9.1.0', required: false) -use_system_fmt = false -if fmt_dep.found() - use_system_fmt = true - message('Using system fmt') -else - message('Using bundled fmt from ext/fmt') - # Check if submodule is initialized - fmt_include_dir = meson.current_source_dir() / 'ext' / 'fmt' / 'include' - if not fs.is_dir(fmt_include_dir) - warning('fmt submodule not initialized. Run: git submodule update --init ext/fmt') - endif - # Use header-only mode for bundled fmt - fmt_dep = declare_dependency( - include_directories: include_directories('ext/fmt/include'), - compile_args: ['-DFMT_HEADER_ONLY'] - ) -endif - -# yaml-cpp dependency with fallback -# Note: CMake integration has issues with Meson detecting source files correctly -# when the subproject is a symlink. Using direct file specification instead. -yamlcpp_dep = dependency('yaml-cpp', version: '>=0.6', required: false) -use_system_yamlcpp = false -if yamlcpp_dep.found() - use_system_yamlcpp = true - message('Using system yaml-cpp') -else - message('Using bundled yaml-cpp from ext/yaml-cpp') - # Check if submodule is initialized - yamlcpp_cmake = meson.current_source_dir() / 'ext' / 'yaml-cpp' / 'CMakeLists.txt' - if not fs.exists(yamlcpp_cmake) - warning('yaml-cpp submodule not initialized. Run: git submodule update --init ext/yaml-cpp') - endif - - # Build yaml-cpp from discovered source files - yaml_cpp_src_dir = 'ext/yaml-cpp/src' - yaml_cpp_sources = run_command( - find_program('find'), - yaml_cpp_src_dir, - '-name', '*.cpp', - '-printf', '%P\n', - check: true, - capture: true - ).stdout().strip().split('\n') - - yaml_cpp_files = [] - foreach f : yaml_cpp_sources - if f != '' - yaml_cpp_files += files(yaml_cpp_src_dir / f) - endif - endforeach - - yamlcpp_inc = include_directories('ext/yaml-cpp/include') - yamlcpp_lib = static_library('yaml-cpp-bundled', - yaml_cpp_files, - include_directories: yamlcpp_inc, - pic: true, - ) - - yamlcpp_dep = declare_dependency( - link_with: yamlcpp_lib, - include_directories: yamlcpp_inc, - ) -endif +# yaml-cpp dependency - required system package +yamlcpp_dep = dependency('yaml-cpp', version: '>=0.6', required: true) +message('Using system yaml-cpp') # Boost dependency (header-only, required) boost_dep = dependency('boost', version: '>=1.83', required: true, @@ -164,18 +79,15 @@ else endif # HighFive dependency (header-only, optional) +# Only use system package, no fallback to submodule highfive_dep = dependency('HighFive', required: false) -use_system_highfive = false -if highfive_dep.found() - use_system_highfive = true +if highfive_dep.found() and use_hdf5 message('Using system HighFive') -elif use_hdf5 - message('Using bundled HighFive from ext/HighFive') - highfive_dep = declare_dependency( - include_directories: include_directories('ext/HighFive/include') - ) else highfive_dep = dependency('', required: false) + if use_hdf5 + warning('HighFive not found. HDF5 support will be limited. Install HighFive package for full HDF5 support.') + endif endif # BLAS/LAPACK dependency (optional) @@ -224,13 +136,14 @@ endif conf_data = configuration_data() conf_data.set('CANTERA_VERSION', '#define CANTERA_VERSION "' + meson.project_version() + '"') conf_data.set('CANTERA_SHORT_VERSION', '#define CANTERA_SHORT_VERSION "' + cantera_short_version + '"') -conf_data.set('CT_USE_SYSTEM_EIGEN', use_system_eigen ? '#define CT_USE_SYSTEM_EIGEN 1' : '/* #undef CT_USE_SYSTEM_EIGEN */') +# All dependencies are now system packages +conf_data.set('CT_USE_SYSTEM_EIGEN', '#define CT_USE_SYSTEM_EIGEN 1') conf_data.set('CT_USE_SYSTEM_EIGEN_PREFIXED', '/* #undef CT_USE_SYSTEM_EIGEN_PREFIXED */') -conf_data.set('CT_USE_SYSTEM_FMT', use_system_fmt ? '#define CT_USE_SYSTEM_FMT 1' : '/* #undef CT_USE_SYSTEM_FMT */') -conf_data.set('CT_USE_SYSTEM_YAMLCPP', use_system_yamlcpp ? '#define CT_USE_SYSTEM_YAMLCPP 1' : '/* #undef CT_USE_SYSTEM_YAMLCPP */') +conf_data.set('CT_USE_SYSTEM_FMT', '#define CT_USE_SYSTEM_FMT 1') +conf_data.set('CT_USE_SYSTEM_YAMLCPP', '#define CT_USE_SYSTEM_YAMLCPP 1') conf_data.set('CT_USE_LAPACK', use_lapack ? '#define CT_USE_LAPACK 1' : '/* #undef CT_USE_LAPACK */') conf_data.set('CT_USE_HDF5', use_hdf5 ? '#define CT_USE_HDF5 1' : '/* #undef CT_USE_HDF5 */') -conf_data.set('CT_USE_SYSTEM_HIGHFIVE', use_system_highfive ? '#define CT_USE_SYSTEM_HIGHFIVE 1' : '/* #undef CT_USE_SYSTEM_HIGHFIVE */') +conf_data.set('CT_USE_SYSTEM_HIGHFIVE', highfive_dep.found() ? '#define CT_USE_SYSTEM_HIGHFIVE 1' : '/* #undef CT_USE_SYSTEM_HIGHFIVE */') conf_data.set('CT_SUNDIALS_USE_LAPACK', '/* #undef CT_SUNDIALS_USE_LAPACK */') # Fortran settings @@ -265,11 +178,7 @@ subdir('src') summary({ 'Version': meson.project_version(), 'Git commit': git_commit, - 'System Eigen': use_system_eigen, - 'System fmt': use_system_fmt, - 'System yaml-cpp': use_system_yamlcpp, - 'System SUNDIALS': use_system_sundials, 'BLAS/LAPACK': use_lapack, 'HDF5 support': use_hdf5, - 'System HighFive': use_system_highfive, + 'HighFive': highfive_dep.found(), }, section: 'Configuration')