diff options
author | Eric Wong <e@80x24.org> | 2023-08-24 01:22:33 +0000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2023-08-24 07:47:51 +0000 |
commit | b18ecb7707e83cb8cb38c3736aecd984999ca0a7 (patch) | |
tree | 0f159212810c98aa07d26b6f7f28f4b8dbc9b302 /lib/PublicInbox/XapHelperCxx.pm | |
parent | cf96412eb8f193ebd334fae340b2d91b6b7f2afe (diff) | |
download | public-inbox-b18ecb7707e83cb8cb38c3736aecd984999ca0a7.tar.gz |
This allows us to perform the expensive "dump_ibx" operations in native C++ code using the Xapian C++ library. This provides the majority of the speedup with the -cindex --associate switch. Eventually this may be expanded to cover all uses of Xapian within the project to ensure we have access to Xapian APIs which aren't available in XS|SWIG bindings; and also for ease-of-installation on systems which don't provide pre-packaged Perl Xapian bindings (e.g. OpenBSD 7.3) but do provide Xapian development libraries. Most of the C++ code is still C, as I'm not remotely familiar with C++ compared to C. I suspect many users and potential hackers being from git, Linux kernel, and glibc world are in the same boat.
Diffstat (limited to 'lib/PublicInbox/XapHelperCxx.pm')
-rw-r--r-- | lib/PublicInbox/XapHelperCxx.pm | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/lib/PublicInbox/XapHelperCxx.pm b/lib/PublicInbox/XapHelperCxx.pm new file mode 100644 index 00000000..4571676b --- /dev/null +++ b/lib/PublicInbox/XapHelperCxx.pm @@ -0,0 +1,93 @@ +# Copyright (C) all contributors <meta@public-inbox.org> +# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> + +# Just-ahead-of-time builder for the lib/PublicInbox/xap_helper.h shim. +# I never want users to be without source code for repairs, so this +# aims to replicate the feel of a scripting language using C++. +# The resulting executable is not linked to Perl in any way. +package PublicInbox::XapHelperCxx; +use v5.12; +use PublicInbox::Spawn; +use PublicInbox::Search; +my $dir = ($ENV{PERL_INLINE_DIRECTORY} // + die('BUG: PERL_INLINE_DIRECTORY unset')) . '/cxx'; +my $bin = "$dir/xap_helper"; +my ($srcpfx) = (__FILE__ =~ m!\A(.+/)[^/]+\z!); +my @srcs = map { $srcpfx.$_ } qw(xap_helper.h); +my @pm_dep = map { $srcpfx.$_ } qw(Search.pm CodeSearch.pm); +my $xflags = ($ENV{CXXFLAGS} // '-Wall -ggdb3 -O0') . ' ' . + ($ENV{LDFLAGS} // '-Wl,-O1 -Wl,--compress-debug-sections=zlib') . + qq{ -DTHREADID=}.PublicInbox::Search::THREADID; + +sub xflags_chg () { + open my $fh, '<', "$dir/XFLAGS" or return 1; + chomp(my $prev = <$fh>); + $prev ne $xflags; +} + +sub build () { + if (!-d $dir) { + my $err; + mkdir($dir) or $err = $!; + die "mkdir($dir): $err" if !-d $dir; + } + use autodie; + require File::Temp; + require PublicInbox::CodeSearch; + my ($prog) = ($bin =~ m!/([^/]+)\z!); + my $pkg_config = $ENV{PKG_CONFIG} // 'pkg-config'; + my $tmp = File::Temp->newdir(DIR => $dir) // die "newdir: $!"; + my $src = "$tmp/$prog.cpp"; + open my $fh, '>', $src; + for (@srcs) { + say $fh qq(# line 1 "$_"); + open my $rfh, '<', $_; + local $/; + print $fh readline($rfh); + } + print $fh PublicInbox::Search::generate_cxx(); + print $fh PublicInbox::CodeSearch::generate_cxx(); + close $fh; + + my $cmd = "$pkg_config --libs --cflags xapian-core"; + chomp(my $fl = `$cmd`); + die "$cmd failed: \$?=$?" if $?; + my $cxx = $ENV{CXX} // 'c++'; + $cmd = "$cxx $src $fl $xflags -o $tmp/$prog"; + system($cmd) and die "$cmd failed: \$?=$?"; + my $cf = "$tmp/XFLAGS"; + open $fh, '>', $cf; + say $fh $xflags; + close $fh; + # not quite atomic, but close enough :P + rename("$tmp/$_", "$dir/$_") for ($prog, 'XFLAGS'); +} + +sub check_build () { + use Time::HiRes qw(stat); + my $ctime = 0; + my @bin = stat($bin) or return build(); + for (@srcs, @pm_dep) { + my @st = stat($_) or die "stat $_: $!"; + if ($st[10] > $ctime) { + $ctime = $st[10]; + return build() if $ctime > $bin[10]; + } + } + xflags_chg() ? build() : 0; +} + +sub start (@) { + check_build(); + my @cmd; + if (my $v = $ENV{VALGRIND}) { + $v = 'valgrind -v' if $v eq '1'; + @cmd = split(/\s+/, $v); + } + push @cmd, $bin, @_; + my $prog = $cmd[0]; + $cmd[0] =~ s!\A.*?/([^/]+)\z!$1!; + exec { $prog } @cmd; +} + +1; |