Closed ahgamut closed 3 years ago
Outstanding! You successfully built Lua as a 336kb Actually Portable Executable using Cosmopolitan! Now we know exactly what features are missing and which things need to change. I intend to get each one of these things fixed. This issue will be updated live as that happens.
I forked the Lua Github mirror and created a cosmopolitan
branch from Lua 5.4.2.
https://github.com/ahgamut/lua/tree/cosmopolitan
Change COSMO_LIBDIR
in the makefile
to the appropriate folder containing cosmopolitan.h
and friends, and run make
.
Just for fun, the git diff
due to the above changes (excluding the README and dummy files) is:
23 8 makefile
18 18 ltable.c
6 6 lgc.c
5 5 lapi.c
4 4 lauxlib.c
4 3 lvm.c
3 1 loslib.c
3 0 lmathlib.c # filled in sinh, cosh, tanh
2 2 lvm.h
2 2 ltests.c
2 2 liolib.c
1 1 luaconf.h
1 1 lua.c
1 1 lobject.h
1 1 loadlib.c
1 1 llex.c
1 1 ldo.c
17 files changed, 78 insertions(+), 57 deletions(-)
Passing by to ask a somewhat related question, what would need to be changed in order to compile lua as a regular elf with cosmopolitan instead of an ape?
On nixos it gets written to a read only location and the binary does not run, I assume it is related to the "self updating headers":
Failed to execute process '/nix/store/0bxwk7hyscxlc0a6fr3wlrzjba4bcp02-lua-unstable/bin/lua'. Reason:
exec: unknown error (errno was 8)
The file '/nix/store/0bxwk7hyscxlc0a6fr3wlrzjba4bcp02-lua-unstable/bin/lua' is marked as an executable but could not be run by the operating system.
with import <nixpkgs> {};
let
cosmopolitan = import ./cosmopolitan.nix ;
in stdenv.mkDerivation rec {
pname = "lua";
version = "unstable";
src = fetchFromGitHub {
owner = "ahgamut";
repo = "lua";
rev = "aa20d02dffc4f96d673d30e7378c0c02a6df13f8";
hash = "sha256-GdXFk4AYE8EP886r7tQk+//rTm4sFMu0x2cVyCyrFgM=";
};
nativeBuildInputs = [ makeWrapper cosmopolitan gcc ];
preBuild = ''
makeFlagsArray=(SHELL=/bin/sh "MKDIR=mkdir -p" "COSMO_LIBDIR=${cosmopolitan}/lib")
'';
installPhase = ''
runHook preInstall
mkdir -p $out/{bin,lib/include}
make
cp lua.exe $out/bin/lua
runHook postInstall
'';
}
with import <nixpkgs> {};
stdenv.mkDerivation rec {
pname = "cosmopolitan";
version = "unstable";
src = fetchFromGitHub {
owner = "jart";
repo = "cosmopolitan";
rev = "cdc54ea1fd86253ced49dd24d45660cadac1d018";
hash = "sha256-vIDNWaM2+ztwx9hknl5+3ENkx9FxH7/VQ8uUW/sckyg=";
};
nativeBuildInputs = [ makeWrapper ];
preBuild = ''
makeFlagsArray=(SHELL=/bin/sh "MKDIR=mkdir -p")
'';
installPhase = ''
runHook preInstall
mkdir -p $out/{bin,lib/include}
install o/cosmopolitan.h $out/lib/include
install o/cosmopolitan.h $out/lib
install o/cosmopolitan.a o/libc/crt/crt.o o/ape/ape.{o,lds} $out/lib
makeWrapper ${gcc}/bin/gcc $out/bin/cosmoc --add-flags "-O -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone -fuse-ld=bfd -Wl,-T,$out/lib/ape.lds -include $out/lib/include/cosmopolitan.h $out/lib/{crt.o,ape.o,cosmopolitan.a}"
runHook postInstall
'';
}
Wouldn't you just need to run lua first as part of the nix install? Maybe lua --version or something?
Strikes me that low-hanging fruit would be to 'namespace' all the macros and internal functions in cosmopolitan, so that you would have cosmo_panic
instead of just panic
.
I haven't played around with cosmopolitan/APE (yet) so this could be completely off base.
Passing by to ask a somewhat related question, what would need to be changed in order to compile lua as a regular elf with cosmopolitan instead of an ape? @ingenieroariel
Try running make CPPFLAGS=-DSUPPORT_VECTOR=113
which disables Windows + Metal + XNU support. By turning off those three systems, the APE bootloader will choose to produce an ELF binary. See https://justine.lol/cosmopolitan/howfat.html and please note that this functionality got added to Cosmopolitan after the 0.2 release so you'll need to be sure you're using the latest nightly until I can cut a 0.3 release. https://justine.lol/cosmopolitan/download.html
@ingenieroariel It's also worth mentioning that the Cosmopolitan Makefile has similarly strict build-time requirements. The way we're currently approaching this problem is by using a wrapper program that creates atomic copies when it's asked to launch a .com binary. Since it uses vfork() and copy_file_range() it's just the fastest thing imaginable. Probably 10x faster than doing the same thing using a shell script.
@ahgamut I believe I've addressed everything now in the previous three linked changes. Please take a look and let me know if there's anything else you need. Thank you again for your contribution. The community is very excited about the work we're doing.
I have listed out the errors that I have seen/fixed during Lua compilation. (Unsure which of these are within the scope of Cosmopolitan).
I am using the cosmopolitan
branch in my fork of the Lua Github mirror:
makefile
crt.o
from the zip file and rest of cosmopolitan compiled from the latest commit.Errors from earlier that do not appear now:
UCHAR_MAX
is available nowsetlocale
/LC_ALL
BUFSIZ
/frame size errorssinh
, cosh
, tanh
are now available (no linker error)panic
, reverse
, isempty
#include
problemssys/wait.h
(lauxlib.c
)sys/types.h
(liolib.c
)unistd.h
(loslib.c
, lua.c
)Errors that still appear / require adding a fix to the Lua source code for successful compilation:
strcoll
is missing (linker error) localeconv()->decimal_point
is not available, so just using .
dlfcn.h
from loadlib.c
(it requires dlopen
)ldo.c
expects _setjmp
/_longjmp
if the LUA_USE_POSIX
flag is enabled (I disabled this)LUA_USE_POSIX
also requires the following functions in liolib.c
#if defined(LUA_USE_POSIX)
#define l_getc(f) getc_unlocked(f)
#define l_lockfile(f) flockfile(f) // linker missing the two below functions
#define l_unlockfile(f) funlockfile(f)
#else
#define l_getc(f) getc(f)
#define l_lockfile(f) ((void)0)
#define l_unlockfile(f) ((void)0)
#endif
With the above minor changes, lua.exe
compiles successfully.
Later I will try some of the tests provided alongside the Lua source.
Anything you need can potentially be in scope, so long as it isn't cross-compiling SDL DLLs for ARM with MSVC that run on BSD. Also I totally overlooked strcoll
. Thanks for the checkboxes. That makes it much easier to digest. Reopening.
I think there might be some weird behavior when calling getc
?
I was trying to run a sample file using lua -W sample.lua
and got segfaults.
Examining the debug with gdb
showed that the first getc
call after opening the file was causing the segfault. The weird part is, I replaced getc
with fgetc
, and no segfault.
static int skipBOM (LoadF *lf) {
const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */
int c;
lf->n = 0;
do {
// this is the first getc call after opening the file successfully
c = getc(lf->f);
// segfault
if (c == EOF || c != *(const unsigned char *)p++) return c;
lf->buff[lf->n++] = c;
} while (*p != '\0');
lf->n = 0;
return getc(lf->f); // if above is fgetc, this does not segfault
}
getc() is a macro wrapper that inlines some of the functionality of fgetc(). I took a quick glance and the code appears ok. I'm not sure how what you describe would happen unless your build is somehow changing the layout of struct FILE
. If you can produce a minimal complete program that lets me reproduce this then I can fix it.
On second glance one possible cause is this might need parenthesis:
#define getc(f) (f->beg < f->end ? f->buf[f->beg++] : fgetc(f))
Try changing that to:
#define getc(f) ((f)->beg < (f)->end ? (f)->buf[(f)->beg++] : fgetc(f))
The macro doesn't seem to be the issue. I tried substituting the macro's generated code.
I also tried using a temporary variable instead of lf->f
and that still crashed.
Somehow the value f->buf
(as per the above macro) is not an accessible memory location. (Is it optimization-related?)
Using fgetc
works, using getc_unlocked
also works.
Minimal example (just opening a file and reading) works perfectly with getc
and fgetc
.
The file containing the above function lauxlib.c
has not been changed in any way either.
Assuming that's not a major error, here's the current status of testing the compiled lua.exe
.
The test scripts are part of the Github mirror, and are also available here.
From their site:
The test suite is not a product; it is just a tool for our internal use. It is available here by popular demand but we cannot give any kind of support for it. You're on your own.
Here's the current performance (partial indicates that Lua's internal APIs have not been tested) : Passing almost half the tests so far :)
closure.lua success
vararg.lua success
locals.lua success
cstack.lua success
tpack.lua success
calls.lua success
utf8.lua success
sort.lua success
goto.lua success
pm.lua success
db.lua success
coroutine.lua partial
nextvar.lua partial
errors.lua partial
gengc.lua partial
gc.lua partial
heavy.lua ignored
constructs.lua failed
bwcoercion.lua failed
literals.lua failed
verybig.lua failed
strings.lua failed
bitwise.lua failed
events.lua failed
attrib.lua failed
files.lua failed
math.lua failed
main.lua failed
code.lua failed
big.lua failed
api.lua failed
Lua 5.4.2 uses the %g
and %Lg
format strings for printing double
and long double
values.
I changed it to %f
in luaconf.h
and now portable Lua prints float
values!
TIL %g
is actually a format for printf
. %g
is defined as the shorter of %e
and %f
.
I've implemented the other posix functions you need. We can't use LUA_USE_DLOPEN
because Cosmopolitan statically links everything. We can do %g
and %e
but I've been holding off temporarily on that since I'd ideally want to do it in a way that keeps Hello World tiny. We export generalized dtoa which can be used for proper float formatting that's more readable than what the POSIX standard for printf() would otherwise allow. See https://justine.lol/cosmopolitan/documentation.html#xdtoa which works great with the gc()
garbage collector macro.
Using gc
works, but requires -std=gnu99
as Lua uses -std=c99
by default.
Can work around it by #define asm __asm__
, though.
I'll stick with using %f
for now.
Available on https://github.com/ahgamut/lua/tree/cosmopolitan
Using the latest commit from this repo (3e19b96
).
I changed all the #define
s related to the header updates.
bad zip cdir
cosmopolitan
from scratch.getc
segfault still exists, so I've used fgetc
)lua.exe
compiles without error (1 warning about luaD_throw
)lua.exe
runs without error and prints floats as 2.1000000
(better than g
)testbench results (partial
means success
, but additional testing requires access to the internal API).
I'll look at individual tests later today to see if the failures are actually relevant (for example a couple of tests need dlopen
).
Edit: a few tests (bitwise.lua
) were failing because they relied on other files in the same directory.
bwcoercion.lua success
literals.lua success (after disabling a locale-changing test)
verybig.lua success
closure.lua success
bitwise.lua success
vararg.lua success
locals.lua success
cstack.lua success
attrib.lua success
tpack.lua success
calls.lua success
utf8.lua success
sort.lua success
main.lua success
goto.lua success
pm.lua success
db.lua success
coroutine.lua partial
nextvar.lua partial
events.lua partial
errors.lua partial
gengc.lua partial
gc.lua partial
heavy.lua ignored
all.lua ignored
constructs.lua failed
strings.lua failed
files.lua failed
math.lua failed
code.lua failed
big.lua failed
api.lua failed
Success % 76.67
I just gave it a build. Printf float formatting seems to be integral to the functioning of the language. We're definitely going to need an adequate implementation of %g
and %e
.
The pow
function gives nan
when the base is negative.
Minimal example:
int main() {
double x = -3;
double y = pow(x,3); // -27
printf("%lf ^ 3 = %lf\n", x, y);
return 0;
}
Output is
-3.000000 ^ 3 = -nan
Note: I've posted an important update on helping to debug language integration issues in https://github.com/jart/cosmopolitan/issues/97#issuecomment-790083959 The amalgamation build is now more helpful. You need to start using new compiler flags. You'll benefit with backtraces and function call tracing.
showcrashreports()
and --ftrace
are really helpful! Now I don't have to step into gdb
if I cause a crash by changing the source, and I can jump right to the corresponding location(s) in the Cosmopolitan source and instead of searching. (Having ftrace
as an internal function like showcrashreports()
might be better for this specific case, because Lua ignores argv
parameters that are followed by --
).
Here's a bug I should have found earlier :(
Using pow
with negative base and even power gives a negative number.
int main(void) {
showcrashreports();
long double x = -3;
long double z1, z2;
z1 = pow(x, 2); // 9
printf("%Lf ^ 2 = %Lf\n", x, z1);
z2 = pow(x, -2); // 0.11111
printf("%Lf ^ 2 = %Lf\n", x, z2);
return 0;
}
-3.000000 ^ 2 = -9.000000
-3.000000 ^ 2 = -0.111111
I tried to fix it by changing the return
of powl.c
, but there might be a better way:
// libc/tinymath/powl.c
asm("fyl2x" : "=t"(u) : "0"(fabsl(x)), "u"(y) : "st(1)");
asm("fprem" : "=t"(t) : "0"(u), "u"(1.L));
asm("f2xm1" : "=t"(t) : "0"(t));
asm("fscale" : "=t"(t) : "0"(t + 1), "u"(u));
// is there a better way than calling fmod?
return (fmod(y, 2) == 0) ? t : copysignl(t, x);
Negative raised to a non-integer is a domain error. So the right thing to do is probably just some if statements checking bits. Let me submit that real quick.
Done. I'm still thinking hard about how we're going to have proper printf / sprintf / etc. formatting of reals. I kind of want to just bite the bullet and use David Gay's gdtoa code for it at this point, and rely on the macro yoink hack to make sure we don't link it unless we're using it in the format specifier. The obstacle is that proper number formatting needs malloc() and LIBC_FMT comes much earlier in the topological order of things than LIBC_MEM. So I'd probably need to refactor a bunch of code internal to the library to either not use string formatting, or possibly I could have a tiny version of printf for low-level libraries.
pow
now behaves as expected when using even exponents (using the latest commit).
asin(x)
gives an incorrect answer when x = 1
, but acos(x)
, atan(x)
and asin(1)
are correct.
int main(void) {
showcrashreports();
long double x = 1;
long double x1 = acos(1-x); // pi/2 = 1.57
long double x2 = asin(x); // pi/2 = 1.57
long double x2b = asin(1);
long double x3 = atan(x); // pi/4 = 0.78
printf("acos(%Lf) = %Lf\n", x, x1);
printf("asin(%Lf) = %Lf, but asin(1) = %Lf\n", x, x2, x2b);
printf("atan(%Lf) = %Lf\n", x, x3);
return 0;
}
acos(1.000000) = 1.570796
asin(1.000000) = -0.000000, but asin(1) = 1.570796
atan(1.000000) = 0.785398
The Lua test suite also triggers a ESPIPE/errno 29
error when testing fseek
, but minimal example works perfectly. Is Lua doing something weird when initializing a FILE*
? I'll try to isolate that error.
90% of the testbench passes:
constructs.lua success
bwcoercion.lua success
literals.lua success (removed locale-related test)
verybig.lua success
closure.lua success
bitwise.lua success
vararg.lua success
locals.lua success
cstack.lua success
attrib.lua success
tpack.lua success
calls.lua success
utf8.lua success
sort.lua success
math.lua success (apart from asin(x))
goto.lua success
big.lua success (removed syntax error w/ coroutine)
pm.lua success
db.lua success
coroutine.lua partial
nextvar.lua partial
events.lua partial
errors.lua partial
gengc.lua partial
code.lua partial
api.lua partial
gc.lua partial
heavy.lua ignored
strings.lua failed (mostly related to printf %g and one string.find)
files.lua failed (???: write+fseek on a tmpfile has issue)
main.lua failed (mostly related to printf %g)
Success % 90.00
Cosmopolitan can (almost) be used as a drop-in replacement for the system libc
when compiling Lua.
Apart from the makefile
, only 3 lines of the Lua source code need to be modified!
28 12 makefile
4 0 .gitignore
3 3 luaconf.h (%g changed at 3 lines)
2 2 testes/literals.lua
1 1 testes/big.lua
Not sure if it helps, but I was looking around the code of Marco Paland's printf
and noticed someone over there has hit the same problems with compiling Lua and %g
format, and they've provided an implementation that doesn't appear to use any malloc: https://github.com/mpaland/printf/pull/96 I had a quick look at how easy it would be to bring in to Cosmopolitan, but there is a bit of divergence in between palandprintf
and the upstream, I think mostly to have a more flexible out
callback, so this is probably better left to Justine to figure out.
Marco Paland's printf is one of the first things I checked-in to the codebase. I've added so many features and changed so many things about it since then, that it probably isn't fair to call it his work anymore. I'm really thankful to him though for getting us this far!
Cosmopolitan's printf family of functions now have float formatting that's based on dtoa(). Doing this turned out to be less disruptive than I anticipated. I'm really happy with the result in terms of code size.
%a
/%A
differ from expected output for -0.0
, inf
and nan
:
int main(void) {
double x = 0.0;
double y = INFINITY;
double z = NAN;
printf("0 = %a; -0 = %a\n",x,-x);
printf("infinity = %a; uppercase = %A\n", y, y);
printf("Not a number = %a; uppercase = %A\n", z, z);
return 0;
}
0 = 0x0p+0; -0 = 0x0p+0
infinity = inf; uppercase = inf
Not a number = nan; uppercase = nan
Fixed. I've added a bunch of tests to make sure we're doing the right thing with casing, negative zeroes, infinities, and nan. I looked into supporting signalling / quiet nans and I'm surprised that printf doesn't appear to specify that we should be printing the binary payload they might have attached.
Now all the Lua tests related to format specifiers don't cause errors. Awesome!
(Well there are a couple errors with%p
, but the script itself says %p
is implementation defined.)
asin(x)
gives -0.0000
when x=1
, but asin(1)
is ok (minimal example a few comments above)The below two errors are both related to the Lua interacting with temporary files. Minimal examples in C work properly. I've read the same lines too much, a fresh set of eyes may be able to isolate the issue.
main.lua
: Lua reads/executes/writes to tempfiles, but output doesn't match for a non-string prompt (line 310)files.lua
: Lua writes/seeks to a tempfile, but seeking fails after file is deleted + opened to write again. (line 88)asin/acos/atan/etc. is taken care of in bfef17eb with lots of tests added. Now we're onto IO which is awesome we're making progress. Taking a look.
main.lua:310 assumes libreadline is linked since it relies on termios to echo stdin to stdout. I sent the Lua project a pull request fixing that test for POSIX mode. https://github.com/lua/lua/pull/25
Alright I just went through the Lua tests and this is very nearly completed. I had to comment out the loading binary file
tests where it's deserializing binary lua code. Could you take a look? The two other things don't concern at me at first glance. One was it expected sh -c 'kill -s HUP $$'"
to exit rather than terminate, and I don't understand why. The other was a torture test for tm::tm_year
and that's a KI since the time code is the oldest code in this codebase and I'm still searching for a suitable way to modernize it.
The loading binary file
-related tests fail because the Lua interpreter tries to parse them as text files.
So it throws a syntax error, and loadfile
returns nil
instead of the appropriate function.
The Lua signature for binary file is 0x1b
followed by Lua
at the start of the file.
The file reader (and later parser) checks for 0x1b
at the start of the file. At the file reader stage this check is successful, (calls freopen
to open as binary file), but the file offset is not reset. The reopened file is read from the second character L
instead of the first character 0x1b
.
The parser then gets it wrong (reads L
and proceeds as if text file).
I checked that freopen
does not reset the file offset by fseek
-ing to the start before re-reading a binary file: the files are read without error.
Minimal example (writes to a local file, reads one char in text and rest in binary):
#include <stdio.h>
int writefile(const char* filename)
{
int stat = 0;
FILE* fp = fopen(filename, "w");
stat = fputs("cosmopolitan libc\n", fp);
fclose(fp);
return stat;
}
int readfile(const char* filename)
{
int stat = 0;
char buf1[30];
char buf2[30];
FILE *fp1, *fp2;
fp1 = fopen(filename, "r");
if(!fp1)
{
printf("failed to read %s in r\n", filename);
return 1;
}
buf1[0] = fgetc(fp1);
buf1[1] = '\0';
fp2 = freopen(filename, "rb", fp1);
if(!fp2)
{
printf("failed to read %s in rb\n", filename);
return 1;
}
// fseek(fp2, 0, SEEK_SET); incorrect without this
stat = fread(buf2, sizeof(buf2[0]), 20, fp2);
buf2[stat+1] = '\0';
printf("first char = %s\n", buf1);
printf("full string = %s\n", buf2);
return 0;
}
int main(void) {
int res = 0;
res = writefile("file.txt");
res = readfile("file.txt");
return res;
}
Expected output:
first char = c
full string = cosmopolitan libc
Obtained output:
first char = c
full string = osmopolitan libc
cos
freopen(file, "rb", ptr)
does not move to start of file properly (incorrect read)date/time
I've fixed freopen
. What's this about a breakpoint trap? Did I leave a stray DebugBreak()
statement lying around by mistake?
Lua is now checked-in to the repository. You can now build a 259kb Lua interpreter binary that runs on all operating systems. I can confirm that all tests are passing including when Lua is built with Address Sanitizer. The only exception of the four lines I needed to comment out mentioned above which I believe to be of little consequence. I've made no changes to the Lua codebase itself, aside from normalizing its #include
lines.
git clone https://github.com/jart/cosmopolitan && cd cosmopolitan
make -j8 MODE=tiny o/tiny/third_party/lua/lua.com
ls -hal o/tiny/third_party/lua/lua.com
-rwxr-xr-x 1 jart jart 259.5K Mar 7 13:34 o/tiny/third_party/lua/lua.com
o/tiny/third_party/lua/lua.com
Lua 5.4.2 Copyright (C) 1994-2020 Lua.org, PUC-Rio
> 2 + 2
4
Your Lua interpreter is also a zip file. You can use a tool like InfoZIP to insert Lua scripts into your Lua binary. Such scripts can be launched as follows:
echo 'print(2 + 2)' >hello.lua
zip o/tiny/third_party/lua/lua.com hello.lua
o/tiny/third_party/lua/lua.com zip:hello.lua
4
breakpoint trap
was with context to the time_t
tests in files.lua
(SIGTRAP
), but lua.com
does not trigger any error.
"sh -c 'kill -s HUP $$'"
exits properly when executed by lua.com
.
succeeds when big.lua
has an error at line 56 coroutine.yield'b'
which causes a failed test.big.lua
is loaded as a library.
lua.com
passes all tests otherwise.
The SIGTRAP
error was because I was incorrectly using the lua.com.dbg
instead of the APE in the test scripts. The latest build of lua.exe
on my fork passes all tests without any error.
Where can I download the lua.exe
binary release? Thanks!
@niutech the Cosmopolitan repo provides Lua; clone the repo, run make
, and you will have the lua.com
APE.
Alternatively, you can
cosmopolitan.zip
into the correct subfolder and run make
If anybody is interested, I am attaching the compressed prebuilt APE binary of lua.com.gz [edit: link removed by jart] using Cosmopolitan 0.3.
Please don't post binaries on this issue tracker. Anyone who wants the Lua APE interpreter binary need only run the following commands on Linux.
git clone git@github.com:jart/cosmopolitan.git
cd cosmopolitan
make -j8 o//third_party/lua/lua.com
As a one-time thing, I've posted the Lua binary on my web server. While I intend to continue maining the Lua vendored source tree, I don't have any intent at the moment to distribute other people's software, so once again this link is merely provided for convenience.
The problem is that not everybody has Linux, Mac or WSL with GCC toolchain and GNU make, or they don't want to spend time on building it. They may just want to quickly test the portable Lua interpreter, so thank you for allowing it.
I'd recommend reaching out to the Lua developers on their mailing list, and let them know that portable APE binaries for Lua is something you'd like to see happen. With a little bit of luck, the Lua team might like Cosmopolitan enough that they'll choose to adopt it for their releases. That would be the optimal outcome, since Lua binaries should ideally come from the Lua developers.
The problem is that not everybody has Linux, Mac or WSL with GCC toolchain and GNU make, or they don't want to spend time on building it. They may just want to quickly test the portable Lua interpreter, so thank you for allowing it.
you can post the lua.com on your github site, so that windows user, for example I, can download it. Thanks
@retsyo You can find Cosmopolitan binaries here: https://github.com/burggraf/awesome-cosmo
That page is over a year old. Please see https://github.com/shmup/awesome-cosmopolitan All the official downloads come from
@jart There should be an APE binary repository (app store), similar to Flathub, AppImagehub or Snapcraft, because not everybody can build its own binaries from source. burggraf/awesome-cosmo was a temporary solution, but it seems no longer updated. Maybe there could be an official app store established under justine.lol? There are open source projects: snapcraft, kebe, etc.
I thought it might be fun to compile a portable version of a language which has C source code.
I picked Lua, and I eventually got it to compile and run on Windows/Linux.
I thought some of the compilation errors might be useful info:
cosmopolitan.h
:panic
,reverse
andisempty
.strcoll
,tanh
,sinh
, andcosh
are unimplemented (leads to linker error)UCHAR_MAX
inlimits.h
of the C stdlib is not defined even thoughSCHAR_MAX
is