package # inc::Sereal::BuildTools; use strict; use warnings; use Config; use constant OSNAME => $^O; my %bare_minimum_files= map { $_ => 1 } qw{ typemap ppport.h srl_stack.h srl_common.h srl_inline.h srl_taginfo.h srl_protocol.h srl_reader_error.h srl_reader_types.h inc/Sereal/BuildTools.pm inc/Devel/CheckLib.pm inc/Sereal inc/Devel inc }; sub link_files { my $shared_dir= shift; my $mode= shift || ""; my $exclude_tests= $mode eq "without_tests"; my $tests_only= $mode eq "tests_only"; my $bare_minimum= $mode eq "bare_minimum"; # This fires from a git source tree only. # Right now, all devs are on Linux. Feel free to make portable. eval { # overwrite by default require File::Find; require File::Path; require File::Spec; File::Find::find( { no_chdir => 1, wanted => sub { my $f= $_; s/^\Q$shared_dir\E\/?// or die $_; return unless $_; return if $exclude_tests && m#^/?t/#; return if $tests_only && !m#^/?t/#; return if $bare_minimum && !exists $bare_minimum_files{$_}; if ( -d $f ) { File::Path::mkpath($_); } elsif ( -f $f ) { return if $f =~ /(?:\.bak|\.sw[po]|~)$/; my @d= File::Spec->splitdir($_); my $fname= pop @d; my $ref= join "/", ("..") x scalar(@d); my $subd= join "/", @d; chdir $subd if length($ref); my $srcfname= join( "/", grep length, $ref, $shared_dir, $subd, $fname ); if ( OSNAME eq 'MSWin32' ) { die "link($srcfname, $fname) failed: $!" unless link( $srcfname, $fname ); #only NTFS implements it } else { symlink( $srcfname, $fname ); } chdir($ref) if length($ref); } }, }, $shared_dir ); 1; } or warn $@; } sub generate_constant_includes { # no-op } # Prefer external csnappy and miniz libraries over the bundled ones. sub check_external_libraries { my ( $libs, $defines, $objects, $subdirs )= @_; require Devel::CheckLib; if ( !$ENV{SEREAL_USE_BUNDLED_LIBS} && !$ENV{SEREAL_USE_BUNDLED_CSNAPPY} && Devel::CheckLib::check_lib( lib => 'csnappy', header => 'csnappy.h' ) ) { print "Using installed csnappy library\n"; $$libs .= ' -lcsnappy'; $$defines .= ' -DHAVE_CSNAPPY'; } else { print "Using bundled csnappy code\n"; } if ( !$ENV{SEREAL_USE_BUNDLED_LIBS} && !$ENV{SEREAL_USE_BUNDLED_MINIZ} && Devel::CheckLib::check_lib( lib => 'miniz', header => 'miniz.h' ) ) { print "Using installed miniz library\n"; $$libs .= ' -lminiz'; $$defines .= ' -DHAVE_MINIZ'; } else { print "Using bundled miniz code\n"; $$objects .= ' miniz$(OBJ_EXT)'; } if ( !$ENV{SEREAL_USE_BUNDLED_LIBS} && !$ENV{SEREAL_USE_BUNDLED_ZSTD} && Devel::CheckLib::check_lib( lib => 'zstd', header => 'zstd.h' ) ) { print "Using installed zstd library\n"; $$libs .= ' -lzstd'; $$defines .= ' -DHAVE_ZSTD'; } else { print "Using bundled zstd code\n"; push @{$subdirs}, 'zstd'; $$objects .= ' zstd/libzstd$(OBJ_EXT)'; } } sub build_defines { my (@defs)= @_; my $defines= join( " ", map { "-D$_" . ( defined $ENV{$_} ? "=$ENV{$_}" : '' ) } grep { exists $ENV{$_} } ( qw(NOINLINE DEBUG MEMDEBUG NDEBUG), @defs ) ); $defines .= " -DNDEBUG" unless $ENV{DEBUG}; if ( $Config{osname} eq 'hpux' && not $Config{gccversion} ) { # HP-UX cc does not support inline. # Or rather, it does, but it depends on the compiler flags, # assumedly -AC99 instead of -Ae would work. # But we cannot change the compiler config too much from # the one that was used to compile Perl, # so we just fake the inline away. $defines .= " -Dinline= "; } return $defines; } sub build_optimize { my $cc_flags= shift || {}; my $catch_violations= exists $cc_flags->{catch_violations} ? $cc_flags->{catch_violations} : 1; my $OPTIMIZE; my $clang= 0; if ( $Config{gccversion} ) { $OPTIMIZE= '-O3'; if ( $Config{gccversion} =~ /[Cc]lang/ ) { # clang. $clang= 1; } my $gccversion= 0; if ( $Config{gccversion} =~ /^(\d+\.\d+)/ ) { $gccversion= $1; } if ( $catch_violations && ( $clang || $gccversion >= 4.3 ) ) { # -Werror= introduced in GCC 4.3 # For trapping C++ // comments we would need -std=c89 (aka -ansi) # but that may be asking too much of different platforms. $OPTIMIZE .= ' -Werror=declaration-after-statement '; } } elsif ( $Config{osname} eq 'MSWin32' ) { $OPTIMIZE= '-O2 -W4'; } else { $OPTIMIZE= $Config{optimize}; } if ( $ENV{DEBUG} ) { $OPTIMIZE .= ' -g'; if ( $ENV{DEBUG} > 0 && $Config{gccversion} ) { $OPTIMIZE .= ' -Wextra' if $ENV{DEBUG} > 1; $OPTIMIZE .= ' -pedantic' if $ENV{DEBUG} > 5; # not pretty $OPTIMIZE .= ' -Weverything' if ( $ENV{DEBUG} > 6 && $clang ); # really not pretty } } return $OPTIMIZE; } sub WriteMakefile { require ExtUtils::MakeMaker; #Original by Alexandr Ciornii, modified by Yves Orton my %params= @_; my $eumm_version= $ExtUtils::MakeMaker::VERSION; $eumm_version= eval $eumm_version; die "EXTRA_META is deprecated" if exists $params{EXTRA_META}; die "License not specified" if not exists $params{LICENSE}; if ( $params{TEST_REQUIRES} and $eumm_version < 6.6303 ) { $params{BUILD_REQUIRES}= { %{ $params{BUILD_REQUIRES} || {} }, %{ $params{TEST_REQUIRES} } }; delete $params{TEST_REQUIRES}; } if ( $params{BUILD_REQUIRES} and $eumm_version < 6.5503 ) { #EUMM 6.5502 has problems with BUILD_REQUIRES $params{PREREQ_PM}= { %{ $params{PREREQ_PM} || {} }, %{ $params{BUILD_REQUIRES} } }; delete $params{BUILD_REQUIRES}; } if ( $params{CONFIGURE_REQUIRES} and $eumm_version < 6.52 ) { $params{PREREQ_PM}= { %{ $params{PREREQ_PM} || {} }, %{ $params{CONFIGURE_REQUIRES} } }; delete $params{CONFIGURE_REQUIRES}; } delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48; delete $params{META_MERGE} if $eumm_version < 6.46; delete $params{META_ADD} if $eumm_version < 6.46; delete $params{LICENSE} if $eumm_version < 6.31; delete $params{AUTHOR} if $] < 5.005; delete $params{ABSTRACT_FROM} if $] < 5.005; delete $params{BINARY_LOCATION} if $] < 5.005; delete $params{OPTIMIZE} if $^O eq 'MSWin32'; ExtUtils::MakeMaker::WriteMakefile(%params); } 1;