use 5.008_007;
use strict;
use Config;
use FindBin;
use lib "$FindBin::Bin/lib";
use Getopt::Long 'GetOptions';
use File::Find 'find';
# 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";
}
# 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";
}
# Don't support C++ compilers that does not support -std=c++11 option.
{
my $config = SPVM::Builder::Config->new_cpp(file_optional => 1);
my $cc = $config->cc;
my $tmp_dir = File::Temp->newdir;
my $cmd = "$cc -o $tmp_dir/cpp11.o -std=c++11 t/test_files/os_support/cpp11.cpp";
unless (system($cmd) == 0) {
warn "SPVM doesn't support C++ compilers that does not support -std=c++11 option.\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;
}
my $default_config = SPVM::Builder::Util::API::create_default_config;
my $std = $default_config->std;
# Macro
@defines = map { "-D$_" } @defines;
# OPTIMIZE
unless ($optimize) {
$optimize = $default_config->optimize;
}
# CCFLAGS
my $ccflags = $Config{ccflags};
$ccflags .= " -std=$std";
$ccflags .= " " . join(' ', @{$default_config->thread_ccflags});
# LDDLFLAGS
my $lddlflags = $Config{lddlflags};
$lddlflags .= " " . join(' ', @{$default_config->thread_ldflags});
# 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',
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,
LDDLFLAGS => $lddlflags,
OPTIMIZE => $optimize,
LDDLFLAGS => $lddlflags,
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 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',
},
bugtracker => {
},
},
},
EXE_FILES => ['script/spvm', 'script/spvmcc', 'script/spvmdist'],
PREREQ_PM => {
'ExtUtils::CBuilder' => '0.280236',
'Time::Piece' => '1.12',
'JSON::PP' => '2.27105',
},
TEST_REQUIRES => {
'Test::More' => '0.92',
},
NORECURS => 1,
);
# Add Build shared library make rule
sub MY::postamble {
# The content of Makefile
my $make_rule = '';
# Update spvm_version.h
$make_rule .= "dynamic :: \n";
$make_rule .= qq|\tperl -e "utime(undef, undef, 'blib/lib/SPVM/Builder/include/spvm_version.h')"\n|;
unless ($no_build_spvm_modules) {
# For loading resources
local @INC = @INC;
unshift @INC, 'lib';
# 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('Sync::Mutex');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Compiler');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::ClassFile');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Runtime');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Env');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Stack');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::BasicType');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::ClassVar');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Field');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Method');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Arg');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::MethodCall');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::API');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_native('Native::Constant');
# 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');
$make_rule .= SPVM::Builder::Util::API::create_make_rule_precompile('Packer');
}
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;