Skip to content

Commit 970387b

Browse files
committed
Enable cross-platform builds of nobuild configs. Replace shell commands with perl equivalents. Add Info-ZIP workaround for bootstrapping on Windows
1 parent 09a650f commit 970387b

File tree

3 files changed

+98
-23
lines changed

3 files changed

+98
-23
lines changed

Changes

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
Revision history for Perl-Dist-APPerl
2+
vX.X.X 2022-XX-XX
3+
Enable cross-platform builds of `nobuild` configs. Switch
4+
remaining `mv`, `cp`, `rm` shell commands to use their perl
5+
equivalents. Add workaround to `apperlm` for running Info-ZIP
6+
on Windows from APPerl.
7+
28
v0.1.1 2022-11-17
39
Fix 5.10 support and broken pod link, thanks to MJGARDNER
410
(GH#1).

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ on all your PCs multiple computers.
1717
Information on the creation of APPerl can be found in this
1818
[blogpost](https://computoid.com/posts/Perl-is-Actually-Portable.html).
1919

20+
## NON-PERL DEPENDENCIES
21+
22+
A `zip` binary ([Info-ZIP](https://infozip.sourceforge.net/)) is
23+
required to build. Your distro likely has it in its package
24+
repository. For Windows, the official download is available via FTP
25+
<ftp://ftp.info-zip.org/pub/infozip/>.
26+
27+
### Windows x64 Info-ZIP download and install instructions
28+
- Get an FTP client if needed: [WinSCP](https://winscp.net/eng/index.php)
29+
- Connect to the [InfoZip FTP server](ftp://ftp.info-zip.org/pub/infozip/) with anonymous login.
30+
- Enter the `win32` folder and download `zip300xn-x64.zip`.
31+
- Extract the zip file and its inner zip file.
32+
- Add the folder containing `zip.exe` to `%PATH%`: [step-by-step](https://www.computerhope.com/issues/ch000549.htm)
33+
34+
The last step isn't strictly necessary, the absolute path to a zip binary may be passed in to `apperlm build` with the `--zippath` arg.
35+
2036
## TRADITIONAL INSTALLATION
2137

2238
To install this module, run the following commands:

lib/Perl/Dist/APPerl.pm

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,36 @@ use version 0.77; our $VERSION = qv(v0.1.1);
44
use strict;
55
use warnings;
66
use JSON::PP 2.0104 qw(decode_json);
7-
use File::Path 2.07 qw(make_path);
7+
use File::Path 2.07 qw(make_path remove_tree);
88
use Cwd qw(abs_path getcwd);
99
use Data::Dumper qw(Dumper);
1010
use File::Basename qw(basename dirname);
11-
use File::Copy qw(copy);
11+
use File::Copy qw(copy move);
12+
use Env qw(@PATH);
1213
use FindBin qw();
1314
use Getopt::Long qw(GetOptionsFromArray);
1415
Getopt::Long::Configure qw(gnu_getopt);
1516

1617
use constant {
17-
SITE_CONFIG_DIR => (($ENV{XDG_CONFIG_HOME} // ($ENV{HOME}.'/.config')).'/apperl'),
18-
SITE_REPO_DIR => (($ENV{XDG_DATA_HOME} // ($ENV{HOME}.'/.local/share')).'/apperl'),
19-
PROJECT_FILE => 'apperl-project.json',
2018
START_WD => getcwd(),
21-
PROJECT_TMP_DIR => abs_path('.apperl')
19+
PROJECT_FILE => 'apperl-project.json',
20+
};
21+
use constant {
22+
PROJECT_TMP_DIR => (START_WD.'/.apperl'),
23+
};
24+
use constant {
25+
# DEFDATAROOT is used if the XDG base directories cannot be found
26+
DEFDATAROOT => defined($ENV{HOME}) ? $ENV{HOME}
27+
: defined($ENV{APPDATA}) ? $ENV{APPDATA} .'/apperl'
28+
: PROJECT_TMP_DIR.'/site',
29+
PROJECT_TMP_CONFIG_FILE => (PROJECT_TMP_DIR.'/user-project.json'),
30+
};
31+
use constant {
32+
SITE_CONFIG_DIR => ($ENV{XDG_CONFIG_HOME} // (DEFDATAROOT.'/.config')) . '/apperl',
33+
SITE_REPO_DIR => ($ENV{XDG_DATA_HOME} // (DEFDATAROOT.'/.local/share')).'/apperl',
2234
};
2335
use constant {
2436
SITE_CONFIG_FILE => (SITE_CONFIG_DIR."/site.json"),
25-
PROJECT_TMP_CONFIG_FILE => (PROJECT_TMP_DIR.'/user-project.json')
2637
};
2738

2839
sub _load_apperl_configs {
@@ -887,7 +898,10 @@ sub Set {
887898
chdir($SiteConfig->{perl_repo}) or die "Failed to enter perl repo";
888899
print "make veryclean\n";
889900
system("make", "veryclean");
890-
_command_or_die('rm', '-f', 'miniperl.com', 'miniperl.elf', 'perl.com', 'perl.elf');
901+
foreach my $todelete ('miniperl.com', 'perl.com', 'miniperl.elf', 'perl.elf') {
902+
print "rm $todelete\n";
903+
unlink($todelete) || $!{ENOENT} or die "failed to delete $todelete";
904+
}
891905
_command_or_die('git', 'checkout', $itemconfig->{perl_id});
892906

893907
print "cd ".START_WD."\n";
@@ -957,7 +971,23 @@ sub _fix_bases {
957971
return $in;
958972
}
959973

974+
# system is pretty broken on APPerl when running on Windows
975+
# let's search PATH ourselves ...
976+
sub _find_zip {
977+
if(($^O ne 'cosmo') || (! -f '/C/Windows/System32/cmd.exe')) {
978+
return 'zip';
979+
}
980+
else {
981+
foreach my $dir (@PATH) {
982+
my $zippath = "$dir/zip.exe";
983+
return $zippath if(-f $zippath);
984+
}
985+
}
986+
die("Failed to find zip.exe, did you download Info-Zip and add the folder containing zip.exe to \%PATH\%?");
987+
}
988+
960989
sub Build {
990+
my ($zippath) = @_;
961991
my $Configs = _load_apperl_configs();
962992
my $UserProjectConfig = _load_valid_user_project_config_with_default($Configs) or die "cannot Build without valid UserProjectConfig";
963993
my $CurAPPerlName = $UserProjectConfig->{current_apperl};
@@ -986,10 +1016,12 @@ sub Build {
9861016
-f $PERL_APE or die "apperlm build: perl ape not found";
9871017
my $OUTPUTDIR = "$UserProjectConfig->{apperl_output}/$CurAPPerlName";
9881018
if(-d $OUTPUTDIR) {
989-
_command_or_die('rm', '-rf', $OUTPUTDIR);
1019+
print "rm -rf $OUTPUTDIR\n";
1020+
remove_tree($OUTPUTDIR);
9901021
}
9911022
my $TEMPDIR = "$OUTPUTDIR/tmp";
992-
_command_or_die('mkdir', '-p', $TEMPDIR);
1023+
print "mkdir -p $TEMPDIR\n";
1024+
make_path($TEMPDIR);
9931025
my $PERL_PREFIX = _cmdoutput_or_die(@perl_config_cmd, '-e', 'use Config; print $Config{prefix}');
9941026
my $PREFIX_NOZIP = $PERL_PREFIX;
9951027
$PREFIX_NOZIP =~ s/^\/zip\/*//;
@@ -1001,7 +1033,9 @@ sub Build {
10011033
# install cosmo perl if this isn't a nobuild config
10021034
if(! exists $UserProjectConfig->{nobuild_perl_bin}){
10031035
_command_or_die('make', "DESTDIR=$TEMPDIR", 'install');
1004-
_command_or_die('rm', "$TEMPDIR$PERL_PREFIX/bin/perl", "$TEMPDIR$PERL_PREFIX/bin/perl$PERL_VERSION");
1036+
my @toremove = ("$TEMPDIR$PERL_PREFIX/bin/perl", "$TEMPDIR$PERL_PREFIX/bin/perl$PERL_VERSION");
1037+
print 'rm '.join(' ', @toremove)."\n";
1038+
unlink(@toremove) == scalar(@toremove) or die "Failed to unlink some files";
10051039
}
10061040
else {
10071041
make_path($ZIP_ROOT);
@@ -1010,8 +1044,10 @@ sub Build {
10101044
# pack
10111045
my $APPNAME = basename($PERL_APE);
10121046
my $APPPATH = "$TEMPDIR/$APPNAME";
1013-
_command_or_die('cp', $PERL_APE, $APPPATH);
1014-
_command_or_die('chmod', 'u+w', $APPPATH);
1047+
print "cp $PERL_APE $APPPATH\n";
1048+
copy($PERL_APE, $APPPATH) or die "copy failed: $!";
1049+
print "chmod 755 $APPPATH\n";
1050+
chmod(0755, $APPPATH) or die $!;
10151051
if((! exists $UserProjectConfig->{nobuild_perl_bin}) || scalar(keys %{$itemconfig->{zip_extra_files}})) {
10161052
print "cd $ZIP_ROOT\n";
10171053
chdir($ZIP_ROOT) or die "failed to enter ziproot";
@@ -1021,15 +1057,18 @@ sub Build {
10211057
_copy_recursive($file, $dest);
10221058
}
10231059
}
1024-
_command_or_die('zip', '-r', $APPPATH, @zipfiles);
1060+
_command_or_die($zippath // _find_zip(), '-r', $APPPATH, @zipfiles);
10251061
}
1026-
_command_or_die('mv', $APPPATH, "$OUTPUTDIR/perl.com");
1062+
print "mv $APPPATH $OUTPUTDIR/perl.com\n";
1063+
move($APPPATH, "$OUTPUTDIR/perl.com") or die "move failed: $!";
10271064

10281065
# copy to user specified location
10291066
if(exists $itemconfig->{dest}) {
10301067
print "cd ".START_WD."\n";
10311068
chdir(START_WD) or die "Failed to restore cwd";
1032-
_command_or_die('cp', "$UserProjectConfig->{apperl_output}/$CurAPPerlName/perl.com", $itemconfig->{dest});
1069+
my @args = ("$UserProjectConfig->{apperl_output}/$CurAPPerlName/perl.com", $itemconfig->{dest});
1070+
print 'cp '.join(' ', @args)."\n";
1071+
copy(@args) or die "copy failed: $!";
10331072
}
10341073
}
10351074

@@ -1064,12 +1103,21 @@ END_USAGE
10641103
}
10651104
elsif($command eq 'build') {
10661105
my $usage = <<'END_USAGE';
1067-
apperlm build
1106+
apperlm build [-z|--zippath <zip_binary_path>]
1107+
-z|--zippath Path to InfoZip zip executable
10681108
Build APPerl. If the current config is a from-scratch build, you must
10691109
run `apperlm configure` first.
10701110
END_USAGE
1071-
die($usage) if(@_);
1072-
Perl::Dist::APPerl::Build();
1111+
my $zippath;
1112+
my $help;
1113+
GetOptionsFromArray(\@_, "zippath|z=s" => \$zippath,
1114+
"help|h" => \$help,
1115+
) or die($usage);
1116+
if($help) {
1117+
print $usage;
1118+
exit 0;
1119+
}
1120+
Perl::Dist::APPerl::Build($zippath);
10731121
}
10741122
elsif($command eq 'configure') {
10751123
Perl::Dist::APPerl::Configure(@_);
@@ -1482,7 +1530,10 @@ and runs Perl's C<Configure>
14821530
14831531
C<apperlm build> C<make>s perl and builds apperl. The output binary by
14841532
default is copied to C<perl.com> in the current directory, set dest in
1485-
C<apperl-project.json> to customize output binary path and name.
1533+
C<apperl-project.json> to customize output binary path and name. A
1534+
C<zip> binary is required to build, see README.md for details. The
1535+
C<zip> binary path may be explictly set by passing in
1536+
--zippath <zip_binary_path> .
14861537
14871538
=back
14881539
@@ -1603,9 +1654,11 @@ permissively already.
16031654
16041655
If your application requires non-standard C or XS extensions, APPerl
16051656
must be built from scratch as it does not support dynamic libraries,
1606-
only static linking. This tutorial assumes you already have an APPerl
1607-
project, possibly from following the
1608-
L</BUILDING AN APPLICATION FROM EXISTING APPERL> tutorial.
1657+
only static linking. Note, this process can only be completed on
1658+
Linux as building the Cosmopolitan Libc from scratch is only supported
1659+
on Linux and APPerl uses the unix-like C<Configure> to configure perl.
1660+
This tutorial assumes you already have an APPerl project, possibly from
1661+
following the L</BUILDING AN APPLICATION FROM EXISTING APPERL> tutorial.
16091662
16101663
First install the APPerl build dependencies and create a new config
16111664
based on the current small config, checkout, configure, and build.

0 commit comments

Comments
 (0)