diff --git a/cosmo-kuroko/Dockerfile b/cosmo-kuroko/Dockerfile new file mode 100644 index 0000000..69e31d2 --- /dev/null +++ b/cosmo-kuroko/Dockerfile @@ -0,0 +1,133 @@ +# MAIN: https://kuroko-lang.github.io/ +# REPO: https://github.com/kuroko-lang/kuroko +# TODO: add /zip/ support by default and include dist modules. + +FROM localhost/notwa-util AS downloader +# 1 commit after version 1.3.0: +ARG KUROKO_COMMIT=5f4d3df5d09a1f50e99c1e4d9673af1ad56fb110 +ARG KUROKO_SHA256=ddf09ad47b61d1b3602bf59214f5c596cd6a51f5bea07542a01340e86494db1a + +RUN --mount=type=cache,id=common,target=/media/common,sharing=locked \ + --mount=type=tmpfs,target=/tmp : \ + && cd /media/common \ + && name=kuroko \ + && export remote_fn="$KUROKO_COMMIT.tar.gz" \ + && export local_fn="$name-$remote_fn" \ + && export remote_url="https://github.com/kuroko-lang/$name/archive/$remote_fn" \ + && export dest=/$name \ + && export sha256="$KUROKO_SHA256" \ + && acquire \ +; + +FROM localhost/cosmo AS builder +COPY --from=downloader /kuroko /kuroko +WORKDIR /kuroko + +RUN : \ + && sed -i '/bind(gamma)/{N;N;d;}' src/modules/module_math.c \ + && sed -i '/MATH_ONE(gamma)/d' src/modules/module_math.c \ + \ + && sed -i 's_.*char \*\* environ.*_/* & */_' src/os.c \ + \ + && sed -i '/FUNC_SIG(list,append)/d' src/vm.c \ + && sed -i '/void _callSetName/i\\extern FUNC_SIG(list,append);' src/vm.c \ + \ + && sed -i '/static.*cache/c\\static KrkClassCacheEntry * cache = 0;' src/vm.c \ + && sed -i $'/define CACHE_SIZE/,/nextCount/{N;w /temp\nd}' src/vm.c \ + && sed -i $'/void krk_initVM/{r /temp\nN}' src/vm.c \ + && sed -i '/Reset current thread/i\\cache = calloc(CACHE_SIZE, sizeof(KrkClassCacheEntry));' src/vm.c \ + && sed -i '/krk_freeMemoryDebugger/a\\cache = (free(cache), NULL);' src/vm.c \ + \ + && sed -i '/define gettid/d' src/threads.c \ + && sed -i '/initial-exec/d' src/vm.c \ + \ + && sed -i $'/Ensure we don\'t have a macro/{\ni\\\ +\#ifdef KRK_DISABLE_DYNAMIC\\\n\ +KrkValue krk_module_onload_math(void);\\\n\ +KrkValue krk_module_onload_random(void);\\\n\ +KrkValue krk_module_onload_socket(void);\\\n\ +KrkValue krk_module_onload_timeit(void);\\\n\ +KrkValue krk_module_onload_wcwidth(void);\\\n\ +\#endif\\\n\ +\n\ +}' src/vm.c \ + && sed -i $'/Ensure we don\'t have a macro/{\ni\\\ +\#define BUILTIN_MODULE(name, init) { \\\\\\\n\ +\tKrkInstance * module = (KrkInstance*)AS_OBJECT(init()); \\\\\\\n\ +\tkrk_attachNamedObject(&vm.modules, name, (KrkObj*)module); \\\\\\\n\ +\tkrk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S(name)); \\\\\\\n\ +\tkrk_attachNamedValue(&module->fields, "__file__", NONE_VAL()); \\\\\\\n\ +} \\\n\ +\n\ +}' src/vm.c \ + && sed -i $'/krk_module_init_dis/{\na\\\ +\#endif\\\n\ +\#ifdef KRK_DISABLE_DYNAMIC\\\n\ +\t\tBUILTIN_MODULE("math", krk_module_onload_math)\\\n\ +\t\tBUILTIN_MODULE("random", krk_module_onload_random)\\\n\ +\t\tBUILTIN_MODULE("socket", krk_module_onload_socket)\\\n\ +\t\tBUILTIN_MODULE("timeit", krk_module_onload_timeit)\\\n\ +\t\tBUILTIN_MODULE("wcwidth", krk_module_onload_wcwidth)\n\ +}' src/vm.c \ + && sed -i $'/switch (afval)/{\ni\\\ +\tif (afval == AF_INET) return "AF_INET";\\\n\ +\tif (afval == AF_INET6) return "AF_INET6";\\\n\ +\tif (afval == AF_UNIX) return "AF_UNIX";\\\n\ +\tsnprintf(tmp,30,"%d",afval);\\\n\ +\treturn tmp;\n\ +}\n\ +/switch (afval)/,/}/d' src/modules/module_socket.c \ + \ + && sed -i $'/strlen(buf)-1/{\n\ +s/if .*/if (buf[buflen-1] == \'\\\\n\') {/\n\ +i\\\ +\t\t\t\tsize_t buflen = strlen(buf);\n\ +a\\\ +\t\t\t\t\t\\if (buflen >= 2 && buf[buflen-2] == \'\\\\r\') buf[buflen-2] = \'\\\\n\', buf[buflen-1] = \'\\\\0\';\\\n\ +\t\t\t\t} else {\n\ +}' src/kuroko.c \ + \ + && { diff -NrU3 /kuroko.orig/ /kuroko/ > /kuroko.patch; [ $? -le 1 ]; } +# diff exit status is normally 0 or 1, anything greater is an error. + +RUN : \ +# this isn't included in the patch because it's super specific to cosmopolitan. \ + && sed -i 's/int main/dontinline int _main/' src/kuroko.c \ + && printf %s $'\n\ +STATIC_YOINK("__die");\n\ +int LoadZipArgs(int *, char ***);\n\ +int main(int argc, char * argv[]) {\n\ +\tShowCrashReports();\n\ +\tLoadZipArgs(&argc, &argv);\n\ +\treturn _main(argc, argv);\n\ +}\n\ +' >> src/kuroko.c + +RUN : \ + && cd /cosmopolitan \ + && . ./env \ + && cd dist/"$flavor" \ + && mkdir -p /kuroko/libcosmo \ + && ln ape-copy-self.o ape.lds cosmopolitan.a crt.o ape-no-modify-self.o ape.o cosmopolitan.h \ + /kuroko/libcosmo/ + +COPY super.mk . +RUN : \ + && CC=x86_64-linux-musl-gcc \ + make.com -f super.mk -j2 \ + KRK_DISABLE_RLINE=1 \ + KRK_DISABLE_DYNAMIC=1 \ +# KRK_DISABLE_THREADS=1 \ +# KRK_DISABLE_DEBUG=1 KRK_NO_DISASSEMBLY=1 KRK_NO_TRACING=1 \ +; + +RUN : \ + && make.com -f super.mk test \ +; + +FROM scratch AS runner +COPY --chmod=0755 --from=localhost/notwa-util /usr/local/bin/busybox /bin/busybox +COPY --chmod=0755 --from=builder /cosmopolitan/bin/ape /bin/ape +COPY --chmod=0755 --from=builder /kuroko/kuroko.com /kuroko/kuroko.com.dbg /bin/ +COPY --from=builder /kuroko.patch /var/local/kuroko.patch +ENTRYPOINT ["/bin/ape", "/bin/kuroko.com"] diff --git a/cosmo-kuroko/super.mk b/cosmo-kuroko/super.mk new file mode 100755 index 0000000..ccb1e9d --- /dev/null +++ b/cosmo-kuroko/super.mk @@ -0,0 +1,102 @@ +CC ?= gcc +CFLAGS = -Isrc -Os -fdiagnostics-color=always -fmax-errors=5 +LDFLAGS = +LDLIBS = + +COSMO_LIBDIR = ./libcosmo + +COSMO_PREFLAGS = -g -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone +COSMO_PREFLAGS += -fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs +COSMO_PREFLAGS += -include $(COSMO_LIBDIR)/cosmopolitan.h -Idummy + +COSMO_POSTFLAGS += -Wl,--gc-sections -fuse-ld=bfd -Wl,--gc-sections +COSMO_POSTFLAGS += -Wl,-T,$(COSMO_LIBDIR)/ape.lds +COSMO_POSTFLAGS += $(COSMO_LIBDIR)/crt.o $(COSMO_LIBDIR)/ape-no-modify-self.o $(COSMO_LIBDIR)/cosmopolitan.a + +COSMO_FILES = $(COSMO_LIBDIR)/ape-copy-self.o $(COSMO_LIBDIR)/ape-no-modify-self.o +COSMO_FILES += $(COSMO_LIBDIR)/ape.lds $(COSMO_LIBDIR)/ape.o $(COSMO_LIBDIR)/crt.o +COSMO_FILES += $(COSMO_LIBDIR)/cosmopolitan.a $(COSMO_LIBDIR)/cosmopolitan.h + +DUMMY_HEADERS = arpa/inet.h assert.h dirent.h dlfcn.h errno.h fcntl.h inttypes.h limits.h locale.h math.h netdb.h pthread.h sched.h signal.h stdarg.h stddef.h stdint.h stdio.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/stat.h sys/syscall.h sys/time.h sys/types.h sys/utsname.h termios.h time.h unistd.h wchar.h +DUMMY_MISSING = $(foreach header,$(DUMMY_HEADERS),$(if $(wildcard dummy/$(header)),,dummy/$(header))) + +TARGET = kuroko +OBJS = $(patsubst %.c, %.o, $(filter-out src/kuroko.c,$(sort $(wildcard src/*.c)))) +HEADERS = $(wildcard src/kuroko/*.h) +GENMODS = modules/codecs/sbencs.krk modules/codecs/dbdata.krk + +ifdef KRK_DISABLE_DOCS + CFLAGS += -DKRK_NO_DOCUMENTATION -Wno-unused-value +endif + +ifndef KRK_DISABLE_RLINE + BIN_OBJS += src/vendor/rline.o +else + CFLAGS += -DNO_RLINE +endif + +ifdef KRK_DISABLE_DEBUG + CFLAGS += -DKRK_DISABLE_DEBUG +endif + +ifdef KRK_DISABLE_DYNAMIC + BIN_OBJS += src/modules/module_math.o src/modules/module_random.o src/modules/module_socket.o src/modules/module_timeit.o src/modules/module_wcwidth.o + CFLAGS += -DKRK_DISABLE_DYNAMIC -DSTATIC_ONLY +endif + +ifdef KRK_DISABLE_THREADS + CFLAGS += -DKRK_DISABLE_THREADS +else + CFLAGS += -DKRK_MEDIOCRE_TLS +endif + +ifdef KRK_NO_DISASSEMBLY + CFLAGS += -DKRK_NO_DISASSEMBLY=1 +endif + +ifdef KRK_NO_TRACING + CFLAGS += -DKRK_NO_TRACING=1 +endif + +ifdef KRK_NO_STRESS_GC + CFLAGS += -DKRK_NO_STRESS_GC=1 +endif + +HEADERS += $(COSMO_LIBDIR)/cosmopolitan.h +BIN_OBJS += $(OBJS) + +all: $(TARGET).com $(GENMODS) + +dummy/%.h: + mkdir -p dummy && touch $@ + +dummy/arpa/%.h: + mkdir -p dummy/arpa && touch $@ + +dummy/sys/%.h: + mkdir -p dummy/sys && touch $@ + +%.o: %.c $(HEADERS) $(DUMMY_MISSING) + $(CC) $(CFLAGS) $(COSMO_PREFLAGS) -c -o $@ $< + +$(TARGET).com.dbg: src/$(TARGET).c $(BIN_OBJS) $(HEADERS) $(DUMMY_MISSING) + $(CC) $(CFLAGS) $(LDFLAGS) $(COSMO_PREFLAGS) -o $@ $< $(BIN_OBJS) $(LDLIBS) $(COSMO_POSTFLAGS) + +$(TARGET).com: $(TARGET).com.dbg + objcopy -S -O binary $< $@ + +.PHONY: test +test: + @for i in test/*.krk; do echo $$i; KUROKO_TEST_ENV=1 $(TESTWRAPPER) ./$(TARGET).com.dbg $$i > $$i.actual; diff $$i.expect $$i.actual || exit 1; rm $$i.actual; done + +.PHONY: clean +clean: + -rm -f $(OBJS) $(TARGET).com $(TARGET).com.dbg src/*.o src/vendor/*.o + +# special cases: + +modules/codecs/sbencs.krk: tools/codectools/gen_sbencs.krk tools/codectools/encodings.json tools/codectools/indexes.json | $(TARGET).com.dbg + ./$(TARGET).com.dbg tools/codectools/gen_sbencs.krk + +modules/codecs/dbdata.krk: tools/codectools/gen_dbdata.krk tools/codectools/encodings.json tools/codectools/indexes.json | $(TARGET).com.dbg + ./$(TARGET).com.dbg tools/codectools/gen_dbdata.krk