]> Dogcows Code - chaz/p5-Alien-ZMQ/blob - inc/My/Build.pm
do not print Ø for the benefit of unicode-unaware terminals
[chaz/p5-Alien-ZMQ] / inc / My / Build.pm
1 package My::Build;
2
3 use warnings FATAL => 'all';
4 use strict;
5
6 use Archive::Tar;
7 use Cwd qw/realpath/;
8 use Digest::SHA qw/sha1_hex/;
9 use File::Path qw/remove_tree/;
10 use File::Spec::Functions qw/catdir catfile/;
11 use IPC::Run qw/run/;
12 use LWP::Simple qw/getstore RC_OK/;
13 use Module::Build;
14
15 use base 'Module::Build';
16
17 sub ACTION_code {
18 my $self = shift;
19
20 $self->SUPER::ACTION_code;
21
22 return if -e 'build-zeromq';
23 $self->add_to_cleanup('build-zeromq');
24
25 my %args = $self->args;
26 my %vars;
27
28 $self->have_c_compiler or die "C compiler not found";
29
30 unless (exists $args{'zmq-skip-probe'}) {
31 print "Probing...\n";
32 %vars = $self->probe_zeromq;
33 }
34
35 if ($vars{inc_version} && $vars{lib_version} && $vars{inc_dir} && $vars{lib_dir}) {
36 print "Found libzmq $vars{lib_version}; skipping installation\n";
37 } else {
38 print "libzmq not found; building from source...\n";
39 %vars = $self->install_zeromq;
40 }
41
42 # write vars to ZMQ.pm
43 my $module = catfile qw/blib lib Alien ZMQ.pm/;
44 open my $LIB, '<', $module or die "Cannot read module";
45 my $lib = do { local $/; <$LIB> };
46 close $LIB;
47 $lib =~ s/^sub inc_dir.*$/sub inc_dir { "$vars{inc_dir}" }/m;
48 $lib =~ s/^sub lib_dir.*$/sub lib_dir { "$vars{lib_dir}" }/m;
49 $lib =~ s/^sub inc_version.*$/sub inc_version { v$vars{inc_version} }/m;
50 $lib =~ s/^sub lib_version.*$/sub lib_version { v$vars{lib_version} }/m;
51 my @stats = stat $module;
52 chmod 0644, $module;
53 open $LIB, '>', $module or die "Cannot write config to module";
54 print $LIB $lib;
55 close $LIB;
56 chmod $stats[2], $module;
57
58 open my $TARGET, '>', "build-zeromq";
59 print $TARGET time, "\n";
60 close $TARGET;
61 }
62
63 sub probe_zeromq {
64 my $self = shift;
65 my $cb = $self->cbuilder;
66 my %config = $cb->get_config;
67
68 my $src = "test-$$.c";
69 open my $SRC, '>', $src;
70 print $SRC <<END;
71 #include <stdio.h>
72 #include <zmq.h>
73 int main(int argc, char* argv[]) {
74 int major, minor, patch;
75 zmq_version(&major, &minor, &patch);
76 printf("%d.%d.%d %d.%d.%d",
77 ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH,
78 major, minor, patch);
79 return 0;
80 }
81 END
82 close $SRC;
83
84 my @inc_search;
85 my @lib_search;
86
87 my $cflags = $self->args('zmq-cflags');
88 my $libs = $self->args('zmq-libs');
89
90 my $pkg_version;
91
92 my $pkg_config = $ENV{PKG_CONFIG_COMMAND} || "pkg-config";
93 for my $pkg (qw/libzmq zeromq3/) {
94 $pkg_version = `$pkg_config $pkg --modversion`;
95 chomp $pkg_version;
96 next unless $pkg_version;
97
98 $cflags ||= `$pkg_config $pkg --cflags`;
99 $libs ||= `$pkg_config $pkg --libs`;
100
101 # use -I and -L flag arguments as extra search directories
102 my $inc = `$pkg_config $pkg --cflags-only-I`;
103 push @inc_search, map { s/^-I//; $_ } $cb->split_like_shell($inc);
104 my $lib = `$pkg_config $pkg --libs-only-L`;
105 push @lib_search, map { s/^-L//; $_ } $cb->split_like_shell($lib);
106
107 last;
108 }
109
110 my $obj = eval {
111 $cb->compile(source => $src, include_dirs => [@inc_search], extra_compiler_flags => $cflags);
112 };
113 unlink $src;
114 return unless $obj;
115
116 my $exe = eval {
117 $cb->link_executable(objects => $obj, extra_linker_flags => $libs);
118 };
119 unlink $obj;
120 return unless $exe;
121
122 my $out = `./$exe`;
123 unlink $exe;
124 my ($inc_version, $lib_version) = $out =~ /(\d\.\d\.\d) (\d\.\d\.\d)/;
125
126 # query the compiler for include and library search paths
127 push @lib_search, map {
128 my $path = $_;
129 $path =~ s/^.+ =?//;
130 $path =~ s/\n.*$//;
131 -d $path ? realpath($path) : ();
132 } split /:/, `$config{cc} -print-search-dirs`;
133 push @inc_search, map {
134 my $path = $_;
135 $path =~ s/lib(32|64)?$/include/;
136 $path;
137 } @lib_search;
138
139 # search for the header and library files
140 my ($inc_dir) = grep { -f catfile($_, "zmq.h") } @inc_search;
141 my ($lib_dir) = grep { -f catfile($_, $cb->lib_file("libzmq")) } @lib_search;
142
143 (
144 inc_version => $inc_version,
145 lib_version => $lib_version,
146 pkg_version => $pkg_version,
147 inc_dir => $inc_dir,
148 lib_dir => $lib_dir,
149 );
150 }
151
152 sub install_zeromq {
153 my $self = shift;
154 my $cb = $self->cbuilder;
155
156 my $version = $self->notes('zmq-version');
157 my $sha1 = $self->notes('zmq-sha1');
158 my $archive = "zeromq-$version.tar.gz";
159
160 print "Downloading libzmq $version source archive from download.zeromq.org...\n";
161 getstore("http://download.zeromq.org/$archive", $archive) == RC_OK
162 or die "Failed to download libzmq source archive";
163
164 print "Verifying...\n";
165 my $sha1sum = Digest::SHA->new;
166 open my $ARCHIVE, '<', $archive or die "Can't open source archive";
167 binmode $ARCHIVE;
168 $sha1sum->addfile($ARCHIVE);
169 close $ARCHIVE;
170 $sha1sum->hexdigest eq $sha1 or die "Source archive checksum mismatch";
171
172 print "Extracting...\n";
173 Archive::Tar->new($archive)->extract;
174 unlink $archive;
175
176 my $prefix = catdir($self->install_destination("lib"), qw/auto share dist Alien-ZMQ/);
177 my $basedir = $self->base_dir;
178 my $datadir = catdir($basedir, "share");
179 my $srcdir = catdir($basedir, "zeromq-$version");
180 chdir $srcdir;
181
182 print "Patching...\n";
183 for my $patch (glob("$basedir/files/zeromq-$version-*.patch")) {
184 run [qw/patch -p1/], '<', $patch or die "Failed to patch libzmq";
185 }
186
187 print "Configuring...\n";
188 my @config = $cb->split_like_shell($self->args('zmq-config') || "");
189 $cb->do_system(qw/sh configure CPPFLAGS=-Wno-error/, "--prefix=$prefix", @config)
190 or die "Failed to configure libzmq";
191
192 print "Compiling...\n";
193 $cb->do_system("make") or die "Failed to make libzmq";
194
195 print "Installing...\n";
196 $cb->do_system(qw|make install prefix=/|, "DESTDIR=$datadir")
197 or die "Failed to install libzmq";
198
199 chdir $basedir;
200 remove_tree($srcdir);
201
202 (
203 inc_version => $version,
204 lib_version => $version,
205 inc_dir => catdir($prefix, "include"),
206 lib_dir => catdir($prefix, "lib"),
207 );
208 }
209
210 1;
This page took 0.042858 seconds and 4 git commands to generate.