Usage
interface $class_name;
Details
Interface Methods
EOS } elsif ($resource) { $description = "$class_name class in SPVM is a resource class for something.";
my $native = $self->native;
my $new_method;
if ($native eq 'c') {
$new_method = 'new_c99';
}
elsif ($native eq 'c++') {
$new_method = 'new_cpp';
}
my $native_module_ext;
if (defined $native) {
if ($native eq 'c') {
$native_module_ext = 'c';
}
elsif ($native eq 'c++') {
$native_module_ext = 'cpp';
}
}
# extern C for C++
my $extern_c_start;
my $extern_c_end;
if ($native eq 'c++') {
$extern_c_start = qq(extern "C" {);
$extern_c_end = "}";
}
else {
$extern_c_start = '';
$extern_c_end = '';
}
$main_doc = <<"EOS";
=head1 Usage
MyClass.config:
my \$config = SPVM::Builder::Config->$new_method;
\$config->use_resource('$class_name');
\$config;
MyClass.$native_module_ext:
#include "spvm_native.h"
#include "foo.h"
$extern_c_start
int32_t SPVM__MyClass__test(SPVM_ENV* env, SPVM_VALUE* stack) {
// Use functions in foo.h
return 0;
}
$extern_c_end
Details
Original Product
Original Product Version
Language
Language Standard
Required Libraries
Required Linker Flags
Required Resources
Header Files
Source Files
Compiler Flags
How to Create Resource
Donwload
Extracting Source Files
Extracting Header Files
EOS } else { $description = "$class_name class in SPVM has methods to do someting."; $main_doc = <<"EOS"; =head1 Usage
use $class_name;
Details
Super Class
Interfaces
Enumerations
Fields
Class Methods
Instance Methods
Well Known Child Classes
See Also
EOS }
my $version_decl = 'our $VERSION = "0.001";';
my $only_lib_files = $self->only_lib_files;
if ($only_lib_files) {
$version_decl = '';
}
# Content
my $perl_class_content = "";
$perl_class_content = <<"EOS";
package SPVM::$class_name;
$version_decl
1;
Name
SPVM::$class_name - Short Description
Description
$description
$main_doc =head1 Repository
Author
$user_name $user_email
Copyright & License
Copyright (c) $year $user_name
MIT License
EOS
# Generate file
my $perl_class_rel_file = SPVM::Builder::Util::convert_class_name_to_rel_file($class_name, 'pm');
$perl_class_rel_file = $self->create_lib_rel_file($perl_class_rel_file);
$self->generate_file($perl_class_rel_file, $perl_class_content);
}
sub generate_native_config_file { my ($self) = @_;
my $class_name = $self->class_name;
# C or C++
my $native = $self->native;
my $new_method;
if ($native eq 'c') {
$new_method = 'new_c99';
}
elsif ($native eq 'c++') {
$new_method = 'new_cpp';
}
# User name
my $user_name = $self->user_name;
unless (defined $user_name) {
$user_name = '[--user-name]'
}
# Year
my $year = $self->_year;
my $is_resource = $self->{resource};
my $is_resource_code = '';
if ($is_resource) {
$is_resource_code = '$config->is_resource(1);';
}
# Content
my $native_config_content = <<"EOS";
# Copyright (c) $year $user_name
# MIT License
my \$config = SPVM::Builder::Config->$new_method;
$is_resource_code
\$config; EOS
# Generate file
my $native_config_rel_file = SPVM::Builder::Util::convert_class_name_to_rel_file($class_name, 'config');
$native_config_rel_file = $self->create_lib_rel_file($native_config_rel_file);
$self->generate_file($native_config_rel_file, $native_config_content);
}
sub generate_native_class_file { my ($self) = @_;
my $class_name = $self->class_name;
# extern C for C++
my $native = $self->native;
my $extern_c_start;
my $extern_c_end;
if ($native eq 'c++') {
$extern_c_start = qq(extern "C" {);
$extern_c_end = "}";
}
else {
$extern_c_start = '';
$extern_c_end = '';
}
# Generate file
my $native_module_ext;
if (defined $native) {
if ($native eq 'c') {
$native_module_ext = 'c';
}
elsif ($native eq 'c++') {
$native_module_ext = 'cpp';
}
}
# Content
my $native_class_name = $class_name;
$native_class_name =~ s/::/__/g;
my $native_class_file = $class_name;
$native_class_file =~ s/::/\//g;
$native_class_file .= ".$native_module_ext";
# User name
my $user_name = $self->user_name;
unless (defined $user_name) {
$user_name = '[--user-name]'
}
# Year
my $year = $self->_year;
my $native_class_content = <<"EOS";
// Copyright (c) $year $user_name
// MIT License
#include "spvm_native.h"
$extern_c_start
static const char* FILE_NAME = "$native_class_file";
int32_t SPVM__${native_class_name}__foo(SPVM_ENV* env, SPVM_VALUE* stack) {
return 0;
}
$extern_c_end EOS
my $native_class_rel_file = SPVM::Builder::Util::convert_class_name_to_rel_file($class_name, $native_module_ext);
$native_class_rel_file = $self->create_lib_rel_file($native_class_rel_file);
$self->generate_file($native_class_rel_file, $native_class_content);
}
sub generate_gitkeep_file_for_native_module_include_dir { my ($self) = @_;
my $class_name = $self->class_name;
# Generate file
my $gitkeep_rel_file_for_native_module_include_dir = SPVM::Builder::Util::convert_class_name_to_rel_file($class_name, 'native');
$gitkeep_rel_file_for_native_module_include_dir .= '/include/.gitkeep';
$gitkeep_rel_file_for_native_module_include_dir = $self->create_lib_rel_file($gitkeep_rel_file_for_native_module_include_dir);
$self->generate_file($gitkeep_rel_file_for_native_module_include_dir, '');
}
sub generate_gitkeep_file_for_native_module_src_dir { my ($self) = @_;
my $class_name = $self->class_name;
# Generate file
my $gitkeep_rel_file_for_native_module_include_dir = SPVM::Builder::Util::convert_class_name_to_rel_file($class_name, 'native');
$gitkeep_rel_file_for_native_module_include_dir .= '/src/.gitkeep';
$gitkeep_rel_file_for_native_module_include_dir = $self->create_lib_rel_file($gitkeep_rel_file_for_native_module_include_dir);
$self->generate_file($gitkeep_rel_file_for_native_module_include_dir, '');
}
sub generate_gitignore_file { my ($self) = @_;
my $gitignore_content = <<'EOS';
/blib
/Makefile
/Makefile.old
/MYMETA.yml
/MYMETA.json
/pm_to_blib
/core.*
/core
/SPVM-*
*.bak
*.BAK
*.tmp
*.o
*.bs
.tmp
.git
.spvm_build
EOS
# Generate file
my $gitignore_rel_file = '.gitignore';
$self->generate_file($gitignore_rel_file, $gitignore_content);
}
sub generate_gitattributes_file { my ($self) = @_;
my $gitattributes_content = <<'EOS';
*.spvm text eol=lf
EOS
# Generate file
my $gitattributes_rel_file = '.gitattributes';
$self->generate_file($gitattributes_rel_file, $gitattributes_content);
}
sub generate_manifest_skip_file { my ($self) = @_;
# Content
my $manifest_skip_content = <<'EOS';
^blib(/|$)
^Makefile$
^Makefile.old$
^MYMETA.yml$
^MYMETA.json$
^pm_to_blib$
^core\.
^core$
^SPVM-
\.bak$
\.BAK$
\.tmp$
\.o$
\.bs$
(^|/)\.tmp(/|$)
(^|/)\.git(/|$)
(^|/)\.spvm_build(/|$)
EOS
# Generate file
my $manifest_skip_rel_file = 'MANIFEST.SKIP';
$self->generate_file($manifest_skip_rel_file, $manifest_skip_content);
}
sub generate_changes_file { my ($self) = @_;
# Year
my $today_tp = Time::Piece::localtime;
my $today = $today_tp->strftime('%Y-%m-%d');
# Content
my $changes_content = <<"EOS";
0.001 $today
[Changes]
* First release.
EOS
# Generate file
my $changes_rel_file = 'Changes';
$self->generate_file($changes_rel_file, $changes_content);
}
sub generate_readme_markdown_file { my ($self) = @_;
my $class_name = $self->class_name;
# Content
my $readme_markdown_content = <<"EOS";
# SPVM::$class_name
## Document
<a href="https://metacpan.org/pod/SPVM::$class_name">SPVM::$class_name - CPA/a
## See Also
<a href="https://github.com/yuki-kimoto/SPVM">SPVM - Github</a>
EOS
# Generate file
my $readme_markdown_rel_file = 'README.md';
$self->generate_file($readme_markdown_rel_file, $readme_markdown_content);
}
sub generate_makefile_pl_file { my ($self) = @_;
my $class_name = $self->class_name;
# Resource
my $resource = $self->resource;
# Make rule
my $native_class_literal = $self->native ? "'$class_name'" : '';
my $precompile_class_literal = $self->precompile ? "'$class_name'" : '';
my $make_rule_parallel = !$resource ? "\$make_rule .= SPVM::Builder::Util::API::create_make_rule_parallel(\$options);" : '';
my $perl_class_rel_file = SPVM::Builder::Util::convert_class_name_to_rel_file($class_name, 'pm');
$perl_class_rel_file = $self->create_lib_rel_file($perl_class_rel_file);
my $spvm_class_rel_file = SPVM::Builder::Util::convert_class_name_to_rel_file($class_name, 'spvm');
$spvm_class_rel_file = $self->create_lib_rel_file($spvm_class_rel_file);
# User name
my $user_name = $self->user_name;
unless (defined $user_name) {
$user_name = '[--user-name]'
}
# User email
my $user_email = $self->user_email;
unless (defined $user_email) {
$user_email = '[--user-email]'
}
# "Makefile.PL" content
my $makefile_pl_content = <<"END_OF_STRING";
use 5.020;
use ExtUtils::MakeMaker;
use strict;
use warnings;
use Config;
use Getopt::Long 'GetOptions';
use File::Path 'mkpath', 'rmtree';
use FindBin; use lib "\$FindBin::Bin/lib"; use SPVM::Builder::Util::API;
GetOptions( 'meta' => \\my \$meta, 'no-build-spvm-modules' => \\my \$no_build_spvm_modules, 'ccflag=s' => \\my \@ccflags, 'define=s' => \\my \@defines, 'ldflag=s' => \\my \@ldflags, 'debug' => \\my \$debug, 'build-type=s' => \\my \$build_type, 'asan-on-linux' => \\my \$asan_on_linux, 'parallel-make' => \\my \$parallel_make, 'parallel-test' => \\my \$parallel_test, 'jobs=i' => \\my \$jobs, );
my \$build_dir = '.spvm_build'; mkpath \$build_dir;
my \$config_global_file = '.spvm_build/global.config'; generate_config_global_file(\$config_global_file, { ccflags => \\\@ccflags, defines => \\\@defines, ldflags => \\\@ldflags, debug => \$debug, build_type => \$build_type, asan_on_linux => \$asan_on_linux, });
my \$gnu_make = SPVM::Builder::Util::API::search_gnu_make_command();
if (\$meta) { \$no_build_spvm_modules = 1; }
unless (\$meta) { # Do something such as environment check. }
if (\$debug) { \$build_type = 'Debug'; }
my \$asan_logs_dir = "\$FindBin::Bin/.tmp/asan_logs"; if (\$asan_on_linux) { push \@ccflags, "-fsanitize=address", "-fno-omit-frame-pointer"; push \@ldflags, "-fsanitize=address"; rmtree \$asan_logs_dir; mkpath \$asan_logs_dir; }
unless (defined \$jobs) { my \$cpus = SPVM::Builder::Util::API::get_cpu_count(); \$jobs = \$cpus + 2; }
if (\$jobs > 16) { \$jobs = 16; }
my \%configure_and_runtime_requires = ('SPVM' => '$SPVM::VERSION'); WriteMakefile( NAME => 'SPVM::$class_name', VERSION_FROM => '$perl_class_rel_file', LICENSE => 'mit', (\$] >= 5.005 ? (ABSTRACT_FROM => '$perl_class_rel_file', AUTHOR => '$user_name<$user_email>') : ()), test => {TESTS => 't/*.t t/*/*.t t/*/*/*.t'}, clean => {FILES => ['.spvm_build']}, META_MERGE => { 'meta-spec' => { version => 2, # release_status => 'stable', # stable, testing, or unstable }, resources => { repository => { type => 'git', url => '', web => '', }, }, no_index => { directory => [], } }, MAKE => \$gnu_make, macro => { \$parallel_make ? (MAKEFLAGS => "-j\$jobs") : (), \$parallel_test ? ('override TEST_VERBOSE' => "scalar (eval chr(36) . q(ENV{HARNESS_OPTIONS}='j\$jobs'), 0)") : (), \$asan_on_linux ? ('override FULLPERL' => qq|LD_PRELOAD=\\\$\\\$(\$Config{cc} -print-file-name=libasan.so) ASAN_OPTIONS="log_path=\$asan_logs_dir/asan.log:exitcode=0" \$^X|) : (), }, NORECURS => 1, CONFIGURE_REQUIRES => { \%configure_and_runtime_requires, }, PREREQ_PM => { \%configure_and_runtime_requires, }, TEST_REQUIRES => { }, );
package MY {
sub postamble {
my \$make_rule = '';
unless (\$no_build_spvm_modules) {
my \$options = {};
\$options->{native_classes} = [
$native_class_literal
];
\$options->{precompile_classes} = [
$precompile_class_literal
];
\$options->{config_global_file} = \$config_global_file;
$make_rule_parallel
}
return \$make_rule;
}
}
sub generate_config_global_file { my (\$config_global_file, \$options) = \@_;
my \$ccflags = \$options->{ccflags} // [];
my \$defines = \$options->{defines} // [];
my \$ldflags = \$options->{ldflags} // [];
my \$build_type = \$options->{build_type};
my \$debug = \$options->{debug};
my \$asan_on_linux = \$options->{asan_on_linux};
# --- Handle options ---
if (\$debug) {
\$build_type = 'Debug';
}
if (\$asan_on_linux) {
push \@\$ccflags, "-fsanitize=address", "-fno-omit-frame-pointer";
push \@\$ldflags, "-fsanitize=address";
}
# --- Generate content ---
my \$config_global_content = '';
\$config_global_content .= <<"EOS";
my \\\$config_global = SPVM::Builder::Config::Global->new;
EOS
if (defined \$build_type) {
\$config_global_content .= <<"EOS";
\\\$config_global->build_type('\$build_type');
EOS
}
for my \$ccflag (\@\$ccflags) {
\$config_global_content .= <<"EOS";
\\\$config_global->build_rule_any({'+ccflags' => ['\$ccflag']});
EOS
}
for my \$define (\@\$defines) {
\$config_global_content .= <<"EOS";
\\\$config_global->build_rule_any({'+defines' => ['\$define']});
EOS
}
for my \$ldflag (\@\$ldflags) {
\$config_global_content .= <<"EOS";
\\\$config_global->build_rule_any({'+ldflags' => ['\$ldflag']});
EOS
}
\$config_global_content .= <<"EOS";
\\\$config_global;
EOS
# --- Write to file ---
open my \$fh, '>', \$config_global_file or die "Can't open file '\$config_global_file': \$!";
print \$fh \$config_global_content;
}
1;
Name
SPVM::$class_name Makefile.PL
Description
Makefile.PL for SPVM::$class_name build.
Command Line Options
See the following URL for the command line options:
https://github.com/yuki-kimoto/SPVM/blob/master/Makefile.PL
Name
SPVM::Dist - Generating SPVM Distrubution
Description
SPVM::Dist class has methods to generate an SPVM Distrubution.
Usage
my $dist = SPVM::Dist->new(
class_name => 'Math',
);
$dist->generate_dist;
Copyright & License
Copyright (c) 2023 Yuki Kimoto
MIT License
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 815:
Deleting unknown formatting code N<>