#
# Copyright (c) 2004-2012 by the cairo perl team (see the file README)
#
# Licensed under the LGPL, see LICENSE file for more information.
#
# $Id$
#
BEGIN { require 5.006; }
use strict;
use warnings;
use ExtUtils::MakeMaker;
require './inc/MakeHelper.pm';
my %extreqs = (
'cairo' => '1.0.0',
);
# Unfortunately we already need these prereqs for writing the Makefile ...
my %prereqs = (
'ExtUtils::Depends' => 0.2,
'ExtUtils::PkgConfig' => 1.0,
);
my %meta_merge = (
q(meta-spec) => {
version => '2',
url => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
},
author =>
['Cairo Perl Team <gtk-perl-list at gnome dot org>'],
release_status => 'stable',
# valid values: https://metacpan.org/module/CPAN::Meta::Spec#license
license => 'lgpl_2_1',
resources => {
license => 'http://www.gnu.org/licenses/lgpl-2.1.html',
homepage => 'http://gtk2-perl.sourceforge.net',
x_MailingList =>
'https://mail.gnome.org/mailman/listinfo/gtk-perl-list',
bugtracker => {
web =>
'http://rt.cpan.org/Public/Dist/Display.html?Name=Cairo',
mailto => 'bug-Cairo [at] rt.cpan.org',
},
repository => {
url => 'git://git.gnome.org/perl-Cairo',
type => 'git',
web => 'http://git.gnome.org/browse/perl-Cairo',
},
},
prereqs => {
configure => {
requires => {%prereqs}, # no direct ref for 5.14 compatibility
},
test => {
recommends => {
'Test::Number::Delta' => 1.0,
},
},
},
no_index => {
file => [qw(inc/MakeHelper.pm)],
},
);
# ... thus we have to make sure they are installed.
while ((my $module, my $version) = each(%prereqs)) {
unless (eval "use $module $version; 1" ) {
print "This module requires $module to install itself.\n";
my $yn = ExtUtils::MakeMaker::prompt(" Install $module from CPAN?", 'n');
unless ($yn =~ /^y/i) {
die " *** Cannot install without $module. Exiting ...\n";
}
require Cwd;
require File::Spec;
require CPAN;
# Save this 'cause CPAN will chdir all over the place.
my $cwd = Cwd::cwd();
my $makefile = File::Spec->rel2abs($0);
CPAN::Shell->install($module);
chdir $cwd
or die "Cannot chdir() back to $cwd: $!";
}
eval "use $module $version; 1" or die $@;
}
my $autogen_dir = 'build';
mkdir $autogen_dir unless (-d $autogen_dir);
$MakeHelper::autogen_dir = $autogen_dir;
my %cairo_cfg;
eval { %cairo_cfg = ExtUtils::PkgConfig->find ("cairo >= $extreqs{cairo}"); };
if ($@ ne '') {
warn $@;
exit 0;
}
my %objects = (
'cairo_t *' => 'Cairo::Context',
'cairo_font_face_t *' => 'Cairo::FontFace',
'cairo_pattern_t *' => 'Cairo::Pattern',
'cairo_region_t *' => 'Cairo::Region',
'cairo_scaled_font_t *' => 'Cairo::ScaledFont',
'cairo_surface_t *' => 'Cairo::Surface',
);
my %structs = (
'cairo_font_options_t *' => 'Cairo::FontOptions',
'cairo_matrix_t *' => 'Cairo::Matrix',
'cairo_rectangle_t *' => 'Cairo::Rectangle',
'cairo_rectangle_int_t *' => 'Cairo::RectangleInt',
);
my %enums = (
cairo_antialias_t => [qw/
CAIRO_ANTIALIAS_
CAIRO_ANTIALIAS_DEFAULT
CAIRO_ANTIALIAS_NONE
CAIRO_ANTIALIAS_GRAY
CAIRO_ANTIALIAS_SUBPIXEL
/],
cairo_content_t => [qw/
CAIRO_CONTENT_
CAIRO_CONTENT_COLOR
CAIRO_CONTENT_ALPHA
CAIRO_CONTENT_COLOR_ALPHA
/],
cairo_extend_t => [qw/
CAIRO_EXTEND_
CAIRO_EXTEND_NONE
CAIRO_EXTEND_REPEAT
CAIRO_EXTEND_REFLECT
/],
cairo_fill_rule_t => [qw/
CAIRO_FILL_RULE_
CAIRO_FILL_RULE_WINDING
CAIRO_FILL_RULE_EVEN_ODD
/],
cairo_filter_t => [qw/
CAIRO_FILTER_
CAIRO_FILTER_FAST
CAIRO_FILTER_GOOD
CAIRO_FILTER_BEST
CAIRO_FILTER_NEAREST
CAIRO_FILTER_BILINEAR
CAIRO_FILTER_GAUSSIAN
/],
cairo_font_slant_t => [qw/
CAIRO_FONT_SLANT_
CAIRO_FONT_SLANT_NORMAL
CAIRO_FONT_SLANT_ITALIC
CAIRO_FONT_SLANT_OBLIQUE
/],
cairo_font_weight_t => [qw/
CAIRO_FONT_WEIGHT_
CAIRO_FONT_WEIGHT_NORMAL
CAIRO_FONT_WEIGHT_BOLD
/],
cairo_format_t => [qw/
CAIRO_FORMAT_
CAIRO_FORMAT_ARGB32
CAIRO_FORMAT_RGB24
CAIRO_FORMAT_A8
CAIRO_FORMAT_A1
/],
cairo_hint_metrics_t => [qw/
CAIRO_HINT_METRICS_
CAIRO_HINT_METRICS_DEFAULT
CAIRO_HINT_METRICS_OFF
CAIRO_HINT_METRICS_ON
/],
cairo_hint_style_t => [qw/
CAIRO_HINT_STYLE_
CAIRO_HINT_STYLE_DEFAULT
CAIRO_HINT_STYLE_NONE
CAIRO_HINT_STYLE_SLIGHT
CAIRO_HINT_STYLE_MEDIUM
CAIRO_HINT_STYLE_FULL
/],
cairo_line_cap_t => [qw/
CAIRO_LINE_CAP_
CAIRO_LINE_CAP_BUTT
CAIRO_LINE_CAP_ROUND
CAIRO_LINE_CAP_SQUARE
/],
cairo_line_join_t => [qw/
CAIRO_LINE_JOIN_
CAIRO_LINE_JOIN_MITER
CAIRO_LINE_JOIN_ROUND
CAIRO_LINE_JOIN_BEVEL
/],
cairo_operator_t => [qw/
CAIRO_OPERATOR_
CAIRO_OPERATOR_CLEAR
CAIRO_OPERATOR_SOURCE
CAIRO_OPERATOR_OVER
CAIRO_OPERATOR_IN
CAIRO_OPERATOR_OUT
CAIRO_OPERATOR_ATOP
CAIRO_OPERATOR_DEST
CAIRO_OPERATOR_DEST_OVER
CAIRO_OPERATOR_DEST_IN
CAIRO_OPERATOR_DEST_OUT
CAIRO_OPERATOR_DEST_ATOP
CAIRO_OPERATOR_XOR
CAIRO_OPERATOR_ADD
CAIRO_OPERATOR_SATURATE
/],
cairo_path_data_type_t => [qw/
CAIRO_PATH_
CAIRO_PATH_MOVE_TO
CAIRO_PATH_LINE_TO
CAIRO_PATH_CURVE_TO
CAIRO_PATH_CLOSE_PATH
/],
cairo_status_t => [qw/
CAIRO_STATUS_
CAIRO_STATUS_SUCCESS
CAIRO_STATUS_NO_MEMORY
CAIRO_STATUS_INVALID_RESTORE
CAIRO_STATUS_INVALID_POP_GROUP
CAIRO_STATUS_NO_CURRENT_POINT
CAIRO_STATUS_INVALID_MATRIX
CAIRO_STATUS_INVALID_STATUS
CAIRO_STATUS_NULL_POINTER
CAIRO_STATUS_INVALID_STRING
CAIRO_STATUS_INVALID_PATH_DATA
CAIRO_STATUS_READ_ERROR
CAIRO_STATUS_WRITE_ERROR
CAIRO_STATUS_SURFACE_FINISHED
CAIRO_STATUS_SURFACE_TYPE_MISMATCH
CAIRO_STATUS_PATTERN_TYPE_MISMATCH
CAIRO_STATUS_INVALID_CONTENT
CAIRO_STATUS_INVALID_FORMAT
CAIRO_STATUS_INVALID_VISUAL
CAIRO_STATUS_FILE_NOT_FOUND
CAIRO_STATUS_INVALID_DASH
/],
cairo_subpixel_order_t => [qw/
CAIRO_SUBPIXEL_ORDER_
CAIRO_SUBPIXEL_ORDER_DEFAULT
CAIRO_SUBPIXEL_ORDER_RGB
CAIRO_SUBPIXEL_ORDER_BGR
CAIRO_SUBPIXEL_ORDER_VRGB
CAIRO_SUBPIXEL_ORDER_VBGR
/],
);
my %flags = ();
# --------------------------------------------------------------------------- #
my @exports = qw(
cairo_font_face_to_sv
cairo_font_type_from_sv
cairo_font_type_to_sv
cairo_object_from_sv
cairo_object_to_sv
cairo_pattern_to_sv
cairo_struct_from_sv
cairo_struct_to_sv
cairo_surface_to_sv
newSVCairoGlyph
SvCairoGlyph
newSVCairoPath
SvCairoPath
newSVCairoFontExtents
newSVCairoTextExtents
cairo_antialias_from_sv
cairo_antialias_to_sv
cairo_content_from_sv
cairo_content_to_sv
cairo_extend_from_sv
cairo_extend_to_sv
cairo_fill_rule_from_sv
cairo_fill_rule_to_sv
cairo_filter_from_sv
cairo_filter_to_sv
cairo_font_slant_from_sv
cairo_font_slant_to_sv
cairo_font_weight_from_sv
cairo_font_weight_to_sv
cairo_format_from_sv
cairo_format_to_sv
cairo_hint_metrics_from_sv
cairo_hint_metrics_to_sv
cairo_hint_style_from_sv
cairo_hint_style_to_sv
cairo_line_cap_from_sv
cairo_line_cap_to_sv
cairo_line_join_from_sv
cairo_line_join_to_sv
cairo_operator_from_sv
cairo_operator_to_sv
cairo_path_data_type_from_sv
cairo_path_data_type_to_sv
cairo_status_from_sv
cairo_status_to_sv
cairo_subpixel_order_from_sv
cairo_subpixel_order_to_sv
);
# --------------------------------------------------------------------------- #
sub add_new_enum_values {
my (%new) = @_;
foreach my $enum (keys %new) {
foreach my $value (@{$new{$enum}}) {
push @{$enums{$enum}}, $value;
}
}
}
my $have_cairo_1_2 = ExtUtils::PkgConfig->atleast_version("cairo", "1.2.0");
my $have_cairo_1_4 = ExtUtils::PkgConfig->atleast_version("cairo", "1.4.0");
my $have_cairo_1_6 = ExtUtils::PkgConfig->atleast_version("cairo", "1.6.0");
my $have_cairo_1_8 = ExtUtils::PkgConfig->atleast_version("cairo", "1.8.0");
my $have_cairo_1_10 = ExtUtils::PkgConfig->atleast_version("cairo", "1.10.0");
if ($have_cairo_1_2) {
add_new_enum_values(
cairo_extend_t => [qw/CAIRO_EXTEND_PAD/],
cairo_format_t => [qw/CAIRO_FORMAT_RGB16_565/],
cairo_status_t => [qw/CAIRO_STATUS_INVALID_DSC_COMMENT/],
);
$enums{cairo_font_type_t} = [qw/
CAIRO_FONT_TYPE_
CAIRO_FONT_TYPE_TOY
CAIRO_FONT_TYPE_FT
CAIRO_FONT_TYPE_WIN32
CAIRO_FONT_TYPE_ATSUI
/];
$enums{cairo_pattern_type_t} = [qw/
CAIRO_PATTERN_TYPE_
CAIRO_PATTERN_TYPE_SOLID
CAIRO_PATTERN_TYPE_SURFACE
CAIRO_PATTERN_TYPE_LINEAR
CAIRO_PATTERN_TYPE_RADIAL
/];
$enums{cairo_surface_type_t} = [qw/
CAIRO_SURFACE_TYPE_
CAIRO_SURFACE_TYPE_IMAGE
CAIRO_SURFACE_TYPE_PDF
CAIRO_SURFACE_TYPE_PS
CAIRO_SURFACE_TYPE_XLIB
CAIRO_SURFACE_TYPE_XCB
CAIRO_SURFACE_TYPE_GLITZ
CAIRO_SURFACE_TYPE_QUARTZ
CAIRO_SURFACE_TYPE_WIN32
CAIRO_SURFACE_TYPE_BEOS
CAIRO_SURFACE_TYPE_DIRECTFB
CAIRO_SURFACE_TYPE_SVG
/];
$enums{cairo_svg_version_t} = [qw/
CAIRO_SVG_VERSION_
CAIRO_SVG_VERSION_1_1
CAIRO_SVG_VERSION_1_2
/];
push @exports, qw/cairo_font_type_from_sv
cairo_font_type_to_sv
cairo_pattern_type_from_sv
cairo_pattern_type_to_sv
cairo_surface_type_from_sv
cairo_surface_type_to_sv
cairo_svg_version_from_sv
cairo_svg_version_to_sv/;
} else {
# We need to create empty enum entries for new types so that typemaps
# are generated for them. xsubpp demands typemaps even if the code is
# #if'd out.
$enums{cairo_font_type_t} = [];
$enums{cairo_pattern_type_t} = [];
$enums{cairo_surface_type_t} = [];
$enums{cairo_svg_version_t} = [];
}
if ($have_cairo_1_4) {
add_new_enum_values(
cairo_status_t => [qw/CAIRO_STATUS_INVALID_INDEX
CAIRO_STATUS_CLIP_NOT_REPRESENTABLE/],
cairo_surface_type_t => [qw/CAIRO_SURFACE_TYPE_OS2/],
);
push @exports, qw/newSVCairoRectangle
SvCairoRectangle/;
}
if ($have_cairo_1_6) {
add_new_enum_values(
cairo_font_type_t => [qw/CAIRO_FONT_TYPE_QUARTZ/],
cairo_status_t => [qw/CAIRO_STATUS_TEMP_FILE_ERROR
CAIRO_STATUS_INVALID_STRIDE/],
cairo_surface_type_t => [qw/CAIRO_SURFACE_TYPE_WIN32_PRINTING
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE/],
);
$enums{cairo_ps_level_t} = [qw/
CAIRO_PS_LEVEL_
CAIRO_PS_LEVEL_2
CAIRO_PS_LEVEL_3
/];
push @exports, qw/cairo_ps_level_from_sv
cairo_ps_level_to_sv/;
} else {
$enums{cairo_ps_level_t} = [];
}
if ($have_cairo_1_8) {
add_new_enum_values(
cairo_status_t => [qw/CAIRO_STATUS_FONT_TYPE_MISMATCH
CAIRO_STATUS_USER_FONT_IMMUTABLE
CAIRO_STATUS_USER_FONT_ERROR
CAIRO_STATUS_NEGATIVE_COUNT
CAIRO_STATUS_INVALID_CLUSTERS
CAIRO_STATUS_INVALID_SLANT
CAIRO_STATUS_INVALID_WEIGHT/],
cairo_font_type_t => [qw/CAIRO_FONT_TYPE_USER/],
);
$flags{cairo_text_cluster_flags_t} = [qw/
CAIRO_TEXT_CLUSTER_FLAG_
CAIRO_TEXT_CLUSTER_FLAG_BACKWARD
/];
push @exports, qw/newSVCairoTextCluster
SvCairoTextCluster
cairo_text_cluster_flags_from_sv
cairo_text_cluster_flags_to_sv/;
} else {
$flags{cairo_text_cluster_flags_t} = [];
}
if ($have_cairo_1_10) {
add_new_enum_values(
cairo_surface_type_t => [
qw/CAIRO_SURFACE_TYPE_SCRIPT
CAIRO_SURFACE_TYPE_QT
CAIRO_SURFACE_TYPE_RECORDING
CAIRO_SURFACE_TYPE_VG
CAIRO_SURFACE_TYPE_GL
CAIRO_SURFACE_TYPE_DRM
CAIRO_SURFACE_TYPE_TEE
CAIRO_SURFACE_TYPE_XML
CAIRO_SURFACE_TYPE_SKIA
CAIRO_SURFACE_TYPE_SUBSURFACE/],
cairo_operator_t => [
qw/CAIRO_OPERATOR_MULTIPLY
CAIRO_OPERATOR_SCREEN
CAIRO_OPERATOR_OVERLAY
CAIRO_OPERATOR_DARKEN
CAIRO_OPERATOR_LIGHTEN
CAIRO_OPERATOR_COLOR_DODGE
CAIRO_OPERATOR_COLOR_BURN
CAIRO_OPERATOR_HARD_LIGHT
CAIRO_OPERATOR_SOFT_LIGHT
CAIRO_OPERATOR_DIFFERENCE
CAIRO_OPERATOR_EXCLUSION
CAIRO_OPERATOR_HSL_HUE
CAIRO_OPERATOR_HSL_SATURATION
CAIRO_OPERATOR_HSL_COLOR
CAIRO_OPERATOR_HSL_LUMINOSITY/],
);
$enums{cairo_pdf_version_t} = [qw/
CAIRO_PDF_VERSION_
CAIRO_PDF_VERSION_1_4
CAIRO_PDF_VERSION_1_5
/];
$enums{cairo_region_overlap_t} = [qw/
CAIRO_REGION_OVERLAP_
CAIRO_REGION_OVERLAP_IN
CAIRO_REGION_OVERLAP_OUT
CAIRO_REGION_OVERLAP_PART
/];
push @exports, qw/newSVCairoRectangleInt
SvCairoRectangleInt
cairo_pdf_version_from_sv
cairo_pdf_version_to_sv
cairo_region_overlap_from_sv
cairo_region_overlap_to_sv/;
} else {
$enums{cairo_pdf_version_t} = [];
$enums{cairo_region_overlap_t} = [];
}
# --------------------------------------------------------------------------- #
my %object_guards = (
cairo_region_t => '#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)',
);
my %struct_guards = (
cairo_rectangle_t => '#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 4, 0)',
cairo_rectangle_int_t => '#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)',
);
my %enum_guards = (
cairo_ps_level_t => '#ifdef CAIRO_HAS_PS_SURFACE',
cairo_svg_version_t => '#ifdef CAIRO_HAS_SVG_SURFACE',
);
my %flag_guards = ();
MakeHelper::do_enums (\%enums, \%enum_guards);
MakeHelper::do_flags (\%flags, \%flag_guards);
my @xs_files = qw(
Cairo.xs
CairoFont.xs
CairoMatrix.xs
CairoPath.xs
CairoPattern.xs
CairoSurface.xs
);
if ($have_cairo_1_10) {
push @xs_files, 'CairoRegion.xs';
}
my $have_cairo_ft = !system qw(pkg-config --exists --silence-errors cairo-ft);
if ($have_cairo_ft) {
print "Compiling Cairo with FreeType support\n";
push @xs_files, 'CairoFt.xs';
my %ft_cfg = ExtUtils::PkgConfig->find ('cairo-ft');
$cairo_cfg{cflags} .= ' '.$ft_cfg{cflags};
$cairo_cfg{libs} .= ' '.$ft_cfg{libs};
}
MakeHelper::write_boot (
xs_files => \@xs_files,
ignore => '^Cairo$',
);
my @typemaps = MakeHelper::do_typemaps (\%objects, \%structs, \%enums, \%flags,
\%object_guards,
\%struct_guards,
\%enum_guards,
\%flag_guards);
push @typemaps, 'cairo-perl.typemap';
my $dep = ExtUtils::Depends->new ('Cairo');
$dep->set_inc ('-I. -I'.$autogen_dir.' '.$cairo_cfg{cflags});
$dep->set_libs ($cairo_cfg{libs});
$dep->add_xs (@xs_files);
$dep->add_c (qw/cairo-perl-enums.c cairo-perl-flags.c/);
$dep->add_pm ('lib/Cairo.pm' => '$(INST_LIBDIR)/Cairo.pm');
$dep->add_typemaps (@typemaps);
$dep->install (qw(cairo-perl.h
cairo-perl.typemap
doctypes
build/cairo-perl-auto.h
build/cairo-perl-auto.typemap));
$dep->save_config ('build/IFiles.pm');
# On OpenBSD, any program that directly or indirectly wants to load
# libpthread.so must do so from the start. But when perl is built without
# ithreads, it will also most likely not be compiled with "-pthread". When
# libglib/libgobject then go and try to load libpthread.so, the loader will
# error out.
my @openbsd_compat_flags = ();
if ($^O eq 'openbsd' && $Config::Config{ldflags} !~ m/-pthread\b/) {
warn " ***\n *** on OpenBSD, we either need perl linked with '-pthread',\n",
" *** or we need to set LD_PRELOAD=libpthread.so; doing the latter now...\n ***\n";
@openbsd_compat_flags = (
macro => {FULLPERLRUN => 'LD_PRELOAD=libpthread.so $(FULLPERL)'},
);
}
WriteMakefile (
NAME => 'Cairo',
#AUTHOR, LICENSE are now part of %meta_merge
VERSION_FROM => 'lib/Cairo.pm',
ABSTRACT_FROM => 'lib/Cairo.pm',
PREREQ_PM => \%prereqs,
XSPROTOARG => '-noprototypes',
FUNCLIST => \@exports,
DL_FUNCS => { Cairo=> [] },
META_MERGE => \%meta_merge,
$dep->get_makefile_vars,
@openbsd_compat_flags,
);
sub MY::postamble
{
my $autogen_dir = $MakeHelper::autogen_dir;
"realclean ::
-\$(RM_RF) $autogen_dir cairo-perl-enums.*";
}