diff options
| author | hachem <im@hachem.wtf> | 2026-09-18 18:40:37 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-18 18:40:37 +0200 |
| commit | 2e9e1221538fe8148e542103552ff339891dd21b (patch) | |
| tree | 7bb2a930f7df4c59cf6a17d0988b162eb3e213a3 /mkproj.c | |
| parent | 875e2a75eae13298a36a9f631305a68e40653606 (diff) | |
feat: add nasm projects
Diffstat (limited to 'mkproj.c')
| -rw-r--r-- | mkproj.c | 149 |
1 files changed, 139 insertions, 10 deletions
@@ -29,6 +29,7 @@ enum Language language_c, language_cpp, language_objc, + language_nasm, language_count }; @@ -149,6 +150,16 @@ static const struct Language_Info languages[language_count] = .standard_count = sizeof c_standards / sizeof c_standards[0], .default_standard = "c17", }, + [language_nasm] = + { + .key = "nasm", + .name = "NASM", + .compiler = "nasm", + .extension = "asm", + .standards = NULL, + .standard_count = 0, + .default_standard = NULL, + }, }; static const struct Build_Info build_systems[build_system_count] = @@ -216,7 +227,7 @@ static void print_usage(FILE* stream) " %s [-v | -h]\n" "\n" "options:\n" - " -l, --lang LANG language: c, cpp, objc (default c)\n" + " -l, --lang LANG language: c, cpp, objc, nasm (default c)\n" " -s, --std STD language standard (default per language)\n" " -b, --build SYSTEM build system: make, cmake, meson, premake, xmake (default make)\n" " -k, --kind KIND exe or lib (default exe)\n" @@ -519,7 +530,17 @@ static int parse_args(int argc, char** argv, struct Config* config) return 1; } - if (std_arg != NULL) + if (config->language == language_nasm) + { + if (std_arg != NULL) + { + error("nasm has no language standard", std_arg); + return 1; + } + + config->standard = NULL; + } + else if (std_arg != NULL) { if (!valid_standard(config->language, std_arg)) { @@ -563,6 +584,18 @@ static int parse_args(int argc, char** argv, struct Config* config) return 1; } + if (config->language == language_nasm && config->build != build_make) + { + error("nasm projects only support make", build_systems[config->build].key); + return 1; + } + + if (config->language == language_nasm && config->kind == kind_lib) + { + error("nasm projects only support executables", NULL); + return 1; + } + config->bin_dir = bin_arg != NULL ? bin_arg : build_systems[config->build].default_bin; config->bin_int_dir = bin_int_arg != NULL ? bin_int_arg : build_systems[config->build].default_bin_int; @@ -616,6 +649,27 @@ static int git_init(const char* root) static const char* main_source(const struct Config* config) { + if (config->language == language_nasm) + return + " default rel\n" + "\n" + " global _main\n" + " extern _printf\n" + "\n" + " section .text\n" + "_main:\n" + " push rbp\n" + " mov rbp, rsp\n" + " lea rdi, [msg]\n" + " xor eax, eax\n" + " call _printf\n" + " xor eax, eax\n" + " pop rbp\n" + " ret\n" + "\n" + " section .data\n" + "msg: db \"type shi\", 10, 0\n"; + if (config->language == language_objc) return "#import <Foundation/Foundation.h>\n" @@ -759,8 +813,76 @@ static const char* cmake_language(enum Language language) return "C"; } +/* nasm is its own thing: assemble each .asm with nasm, then link with cc. no + * -std, no warning flags, no sanitizers. macho64 is the macOS object format. */ +static void write_makefile_nasm(FILE* out, const struct Config* config) +{ + const char* obj_dir = config->use_intermediate ? config->bin_int_dir : config->bin_dir; + + char clean[2 * PATH_MAX + 16]; + + if (config->use_intermediate) + (void) snprintf(clean, sizeof clean, "rm -rf %s %s", config->bin_dir, config->bin_int_dir); + else + (void) snprintf(clean, sizeof clean, "rm -rf %s", config->bin_dir); + + (void) fprintf( + out, + "AS := nasm\n" + "LD := cc\n" + "\n" + "DEBUG ?= 1\n" + "\n" + "ASFLAGS := -f macho64\n" + "LDFLAGS := -arch x86_64\n" + "\n" + "ifeq ($(DEBUG),1)\n" + "ASFLAGS += -g -F dwarf\n" + "endif\n" + "\n" + "TARGET := %s/%s\n", + config->bin_dir, config->name); + + if (config->use_flat) + (void) fprintf(out, "SRC := $(wildcard *.asm)\nOBJ := $(SRC:%%=%s/%%.o)\n", obj_dir); + else + (void) fprintf(out, "SRC := $(shell find src -name '*.asm')\nOBJ := $(SRC:src/%%=%s/%%.o)\n", obj_dir); + + (void) fprintf( + out, + "\n" + "all: $(TARGET)\n" + "\n" + "$(TARGET): $(OBJ)\n" + "\t@mkdir -p $(@D)\n" + "\t$(LD) $^ -o $@ $(LDFLAGS)\n" + "\n"); + + if (config->use_flat) + (void) fprintf(out, "%s/%%.asm.o: %%.asm\n", obj_dir); + else + (void) fprintf(out, "%s/%%.asm.o: src/%%.asm\n", obj_dir); + + (void) fprintf( + out, + "\t@mkdir -p $(@D)\n" + "\t$(AS) $(ASFLAGS) $< -o $@\n" + "\n" + "clean:\n" + "\t%s\n" + "\n" + ".PHONY: all clean\n", + clean); +} + static void write_makefile(FILE* out, const struct Config* config) { + if (config->language == language_nasm) + { + write_makefile_nasm(out, config); + return; + } + const struct Language_Info* lang = &languages[config->language]; const char* ext = lang->extension; const char* obj_dir = config->use_intermediate ? config->bin_int_dir : config->bin_dir; @@ -1272,7 +1394,7 @@ static void write_gitignore(FILE* out, const struct Config* config) if (config->build == build_xmake) (void) fputs(".xmake/\n", out); - if (config->use_clangd) + if (config->use_clangd && config->language != language_nasm) (void) fputs("\n" ".clangd\n" "compile_commands.json\n", @@ -1316,11 +1438,17 @@ static int make_dir(const char* path) static void print_next_steps(const struct Config* config) { - (void) printf("\ncreated %s (%s, %s, %s)\n\n", - config->name, - languages[config->language].name, - config->standard, - build_systems[config->build].name); + if (config->standard != NULL) + (void) printf("\ncreated %s (%s, %s, %s)\n\n", + config->name, + languages[config->language].name, + config->standard, + build_systems[config->build].name); + else + (void) printf("\ncreated %s (%s, %s)\n\n", + config->name, + languages[config->language].name, + build_systems[config->build].name); (void) printf(" cd %s\n", config->name); @@ -1328,7 +1456,8 @@ static void print_next_steps(const struct Config* config) { case build_make: (void) printf(" make\n"); - (void) printf(" make check\n"); + if (config->language != language_nasm) + (void) printf(" make check\n"); break; case build_cmake: @@ -1423,7 +1552,7 @@ static int generate_project(const struct Config* config) if (emit(path, config, write_gitignore) != 0) return -1; - if (config->use_clangd) + if (config->use_clangd && config->language != language_nasm) { (void) snprintf(path, sizeof path, "%s/compile_flags.txt", config->name); |
