public-inbox.git  about / heads / tags
an "archives first" approach to mailing lists
blob 1121340abf10195eeed0f5bdbc2a1ffc493385c1 2440 bytes (raw)
$ git show fuse3:lib/PublicInbox/LeiF3.pm	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 
# 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/f3.h FUSE3 shim.
# I never want users to be without source code for repairs, so this
# aims to replicate the feel of a scripting language using C11.
# This does NOT use Inline::C and the resulting executable is not
# linked to Perl in any way.
package PublicInbox::LeiF3;
use v5.12;
use Time::HiRes qw(stat);
use PublicInbox::Spawn;
my $dir = ($ENV{PERL_INLINE_DIRECTORY} //
	die('BUG: PERL_INLINE_DIRECTORY unset')) . '/f3';
my $F3_NS = 'lei';
my $bin = "$dir/${F3_NS}.fuse";
my ($srcpfx) = (__FILE__ =~ m!\A(.+/)[^/]+\z!);
my @srcs = map { $srcpfx.$_ } qw(f3.h);
my $xflags = ($ENV{CFLAGS} // '-Wall -ggdb3 -O0') . ' ' .
	($ENV{LDFLAGS} // '-Wl,-O1 -Wl,--compress-debug-sections=zlib') .
	qq{ -DF3_NS='"$F3_NS"'};

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 Config;
	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.c";
	open my $csrc, '>', $src;
	for (@srcs) {
		say $csrc qq(# line 1 "$_");
		open my $fh, '<', $_;
		local $/;
		print $csrc readline($fh);
	}
	close $csrc;
	my $cmd = "$pkg_config --libs --cflags fuse3 liburcu-cds liburcu-bp";
	chomp(my $fl = `$cmd`);
	die "$cmd failed: \$?=$?" if $?;
	my $cc = $ENV{CC} // $Config::Config{cc};
	$cmd = "$cc $src $fl $xflags -o $tmp/$prog";
	system($cmd) and die "$cmd failed: \$?=$?";
	my $cf = "$tmp/XFLAGS";
	open my $fh, '>', $cf;
	say $fh $xflags;
	close $fh;
	# not quite atomic, but close enough :P
	rename("$tmp/$_", "$dir/$_") for ($prog, 'XFLAGS');
}

sub start (@) {
	my $ctime = 0;
	my @bin = stat($bin);
	for ((@bin ? @srcs : ())) {
		my @st = stat($_) or die "stat $_: $!";
		$ctime = $st[10] if $st[10] > $ctime;
	}
	build() if !@bin || (@bin && $ctime > $bin[10]) || xflags_chg();
	my @cmd;
	if (my $v = $ENV{VALGRIND}) {
		$v = 'valgrind -v' if $v eq '1';
		@cmd = split(/\s+/, $v);
	}
	push @cmd, $bin, '-o', "subtype=$F3_NS,default_permissions", @_;
	my $prog = $cmd[0];
	$cmd[0] =~ s!\A.*?/([^/]+)\z!$1!;
	exec { $prog } @cmd;
}

1;

git clone https://public-inbox.org/public-inbox.git
git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/public-inbox.git