From 2a3a82949977ff880639b50cb90870a0be528077 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Fri, 7 Jun 2013 16:11:38 -0600 Subject: [PATCH] add support for the MSWin32 platform see #1 --- Build.PL | 14 +++- inc/My/Build.pm | 152 +-------------------------------------- inc/My/Build/Unix.pm | 156 ++++++++++++++++++++++++++++++++++++++++ inc/My/Build/Windows.pm | 53 ++++++++++++++ inc/My/Util.pm | 25 +++++++ 5 files changed, 249 insertions(+), 151 deletions(-) create mode 100644 inc/My/Build/Unix.pm create mode 100644 inc/My/Build/Windows.pm create mode 100644 inc/My/Util.pm diff --git a/Build.PL b/Build.PL index e20a3bd..b951758 100644 --- a/Build.PL +++ b/Build.PL @@ -3,12 +3,17 @@ use strict; use lib 'inc'; use File::Path qw/make_path/; -use My::Build; + +my %platforms = ( + MSWin32 => 'Windows', +); +my $build = 'My::Build::' . ($platforms{$^O} || 'Unix'); +eval "require $build" or die "Require '$build' failed: $@"; # prevent warnings about missing share directory make_path("share"); -my $builder = My::Build->new( +my $builder = $build->new( ##{ $plugin->get_prereqs ##} ##{ $plugin->get_default(qw/dist_name license dist_abstract/) ##} ##{ $plugin->get_default(qw/dist_author/) ##} @@ -18,4 +23,9 @@ my $builder = My::Build->new( $builder->notes('zmq-version', '3.2.3'); $builder->notes('zmq-sha1', '6857a3a0e908eca58f7c0f90e2ba4695f6700957'); +$builder->notes('zmq-win32-dist', 'http://miru.hk/archive/ZeroMQ-3.2.3~miru1.0-x86.exe'); +$builder->notes('zmq-win32-sha1', 'a26b405695454c98904709924e40e2902738dddd'); +$builder->notes('zmq-win64-dist', 'http://miru.hk/archive/ZeroMQ-3.2.3~miru1.0-x64.exe'); +$builder->notes('zmq-win64-sha1', '1de71d1dea5084308a6ca00593484b8145d7d582'); + $builder->create_build_script; diff --git a/inc/My/Build.pm b/inc/My/Build.pm index d9ca6c7..18c00d4 100644 --- a/inc/My/Build.pm +++ b/inc/My/Build.pm @@ -3,14 +3,7 @@ package My::Build; use warnings FATAL => 'all'; use strict; -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::Run qw/run/; -use LWP::Simple qw/getstore RC_OK/; -use Module::Build; +use File::Spec::Functions qw/catfile/; use base 'Module::Build'; @@ -61,150 +54,11 @@ sub ACTION_code { } sub probe_zeromq { - my $self = shift; - my $cb = $self->cbuilder; - my %config = $cb->get_config; - - my $src = "test-$$.c"; - open my $SRC, '>', $src; - print $SRC < -#include -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//; $_ } $cb->split_like_shell($inc); - my $lib = `$pkg_config $pkg --libs-only-L`; - push @lib_search, map { s/^-L//; $_ } $cb->split_like_shell($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 - push @lib_search, map { - my $path = $_; - $path =~ s/^.+ =?//; - $path =~ s/\n.*$//; - -d $path ? realpath($path) : (); - } split /:/, `$config{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($_, $cb->lib_file("libzmq")) } @lib_search; - - ( - inc_version => $inc_version, - lib_version => $lib_version, - pkg_version => $pkg_version, - inc_dir => $inc_dir, - lib_dir => $lib_dir, - ); + die "Subclasses of " . __PACKAGE__ . " must override"; } sub install_zeromq { - my $self = shift; - my $cb = $self->cbuilder; - - my $version = $self->notes('zmq-version'); - my $sha1 = $self->notes('zmq-sha1'); - my $archive = "zeromq-$version.tar.gz"; - - print "Downloading libzmq $version source archive from download.zeromq.org...\n"; - getstore("http://download.zeromq.org/$archive", $archive) == RC_OK - or die "Failed to download libzmq source archive"; - - print "Verifying...\n"; - my $sha1sum = Digest::SHA->new; - open my $ARCHIVE, '<', $archive or die "Can't open source archive"; - binmode $ARCHIVE; - $sha1sum->addfile($ARCHIVE); - close $ARCHIVE; - $sha1sum->hexdigest eq $sha1 or die "Source archive checksum mismatch"; - - print "Extracting...\n"; - 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"); - chdir $srcdir; - - print "Patching...\n"; - for my $patch (glob("$basedir/files/zeromq-$version-*.patch")) { - run [qw/patch -p1/], '<', $patch or die "Failed to patch libzmq"; - } - - print "Configuring...\n"; - my @config = $cb->split_like_shell($self->args('zmq-config') || ""); - $cb->do_system(qw/sh configure CPPFLAGS=-Wno-error/, "--prefix=$prefix", @config) - or die "Failed to configure libzmq"; - - print "Compiling...\n"; - $cb->do_system("make") or die "Failed to make libzmq"; - - print "Installing...\n"; - $cb->do_system(qw|make install prefix=/|, "DESTDIR=$datadir") - or die "Failed to install libzmq"; - - chdir $basedir; - remove_tree($srcdir); - - ( - inc_version => $version, - lib_version => $version, - inc_dir => catdir($prefix, "include"), - lib_dir => catdir($prefix, "lib"), - ); + die "Subclasses of " . __PACKAGE__ . " must override"; } 1; diff --git a/inc/My/Build/Unix.pm b/inc/My/Build/Unix.pm new file mode 100644 index 0000000..dc40fa4 --- /dev/null +++ b/inc/My/Build/Unix.pm @@ -0,0 +1,156 @@ +package My::Build::Unix; + +use warnings FATAL => 'all'; +use strict; + +use Archive::Tar; +use Cwd qw/realpath/; +use File::Path qw/remove_tree/; +use File::Spec::Functions qw/catdir catfile/; +use IPC::Run qw/run/; +use My::Util; + +use base 'My::Build'; + +sub probe_zeromq { + my $self = shift; + my $cb = $self->cbuilder; + my %config = $cb->get_config; + + my $src = "test-$$.c"; + open my $SRC, '>', $src; + print $SRC < +#include +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//; $_ } $cb->split_like_shell($inc); + my $lib = `$pkg_config $pkg --libs-only-L`; + push @lib_search, map { s/^-L//; $_ } $cb->split_like_shell($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 + push @lib_search, map { + my $path = $_; + $path =~ s/^.+ =?//; + $path =~ s/\n.*$//; + -d $path ? realpath($path) : (); + } split /:/, `$config{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($_, $cb->lib_file("libzmq")) } @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; + my $cb = $self->cbuilder; + + my $version = $self->notes('zmq-version'); + my $sha1 = $self->notes('zmq-sha1'); + my $archive = "zeromq-$version.tar.gz"; + + print "Downloading libzmq $version source archive from download.zeromq.org...\n"; + My::Util::download("http://download.zeromq.org/$archive", $archive); + + print "Verifying...\n"; + My::Util::verify($archive, $sha1); + + print "Extracting...\n"; + 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 $destdir = catdir($basedir, "share"); + my $srcdir = catdir($basedir, "zeromq-$version"); + chdir $srcdir; + + print "Patching...\n"; + for my $patch (glob("$basedir/files/zeromq-$version-*.patch")) { + run [qw/patch -p1/], '<', $patch or die "Failed to patch libzmq"; + } + + print "Configuring...\n"; + my @config = $cb->split_like_shell($self->args('zmq-config') || ""); + $cb->do_system(qw/sh configure CPPFLAGS=-Wno-error/, "--prefix=$prefix", @config) + or die "Failed to configure libzmq"; + + print "Compiling...\n"; + $cb->do_system("make") or die "Failed to make libzmq"; + + print "Installing...\n"; + $cb->do_system(qw|make install prefix=/|, "DESTDIR=$destdir") + or die "Failed to install libzmq"; + + 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/inc/My/Build/Windows.pm b/inc/My/Build/Windows.pm new file mode 100644 index 0000000..89dfdee --- /dev/null +++ b/inc/My/Build/Windows.pm @@ -0,0 +1,53 @@ +package My::Build::Windows; + +use warnings FATAL => 'all'; +use strict; + +use Config; +use File::Spec::Functions qw/catdir/; +use My::Util; + +use base 'My::Build'; + +sub probe_zeromq { + # probing on windows is not supported +} + +sub install_zeromq { + my $self = shift; + + my $version = $self->notes('zmq-version'); + my ($archive, $sha1); + # check of this is a 32-bit or 64-bit perl + if ($Config{ptrsize} == 8) { + $archive = $self->notes('zmq-win64-dist'); + $sha1 = $self->notes('zmq-win64-sha1'); + } else { + $archive = $self->notes('zmq-win32-dist'); + $sha1 = $self->notes('zmq-win32-sha1'); + } + + print "Downloading libzmq $version installer from miru.hk...\n"; + My::Util::download($archive, "setup.exe"); + $self->add_to_cleanup('setup.exe'); + + print "Verifying...\n"; + My::Util::verify("setup.exe", $sha1); + + my $prefix = catdir($self->install_destination("lib"), qw/auto share dist Alien-ZMQ/); + my $basedir = $self->base_dir; + my $destdir = catdir($basedir, "share"); + $self->add_to_cleanup($destdir); + + print "Installing...\n"; + system(qw|setup.exe /S|, "/D=$destdir") == 0 or die "Failed to install libzmq"; + + ( + inc_version => $version, + lib_version => $version, + inc_dir => catdir($prefix, "include"), + lib_dir => catdir($prefix, "lib"), + ); +} + +1; diff --git a/inc/My/Util.pm b/inc/My/Util.pm new file mode 100644 index 0000000..b85903c --- /dev/null +++ b/inc/My/Util.pm @@ -0,0 +1,25 @@ +package My::Util; + +use warnings FATAL => 'all'; +use strict; + +use Digest::SHA qw/sha1_hex/; +use LWP::Simple qw/getstore RC_OK/; + +sub download { + my ($uri, $filename) = @_; + getstore($uri, $filename) == RC_OK or die "Failed to download from $uri"; +} + +sub verify { + my ($filepath, $sha1) = @_; + + my $sha1sum = Digest::SHA->new; + open my $FILE, '<', $filepath or die "Can't open $filepath: $!"; + binmode $FILE; + $sha1sum->addfile($FILE); + close $FILE; + $sha1sum->hexdigest eq $sha1 or die "Checksum mismatch for $filepath"; +} + +1; -- 2.45.2