aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-08 12:00:49 +0200
committerhachem <im@hachem.wtf>2026-09-08 12:00:49 +0200
commit9d47486aac9cd1a4422b78ee273b7a27bf7b733a (patch)
treea015067fe963f3a24e8f37a8b9cd581540b3bb8c
parent21be45a904a0afc767214298721bd2bbce19a054 (diff)
refactor: flatten src and migrate to meson
-rw-r--r--.gitignore11
-rw-r--r--Dockerfile11
-rw-r--r--README.md25
-rw-r--r--meson.build79
-rw-r--r--premake5.lua178
-rwxr-xr-xscripts/run.sh6
-rwxr-xr-xscripts/run_suite.sh6
-rwxr-xr-xscripts/test_examples.sh4
-rw-r--r--src/args.c (renamed from src/cli/args.c)2
-rw-r--r--src/args.h (renamed from src/cli/args.h)0
-rw-r--r--src/ast.c (renamed from src/parser/ast.c)2
-rw-r--r--src/ast.h (renamed from src/parser/ast.h)2
-rw-r--r--src/diag.c (renamed from src/diag/diag.c)2
-rw-r--r--src/diag.h (renamed from src/diag/diag.h)2
-rw-r--r--src/file.c (renamed from src/io/file.c)4
-rw-r--r--src/file.h (renamed from src/io/file.h)0
-rw-r--r--src/lexer.c (renamed from src/lexer/lexer.c)2
-rw-r--r--src/lexer.h (renamed from src/lexer/lexer.h)0
-rw-r--r--src/main.c14
-rw-r--r--src/nasm.c (renamed from src/codegen/nasm.c)2
-rw-r--r--src/nasm.h (renamed from src/codegen/nasm.h)2
-rw-r--r--src/parser.c (renamed from src/parser/parser.c)4
-rw-r--r--src/parser.h (renamed from src/parser/parser.h)4
-rw-r--r--src/sema.c (renamed from src/sema/sema.c)2
-rw-r--r--src/sema.h (renamed from src/sema/sema.h)4
-rw-r--r--tests/codegen_test.c4
-rw-r--r--tests/lexer_test.c2
-rw-r--r--tests/parser_test.c2
-rw-r--r--tests/sema_test.c4
29 files changed, 136 insertions, 244 deletions
diff --git a/.gitignore b/.gitignore
index 843c7fa..a850c5a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,15 +1,8 @@
-bin/
-bin-int/
-
-Makefile
-*.make
-*.sln
-*.vcxproj
-*.vcxproj.*
+build/
+build-*/
compile_commands.json
compile_flags.txt
.clangd
.DS_Store
-
diff --git a/Dockerfile b/Dockerfile
index 2fccad9..e8f37e0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,18 +1,11 @@
FROM --platform=linux/amd64 debian:trixie-slim
-ARG PREMAKE_VERSION=5.0.0-beta8
-
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
nasm \
binutils \
- make \
- curl \
- ca-certificates \
+ meson \
+ ninja-build \
&& rm -rf /var/lib/apt/lists/*
-RUN curl -fsSL "https://github.com/premake/premake-core/releases/download/v${PREMAKE_VERSION}/premake-${PREMAKE_VERSION}-linux.tar.gz" \
- | tar -xz -C /usr/local/bin \
- && chmod +x /usr/local/bin/premake5
-
WORKDIR /hdass
diff --git a/README.md b/README.md
index 53e0579..c3e942e 100644
--- a/README.md
+++ b/README.md
@@ -37,18 +37,23 @@ The program still directly controls the registers used for the system calls. Not
The full language reference, shit like directives, declarations, statements, expressions, registers and extensions, is explained in [docs/language.md](docs/language.md).
## Building
-The build is driven by [premake5](https://premake.github.io/). Generate the makefiles and build the compiler:
+The build is driven by [Meson](https://mesonbuild.com/). Configure a build directory and compile the compiler:
```bash
-premake5 gmake
-make config=debug
+meson setup build
+meson compile -C build
```
-This produces the `hdass` binary at `bin/<config>-<system>/hdass` (for example `bin/debug-macosx/hdass` or `bin/debug-linux/hdass`). The available configurations are `debug`, `release` and `dist`. To run the unit tests:
+This produces the `hdass` binary at `build/hdass`. The default build turns on the address and undefined-behaviour sanitizers; for an optimised build without them, configure a separate directory:
```bash
-make config=debug
-./bin/<config>-<system>/tests
+meson setup build-release --buildtype=release -Db_sanitize=none
+meson compile -C build-release
```
+To run the unit tests:
+```bash
+meson test -C build
+```
+If [cppcheck](https://cppcheck.sourceforge.io/) is installed, `ninja -C build cppcheck` runs static analysis over the sources.
-hdass emits x86-64 assembly, so to actually assemble and run its output you need an x86-64 Linux toolchain. The bundled Docker environment provides a consistent one on any host, including Apple Silicon, where the amd64 image runs under emulation. The image is a Debian base with `nasm`, `ld` (binutils), a C toolchain and `premake5` preinstalled.
+hdass emits x86-64 assembly, so to actually assemble and run its output you need an x86-64 Linux toolchain. The bundled Docker environment provides a consistent one on any host, including Apple Silicon, where the amd64 image runs under emulation. The image is a Debian base with `nasm`, `ld` (binutils), a C toolchain and Meson/Ninja preinstalled.
Start the container (this builds the image the first time):
```bash
@@ -62,8 +67,8 @@ docker compose exec hdass bash
From inside the container you can build the compiler and take a program all the way to a running executable:
```bash
-premake5 gmake && make config=debug
-./bin/debug-linux/hdass examples/hello_world.hdass -o hello.asm
+meson setup build-linux && meson compile -C build-linux
+./build-linux/hdass examples/hello_world.hdass -o hello.asm
nasm -f elf64 hello.asm -o hello.o
ld -e main hello.o -o hello
./hello
@@ -71,7 +76,7 @@ ld -e main hello.o -o hello
To transpile, assemble, link and run every program in [examples/](examples/) and check its output, use the end-to-end test script (also from inside the container):
```bash
-make config=debug && ./scripts/test_examples.sh
+meson setup build-linux && meson compile -C build-linux && ./scripts/test_examples.sh
```
Or, from the host, run the whole suite (unit tests plus the example tests) in one shot, bringing the container up if needed:
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..b445e94
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,79 @@
+project(
+ 'hdass',
+ 'c',
+ version: '0.1.0',
+ license: 'MIT',
+ meson_version: '>=1.0.0',
+ default_options: [
+ 'c_std=c17',
+ 'warning_level=3',
+ 'b_sanitize=address,undefined',
+ 'b_lundef=false',
+ ],
+)
+
+cc = meson.get_compiler('c')
+
+add_project_arguments(
+ cc.get_supported_arguments(
+ '-Wconversion',
+ '-Wsign-conversion',
+ '-Wshadow',
+ '-Wstrict-prototypes',
+ '-Wmissing-prototypes',
+ '-fno-omit-frame-pointer',
+ ),
+ language: 'c',
+)
+
+src_inc = include_directories('src')
+
+core = static_library(
+ 'hdass_core',
+ files(
+ 'src/args.c',
+ 'src/ast.c',
+ 'src/diag.c',
+ 'src/file.c',
+ 'src/lexer.c',
+ 'src/nasm.c',
+ 'src/parser.c',
+ 'src/sema.c',
+ ),
+ include_directories: src_inc,
+)
+
+executable(
+ 'hdass',
+ 'src/main.c',
+ include_directories: src_inc,
+ link_with: core,
+)
+
+tests = executable(
+ 'tests',
+ files(
+ 'tests/main.c',
+ 'tests/codegen_test.c',
+ 'tests/lexer_test.c',
+ 'tests/parser_test.c',
+ 'tests/sema_test.c',
+ ),
+ include_directories: [src_inc, include_directories('tests')],
+ link_with: core,
+)
+
+test('unit', tests)
+
+cppcheck = find_program('cppcheck', required: false)
+if cppcheck.found()
+ run_target(
+ 'cppcheck',
+ command: [
+ cppcheck,
+ '--project=@0@'.format(meson.project_build_root() / 'compile_commands.json'),
+ '--enable=warning,style,performance,portability',
+ '--error-exitcode=1',
+ ],
+ )
+endif
diff --git a/premake5.lua b/premake5.lua
deleted file mode 100644
index 178c730..0000000
--- a/premake5.lua
+++ /dev/null
@@ -1,178 +0,0 @@
-output_dir = "%{cfg.buildcfg}-%{cfg.system}"
-
-function setup_target()
- targetdir ("bin/" .. output_dir)
- objdir ("bin-int/" .. output_dir .. "/%{prj.name}")
- staticruntime "On"
-end
-
-function setup_c_target()
- setup_target()
-
- filter { "system:macosx or system:linux" }
- buildoptions {
- "-Wall",
- "-Wextra",
- "-Wpedantic",
- "-Wconversion",
- "-Wsign-conversion",
- "-Wshadow",
- "-Wstrict-prototypes",
- "-Wmissing-prototypes",
- }
- filter {}
-
- filter "configurations:debug"
- runtime "Debug"
- symbols "On"
-
- filter { "system:macosx or system:linux" }
- buildoptions {
- "-g",
- "-fno-omit-frame-pointer",
- "-fsanitize=address,undefined",
- }
-
- linkoptions {
- "-fsanitize=address,undefined",
- }
- filter {}
-
- filter { "configurations:release", "configurations:dist" }
- runtime "Release"
- optimize "Speed"
- filter {}
-
- filter "configurations:dist"
- symbols "Off"
- filter {}
-end
-
-newaction {
- trigger = "clean",
- description = "Remove build output and generated project files",
-
- execute = function()
- os.rmdir("bin")
- os.rmdir("bin-int")
- os.remove("Makefile")
-
- for _, file in ipairs(os.matchfiles("*.make")) do
- os.remove(file)
- end
-
- print("Cleaned build output and generated project files")
- end
-}
-
-newaction {
- trigger = "check",
- description = "Run static analysis with cppcheck",
-
- execute = function()
- local result = os.execute("make clean")
-
- if result ~= true and result ~= 0 then
- error("Failed to clean project")
- end
-
- result = os.execute(
- "bear -- make config=debug"
- )
-
- if result ~= true and result ~= 0 then
- error("Failed to generate compile_commands.json")
- end
-
- result = os.execute(
- "cppcheck " ..
- "--project=compile_commands.json " ..
- "--file-filter=src/** " ..
- "--file-filter=tests/** " ..
- "--enable=warning,style,performance,portability " ..
- "--error-exitcode=1"
- )
-
- if result ~= true and result ~= 0 then
- error("cppcheck found issues")
- end
- end
-}
-
-workspace "hdass"
- architecture "x64"
- startproject "hdass"
- multiprocessorcompile "On"
-
- configurations {
- "debug",
- "release",
- "dist",
- }
-
- filter "system:windows"
- defines "HDASS_WINDOWS"
-
- filter "system:linux"
- defines "HDASS_LINUX"
-
- filter "system:macosx"
- architecture "ARM64"
- defines "HDASS_MACOS"
-
- filter {}
-
-project "hdass"
- kind "ConsoleApp"
- language "C"
- cdialect "C17"
-
- setup_c_target()
-
- files {
- "src/**.h",
- "src/**.c",
- }
-
- includedirs "src"
-
- filter "system:windows"
- systemversion "latest"
-
- filter "configurations:debug"
- defines "HDASS_DEBUG"
-
- filter "configurations:release"
- defines "HDASS_RELEASE"
-
- filter "configurations:dist"
- defines "HDASS_DIST"
-
- filter {}
-
-project "tests"
- kind "ConsoleApp"
- language "C"
- cdialect "C17"
-
- setup_c_target()
-
- files {
- "src/**.h",
- "src/**.c",
- "tests/**.h",
- "tests/**.c",
- }
-
- removefiles "src/main.c"
-
- includedirs {
- "src",
- "tests",
- }
-
- filter "system:windows"
- systemversion "latest"
-
- filter {}
-
diff --git a/scripts/run.sh b/scripts/run.sh
index 01d3882..2bdb450 100755
--- a/scripts/run.sh
+++ b/scripts/run.sh
@@ -17,9 +17,9 @@ docker compose up -d >/dev/null
docker compose exec -T -e SRC="$file" -e NAME="$name" hdass bash -c '
set -e
cd /hdass
- premake5 gmake >/dev/null
- make config=debug >/dev/null
- ./bin/debug-linux/hdass "$SRC" -o "/tmp/$NAME.asm"
+ [ -d build-linux ] || meson setup build-linux >/dev/null
+ meson compile -C build-linux >/dev/null
+ ./build-linux/hdass "$SRC" -o "/tmp/$NAME.asm"
echo
cat "/tmp/$NAME.asm"
echo
diff --git a/scripts/run_suite.sh b/scripts/run_suite.sh
index 48cf67f..38598ad 100755
--- a/scripts/run_suite.sh
+++ b/scripts/run_suite.sh
@@ -10,7 +10,7 @@ else
fi
printf '%s━━ building compiler ━━%s\n' "$bold" "$reset"
-if ! build=$(premake5 gmake 2>&1 && make config=debug 2>&1); then
+if ! build=$({ [ -d build-linux ] || meson setup build-linux; } 2>&1 && meson compile -C build-linux 2>&1); then
printf '%s\n' "$build"
printf ' %s✘ build failed%s\n' "$red" "$reset"
exit 1
@@ -18,11 +18,11 @@ fi
printf ' %s✔ compiler built%s\n\n' "$green" "$reset"
printf '%s━━ unit tests ━━%s\n' "$bold" "$reset"
-if units=$(./bin/debug-linux/tests 2>/dev/null); then
+if units=$(./build-linux/tests 2>/dev/null); then
printf ' %s✔%s %s\n\n' "$green" "$reset" "$(printf '%s' "$units" | tail -1)"
else
printf '%s\n' "$units"
- ./bin/debug-linux/tests || true
+ ./build-linux/tests || true
printf ' %s✘ unit tests failed%s\n' "$red" "$reset"
exit 1
fi
diff --git a/scripts/test_examples.sh b/scripts/test_examples.sh
index c13ee1d..f8d1462 100755
--- a/scripts/test_examples.sh
+++ b/scripts/test_examples.sh
@@ -10,10 +10,10 @@ else
bold=; dim=; red=; green=; reset=
fi
-hdass="${HDASS:-./bin/debug-linux/hdass}"
+hdass="${HDASS:-./build-linux/hdass}"
if [ ! -x "$hdass" ]; then
echo "${red}error:${reset} '$hdass' not found; build it first with:" >&2
- echo " premake5 gmake && make config=debug" >&2
+ echo " meson setup build-linux && meson compile -C build-linux" >&2
exit 1
fi
diff --git a/src/cli/args.c b/src/args.c
index 501406f..b31def5 100644
--- a/src/cli/args.c
+++ b/src/args.c
@@ -2,7 +2,7 @@
#include <string.h>
#include <stdbool.h>
-#include "cli/args.h"
+#include "args.h"
#define HDASS_VERSION "0.1.0"
diff --git a/src/cli/args.h b/src/args.h
index f80b736..f80b736 100644
--- a/src/cli/args.h
+++ b/src/args.h
diff --git a/src/parser/ast.c b/src/ast.c
index 63d8a08..28bb98e 100644
--- a/src/parser/ast.c
+++ b/src/ast.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
-#include "parser/ast.h"
+#include "ast.h"
void free_expr(struct Expr* expr)
{
diff --git a/src/parser/ast.h b/src/ast.h
index 288bddf..074c9b2 100644
--- a/src/parser/ast.h
+++ b/src/ast.h
@@ -4,7 +4,7 @@
#include <stdint.h>
#include <stdbool.h>
-#include "lexer/lexer.h"
+#include "lexer.h"
enum StoreSize
{
diff --git a/src/diag/diag.c b/src/diag.c
index cc61e89..6962046 100644
--- a/src/diag/diag.c
+++ b/src/diag.c
@@ -2,7 +2,7 @@
#include <stdlib.h>
#include <stdbool.h>
-#include "diag/diag.h"
+#include "diag.h"
static bool colored(void)
{
diff --git a/src/diag/diag.h b/src/diag.h
index 7a99266..e79b465 100644
--- a/src/diag/diag.h
+++ b/src/diag.h
@@ -1,6 +1,6 @@
#pragma once
-#include "lexer/lexer.h"
+#include "lexer.h"
struct Source
{
diff --git a/src/io/file.c b/src/file.c
index 3d7083c..a122468 100644
--- a/src/io/file.c
+++ b/src/file.c
@@ -1,8 +1,8 @@
#include <stdio.h>
#include <stdlib.h>
-#include "diag/diag.h"
-#include "io/file.h"
+#include "diag.h"
+#include "file.h"
static void report_file_error(const char* verb, const char* path)
{
diff --git a/src/io/file.h b/src/file.h
index 7d15bd0..7d15bd0 100644
--- a/src/io/file.h
+++ b/src/file.h
diff --git a/src/lexer/lexer.c b/src/lexer.c
index 4d468e6..0d26f9a 100644
--- a/src/lexer/lexer.c
+++ b/src/lexer.c
@@ -1,7 +1,7 @@
#include <string.h>
#include <stdbool.h>
-#include "lexer/lexer.h"
+#include "lexer.h"
static bool is_alpha(char character)
{
diff --git a/src/lexer/lexer.h b/src/lexer.h
index 73de02f..73de02f 100644
--- a/src/lexer/lexer.h
+++ b/src/lexer.h
diff --git a/src/main.c b/src/main.c
index 71e8918..4153a6e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,12 +1,12 @@
#include <stdio.h>
-#include "io/file.h"
-#include "cli/args.h"
-#include "diag/diag.h"
-#include "sema/sema.h"
-#include "lexer/lexer.h"
-#include "codegen/nasm.h"
-#include "parser/parser.h"
+#include "file.h"
+#include "args.h"
+#include "diag.h"
+#include "sema.h"
+#include "lexer.h"
+#include "nasm.h"
+#include "parser.h"
int main(int argc, char** argv)
{
diff --git a/src/codegen/nasm.c b/src/nasm.c
index 198cb5c..15f5f01 100644
--- a/src/codegen/nasm.c
+++ b/src/nasm.c
@@ -5,7 +5,7 @@
#include <string.h>
#include <stdbool.h>
-#include "codegen/nasm.h"
+#include "nasm.h"
static void emit_const_expr(struct Expr* expr, FILE* out)
{
diff --git a/src/codegen/nasm.h b/src/nasm.h
index b9c2c90..1a93b31 100644
--- a/src/codegen/nasm.h
+++ b/src/nasm.h
@@ -2,6 +2,6 @@
#include <stdio.h>
-#include "parser/ast.h"
+#include "ast.h"
void generate_nasm(struct Program* program, FILE* out);
diff --git a/src/parser/parser.c b/src/parser.c
index 97b8569..4c01c86 100644
--- a/src/parser/parser.c
+++ b/src/parser.c
@@ -2,8 +2,8 @@
#include <stdlib.h>
#include <string.h>
-#include "diag/diag.h"
-#include "parser/parser.h"
+#include "diag.h"
+#include "parser.h"
struct Parser
{
diff --git a/src/parser/parser.h b/src/parser.h
index 82d306a..82a3019 100644
--- a/src/parser/parser.h
+++ b/src/parser.h
@@ -2,7 +2,7 @@
#include <stdbool.h>
-#include "lexer/lexer.h"
-#include "parser/ast.h"
+#include "ast.h"
+#include "lexer.h"
bool parse_program(struct Lexer* lexer, struct Program* out);
diff --git a/src/sema/sema.c b/src/sema.c
index 748ccbe..12f2689 100644
--- a/src/sema/sema.c
+++ b/src/sema.c
@@ -3,7 +3,7 @@
#include <string.h>
#include <stdarg.h>
-#include "sema/sema.h"
+#include "sema.h"
static bool token_is(struct Token token, const char* text)
{
diff --git a/src/sema/sema.h b/src/sema.h
index 468d1be..f28c49c 100644
--- a/src/sema/sema.h
+++ b/src/sema.h
@@ -2,7 +2,7 @@
#include <stdbool.h>
-#include "diag/diag.h"
-#include "parser/ast.h"
+#include "ast.h"
+#include "diag.h"
bool analyze_program(struct Source source, struct Program* program);
diff --git a/tests/codegen_test.c b/tests/codegen_test.c
index e2969db..1da711c 100644
--- a/tests/codegen_test.c
+++ b/tests/codegen_test.c
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <string.h>
-#include "parser/parser.h"
-#include "codegen/nasm.h"
+#include "nasm.h"
#include "tests.h"
+#include "parser.h"
static void generate_to_buffer(struct Program* program, char* buffer, size_t size)
{
diff --git a/tests/lexer_test.c b/tests/lexer_test.c
index a44b1f0..0810c3b 100644
--- a/tests/lexer_test.c
+++ b/tests/lexer_test.c
@@ -1,7 +1,7 @@
#include <string.h>
#include <stdbool.h>
-#include "lexer/lexer.h"
+#include "lexer.h"
#include "tests.h"
static bool token_matches(struct Token token, enum TokenType type, const char* text)
diff --git a/tests/parser_test.c b/tests/parser_test.c
index e1199eb..b51093e 100644
--- a/tests/parser_test.c
+++ b/tests/parser_test.c
@@ -1,8 +1,8 @@
#include <string.h>
#include <stdbool.h>
-#include "parser/parser.h"
#include "tests.h"
+#include "parser.h"
static bool text_is(struct Token token, const char* text)
{
diff --git a/tests/sema_test.c b/tests/sema_test.c
index 643ffdf..3c12001 100644
--- a/tests/sema_test.c
+++ b/tests/sema_test.c
@@ -1,8 +1,8 @@
#include <stdbool.h>
-#include "parser/parser.h"
-#include "sema/sema.h"
+#include "sema.h"
#include "tests.h"
+#include "parser.h"
static bool analyze_source(const char* source)
{