Compare commits

...

7 Commits

Author SHA1 Message Date
a1f1c841c0 write a CI workflow for multiple OSes, that compile and test the code using the makefile. 2025-09-13 20:27:40 +02:00
d9ddae770a fix: just use compiler builtins with endianess
this is the most portable and clean approach. Compiler built-ins should
always be present regardless, and is more maintainable, since we're not
trying to keep up with various versions of this header.
2025-09-13 20:25:38 +02:00
c2e1b67b4c seperate out library compilation from general compilation
This can help with a more nuanced compilation. (eg. use system libraries
rather than compile our own)
Furthermore, it decreases the needed compilation time, since we needn't
recompile the whole thing when having cleaned out our local sources.
2025-09-13 20:25:38 +02:00
8548c2d037 fix: log macros were using GNU extensions without them needing them.
We can optionally add `,` utilising the `__VA_OPT__` macro. However,
this lead to the next problem, which is that an empty vardiac parameter
is a C23 extension. This was solved by dropping the string parameter,
making it be part of the vardiac parameters.
2025-09-13 20:25:38 +02:00
7ec6a3b91a fix: using __bswap_X functions over bswap_X macros, which we should be using. 2025-09-13 20:25:38 +02:00
3f48a7abb2 add compile commands events to gitignore 2025-09-13 20:25:38 +02:00
667814fb72 rework makefile to put extera emphasis on us no longer performing cross-platform compilation
Furthermore, we removed a bunch of behaviour that wasn't needed, and
simplified the bunch.
2025-09-13 20:25:38 +02:00
8 changed files with 109 additions and 124 deletions

30
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: CI
on:
push:
branches: [main]
jobs:
compile-and-test:
strategy:
matrix:
os:
- ubuntu-latest
- ubuntu-24.04-arm
- windows-latest
- windows-11-arm
- macos-latest
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v5
with:
repository: ${{github.repository}}
submodules: true
fetch-depth: 1
- uses: actions/cache@v4
with:
path: lib/obj/
key: ${{runner.os}}-lib/obj-${{github.sha}}
restore-keys: ${{runner.os}}-lib/obj-
- run: make libs
- run: make all
- run: make test

2
.gitignore vendored
View File

@@ -18,4 +18,6 @@
*.lock
/bin/
/obj/
/lib/obj/
compile_commands.json
compile_commands.events.json

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "lib/glfw"]
path = lib/glfw
url = https://github.com/glfw/glfw
[submodule "lib/libarchive"]
path = lib/libarchive
url = https://github.com/libarchive/libarchive

143
Makefile
View File

