]> Dogcows Code - chaz/p5-Alien-ZMQ/commitdiff
initial commit v0.02
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 16 Jan 2013 19:52:02 +0000 (12:52 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 16 Jan 2013 20:57:04 +0000 (13:57 -0700)
Build.PL [new file with mode: 0644]
dist.ini [new file with mode: 0644]
inc/My/Build.pm [new file with mode: 0644]
lib/Alien/ZMQ.pm [new file with mode: 0644]
perlcritic.rc [new file with mode: 0644]
t/00-basic.t [new file with mode: 0644]

diff --git a/Build.PL b/Build.PL
new file mode 100644 (file)
index 0000000..cd66aba
--- /dev/null
+++ b/Build.PL
@@ -0,0 +1,21 @@
+use warnings FATAL => 'all';
+use strict;
+
+use lib 'inc';
+use File::Path qw/make_path/;
+use My::Build;
+
+# prevent warnings about missing share directory
+make_path("share");
+
+my $builder = My::Build->new(
+    ##{ $plugin->get_prereqs ##}
+    ##{ $plugin->get_default(qw/dist_name license dist_abstract/) ##}
+    ##{ $plugin->get_default(qw/dist_author/) ##}
+    dist_version_from => "lib/Alien/ZMQ.pm",
+    share_dir => "share",
+);
+$builder->notes('zmq-version', '3.2.2');
+$builder->notes('zmq-sha1', '0e8734c773b6a757b474c16fc3c517993ba47283');
+
+$builder->create_build_script;
diff --git a/dist.ini b/dist.ini
new file mode 100644 (file)
index 0000000..f97072a
--- /dev/null
+++ b/dist.ini
@@ -0,0 +1,39 @@
+
+name = Alien-ZMQ
+version = 0.02
+author = Charles McGarvey <chazmcgarvey@brokenzipper.com>
+license = Perl_5
+copyright_holder = Charles McGarvey
+
+[@Filter]
+-bundle = @Basic
+-remove = MakeMaker
+
+[PodSyntaxTests]
+[PodCoverageTests]
+[Test::Perl::Critic]
+
+[PruneFiles]
+filename = dist.ini
+
+[Clean]
+[MetaJSON]
+[ModuleBuild::Custom]
+[PkgVersion]
+[PodWeaver]
+
+[GitFmtChanges]
+file_name = Changes
+tax_regexp = ^v\d+
+
+[AutoPrereqs]
+
+[Prereqs / ConfigureRequires]
+Archive::Tar = 0
+Cwd = 0
+Digest::SHA = 0
+File::Path = 0
+File::Spec::Functions = 0
+IPC::Cmd = 0
+LWP::Simple = 0
+
diff --git a/inc/My/Build.pm b/inc/My/Build.pm
new file mode 100644 (file)
index 0000000..8c7d987
--- /dev/null
@@ -0,0 +1,212 @@
+package My::Build;
+
+use v5.10;
+use warnings FATAL => 'all';
+use strict;
+use utf8;
+
+use Archive::Tar;
+use Cwd qw/realpath/;
+use Digest::SHA qw/sha1_hex/;
+use File::Path qw/remove_tree/;
+use File::Spec::Functions qw/catdir catfile/;
+use IPC::Cmd qw/can_run run/;
+use LWP::Simple qw/getstore RC_OK/;
+use Module::Build;
+
+use base 'Module::Build';
+
+sub ACTION_code {
+    my $self = shift;
+
+    $self->SUPER::ACTION_code;
+
+    return if -e 'build-zeromq';
+    $self->add_to_cleanup('build-zeromq');
+
+    my %args = $self->args;
+    my %vars;
+
+    $self->have_c_compiler or die "C compiler not found";
+
+    unless (exists $args{'zmq-skip-probe'}) {
+        say "Probing...";
+        %vars = $self->probe_zeromq;
+    }
+
+    if ($vars{inc_version} && $vars{lib_version}) {
+        say "Found ØMQ $vars{lib_version}; skipping installation";
+    } else {
+        say "ØMQ not found; building from source...";
+        %vars = $self->install_zeromq;
+    }
+
+    # write vars to ZMQ.pm
+    my $module = catfile qw/blib lib Alien ZMQ.pm/;
+    open my $LIB, "<$module" or die "Cannot read module";
+    my $lib = do { local $/; <$LIB> };
+    close $LIB;
+    $lib =~ s/^sub inc_dir.*$/sub inc_dir { "$vars{inc_dir}" }/m;
+    $lib =~ s/^sub lib_dir.*$/sub lib_dir { "$vars{lib_dir}" }/m;
+    $lib =~ s/^sub inc_version.*$/sub inc_version { v$vars{inc_version} }/m;
+    $lib =~ s/^sub lib_version.*$/sub lib_version { v$vars{lib_version} }/m;
+    my @stats = stat $module;
+    chmod 0644, $module;
+    open $LIB, ">$module" or die "Cannot write config to module";
+    print $LIB $lib;
+    close $LIB;
+    chmod $stats[2], $module;
+
+    open my $TARGET, ">build-zeromq";
+    print $TARGET time, "\n";
+    close $TARGET;
+}
+
+sub probe_zeromq {
+    my $self = shift;
+    my $cb = $self->cbuilder;
+
+    my $src = "test-$$.c";
+    open my $SRC, ">$src";
+    print $SRC <<END;
+#include <stdio.h>
+#include <zmq.h>
+int main(int argc, char* argv[]) {
+    int major, minor, patch;
+    zmq_version(&major, &minor, &patch);
+    printf("%d.%d.%d %d.%d.%d",
+        ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH,
+        major, minor, patch);
+    return 0;
+}
+END
+    close $SRC;
+
+    my @inc_search;
+    my @lib_search;
+
+    my $cflags = $self->args('zmq-cflags');
+    my $libs   = $self->args('zmq-libs');
+
+    my $pkg_version;
+
+    my $pkg_config = $ENV{PKG_CONFIG_COMMAND} || "pkg-config";
+    for my $pkg (qw/libzmq zeromq3/) {
+        $pkg_version = `$pkg_config $pkg --modversion`;
+        chomp $pkg_version;
+        next unless $pkg_version;
+
+        $cflags ||= `$pkg_config $pkg --cflags`;
+        $libs   ||= `$pkg_config $pkg --libs`;
+
+        # use -I and -L flag arguments as extra search directories
+        my $inc = `$pkg_config $pkg --cflags-only-I`;
+        push @inc_search, map { s/^-I//; $_ } split(/\s+/, $inc);
+        my $lib = `$pkg_config $pkg --libs-only-L`;
+        push @lib_search, map { s/^-L//; $_ } split(/\s+/, $lib);
+
+        last;
+    }
+
+    my $obj = eval {
+        $cb->compile(source => $src, include_dirs => [@inc_search], extra_compiler_flags => $cflags);
+    };
+    unlink $src;
+    return unless $obj;
+
+    my $exe = eval {
+        $cb->link_executable(objects => $obj, extra_linker_flags => $libs);
+    };
+    unlink $obj;
+    return unless $exe;
+
+    my $out = `./$exe`;
+    unlink $exe;
+    my ($inc_version, $lib_version) = $out =~ /(\d\.\d\.\d) (\d\.\d\.\d)/;
+
+    # query the compiler for include and library search paths
+    my $cc = $ENV{CC} || "cc";
+    push @lib_search, map {
+        my $path = $_;
+        $path =~ s/^.+ =?//;
+        $path =~ s/\n.*$//;
+        -d $path ? realpath($path) : ();
+    } split /:/, `$cc -print-search-dirs`;
+    push @inc_search, map {
+        my $path = $_;
+        $path =~ s/lib(32|64)?$/include/;
+        $path;
+    } @lib_search;
+
+    # search for the header and library files
+    my ($inc_dir) = grep { -f catfile($_, "zmq.h") } @inc_search;
+    my ($lib_dir) = grep {
+        -f catfile($_, "libzmq.so")    ||
+        -f catfile($_, "libzmq.dylib") ||
+        -f catfile($_, "libzmq.dll")
+    } @lib_search;
+
+    (
+        inc_version => $inc_version,
+        lib_version => $lib_version,
+        pkg_version => $pkg_version,
+        inc_dir            => $inc_dir,
+        lib_dir            => $lib_dir,
+    );
+}
+
+sub install_zeromq {
+    my $self = shift;
+
+    can_run("libtool") or die "The libtool command cannot be found";
+
+    my $version = $self->notes('zmq-version');
+    my $sha1 = $self->notes('zmq-sha1');
+    my $archive = "zeromq-$version.tar.gz";
+
+    say "Downloading ØMQ $version source archive from download.zeromq.org...";
+    getstore("http://download.zeromq.org/$archive", $archive) == RC_OK
+        or die "Failed to download ØMQ source archive";
+
+    say "Verifying...";
+    my $sha1sum = Digest::SHA->new;
+    open my $ARCHIVE, "<$archive";
+    binmode $ARCHIVE;
+    $sha1sum->addfile($ARCHIVE);
+    close $ARCHIVE;
+    $sha1sum->hexdigest eq $sha1 or die "Source archive checksum mismatch";
+
+    say "Extracting...";
+    Archive::Tar->new($archive)->extract;
+    unlink $archive;
+
+    my $prefix  = catdir($self->install_destination("lib"), qw/auto share dist Alien-ZMQ/);
+    my $basedir = $self->base_dir;
+    my $datadir = catdir($basedir, "share");
+    my $srcdir  = catdir($basedir, "zeromq-$version");
+
+    say "Configuring...";
+    my @config = split(/\s/, $self->args('zmq-config') || "");
+    chdir $srcdir;
+    run(command => ["./configure", "--prefix=$prefix", @config])
+        or die "Failed to configure ØMQ";
+
+    say "Compiling...";
+    run(command => ['make']) or die "Failed to make ØMQ";
+
+    say "Installing...";
+    run(command => [qw|make install prefix=/|, "DESTDIR=$datadir"])
+        or die "Failed to install ØMQ";
+
+    chdir $basedir;
+    remove_tree($srcdir);
+
+    (
+        inc_version => $version,
+        lib_version => $version,
+        inc_dir            => catdir($prefix, "include"),
+        lib_dir            => catdir($prefix, "lib"),
+    );
+}
+
+1;
diff --git a/lib/Alien/ZMQ.pm b/lib/Alien/ZMQ.pm
new file mode 100644 (file)
index 0000000..4c0e2f9
--- /dev/null
@@ -0,0 +1,135 @@
+package Alien::ZMQ;
+# ABSTRACT: detect and/or install zeromq
+
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+Upon installation, the target system is probed for the presence of libzmq.  If
+it is not found, zeromq 3.2.2 is installed in a shared directory.  In short,
+modules that need libzmq can depend on this module to make sure that it is
+available.
+
+=head1 SYNOPSIS
+
+    use Alien::ZMQ;
+
+    my $version = Alien::ZMQ::lib_version;
+
+=head1 OPTIONS
+
+These options to F<Build.PL> affect the installation of this module.
+
+=over 4
+
+=item --zmq-skip-probe
+
+By default, zeromq is not compiled and installed if it is detected to already
+be on the system.  Use this to skip those checks and always install zeromq.
+
+=item --zmq-config=...
+
+Pass extra flags to zeromq's F<configure> script.  You may want to consider
+passing either C<--with-pgm> or C<--with-system-pgm> if you need support for
+PGM; this is not enabled by default because it is not supported by every
+system.
+
+=item --zmq-libs=...
+
+Pass extra flags to the linker when probing for an existing installation of
+zeromq.  In particular, if your F<libzmq.so> file is installed to a special
+location, you may pass flags such as C<-L/opt/libzmq2/lib -lzmq>.
+
+=item --zmq-cflags=...
+
+Pass extra flags to the compiler when probing for an existing installation of
+zeromq.  These flags will not be used when actually compiling zeromq from
+source.  For that, just use the C<CFLAGS> environment variable.
+
+=back
+
+=head1 CAVEATS
+
+Probing is only done upon installation, so if you are using a system-installed
+version of libzmq and you uninstall or upgrade it, you will also need to
+reinstall this module.
+
+=head1 BUGS
+
+Windows is not yet supported.  Patches are welcome.
+
+=head1 SEE ALSO
+
+=over 4
+
+=item * L<GitHub project|https://github.com/chazmcgarvey/p5-Alien-ZMQ>
+
+=item * L<ZMQ> - good perl bindings for zeromq
+
+=item * L<ZeroMQ|http://www.zeromq.org/> - official libzmq website
+
+=back
+
+=head1 ACKNOWLEDGEMENTS
+
+The design and implementation of this module were influenced by other L<Alien>
+modules, including L<Alien::GMP> and L<Alien::Tidyp>.
+
+=method inc_version
+
+Get the version number of libzmq as a dotted version string according to the
+F<zmq.h> header file.
+
+=cut
+
+sub inc_version { }
+
+=method lib_version
+
+Get the version number of libzmq as a dotted version string according to the
+F<libzmq.so> file.
+
+=cut
+
+sub lib_version { }
+
+=method inc_dir
+
+Get the directory containing the F<zmq.h> header file.
+
+=cut
+
+sub inc_dir { }
+
+=method lib_dir
+
+Get the directory containing the F<libzmq.so> file.
+
+=cut
+
+sub lib_dir { }
+
+=method cflags
+
+Get the C compiler flags required to compile a program that uses libzmq.  This
+is a shortcut for constructing a C<-I> flag using C<inc_dir>.
+
+=cut
+
+sub cflags {
+    "-I'" . inc_dir . "'";
+}
+
+=method libs
+
+Get the linker flags required to link a program against libzmq.  This is
+a shortcut for constructing a C<-L> flag using C<lib_dir>, plus C<-lzmq>.
+
+=cut
+
+sub libs {
+    "-L'" . lib_dir . "' -lzmq";
+}
+
+1;
diff --git a/perlcritic.rc b/perlcritic.rc
new file mode 100644 (file)
index 0000000..261a4b2
--- /dev/null
@@ -0,0 +1,4 @@
+#severity    = brutal
+exclude            = TestingAndDebugging::RequireUseStrict
+# RequireUseStrict is a good policy, but sadly it doesn't play well with
+# dzil's Pod::Weaver plugin.
diff --git a/t/00-basic.t b/t/00-basic.t
new file mode 100644 (file)
index 0000000..f819d60
--- /dev/null
@@ -0,0 +1,20 @@
+#!perl
+
+use warnings;
+use strict;
+
+use Test::More tests => 8;
+
+BEGIN {
+    use_ok 'Alien::ZMQ';
+}
+
+ok Alien::ZMQ::inc_version, "include version number";
+ok Alien::ZMQ::lib_version, "library version number";
+ok Alien::ZMQ::inc_dir,     "include directory path";
+ok Alien::ZMQ::inc_dir,     "library directory path";
+
+like Alien::ZMQ::cflags, qr/-I\S+/, "cflags has -I";
+like Alien::ZMQ::libs,   qr/-L\S+/, "libs has -L";
+like Alien::ZMQ::libs,   qr/-lzmq/, "libs has -lzmq";
+
This page took 0.030604 seconds and 4 git commands to generate.