实际上是便携式可执行文件

2021-02-28 21:46:08

我在Hacker News上遇到了Cosmopolitan,最初我很困惑,因为有一些交叉编译噩梦的回忆:尽管有可能在不考虑操作系统的情况下为相同的体系结构进行编译,但是OS不会被Windows所迷惑。可执行文件的前导字节?我阅读了解释其工作原理的文章,但大部分内容都超出了我的脑海。

gcc -g -O-静态-nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ -o hello.com.dbg hello.c -fuse-ld = bfd -Wl,-T,ape。 lds \ -include cosmopolitan.h crt.o ape.o cosmopolitan.aobjcopy -S -O二进制hello.com.dbg hello.com

我将其转换为简单的Makefile以运行编译命令。我在Linux + Windows(在Linux上编译)上尝试了一堆简单的C程序(基本算术,读取和写入文件),并且所有这些程序都能正常工作。

我决定尝试编译一种基于C的高级语言。我最初选择了Python,但是Python的Makefile似乎太复杂而无法使用,因此我选择了Lua,相比之下Lua看起来要简单得多。

我从盲目复制粘贴标志开始,并包括在Github上的示例编译中使用的标志。啊,如果我开箱即用,对我的懒惰来说真是太好了。以下是尝试编译Lua的逐条解说。

我遇到的第一个问题是标头冲突:如果我在编译每个目标文件时未放入-nostdlib -nostdinc,则-include cosmopolitan.h将与系统标头冲突。但是阻止系统头文件意味着我将不得不更改系统头文件的每个#include。我创建了一堆虚假的标头,它们的名称与C stdlib中的标头相同,并包含在其中。

命名冲突:cosmopolitan.h中的某些宏与Lua中的宏/函数名称冲突:反向和空。为了避免这种情况,我更改了Lua来源。

宏FIRST_RESERVED已损坏,因为缺少UCHAR_MAX。我以为UCHAR_MAX应该在limits.h中– cosmopolitan.h的limits.h部分没有UCHAR_MAX(但是有SCHAR_MAX。)我在#define中添加了说明UCHAR_MAX的名称为__UINT8_MAX __(即255)。

在Linux上时,默认的Lua Makefile会尝试在ldo.c中使用_setjmp / _longjmp。我禁用了用于编译目标文件的LUA_USE_LINUX标志,但是这导致loslib.c中的tmpnam出现问题(Cosmopolitan中提供了mkstemp)。我将Lua的源代码更改为使用setjmp / longjmp。对于sys / wait.h,在lauxlib.c中显示了类似的问题(根据Lua源代码,在非POSIX系统中是no-op);对于sys / types.h,在liolib中显示了类似问题,因此在那禁用LUA_USE_POSIX出色地。

cosmopolitan.h中未实现localeconv()函数(locale.h的一部分),这在编译lobject.c时引起错误(宏lua_getlocaledecpoint()取决于localeconv())。将宏更改为仅返回'。

Lua static int panic(lua_state *)中的panic函数与Cosmopolitan void panic(void)中的panic函数冲突。将lua函数重命名为lua_panic。这触发了在luaL_newstate中调用panic函数的错误,因此我也在那里更改了名称。

luaL_loadfilex导致帧大小错误–我以前从未见过。快速的互联网搜索表明这是因为在进入函数时在堆栈上分配了一个较大的缓冲区,是的,luaL_loadfilex分配了一个包含BUFSIZ字符缓冲区的loadF对象。我将缓冲区的大小减小到BUFSIZ-64。

loslib.c从locale.h中获取setlocale()和LC_ *,这在cosmopolitan.h中定义为外部值,但是该定义还不够。.拧紧它,我只是在loslib.c中禁用了os_setlocale,并且然后编译。

gcc -std = gnu99 -o lua lua.o liblua.a -lm -Wl,-E -ldl / usr / bin / ld:errno://lib/x86_64-linux-gnu/libc.so.6中的TLS定义section.tbss与liblua.a(lauxlib.o)/ usr / bin / ld中的非TLS参考不匹配://lib/x86_64-linux-gnu/libc.so.6:错误添加符号:错误valuecollect2:错误:ld返回了1个退出状态

我忘了,我不应该-lm或-ldl。好的,让我们尝试所有的目标文件而不是liblua.a:

/usr/bin/ld.bfd:lvm.o:在函数`l_strcmp':lvm.c :(。text + 0x59):未定义对`strcoll' /usr/bin/ld.bfd的引用:lmathlib .o:在函数`math_tanh':lmathlib.c :(。text + 0x21f):对`tanh' /usr/bin/ld.bfd的未定义引用:lmathlib.o:在函数`math_sinh'中:lmathlib.c :(。text + 0x24f):对`sinh' /usr/bin/ld.bfd的未定义引用:lmathlib.o:在函数`math_cosh':lmathlib.c :(。text + 0x27f ):对`cosh' collect2的未定义引用:错误:ld返回1退出状态

嗯...好吧,看起来世界化标头中定义的某些功能尚未在静态库中实现。没关系,我可以快速填写数学函数,而现在暂时将strcoll注释掉,只是因为我想看到它可以编译…。并成功编译!不过,让我们先运行objcopy,然后再在系统上进行尝试。

$ objcopy -S -O二进制lua lua.exe $ ls -al-rwxr-xr-x 1 1953720 2月27日01:33 lua-rwxr-xr-x 1 344064 2月27日01:39 lua.exe

减小大小似乎有些过激,但让我们看看它是否可以在Linux上运行:

这简直令人难以置信:我只需要修改Makefile和一些C源文件中的几行,就得到了一个Lua可执行文件,它可以在Linux和Windows(以及可能的其他文件)上运行。当然,仍然需要填写一些细节(上面的浮点计算会打印出g),但是Cosmopolitan当前的版本是0.0.2,因此有很多时间。

希望这意味着其他完全使用C语言提供源代码的语言也可以编译一次并在任何地方运行。下一步可能是便携式Python吗?