1#  Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization
2#  dedicated to making software imaging solutions freely available.
3#
4#  You may not use this file except in compliance with the License.  You may
5#  obtain a copy of the License at
6#
7#    https://imagemagick.org/script/license.php
8#
9#  Unless required by applicable law or agreed to in writing, software
10#  distributed under the License is distributed on an "AS IS" BASIS,
11#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12#  See the License for the specific language governing permissions and
13#  limitations under the License.
14#
15#  Exercise all regression tests:
16#
17#    make test
18#
19#  Exersise one regression test:
20#
21#    make TEST_VERBOSE=1 TEST_FILES=t/filter.t test
22#
23
24use ExtUtils::MakeMaker;
25use Config;
26use File::Spec::Functions qw/catfile catdir devnull catpath splitpath/;
27use Cwd;
28
29sub AutodetectWin32gcc {
30  my $wrkdir = getcwd();
31  my $devnull = devnull();
32
33  my @incdir = ();
34  my @libdir = ($wrkdir);
35  my @bindir = ();
36
37  #try to get configuration info via magick or identify utilities
38  my $conf = `magick identify -list Configure 2>$devnull` || `identify -list Configure 2>$devnull`;
39  foreach my $line (split '\n', $conf) {
40    if ($line =~ /^Path:\s+(.*)/) {
41      my ($vol,$dir,$file) = splitpath($1);
42      next unless $dir;
43      my $dirpath = catpath( $vol, $dir);
44      my (@l,@b,@i) = ( (),(),() );
45
46      # try to detect 'lib' dir
47      push @l, catfile($dirpath,'lib');
48      push @l, catfile($dirpath,'..','lib');
49      push @l, catfile($dirpath,'..','..','lib');
50      push @l, catfile($dirpath,'..','..','..','lib');
51      foreach (@l) { push @libdir, $_ if (-d $_) };
52
53      # try to detect 'bin' dir
54      push @b, catfile($dirpath);
55      push @b, catfile($dirpath,'bin');
56      push @b, catfile($dirpath,'..');
57      push @b, catfile($dirpath,'..','bin');
58      push @b, catfile($dirpath,'..','..');
59      push @b, catfile($dirpath,'..','..','bin');
60      push @b, catfile($dirpath,'..','..','..');
61      push @b, catfile($dirpath,'..','..','..','bin');
62      foreach (@b) { push @bindir, $_ if (-e "$_/magick.exe" || -e "$_/identify.exe") };
63
64      # try to detect 'include' dir
65      push @i, catfile($dirpath,'include');
66      push @i, catfile($dirpath,'include','ImageMagick');
67      push @i, catfile($dirpath,'..','include');
68      push @i, catfile($dirpath,'..','include','ImageMagick');
69      push @i, catfile($dirpath,'..','..','include');
70      push @i, catfile($dirpath,'..','..','include','ImageMagick');
71      push @i, catfile($dirpath,'..','..','..','include');
72      push @i, catfile($dirpath,'..','..','..','include','ImageMagick');
73      foreach (@i) { push @incdir, $_ if (-e "$_/MagickCore/MagickCore.h") };
74    }
75  };
76
77  foreach my $bin (@bindir) {
78    opendir(my $bindir, $bin) or die qq{Cannot opendir $bin: $!};
79    my @dlls = map {catfile($bin, $_)} grep /^\S*magick[^\+]\S*?\.dll$/i, readdir $bindir;
80    foreach my $d (@dlls) {
81      unlink "$wrkdir/libMagickCore.def", "$wrkdir/libMagickCore.a";
82      system("pexports \"$d\" >\"$wrkdir/libMagickCore.def\" 2>$devnull");
83      open(DEF, "<$wrkdir/libMagickCore.def");
84      my @found = grep(/MagickCoreGenesis/, <DEF>); #checking if we have taken the right DLL
85      close(DEF);
86      next unless(@found);
87      print STDERR "Gonna create 'libMagickCore.a' from '$d'\n";
88      system("dlltool -D \"$d\" -d \"$wrkdir/libMagickCore.def\" -l \"$wrkdir/libMagickCore.a\" 2>$devnull");
89      last if -s "$wrkdir/libMagickCore.a";
90    }
91    last if -s "$wrkdir/libMagickCore.a";
92  }
93
94  unless(@incdir && @libdir && @bindir && (-s "$wrkdir/libMagickCore.a")) {
95    print STDERR <<EOF
96################################### WARNING! ###################################
97# It seems that you are trying to install Perl::Magick on a MS Windows box with
98# perl + gcc compiler (e.g. strawberry perl), however we cannot find ImageMagick
99# binaries installed on your system.
100#
101# Please check the following prerequisites:
102#
103# 1) You need to have installed ImageMagick Windows binaries from
104#    https://imagemagick.org/script/binary-releases.php#windows
105#
106# 2) We only support dynamic (DLL) ImageMagick binaries
107#    note: it is not possible to mix 32/64-bit binaries of perl and ImageMagick
108#
109# 3) During installation select that you want to install ImageMagick's
110#    development files (libraries+headers)
111#
112# 4) You NEED TO have ImageMagick's directory in your PATH.  We are
113#    using the 'magick' tool to determine your actual configuration.
114#
115# 5) You might need Visual C++ Redistributable Package installed on your system
116#    see instructions on ImageMagick's Binary Release webpage
117#
118# We are gonna continue, but chances for successful build are very low!
119################################################################################
120EOF
121  }
122
123  my $inc = join ' ', map "-I\"$_\"", @incdir;
124  my $lib = join ' ', map "-L\"$_\"", @libdir;
125
126  return ($inc, $lib);
127}
128
129sub AutodetectDelegates {
130  #try to get configuration info via magick or identify utilities
131  my $devnull = devnull();
132  my $conf = `magick identify -list Configure 2>$devnull` || `identify -list Configure 2>$devnull`;
133  my @delegates = ();
134  foreach my $line (split '\n', $conf) {
135    next unless $line =~ /^DELEGATES\s+/;
136    (undef, @delegates) = split /\s+/, $line;
137    last;
138  };
139  return @delegates;
140}
141
142# Compute test specification
143my $delegate_tests='t/*.t';
144my @tested_delegates = qw/bzlib djvu fftw fontconfig freetype jpeg jng openjp2 lcms png rsvg tiff x11 xml wmf zlib/;
145my @supported_delegates = AutodetectDelegates();
146# find the intersection of tested and supported delegates
147my %seen_delegates = ();
148$seen_delegates{$_}++ for @supported_delegates;
149foreach my $delegate (@tested_delegates) {
150  if ( $seen_delegates{$delegate} ) {
151    if ( -d "t/$delegate" ) {
152      if ( defined($ENV{'DISPLAY'}) && ($^O ne 'MSWin32') ) {
153        if ( defined $ENV{'DISPLAY'} ) {
154          $delegate_tests .= " t/$delegate/*.t";
155        }
156        next;
157      }
158      $delegate_tests .= " t/$delegate/*.t";
159    }
160  }
161}
162
163# defaults for LIBS & INC & CCFLAGS params that we later pass to Writemakefile
164my $INC_magick = '-I../ -I..  -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=16  -I"' . $Config{'usrinc'} . '/ImageMagick"';
165my $LIBS_magick = '-L../MagickCore/.libs -lMagickCore-7.Q16HDRI -lm -L' . $Config{'archlib'} . '/CORE';
166my $CCFLAGS_magick = "$Config{'ccflags'} -I/usr/include/libxml2    -I/usr/include/libraw  -I/usr/include/libpng16   -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/uuid -I/usr/include/harfbuzz  -I/usr/include/OpenEXR -pthread   -I/usr/include/openjpeg-2.4   -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/fribidi  -I/usr/include/freetype2 -I/usr/include/libpng16  -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/uuid  -pthread    -fopenmp -Wall -g -O2 -mtune=amdfam10 -fexceptions -pthread -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=16";
167my $LDFLAGS_magick   = "-L../MagickCore/.libs -lMagickCore-7.Q16HDRI $Config{'ldflags'}  ";
168my $LDDLFLAGS_magick = "-L../MagickCore/.libs -lMagickCore-7.Q16HDRI $Config{'lddlflags'}  ";
169
170if (($^O eq 'MSWin32') && ($Config{cc} =~ /gcc/)) {
171  my($Ipaths, $Lpaths) = AutodetectWin32gcc();
172
173  #
174  # Setup for strawberry perl.
175  #
176  $INC_magick       = "$Ipaths";
177  $LIBS_magick      = "-lMagickCore-7.Q16HDRI";
178  $CCFLAGS_magick   = "$Config{'ccflags'}";
179  $LDFLAGS_magick   = "$Config{'ldflags'} $Lpaths ";
180  $LDDLFLAGS_magick = "$Config{'lddlflags'} $Lpaths ";
181}
182
183# See lib/ExtUtils/MakeMaker.pm for details of how to influence
184# the contents of the Makefile that is written.
185WriteMakefile
186  (
187   # Module description
188   'ABSTRACT'	=> 'ImageMagick PERL Extension',
189
190   # Perl module name is Image::Magick
191   'NAME'	=> 'Image::Magick',
192
193   # Module author
194   'AUTHOR' => 'ImageMagick Studio LLC',
195
196   # Module version
197   'VERSION' => '7.1.0',
198
199   # Prerequisite version
200   'PREREQ_PM' => {'parent' => '0'},
201
202   # Preprocessor defines
203   'DEFINE'	=> ' -D_LARGE_FILES=1 -DHAVE_CONFIG_H',     # e.g., '-DHAVE_SOMETHING'
204
205   # Header search specfication and preprocessor flags
206   'INC'	=> $INC_magick,
207
208   # C compiler
209   #'CC' => 'gcc',
210
211   # C pre-processor flags (e.g. -I & -D options)
212   # 'CPPFLAGS' => "$Config{'cppflags'}  -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=16 ",
213
214   # C compiler flags (e.g. -O -g)
215   'CCFLAGS' => $CCFLAGS_magick,
216
217   # Linker
218   #'LD' => $Config{'ld'} == $Config{'cc'} ? 'gcc' : $Config{'ld'},
219
220   # Linker flags for building an executable
221   'LDFLAGS' =>  $LDFLAGS_magick,
222
223   # Linker flags for building a dynamically loadable module
224   'LDDLFLAGS' => $LDDLFLAGS_magick,
225
226   # Install PerlMagick binary into ImageMagick bin directory
227   'INSTALLBIN'	=> '/usr/bin',
228
229   # Library specification
230   'LIBS' => [ $LIBS_magick ],
231
232   # Perl binary name (if a Perl binary is built)
233   'MAP_TARGET'	=> 'PerlMagick',
234
235   # Let CFLAGS drive optimization flags by setting OPTIMIZE to empty
236   # 'OPTIMIZE'	=> '',
237
238   # Use same compiler as ImageMagick
239   'PERLMAINCC'	=> ' -fopenmp',
240   'AR' => 'ar',
241   'LD' => '',
242
243   # Set Perl installation prefix to ImageMagick installation prefix
244#   'PREFIX'	=> '/usr',
245
246   # Include delegate directories in tests
247   test	=> { TESTS	=>	$delegate_tests},
248
249   ($Config{'archname'} =~ /-object$/i ? ('CAPI' => 'TRUE') : ()),
250
251   # sane version
252   depend => { '$(FIRST_MAKEFILE)' => '$(VERSION_FROM)' }
253);
254
255
256#
257# Substitutions for "makeaperl" section.
258#
259sub MY::makeaperl {
260     package MY; # so that "SUPER" works right
261     my $inherited = shift->SUPER::makeaperl(@_);
262
263     # Stinky ExtUtils::MM_Unix likes to append its own library path to $(CC),
264     # prior to any user-specified library path so that an installed library is
265     # used rather than the library just built.  This substitution function
266     # tries to insert our library path first. Also, use the same compiler used
267     # to build perlmain.c to link so that a C++ compiler may be used if
268     # necessary.
269     $inherited =~ s:MAP_LINKCMD\s.*\s*\$\(CC\):MAP_LINKCMD   = \$(PERLMAINCC) -L/usr/lib64: ;
270     $inherited;
271 }
272