1package    #
2    inc::Sereal::BuildTools;
3use strict;
4use warnings;
5
6use Config;
7use constant OSNAME   => $^O;
8
9my %bare_minimum_files= map { $_ => 1 } qw{
10    typemap
11    ppport.h
12    srl_stack.h
13    srl_common.h
14    srl_inline.h
15    srl_taginfo.h
16    srl_protocol.h
17    srl_reader_error.h
18    srl_reader_types.h
19    inc/Sereal/BuildTools.pm
20    inc/Devel/CheckLib.pm
21    inc/Sereal
22    inc/Devel
23    inc
24};
25
26sub link_files {
27    my $shared_dir= shift;
28    my $mode= shift || "";
29    my $exclude_tests= $mode eq "without_tests";
30    my $tests_only= $mode eq "tests_only";
31    my $bare_minimum= $mode eq "bare_minimum";
32
33    # This fires from a git source tree only.
34    # Right now, all devs are on Linux. Feel free to make portable.
35    eval {
36        # overwrite by default
37        require File::Find;
38        require File::Path;
39        require File::Spec;
40        File::Find::find( {
41                no_chdir => 1,
42                wanted   => sub {
43                    my $f= $_;
44                    s/^\Q$shared_dir\E\/?// or die $_;
45                    return unless $_;
46                    return if $exclude_tests && m#^/?t/#;
47                    return if $tests_only    && !m#^/?t/#;
48                    return if $bare_minimum  && !exists $bare_minimum_files{$_};
49
50                    if ( -d $f ) {
51                        File::Path::mkpath($_);
52                    }
53                    elsif ( -f $f ) {
54                        return if $f =~ /(?:\.bak|\.sw[po]|~)$/;
55                        my @d= File::Spec->splitdir($_);
56                        my $fname= pop @d;
57                        my $ref= join "/", ("..") x scalar(@d);
58                        my $subd= join "/", @d;
59                        chdir $subd if length($ref);
60                        my $srcfname= join( "/", grep length, $ref, $shared_dir, $subd, $fname );
61                        if ( OSNAME eq 'MSWin32' ) {
62                            die "link($srcfname, $fname) failed: $!"
63                                unless link( $srcfname, $fname );    #only NTFS implements it
64                        }
65                        else {
66                            symlink( $srcfname, $fname );
67                        }
68                        chdir($ref) if length($ref);
69                    }
70                },
71            },
72            $shared_dir
73        );
74        1;
75    } or warn $@;
76}
77
78sub generate_constant_includes {
79
80    # no-op
81}
82
83# Prefer external csnappy and miniz libraries over the bundled ones.
84sub check_external_libraries {
85    my ( $libs, $defines, $objects, $subdirs )= @_;
86    require Devel::CheckLib;
87
88    if (
89           !$ENV{SEREAL_USE_BUNDLED_LIBS}
90        && !$ENV{SEREAL_USE_BUNDLED_CSNAPPY}
91        && Devel::CheckLib::check_lib(
92            lib    => 'csnappy',
93            header => 'csnappy.h'
94        ) )
95    {
96        print "Using installed csnappy library\n";
97        $$libs    .= ' -lcsnappy';
98        $$defines .= ' -DHAVE_CSNAPPY';
99    }
100    else {
101        print "Using bundled csnappy code\n";
102    }
103
104    if (
105           !$ENV{SEREAL_USE_BUNDLED_LIBS}
106        && !$ENV{SEREAL_USE_BUNDLED_MINIZ}
107        && Devel::CheckLib::check_lib(
108            lib    => 'miniz',
109            header => 'miniz.h'
110        ) )
111    {
112        print "Using installed miniz library\n";
113        $$libs    .= ' -lminiz';
114        $$defines .= ' -DHAVE_MINIZ';
115    }
116    else {
117        print "Using bundled miniz code\n";
118        $$objects .= ' miniz$(OBJ_EXT)';
119    }
120
121    if (
122           !$ENV{SEREAL_USE_BUNDLED_LIBS}
123        && !$ENV{SEREAL_USE_BUNDLED_ZSTD}
124        && Devel::CheckLib::check_lib(
125            lib    => 'zstd',
126            header => 'zstd.h'
127        ) )
128    {
129        print "Using installed zstd library\n";
130        $$libs    .= ' -lzstd';
131        $$defines .= ' -DHAVE_ZSTD';
132    }
133    else {
134        print "Using bundled zstd code\n";
135        push @{$subdirs}, 'zstd';
136        $$objects .= ' zstd/libzstd$(OBJ_EXT)';
137    }
138}
139
140sub build_defines {
141    my (@defs)= @_;
142
143    my $defines= join(
144        " ", map { "-D$_" . ( defined $ENV{$_} ? "=$ENV{$_}" : '' ) }
145            grep { exists $ENV{$_} } ( qw(NOINLINE DEBUG MEMDEBUG NDEBUG), @defs ) );
146
147    $defines .= " -DNDEBUG" unless $ENV{DEBUG};
148    if ( $Config{osname} eq 'hpux' && not $Config{gccversion} ) {
149
150        # HP-UX cc does not support inline.
151        # Or rather, it does, but it depends on the compiler flags,
152        # assumedly -AC99 instead of -Ae would work.
153        # But we cannot change the compiler config too much from
154        # the one that was used to compile Perl,
155        # so we just fake the inline away.
156        $defines .= " -Dinline= ";
157    }
158
159    return $defines;
160}
161
162sub build_optimize {
163    my $cc_flags= shift || {};
164
165    my $catch_violations= exists $cc_flags->{catch_violations} ? $cc_flags->{catch_violations} : 1;
166
167    my $OPTIMIZE;
168
169    my $clang= 0;
170    if ( $Config{gccversion} ) {
171        $OPTIMIZE= '-O3';
172        if ( $Config{gccversion} =~ /[Cc]lang/ ) {    # clang.
173            $clang= 1;
174        }
175
176        my $gccversion= 0;
177        if ( $Config{gccversion} =~ /^(\d+\.\d+)/ ) {
178            $gccversion= $1;
179        }
180
181        if ( $catch_violations && ( $clang || $gccversion >= 4.3 ) ) {
182
183            # -Werror= introduced in GCC 4.3
184            # For trapping C++ // comments we would need -std=c89 (aka -ansi)
185            # but that may be asking too much of different platforms.
186            $OPTIMIZE .= ' -Werror=declaration-after-statement ';
187        }
188
189    }
190    elsif ( $Config{osname} eq 'MSWin32' ) {
191        $OPTIMIZE= '-O2 -W4';
192    }
193    else {
194        $OPTIMIZE= $Config{optimize};
195    }
196
197    if ( $ENV{DEBUG} ) {
198        $OPTIMIZE .= ' -g';
199        if ( $ENV{DEBUG} > 0 && $Config{gccversion} ) {
200            $OPTIMIZE .= ' -Wextra'      if $ENV{DEBUG} > 1;
201            $OPTIMIZE .= ' -pedantic'    if $ENV{DEBUG} > 5;                  # not pretty
202            $OPTIMIZE .= ' -Weverything' if ( $ENV{DEBUG} > 6 && $clang );    # really not pretty
203        }
204    }
205
206    return $OPTIMIZE;
207}
208
209sub WriteMakefile {
210    require ExtUtils::MakeMaker;
211
212    #Original by Alexandr Ciornii, modified by Yves Orton
213    my %params= @_;
214    my $eumm_version= $ExtUtils::MakeMaker::VERSION;
215    $eumm_version= eval $eumm_version;
216    die "EXTRA_META is deprecated" if exists $params{EXTRA_META};
217    die "License not specified" if not exists $params{LICENSE};
218    if ( $params{TEST_REQUIRES} and $eumm_version < 6.6303 ) {
219        $params{BUILD_REQUIRES}=
220            { %{ $params{BUILD_REQUIRES} || {} }, %{ $params{TEST_REQUIRES} } };
221        delete $params{TEST_REQUIRES};
222    }
223    if ( $params{BUILD_REQUIRES} and $eumm_version < 6.5503 ) {
224
225        #EUMM 6.5502 has problems with BUILD_REQUIRES
226        $params{PREREQ_PM}= { %{ $params{PREREQ_PM} || {} }, %{ $params{BUILD_REQUIRES} } };
227        delete $params{BUILD_REQUIRES};
228    }
229    if ( $params{CONFIGURE_REQUIRES} and $eumm_version < 6.52 ) {
230        $params{PREREQ_PM}= { %{ $params{PREREQ_PM} || {} }, %{ $params{CONFIGURE_REQUIRES} } };
231        delete $params{CONFIGURE_REQUIRES};
232    }
233    delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48;
234    delete $params{META_MERGE}       if $eumm_version < 6.46;
235    delete $params{META_ADD}         if $eumm_version < 6.46;
236    delete $params{LICENSE}          if $eumm_version < 6.31;
237    delete $params{AUTHOR}           if $] < 5.005;
238    delete $params{ABSTRACT_FROM}    if $] < 5.005;
239    delete $params{BINARY_LOCATION}  if $] < 5.005;
240    delete $params{OPTIMIZE}         if $^O eq 'MSWin32';
241
242    ExtUtils::MakeMaker::WriteMakefile(%params);
243}
244
2451;
246