The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
use Config;
use ExtUtils::MakeMaker;
use strict;
use warnings;

my $OGRE_REQ_VERSION = '1.6.1';
my $OIS_REQ_VERSION = '0.04';

main();
exit 0;

sub main {
    my $fixed_args = fixed_args('Ogre');
    my $varied_args = varied_args();
    my $gpp_warn_args = gpp_warn_args();

    WriteMakefile(%$fixed_args, %$varied_args, %$gpp_warn_args);
}

sub gpp_warn_args {
    # If you're using gcc >= 4.2, you'll probably
    # get warnings like this during `make` :
    #  OIS.c:1835: warning: deprecated conversion from string constant to 'char*'
    # The C code generated by `xsubpp` uses literal strings (string constants)
    # as args to functions expecting char*. This disables those warnings....

    if (my_compiler() eq 'g++') {
        my $str = `g++ -dumpversion`;
        unless ($?) {
            chomp $str;
            my ($v, $s) = split /\./, $str;
            if (($v == 4 && $s >= 2) || $v > 4) {
                return {'CCFLAGS' => '-Wno-write-strings'};
            }
        }
    }

    # there will be no warnings, or we'll just tolerate them
    return {};
}

sub my_compiler {
    return $ENV{'CXX'} || 'g++';
}

sub fixed_args {
    my ($pkg) = @_;

    return {
        'NAME'          => $pkg,
        'VERSION_FROM'  => "$pkg.pm",
        'ABSTRACT_FROM' => "$pkg.pm",
        'AUTHOR'        => 'Scott Lanning <slanning@cpan.org>',
        'LD'            => '$(CC)',
        'OBJECT'        => '$(O_FILES)',
        'MAN3PODS'      => {},
        'XSOPT'         => '-C++',
        'TYPEMAPS'      => ['perlobject.map'],
    };
}

sub varied_args {
    # Make sure OGRE libs are known by pkg-config
    my $pkgname = 'OGRE';

    my @errors = ();
    push @errors, check_pkg_config($pkgname, $OGRE_REQ_VERSION);
    if (@errors) {
        die(map { "$_$/" } @errors);
    }

    # Get include dirs and defines
    my @cflags = ();
    push @cflags, pkg_config($pkgname, 'cflags');

    # Get lib dirs
    my @libs = ();
    push @libs, pkg_config($pkgname, 'libs');

    my @defines = ();


    # Check if Gtk+ is installed
    # (don't know what version is actually required, gtk2-perl uses 2.0.0)
    $pkgname = 'gtk+-2.0';

    @errors = check_pkg_config($pkgname, '2.0.0');
    if (@errors) {
        print "\nNote: gtk+ support not enabled.\nReasons:\n",
          map({ "- $_$/" } @errors);
        print "See README.txt for information on enabling Gtk2 support.\n";
    }
    else {
        print "\nEnabling gtk+ support.\n";
        push @cflags, pkg_config($pkgname, 'cflags');
        push @libs, pkg_config($pkgname, 'libs');
        push @defines, '-DPERLOGRE_HAS_GTK2';
    }


    my %prereqs = (
        'Test::More' => 0,
    );

    # Check if optional Perl modules are installed.
    unless (eval { require OIS && $OIS::VERSION >= $OIS_REQ_VERSION }) {
        my $msg = "\nNote: the Perl module OIS >= $OIS_REQ_VERSION is not installed,\n"
          . "so you won't be able to run some examples\n"
          . "or use Ogre::ExampleFrameListener.\n"
          . "Installing OIS would be a very good idea\n"
          . "unless you have some other way to handle keyboard and mouse input.\n"
          . "It's fine to install it after installing Ogre.\n\n"
          . "Do you want to install OIS now?";

        my $val = ExtUtils::MakeMaker::prompt($msg, 'n');
        if ($val =~ /^y/i) {
            $prereqs{'OIS'} = $OIS_REQ_VERSION;
            print "\nOIS >= $OIS_REQ_VERSION added to prerequisites.\n";
        }
    }
    # xxx: should remove the Readonly dependency....
    unless (eval { require Readonly }) {
        my $msg = "\nNote: the Perl module Readonly is not installed,\n"
          . "so you won't be able to run some examples.\n"
          . "I recommend installing this module (and Readonly::XS if possible).\n"
          . "It's fine to install it after installing Ogre.\n\n"
          . "Do you want to install Readonly now?";
        my $val = ExtUtils::MakeMaker::prompt($msg, 'n');
        if ($val =~ /^y/i) {
            $prereqs{'Readonly'} = '0';
            print "\nReadonly added to prerequisites.\n";
        }
    }

    return {
        'PREREQ_PM'         => \%prereqs,
        'CC'                => my_compiler(),
        'INC'               => join(' ', @cflags),
        'LIBS'              => join(' ', @libs),
        (@defines ? ('DEFINE' => join(' ', @defines)) : ()),
    };
}

sub check_pkg_config {
    my ($pkg, $required_version) = @_;

    my $pc = 'pkg-config';
    my @errors = ();

    # Check that pkg-config is installed
    my $pcver = `$pc --version`;
    if ($pcver eq '') {
        push @errors, "$pc not found";
    }
    else {
        # Check that pkg-config knows about the package
        my $pkgexists = `$pc --exists $pkg`;
        if ($?) {
            push @errors, "Package $pkg not found by $pc";
        }
        else {
            # Check that the package is the right version
            my $pkgver = `$pc --atleast-version='$required_version' $pkg`;
            if ($?) {
                push @errors, "Package $pkg is not the right version (at least $required_version)";
            }
        }
    }

    return @errors;
}

sub pkg_config {
    my ($pkg, $option, $pc) = @_;

    $pc = 'pkg-config' unless defined $pc;

    my $str = `$pc --$option $pkg`;
    if ($?) {
        die "$pc --$option $pkg: $str\n";
    }
    else {
        chomp $str;
        return $str;
    }
}