@@ -1,102 +1,87 @@
# Copyright (c) 2025 Quinn
# Licensed under the MIT Licence. See LICENSE for details
SHELL = bash
.SHELLFLAGS = -O globstar -c
# build configuration, information about the current build process
NAME = mcaselector-lite
VERSION = 0.0.0
DEBUG ?= 0
CC ?= cc
LD ?= ld
# compilation flags
CFLAGS += -c -std=gnu99 -Wall -Wextra -Wpedantic -MMD -MP
LDFLAGS += -flto
# setting default compilation flags
# some of which are able to be overwritten, others are always appended
CPPFLAGS ?=
CFLAGS ?= -O2 -Wall -Wextra -Wpedantic
LDFLAGS ?= -flto
CFLAGS += -std=gnu99
# architecture/OS detection
ifeq ($(KERNEL),)
ISWIN := $(if $(filter $(OS),Windows_NT),1,0)
ifeq ($(ISWIN),1)
KERNEL = mingw
MARCH = x86_64
# add a few extra flags depending on whether
# we're debugging or not
ifeq ($(DEBUG),0)
CPPFLAGS += -DNDEBUG
else
MARCH := $(shell uname -m)
KERNEL := $(shell uname -s | tr '[:upper:]' '[:lower:]')
CFLAGS += -fsanitize=address -ftrapv -g
LDFLAGS += -fsanitize=address -ftrapv
endif
else
ISWIN := $(if $(filter $(KERNEL),mingw),1,0)
endif
ifeq ($(MARCH),)
$(error must also set MARCH when manually setting KERNEL)
CPPFLAGS += -Iinclude -Ilib/glad/include -Ilib/glfw/include -Ilib/libarchive/libarchive
LDFLAGS += -Llib/obj/glfw/src -Llib/obj/libarchive/libarchive
LDLIBS += -lm -lglfw -larchive
# detect if we're compiling on Windows, meaning
# a lot of things considered "standard" are unavailable.
ifeq ($(OS),Windows_NT)
ISWIN = 1
NAME := $(NAME).exe
$(warning Detected Windows_NT, please refer to the documentation if you encounter issues.)
endif
# profiles
ifeq ($(DEBUG),1)
PROF = dbg
CFLAGS += -UNDEBUG -Og -g -Wextra -Wpedantic
CFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address,undefined) -ftrapv
LDFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address,undefined) -ftrapv
# |--profile: testing
else ifeq ($(DEBUG),test)
PROF = test
CFLAGS += -UNDEBUG -O2 -g
CFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address) -ftrapv
LDFLAGS += $(if $(filter 1,$(ISWIN)),,-fsanitize=address) -ftrapv
else
PROF = rel
CFLAGS += -DNDEBUG -O2
endif
# TODO: find a better method to find all source files
# find all the source files using wildcards
# NOTE: MS-DOS and MS-Windows uses backslash `\`, this might break.
RES := $(wildcard res/*)
SRC := $(wildcard src/*.c src/*/*.c src/*/*/*.c src/*/*/*/*.c src/*/*/*/*/*.c src/*/*/*/*/*/*.c src/*/*/*/*/*/*/*.c src/*/*/*/*/*/*/*/*.c) lib/glad/gl.c
OBJ := $(SRC:%.c=obj/%.o) $(RES:%=obj/%.o)
TSRC := $(wildcard test/*.c test/*/*.c test/*/*/*.c test/*/*/*/*.c test/*/*/*/*/*.c test/*/*/*/*/*/*.c test/*/*/*/*/*/*/*.c test/*/*/*/*/*/*/*/*.c)
TOBJ := $(TSRC:%.c=obj/%.o)
CFLAGS += $(shell pkg-config --cflags glfw3 libarchive) -Iinclude -Ilib/glad/include
LDFLAGS += $(shell pkg-config --libs glfw3 libarchive) -lm
# get source files
SRC := $(shell echo src/**/*.c) lib/glad/src/gl.c
RES := $(wildcard res/*.glsl)
ifeq ($(DEBUG),test)
SRC := $(filter-out src/main.c, $(SRC)) $(shell echo test/**/*.c)
endif
NAME += $(if $(filter 1,$(ISWIN)),.exe,)
DIR_BIN := bin/$(MARCH)-$(KERNEL)/$(VERSION)/$(PROF)
DIR_OBJ := obj/$(MARCH)-$(KERNEL)/$(VERSION)/$(PROF)
# output files
BIN := $(DIR_BIN)/$(NAME)
OBJ := $(SRC:%.c=$(DIR_OBJ)/%.o) $(RES:%=$(DIR_OBJ)/%.o)
DEP := $(OBJ:%.o=%.d)
.PHONY:
run: compile
$(if $(filter 1,$(ISWIN)),wine,) $(BIN)
.PHONY:
compile: $(BIN)
.PHONY .NOTPARALLEL:
# TODO: potentially automatically detect whether we should compile libs, or if we can just go ahead.
.PHONY: all libs test clean clean-libs
all: bin/$(NAME)
libs: lib/obj/glfw/ lib/obj/libarchive/
test: bin/TEST_$(NAME); bin/TEST_$(NAME)
clean:
@[ -d obj/ ] && rm -rv obj/ || true
@[ -d bin/ ] && rm -rv bin/ || true
@[ -d bin/ ] && rm -vr bin/ || true
@[ -d obj/ ] && rm -vr obj/ || true
clean-libs:
@[ -d lib/obj/ ] && rm -vr lib/obj/
$(BIN): $(OBJ)
$(info [CC/LD] $@)
@mkdir -p $(@D)
@$(CC) -o $@ $^ $(LDFLAGS)
$(DIR_OBJ)/%.o: %.c
$(info [CC] $@)
@mkdir -p $(@D)
@$(CC) $(CFLAGS) -o $@ $<
# compiles the libraries using cmake
lib/obj/%/: lib/%/
cmake -S $< -B $@
$(MAKE) -C $@
$(DIR_OBJ)/res/%.o: res/%
$(info [LD] $@)
# link together a runtime binary
bin/$(NAME): $(OBJ)
$(info [CC/LD] $@)
@mkdir -p $(@D)
@$(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
# link together a testing binary
bin/TEST_$(NAME): $(TOBJ) $(filter-out main.o,$(OBJ))
$(info [CC/LD] $@)
@mkdir -p $(@D)
@$(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
obj/res/%.o: res/%
$(info [LD] $@)
@$(LD) -r -b binary -o $@ $<
# some definitions for "default" and assumed compilers, for bulk selection
.PHONY: x86_64-linux-gnu-gcc x86_64-w64-mingw32-gcc
x86_64-linux-gnu-gcc:; $(MAKE) $(CALL) $(MAKEFLAGS) CC=$@ MARCH=x86_64 KERNEL=linux
x86_64-w64-mingw32-gcc:; $(MAKE) $(CALL) $(MAKEFLAGS) CC=$@ MARCH=x86_64 KERNEL=mingw
obj/%.o: %.c
$(info [CC] $@)
@mkdir -p $(@D)
@$(CC) -c $(CPPFLAGS) $(CFLAGS) -MMD -MP -o $@ $<
-include $(DEP)
# Include the generated dependency files.
# Which creates rules for all dependencies,
# as a result updating an .o file when a .h is updated.
-include $(OBJ:%.o=%.d)

View File

@@ -1,46 +1,9 @@
/* Copyright (c) 2025 Quinn
* Licensed under the MIT Licence. See LICENSE for details */
#ifndef PORTABLE_ENDIAN_H
#define PORTABLE_ENDIAN_H 1
#if defined(__GNUC__)
/* test for the byteswap header */
#if __has_include(<byteswap.h>)
#include <byteswap.h>
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define le16toh(x) (x)
#define le32toh(x) (x)
#define le64toh(x) (x)
#define htole16(x) (x)
#define htole32(x) (x)
#define htole64(x) (x)
#define be16toh(x) __bswap_16(x)
#define be32toh(x) __bswap_32(x)
#define be64toh(x) __bswap_64(x)
#define htobe16(x) __bswap_16(x)
#define htobe32(x) __bswap_32(x)
#define htobe64(x) __bswap_64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define le16toh(x) __bswap_16(x)
#define le32toh(x) __bswap_32(x)
#define le64toh(x) __bswap_64(x)
#define htole16(x) __bswap_16(x)
#define htole32(x) __bswap_32(x)
#define htole64(x) __bswap_64(x)
#define be16toh(x) (x)
#define be32toh(x) (x)
#define be64toh(x) (x)
#define htobe16(x) (x)
#define htobe32(x) (x)
#define htobe64(x) (x)
#else
#error machine architecture unsupported! Expected either big-endian or little-endian, make sure to use a compiler which defines __BYTE_ORDER__ (like clang or gcc)
#endif /* byte order */
/* otherwise, utilise the compiler built-ins */
#else
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define le16toh(x) __uint16_identity(x)
#define le32toh(x) __uint32_identity(x)
@@ -71,10 +34,7 @@
#error machine architecture unsupported! Expected either big-endian or little-endian, make sure to use a compiler which defines __BYTE_ORDER__ (like clang or gcc)
#endif /* byte order */
#endif /* has byteswap.h */
#else
#error GNU C is unavailable
#endif /* __GNUC__ */
#endif /* PORTABLE_ENDIAN_H */

1
lib/glfw Submodule

Submodule lib/glfw added at 7b6aead9fb

1
lib/libarchive Submodule

Submodule lib/libarchive added at 9525f90ca4

View File

@@ -15,8 +15,8 @@ void error_war(uint ln, const char *restrict file, const char *restrict fmt, ...
void error_err(uint ln, const char *restrict file, const char *restrict fmt, ...);
void error_fat(uint ln, const char *restrict file, const char *restrict fmt, ...) NORET;
#define debug(s, ...) error_dbg(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define info(s, ...) error_inf(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define warn(s, ...) error_war(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define error(s, ...) error_err(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define fatal(s, ...) error_fat(__LINE__, __FILE__, s, ##__VA_ARGS__)
#define debug(...) error_dbg(__LINE__, __FILE__ __VA_OPT__(, ) __VA_ARGS__)
#define info(...) error_inf(__LINE__, __FILE__ __VA_OPT__(, ) __VA_ARGS__)
#define warn(...) error_war(__LINE__, __FILE__ __VA_OPT__(, ) __VA_ARGS__)
#define error(...) error_err(__LINE__, __FILE__ __VA_OPT__(, ) __VA_ARGS__)
#define fatal(...) error_fat(__LINE__, __FILE__ __VA_OPT__(, ) __VA_ARGS__)