jart / cosmopolitan

build-once run-anywhere c library
ISC License
17.67k stars 599 forks source link

Compiling Lua #61

Closed ahgamut closed 3 years ago

ahgamut commented 3 years ago

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:

jart commented 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.

ahgamut commented 3 years ago

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(-)
ingenieroariel commented 3 years ago

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
  '';
}
benwbooth commented 3 years ago

Wouldn't you just need to run lua first as part of the nix install? Maybe lua --version or something?

mnemnion commented 3 years ago

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.

jart commented 3 years ago

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

jart commented 3 years ago

@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.

https://github.com/jart/cosmopolitan/blob/839e2f4cfb0ba4b2a687ecc1ab3e2aac9c93aab9/tool/build/compile.c#L523-L543

jart commented 3 years ago

@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.

ahgamut commented 3 years ago

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:

Errors from earlier that do not appear now:

Errors that still appear / require adding a fix to the Lua source code for successful compilation:

#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.

jart commented 3 years ago

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.

ahgamut commented 3 years ago

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
}
jart commented 3 years ago

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.

jart commented 3 years ago

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))
ahgamut commented 3 years ago

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?)

Screenshot from 2021-03-02 01-13-01

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.

ahgamut commented 3 years ago

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
ahgamut commented 3 years ago

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.

jart commented 3 years ago

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.

ahgamut commented 3 years ago

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 %ffor now.

Available on https://github.com/ahgamut/lua/tree/cosmopolitan

Using the latest commit from this repo (3e19b96).
I changed all the #defines related to the header updates.

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
jart commented 3 years ago

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.

ahgamut commented 3 years ago

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
jart commented 3 years ago

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.

ahgamut commented 3 years ago

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);
jart commented 3 years ago

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.

jart commented 3 years ago

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.

ahgamut commented 3 years ago

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.

ahgamut commented 3 years ago

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
alisonatwork commented 3 years ago

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.

jart commented 3 years ago

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.

ahgamut commented 3 years ago

%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
jart commented 3 years ago

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.

ahgamut commented 3 years ago

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.)

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.

jart commented 3 years ago

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.

jart commented 3 years ago

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

jart commented 3 years ago

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.

ahgamut commented 3 years ago

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
jart commented 3 years ago

I've fixed freopen. What's this about a breakpoint trap? Did I leave a stray DebugBreak() statement lying around by mistake?

jart commented 3 years ago

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
ahgamut commented 3 years ago

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. big.lua has an error at line 56 coroutine.yield'b' which causes a failed test. succeeds when big.lua is loaded as a library.

lua.com passes all tests otherwise.

ahgamut commented 3 years ago

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.

niutech commented 3 years ago

Where can I download the lua.exe binary release? Thanks!

ahgamut commented 3 years ago

@niutech the Cosmopolitan repo provides Lua; clone the repo, run make, and you will have the lua.com APE.

Alternatively, you can

niutech commented 3 years ago

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.

jart commented 3 years ago

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.

niutech commented 3 years ago

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.

jart commented 3 years ago

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.

niutech commented 3 years ago

For now there is portable ULua.

retsyo commented 1 year ago

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

niutech commented 1 year ago

@retsyo You can find Cosmopolitan binaries here: https://github.com/burggraf/awesome-cosmo

jart commented 1 year ago

That page is over a year old. Please see https://github.com/shmup/awesome-cosmopolitan All the official downloads come from

niutech commented 1 year ago

@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.