use 5.008_007;
use ExtUtils::MakeMaker;
use strict;
use warnings;
use Config;
use Getopt::Long;
use FindBin;
use lib "$FindBin::Bin/lib";
use Getopt::Long 'GetOptions';
use File::Find 'find';
use SPVM::Builder::Util;
# If you edit yacc/spvm_yacc.y, spvm_yacc.c must be re-generated by the following command before "perl Makefile.PL"
# yacc/bison.sh
# Check supported environment
{
# SPVM only support 64bit integer Perl
my $ivsize = $Config{ivsize};
if ($ivsize < 8) {
warn "SPVM doesn't support the Perl which \"ivsize\" is lower than 8. The current \"ivsize\" is $ivsize.\n";
die "OS unsupported\n";
}
# Currently SPVM doesn't support Alpine Linux
my $myuname = $Config{myuname};
if ($myuname =~ /\balpine\b/i) {
warn "Currently SPVM doesn't support Alpine Linux because segmentation fault occurs due to incompatibility with glibc. If you want to use SPVM on Alpine Linux, please join SVPM project to fix the problems. The current \"myuname\" is \"$myuname\".\n";
die "OS unsupported\n";
}
# Don't support nmake
my $make = $Config{make};
if ($make eq 'nmake') {
warn "SPVM doesn't support nmake. The current \"make\" is \"$make\"\n";
die "OS unsupported\n";
}
}
my @defines;
my $optimize;
GetOptions(
"DEFINE=s" => \@defines,
"OPTIMIZE=s" => \$optimize,
'meta' => \my $meta,
'no-build-spvm-modules' => \my $no_build_spvm_modules,
'no-precompile-tests' => \my $no_precompile_tests,
);
if ($meta) {
$no_build_spvm_modules = 1;
$no_precompile_tests = 1;
}
# Macro
@defines = map { "-D$_" } @defines;
# OPTIMIZE
unless ($optimize) {
$optimize = '-O3';
}
# CCFLAGS
my $ccflags = $Config{ccflags};
# SPVM is compiled as C99, but some platforms can't compile XS which contains perl.h with pure C99(-std=c99). I select -std=gnu99.
$ccflags .= ' -std=gnu99';
# Fix compile warnings
{
my $compiler_name;
my $compiler_major_version;
my $compiler_minor_version;
my $config_gcc_version = $Config{gccversion};
if ($config_gcc_version =~ /clang-(\d{2})(\d{2})\b/) {
$compiler_name = 'clang';
$compiler_major_version = $1;
$compiler_minor_version = $2;
}
if (defined $compiler_name) {
if ($compiler_name eq 'clang') {
if ($compiler_major_version >= 12) {
$ccflags .= ' -Wno-compound-token-split-by-macro';
}
}
}
}
# I want to print warnings, but if gcc version is different, can't suppress no needed warning message.
# so I dicide not to print warning in release version
if ($ENV{SPVM_TEST_ENABLE_WARNINGS}) {
$ccflags .= ' -Wall -Wextra -Wno-unused-label -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wno-missing-field-initializers';
}
# INC
my $inc = '-Ilib/SPVM/Builder/include';
# Source files
my $spvm_core_source_file_names = SPVM::Builder::Util::get_spvm_core_source_file_names();
my @spvm_csource_files = map { "lib/SPVM/Builder/src/$_" } @$spvm_core_source_file_names;
my @csource_files = ('SPVM.c', @spvm_csource_files);
# Header files(This is only used to resolve dependencies)
my @spvm_header_files = glob 'lib/SPVM/Builder/include/*.h';
my @header_files = ('ppport.h', @spvm_header_files);
WriteMakefile(
NAME => 'SPVM',
VERSION_FROM => 'lib/SPVM.pm', # finds $VERSION
LICENSE => 'mit',
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'lib/SPVM.pm', # retrieve abstract from module
AUTHOR => 'Yuki Kimoto<kimoto.yuki@gmail.com>') : ()),
CCFLAGS => $ccflags,
OPTIMIZE => $optimize,
C => [@csource_files],
H => [@header_files],
OBJECT => '$(O_FILES)', # link all the C files too
INC => $inc,
test => {TESTS => 't/*.t t/*/*.t t/*/*/*.t'},
clean => {FILES => "SPVM.o lib/SPVM/Builder/src/*.o .spvm_build t/.spvm_build t/02_vm/.spvm_build t/03_precompile t/test_files_tmp t/*/test_files_tmp t/exe/.spvm_build"},
DEFINE => "@defines -o \$@",
META_MERGE => {
'meta-spec' => { version => 2 },
resources => {
repository => {
type => 'git',
url => 'https://github.com/yuki-kimoto/SPVM.git',
web => 'https://github.com/yuki-kimoto/SPVM',
},
bugtracker => {
web => "https://github.com/yuki-kimoto/SPVM/issues",
},
},
},
EXE_FILES => ['script/spvmcc', 'script/spvmdist'],
PREREQ_PM => {
'ExtUtils::CBuilder' => '0.280236',
'Time::Piece' => '1.12'
},
TEST_REQUIRES => {
'Test::More' => '0.92',
},
NORECURS => 1,
);
# Add Build shared library make rule
sub MY::postamble {
# The content of Makefile
my $make_rule = '';
unless ($no_build_spvm_modules) {
require SPVM::Builder::Util::API;
# Build native
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Fn');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Array');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Hash');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Format');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Time');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Time::Info');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Compiler');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Runtime');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Env');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Stack');
# Build precompile
$make_rule .= SPVM::Builder::Util::API::create_make_rule_precompile('Fn');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_precompile('Array');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_precompile('Format');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_precompile('Hash');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_precompile('Sort');
}
unless ($no_precompile_tests) {
# Create precompile tests
my @test_files;
find(
sub {
if (-f $File::Find::name) {
my $rel_path = $File::Find::name;
$rel_path =~ s|^\Q$FindBin::Bin/||;
# Slip hidden files
return if $rel_path =~ /[\/\\]\./;
push @test_files, $rel_path;
}
},
"$FindBin::Bin/t/02_vm"
);
my $test_files_str = join(' ', @test_files);
my $time_stamp_file = "$FindBin::Bin/t/03_precompile/time_stamp.txt";
$make_rule .= "dynamic :: $time_stamp_file\n";
$make_rule .= "\t\$(NOECHO) \$(NOOP)\n\n";
$make_rule .= "$time_stamp_file :: $test_files_str\n";
$make_rule .= "\tperl t/utils/copy_vm_to_precompile.pl\n";
}
return $make_rule;
}
1;