From 2639338426fe91175b8cabcb360a430e622e0de8 Mon Sep 17 00:00:00 2001 From: Zack Puhl Date: Mon, 28 Jul 2025 17:44:17 -0400 Subject: [PATCH] Support full paths with `$embed` (#2335) * Support full paths with `$embed` --------- Co-authored-by: Christoffer Lerno --- releasenotes.md | 1 + src/compiler/sema_expr.c | 4 ++-- src/utils/file_utils.c | 14 ++++++++++++++ src/utils/lib.h | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/releasenotes.md b/releasenotes.md index 86c5dc009..656737818 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -31,6 +31,7 @@ - Deprecate allocator::heap() and allocator::temp() - Add `thread::fence` providing a thread fence. - Place output in `out` by default for projects. Use temp folder for building at the command line. +- Allow absolute paths for `$embed`. ### Fixes - mkdir/rmdir would not work properly with substring paths on non-windows platforms. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 9dd2f3b90..74b2e3042 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -9996,12 +9996,12 @@ static inline bool sema_expr_analyse_embed(SemaContext *context, Expr *expr, boo } } if (!expr_is_const_string(filename)) RETURN_SEMA_ERROR(filename, "A compile time string was expected."); - + if (!filename->const_expr.bytes.len) RETURN_SEMA_ERROR(filename, "Expected a non-empty string."); CompilationUnit *unit = context->unit; const char *string = filename->const_expr.bytes.ptr; char *path; char *name; - if (file_namesplit(unit->file->full_path, &name, &path)) + if (file_path_is_relative(string) && file_namesplit(unit->file->full_path, &name, &path)) { string = file_append_path(path, string); } diff --git a/src/utils/file_utils.c b/src/utils/file_utils.c index b55577d12..142708884 100644 --- a/src/utils/file_utils.c +++ b/src/utils/file_utils.c @@ -564,6 +564,20 @@ bool file_exists(const char *path) return S_ISDIR(st.st_mode) || S_ISREG(st.st_mode) || S_ISREG(st.st_mode); } +bool file_path_is_relative(const char *file_name) +{ + assert(file_name); + size_t len = strlen(file_name); + if (!len) return false; + + // returns !full_path condition +#if PLATFORM_WINDOWS + return !(file_name[0] == '\\' || (len >= 2 && char_is_letter(file_name[0]) && file_name[1] == ':')); +#else + return file_name[0] != '/'; +#endif +} + #define PATH_BUFFER_SIZE 16384 static char path_buffer[PATH_BUFFER_SIZE]; diff --git a/src/utils/lib.h b/src/utils/lib.h index d9ff9ed62..c0ab93aed 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -80,6 +80,7 @@ bool file_delete_file(const char *path); void file_delete_dir(const char *path); bool file_is_dir(const char *file); bool file_exists(const char *path); +bool file_path_is_relative(const char *file_name); FILE *file_open_read(const char *path); bool file_touch(const char *path); char *file_read_binary(const char *path, size_t *size);