diff --git a/.github/workflows/netbsd.yml b/.github/workflows/netbsd.yml new file mode 100644 index 00000000..01340440 --- /dev/null +++ b/.github/workflows/netbsd.yml @@ -0,0 +1,26 @@ +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: cross-platform-actions/action@v0.22.0 + env: + PKG_PATH: 'https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/9.3/All' + with: + operating_system: netbsd + version: '9.3' #TODO: bump to 10.0 + run: | + pkg_add clang libLLVM gmake bash diffutils + gmake + ./runtests.sh --verbose" + ./runtests.sh --verbose --verbose" + gmake clean + ./compare_compilers.sh + gmake clean + ./compare_compilers.sh diff --git a/Makefile.posix b/Makefile.posix index 37a66f91..b934b247 100644 --- a/Makefile.posix +++ b/Makefile.posix @@ -7,6 +7,7 @@ LLVM_CONFIG ?= $(shell \ || which /usr/local/opt/llvm@13/bin/llvm-config \ || which llvm-config-11 \ || which /usr/local/opt/llvm@11/bin/llvm-config \ + || which /usr/pkg/libexec/libLLVM/llvm-config \ ) CFLAGS += $(shell $(LLVM_CONFIG) --cflags) CFLAGS += -gdwarf-4 # https://github.com/llvm/llvm-project/issues/56550 @@ -14,7 +15,10 @@ LDFLAGS ?= $(shell $(LLVM_CONFIG) --ldflags --libs) ifeq ($(CC),cc) # default c compiler --> use clang - CC := $(shell $(LLVM_CONFIG) --bindir)/clang + CC := $(shell \ + which `$(LLVM_CONFIG) --bindir`/clang \ + || which clang \ + ) endif all: jou compile_flags.txt @@ -26,10 +30,10 @@ compile_flags.txt: config.h: @v=`$(LLVM_CONFIG) --version`; case "$$v" in 11.*|13.*|14.*) ;; *) echo "Error: Found unsupported LLVM version $$v. Only LLVM 11, 13 and 14 are supported."; exit 1; esac echo "// auto-generated by Makefile" > config.h - echo "#define JOU_CLANG_PATH \"$(shell $(LLVM_CONFIG) --bindir)/clang\"" >> config.h + echo "#define JOU_CLANG_PATH \"$(shell which `$(LLVM_CONFIG) --bindir`/clang || which clang)\"" >> config.h obj/%.o: src/%.c $(wildcard src/*.h) config.h - mkdir -vp obj && $(CC) -c $(CFLAGS) $< -o $@ + mkdir -p obj && $(CC) -c $(CFLAGS) $< -o $@ jou: $(SRC:src/%.c=obj/%.o) $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) @@ -37,7 +41,7 @@ jou: $(SRC:src/%.c=obj/%.o) config.jou: echo "# auto-generated by Makefile" > config.jou echo "def get_jou_clang_path() -> byte*:" >> config.jou - echo " return \"$(shell $(LLVM_CONFIG) --bindir)/clang\"" >> config.jou + echo " return \"$(shell which `$(LLVM_CONFIG) --bindir`/clang || which clang)\"" >> config.jou self_hosted_compiler: jou config.jou $(wildcard self_hosted/*.jou) ./jou -o $@ --linker-flags "$(LDFLAGS)" self_hosted/main.jou diff --git a/README.md b/README.md index 1d205bf4..731cce90 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,12 @@ MacOS support is new. Please create an issue if something doesn't work. +
NetBSD + +Additionally, there is support for NetBSD on an experimental +basis. Packages `clang`, `libLLVM`, `gmake` and `bash` are required. + +
## Updating to the latest version of Jou diff --git a/compare_compilers.sh b/compare_compilers.sh index 575ce24a..ab2eb2d9 100755 --- a/compare_compilers.sh +++ b/compare_compilers.sh @@ -37,13 +37,18 @@ if [ ${#actions[@]} = 0 ]; then fi rm -rf tmp/compare_compilers -mkdir -vp tmp/compare_compilers +mkdir -p tmp/compare_compilers YELLOW="\x1b[33m" GREEN="\x1b[32m" RED="\x1b[31m" RESET="\x1b[0m" +DIFF=$(which gdiff || which diff) +if [[ x"$($DIFF --help | grep -- --color)" != x ]]; then + diff_color="--color=always" +fi + function append_line() { local file="$1" @@ -87,7 +92,7 @@ echo "Compiling the self-hosted compiler..." if [[ "$OS" =~ Windows ]]; then mingw32-make self_hosted_compiler.exe else - make self_hosted_compiler + $(which gmake || which make) self_hosted_compiler fi for file in ${files[@]}; do @@ -126,7 +131,7 @@ for action in ${actions[@]}; do echo " Compilers behave differently as expected (listed in $error_list_file)" fi else - if diff -u --color=always tmp/compare_compilers/compiler_written_in_c.txt tmp/compare_compilers/self_hosted.txt; then + if $DIFF -u $diff_color tmp/compare_compilers/compiler_written_in_c.txt tmp/compare_compilers/self_hosted.txt; then echo " Compilers behave the same as expected" else if [ $fix = yes ]; then diff --git a/examples/x11_window.jou b/examples/x11_window.jou index c79937ec..74280e4b 100644 --- a/examples/x11_window.jou +++ b/examples/x11_window.jou @@ -1,7 +1,9 @@ -# To run this program, you need linux: +# To run this program, you need a system with X11: # +# Linux: # $ ./jou --linker-flags "-lX11" examples/x11_window.jou -# +# NetBSD: +# $ ./jou --linker-flags "-L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib -lX11" examples/x11_window.jou declare usleep(x: int) -> int diff --git a/runtests.sh b/runtests.sh index 996e3964..29c17fe3 100755 --- a/runtests.sh +++ b/runtests.sh @@ -58,9 +58,13 @@ while [ $# != 0 ]; do esac done -if [ $valgrind = yes ] && [[ "$OS" =~ Windows ]]; then - echo "valgrind doesn't work on Windows." >&2 - exit 2 +if [ $valgrind = yes ]; then + case "${OS:=$(uname)}" in + Windows*|NetBSD*) + echo "valgrind doesn't work on $OS." >&2 + exit 2 + ;; + esac fi if [ $run_make = yes ]; then @@ -68,7 +72,7 @@ if [ $run_make = yes ]; then source activate mingw32-make else - make + eval $(which gmake || which make) fi fi @@ -206,12 +210,17 @@ function run_test() printf "\n\n\x1b[33m*** Command: %s ***\x1b[0m\n\n" "$command" > $diffpath - if diff --text -u --color=always <( + DIFF=$(which gdiff || which diff) + if [[ x"$($DIFF --help | grep -- --color)" != x ]]; then + diff_color="--color=always" + fi + + if $DIFF --text -u $diff_color <( generate_expected_output $joufile $correct_exit_code | tr -d '\r' ) <( export PATH="$PWD:$PATH" ulimit -v 500000 2>/dev/null - bash -c "$command; echo Exit code: \$?" 2>&1 | post_process_output $joufile | tr -d '\r' + sh -c "$command; echo Exit code: \$?" 2>&1 | post_process_output $joufile | tr -d '\r' ) &>> $diffpath; then show_ok "$command" rm -f $diffpath diff --git a/self_hosted/create_llvm_ir.jou b/self_hosted/create_llvm_ir.jou index 9ab42a77..1ecf2545 100644 --- a/self_hosted/create_llvm_ir.jou +++ b/self_hosted/create_llvm_ir.jou @@ -800,6 +800,8 @@ class AstToIR: name = "_jou_windows_startup" elif MACOS: name = "_jou_macos_startup" + elif NETBSD: + name = "_jou_netbsd_startup" else: return @@ -817,7 +819,7 @@ class AstToIR: self->llvm_function = self->declare_function(sig) self->new_block("start") - if (WINDOWS or MACOS) and strcmp(sig->name, "main") == 0 and not sig->is_method(): + if (WINDOWS or MACOS or NETBSD) and strcmp(sig->name, "main") == 0 and not sig->is_method(): self->call_the_special_startup_function() # Allocate all local variables at the start of the function. diff --git a/self_hosted/main.jou b/self_hosted/main.jou index 3e29b028..c5d75170 100644 --- a/self_hosted/main.jou +++ b/self_hosted/main.jou @@ -178,6 +178,9 @@ class Compiler: if MACOS: self->automagic_files[1] = malloc(strlen(self->stdlib_path) + 40) sprintf(self->automagic_files[1], "%s/_macos_startup.jou", self->stdlib_path) + if NETBSD: + self->automagic_files[1] = malloc(strlen(self->stdlib_path) + 40) + sprintf(self->automagic_files[1], "%s/_netbsd_startup.jou", self->stdlib_path) def parse_all_files(self) -> None: queue: ParseQueueItem* = malloc(50 * sizeof queue[0]) diff --git a/src/codegen.c b/src/codegen.c index 470cf29b..a596d70a 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -414,14 +414,16 @@ static int find_block(const CfGraph *cfg, const CfBlock *b) assert(0); } -#if defined(_WIN32) || defined(__APPLE__) +#if defined(_WIN32) || defined(__APPLE__) || defined(__NetBSD__) static void codegen_call_to_the_special_startup_function(const struct State *st) { const char *name; -#ifdef _WIN32 +#if defined _WIN32 name = "_jou_windows_startup"; -#else +#elif defined __APPLE__ name = "_jou_macos_startup"; +#else + name = "_jou_netbsd_startup"; #endif LLVMTypeRef functype = LLVMFunctionType(LLVMVoidType(), NULL, 0, false); @@ -448,7 +450,7 @@ static void codegen_function_or_method_def(struct State *st, const CfGraph *cfg) assert(cfg->all_blocks.ptr[0] == &cfg->start_block); LLVMPositionBuilderAtEnd(st->builder, blocks[0]); -#if defined(_WIN32) || defined(__APPLE__) +#if defined(_WIN32) || defined(__APPLE__) || defined(__NetBSD__) if (!get_self_class(&cfg->signature) && !strcmp(cfg->signature.name, "main")) codegen_call_to_the_special_startup_function(st); #endif diff --git a/src/evaluate.c b/src/evaluate.c index f598d39b..dccf373a 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -17,6 +17,13 @@ int get_special_constant(const char *name) return 0; #endif } + if (!strcmp(name, "NETBSD")) { + #ifdef __NetBSD__ + return 1; + #else + return 0; + #endif + } return -1; } diff --git a/src/main.c b/src/main.c index 8589a776..fddfd1e2 100644 --- a/src/main.c +++ b/src/main.c @@ -461,6 +461,9 @@ int main(int argc, char **argv) #ifdef __APPLE__ include_special_stdlib_file(&compst, "_macos_startup.jou"); #endif +#ifdef __NetBSD__ + include_special_stdlib_file(&compst, "_netbsd_startup.jou"); +#endif parse_file(&compst, command_line_args.infile, NULL); parse_all_pending_files(&compst); diff --git a/src/update.c b/src/update.c index bd44e896..e6f52785 100644 --- a/src/update.c +++ b/src/update.c @@ -61,7 +61,7 @@ void update_jou_compiler() fail(); #else confirm("Run \"git pull && make\"?"); - if (system("git pull && make")) + if (system("git pull && `which gmake || which make`")) fail(); #endif diff --git a/stdlib/_netbsd_startup.jou b/stdlib/_netbsd_startup.jou new file mode 100644 index 00000000..2859a865 --- /dev/null +++ b/stdlib/_netbsd_startup.jou @@ -0,0 +1,16 @@ +# A call to the _jou_netbsd_startup() function is inserted to the +# start of every Jou program when compiling for NetBSD. + +declare global __sF: byte[456] +global stdin: void* +global stdout: void* +global stderr: void* + +def _jou_netbsd_startup() -> None: + stdin = &__sF[0*152] + stdout = &__sF[1*152] + stderr = &__sF[2*152] + +declare __errno() -> int* +def __errno_location() -> int*: + return __errno() diff --git a/tests/should_succeed/compiler_cli.jou b/tests/should_succeed/compiler_cli.jou index abf56f03..a9b0b55a 100644 --- a/tests/should_succeed/compiler_cli.jou +++ b/tests/should_succeed/compiler_cli.jou @@ -88,7 +88,7 @@ def main() -> int: # Compile a GUI program if not (WINDOWS or MACOS): - ret = system("./jou -o /dev/null --linker-flags \"-lX11\" examples/x11_window.jou") + ret = system("./jou -o /dev/null --linker-flags \"-L/usr/X11R7/lib -lX11\" examples/x11_window.jou") assert ret == 0 # Compile a program with a memory leak.