From 87468b0f5878e4df7fbb0a18533aee577b514994 Mon Sep 17 00:00:00 2001 From: Benjamin Redelings Date: Wed, 24 Jun 2026 19:29:38 -0700 Subject: [PATCH 1/2] Add Meson build --- meson.build | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 meson.build diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..b1df03ea --- /dev/null +++ b/meson.build @@ -0,0 +1,113 @@ +project('reflex', 'cpp', + version: '6.3.0', + license: 'BSD-3-Clause', + meson_version: '>= 1.1', + default_options: ['cpp_std=c++11']) + +pkg = import('pkgconfig') + +reflex_inc = include_directories('include') + +reflex_headers = files( + 'include/reflex/abslexer.h', + 'include/reflex/absmatcher.h', + 'include/reflex/bits.h', + 'include/reflex/boostmatcher.h', + 'include/reflex/convert.h', + 'include/reflex/debug.h', + 'include/reflex/error.h', + 'include/reflex/flexlexer.h', + 'include/reflex/fuzzymatcher.h', + 'include/reflex/input.h', + 'include/reflex/linematcher.h', + 'include/reflex/matcher.h', + 'include/reflex/pattern.h', + 'include/reflex/pcre2matcher.h', + 'include/reflex/posix.h', + 'include/reflex/ranges.h', + 'include/reflex/setop.h', + 'include/reflex/simd.h', + 'include/reflex/stdmatcher.h', + 'include/reflex/timer.h', + 'include/reflex/traits.h', + 'include/reflex/unicode.h', + 'include/reflex/utf8.h') + +reflex_sources = files( + 'lib/convert.cpp', + 'lib/debug.cpp', + 'lib/error.cpp', + 'lib/input.cpp', + 'lib/matcher.cpp', + 'lib/matcher_avx2.cpp', + 'lib/matcher_avx512bw.cpp', + 'lib/pattern.cpp', + 'lib/posix.cpp', + 'lib/simd.cpp', + 'lib/simd_avx2.cpp', + 'lib/simd_avx512bw.cpp', + 'lib/unicode.cpp', + 'lib/utf8.cpp', + 'unicode/block_scripts.cpp', + 'unicode/language_scripts.cpp', + 'unicode/letter_scripts.cpp', + 'unicode/letter_case.cpp', + 'unicode/composer.cpp') + +reflex_min_sources = files( + 'lib/debug.cpp', + 'lib/error.cpp', + 'lib/input.cpp', + 'lib/matcher.cpp', + 'lib/matcher_avx2.cpp', + 'lib/matcher_avx512bw.cpp', + 'lib/pattern.cpp', + 'lib/simd.cpp', + 'lib/simd_avx2.cpp', + 'lib/simd_avx512bw.cpp', + 'lib/utf8.cpp') + +# The Meson build starts with RE/flex's portable code path. Add SIMD feature +# detection later if the portable matcher is too slow for Meson-built packages. +reflex_lib = library('reflex', + reflex_sources, + include_directories: reflex_inc, + install: true) + +reflexmin_lib = library('reflexmin', + reflex_min_sources, + include_directories: reflex_inc, + install: true) + +reflex_exe = executable('reflex', + 'src/reflex.cpp', + include_directories: reflex_inc, + link_with: reflex_lib, + install: true) + +install_headers(reflex_headers, subdir: 'reflex') + +reflex_dep = declare_dependency( + include_directories: reflex_inc, + link_with: reflex_lib) + +reflexmin_dep = declare_dependency( + include_directories: reflex_inc, + link_with: reflexmin_lib) + +pkg.generate(reflex_lib, + filebase: 'reflex', + name: 'RE/flex', + description: 'high-performance C++ regex library and lexical analyzer generator', + subdirs: '.') + +pkg.generate(reflexmin_lib, + filebase: 'reflexmin', + name: 'RE/flex', + description: 'high-performance C++ regex library and lexical analyzer generator', + subdirs: '.') + +# Register a handler for any requested 'reflex' dependency +meson.override_dependency('reflex', reflex_dep) +# Register a handler for any requested 'reflexmin' dependency +meson.override_dependency('reflexmin', reflexmin_dep) From d239542fd2c967e2de3915ed33821a6e01573bea Mon Sep 17 00:00:00 2001 From: Benjamin Redelings Date: Sat, 18 Jul 2026 16:23:53 -0400 Subject: [PATCH 2/2] Import SIMD handling from meson wrap --- meson.build | 274 ++++++++++++++++++++++++++++++++++---------------- meson.options | 20 ++++ 2 files changed, 208 insertions(+), 86 deletions(-) create mode 100644 meson.options diff --git a/meson.build b/meson.build index b1df03ea..f8a48308 100644 --- a/meson.build +++ b/meson.build @@ -1,113 +1,215 @@ -project('reflex', 'cpp', +project( + 'reflex', + 'cpp', version: '6.3.0', license: 'BSD-3-Clause', - meson_version: '>= 1.1', - default_options: ['cpp_std=c++11']) - -pkg = import('pkgconfig') - -reflex_inc = include_directories('include') - -reflex_headers = files( - 'include/reflex/abslexer.h', - 'include/reflex/absmatcher.h', - 'include/reflex/bits.h', - 'include/reflex/boostmatcher.h', - 'include/reflex/convert.h', - 'include/reflex/debug.h', - 'include/reflex/error.h', - 'include/reflex/flexlexer.h', - 'include/reflex/fuzzymatcher.h', - 'include/reflex/input.h', - 'include/reflex/linematcher.h', - 'include/reflex/matcher.h', - 'include/reflex/pattern.h', - 'include/reflex/pcre2matcher.h', - 'include/reflex/posix.h', - 'include/reflex/ranges.h', - 'include/reflex/setop.h', - 'include/reflex/simd.h', - 'include/reflex/stdmatcher.h', - 'include/reflex/timer.h', - 'include/reflex/traits.h', - 'include/reflex/unicode.h', - 'include/reflex/utf8.h') - -reflex_sources = files( + meson_version: '>= 1.5.0', + default_options: { + 'cpp_std': 'c++11', + }, +) + +includes = include_directories('include') + +cpp = meson.get_compiler('cpp') +msvc = cpp.get_argument_syntax() == 'msvc' + +flags = cpp.get_supported_arguments(['-Wno-non-virtual-dtor']) +add_project_arguments( + flags, + language: 'cpp', +) + +unicode_sources = files( + 'unicode/block_scripts.cpp', + 'unicode/composer.cpp', + 'unicode/language_scripts.cpp', + 'unicode/letter_case.cpp', + 'unicode/letter_scripts.cpp', +) + +libreflex_sources = files( 'lib/convert.cpp', 'lib/debug.cpp', 'lib/error.cpp', 'lib/input.cpp', 'lib/matcher.cpp', - 'lib/matcher_avx2.cpp', - 'lib/matcher_avx512bw.cpp', 'lib/pattern.cpp', 'lib/posix.cpp', 'lib/simd.cpp', - 'lib/simd_avx2.cpp', - 'lib/simd_avx512bw.cpp', 'lib/unicode.cpp', 'lib/utf8.cpp', - 'unicode/block_scripts.cpp', - 'unicode/language_scripts.cpp', - 'unicode/letter_scripts.cpp', - 'unicode/letter_case.cpp', - 'unicode/composer.cpp') +) -reflex_min_sources = files( +libreflexmin_sources = files( 'lib/debug.cpp', 'lib/error.cpp', 'lib/input.cpp', 'lib/matcher.cpp', - 'lib/matcher_avx2.cpp', - 'lib/matcher_avx512bw.cpp', 'lib/pattern.cpp', 'lib/simd.cpp', + 'lib/utf8.cpp', +) + +have_simd_sse2 = cpp.compiles( + ''' + #include + int main(int argc, char** argv) { + __m128i n = _mm_set1_epi8(42); + } + ''', + args: msvc ? '/arch:SSE2' : '-msse2', + name: 'cxx supports SSE2 intrinsics with options [\'-msse2\']', + required: get_option('sse2'), +) + +have_simd_avx2 = cpp.compiles( + ''' + #include + int main(int argc, char** argv) { + __m256i n = _mm256_set1_epi8(42); + (void)_mm256_movemask_epi8(_mm256_and_si256(n, n)); + } + ''', + args: msvc ? '/arch:AVX2' : '-mavx2', + name: 'cxx supports AVX2 intrinsics with options [\'-mavx2\']', + required: get_option('avx2'), +) + +have_simd_avx512bw = cpp.compiles( + ''' + #include + int main(int argc, char** argv) { + __m512i n = _mm512_set1_epi8(42); + (void)_mm512_cmpeq_epi8_mask(n, n); + } + ''', + args: msvc ? '/arch:AVX512' : '-mavx512bw', + name: 'cxx supports AVX512BW intrinsics with options [\'-mavx512bw\']', + required: get_option('avx512bw'), +) + +if have_simd_avx512bw + simd_args = [msvc ? '/arch:SSE2' : '-msse2'] + simd_avx2_args = [msvc ? '/arch:AVX2' : '-mavx2'] + simd_avx512bw_args = [msvc ? '/arch:AVX512' : '-mavx512bw'] + add_project_arguments( + '-DHAVE_AVX512BW', + language: 'cpp', + ) +elif have_simd_avx2 + simd_args = [msvc ? '/arch:SSE2' : '-msse2'] + simd_avx2_args = [msvc ? '/arch:AVX2' : '-mavx2'] + simd_avx512bw_args = [] + add_project_arguments( + '-DHAVE_AVX2', + language: 'cpp', + ) +elif have_simd_sse2 + simd_args = [msvc ? '/arch:SSE2' : '-msse2'] + simd_avx2_args = [] + simd_avx512bw_args = [] + add_project_arguments( + '-DHAVE_SSE2', + language: 'cpp', + ) +else + simd_args = [] + simd_avx2_args = [] + simd_avx512bw_args = [] +endif + +neon_option = get_option('neon') +have_neon = false +if not neon_option.disabled() + foreach args : [[], ['-mfpu=neon'], ['-march=native', '-mfpu=neon']] + have_neon = cpp.compiles( + ''' + #include + int main(int argc, char** argv) { + uint64x2_t n; + uint64_t m = vgetq_lane_u64(n, 0); + } + ''', + args: args, + name: 'cxx supports NEON intrinsics with options @0@'.format(args), + required: false, + ) + if have_neon + simd_args = args + add_project_arguments( + '-DHAVE_NEON', + language: 'cpp', + ) + break + endif + endforeach +endif + +if neon_option.enabled() and not have_neon + error('NEON support was enabled but the compiler does not support NEON intrinsics') +endif + +libsimd_avx2 = static_library( + 'libsimd_avx2', + 'lib/matcher_avx2.cpp', 'lib/simd_avx2.cpp', + cpp_args: simd_avx2_args, + pic: true, + include_directories: includes, + build_by_default: false, +) + +libsimd_avx512bw = static_library( + 'libsimd_avx512bw', + 'lib/matcher_avx512bw.cpp', 'lib/simd_avx512bw.cpp', - 'lib/utf8.cpp') + cpp_args: simd_avx512bw_args, + pic: true, + include_directories: includes, + build_by_default: false, + # clang 14.0 fails to compile this code at optimization levels higher than 0 + override_options: cpp.get_id() == 'clang' and cpp.version() == '14.0.0' ? { + 'optimization': '0', + } : {}, +) -# The Meson build starts with RE/flex's portable code path. Add SIMD feature -# detection later if the portable matcher is too slow for Meson-built packages. -reflex_lib = library('reflex', - reflex_sources, - include_directories: reflex_inc, - install: true) +# No DLLEXPORT declarations, thus only static library supported with MSVC +library = msvc ? 'static_library' : 'library' -reflexmin_lib = library('reflexmin', - reflex_min_sources, - include_directories: reflex_inc, - install: true) +libreflexmin = build_target( + 'reflexmin', + libreflexmin_sources, + include_directories: includes, + cpp_args: simd_args, + # Selected based on a runtime AVX2 AVX512BW check + link_whole: [libsimd_avx2, libsimd_avx512bw], + target_type: library, +) -reflex_exe = executable('reflex', - 'src/reflex.cpp', - include_directories: reflex_inc, - link_with: reflex_lib, - install: true) +libreflex = build_target( + 'reflex', + libreflex_sources, + unicode_sources, + include_directories: includes, + cpp_args: simd_args, + # Selected based on a runtime AVX2 AVX512BW check + link_whole: [libsimd_avx2, libsimd_avx512bw], + target_type: library, +) -install_headers(reflex_headers, subdir: 'reflex') +reflex = executable( + 'reflex', + 'src/reflex.cpp', + link_with: libreflex, + include_directories: includes, + install: true, + cpp_args: ['-DPLATFORM="@0@"'.format(host_machine.system())], +) reflex_dep = declare_dependency( - include_directories: reflex_inc, - link_with: reflex_lib) - -reflexmin_dep = declare_dependency( - include_directories: reflex_inc, - link_with: reflexmin_lib) - -pkg.generate(reflex_lib, - filebase: 'reflex', - name: 'RE/flex', - description: 'high-performance C++ regex library and lexical analyzer generator', - subdirs: '.') - -pkg.generate(reflexmin_lib, - filebase: 'reflexmin', - name: 'RE/flex', - description: 'high-performance C++ regex library and lexical analyzer generator', - subdirs: '.') - -# Register a handler for any requested 'reflex' dependency -meson.override_dependency('reflex', reflex_dep) -# Register a handler for any requested 'reflexmin' dependency -meson.override_dependency('reflexmin', reflexmin_dep) + link_with: libreflex, + include_directories: includes, +) + +meson.override_find_program('reflex', reflex) diff --git a/meson.options b/meson.options new file mode 100644 index 00000000..da4dd837 --- /dev/null +++ b/meson.options @@ -0,0 +1,20 @@ +option( + 'sse2', + type: 'feature', + value: 'auto', +) +option( + 'avx2', + type: 'feature', + value: 'auto', +) +option( + 'avx512bw', + type: 'feature', + value: 'auto', +) +option( + 'neon', + type: 'feature', + value: 'auto', +)