Merge pull request #3673 from laytan/implement-foreign-import-improvements-on-vendor

Implement `#exists(path)` and use it to provide good errors for common missing vendor libraries
This commit is contained in:
gingerBill
2024-06-04 19:57:09 +01:00
committed by GitHub
28 changed files with 244 additions and 135 deletions

View File

@@ -54,6 +54,12 @@ jobs:
- name: Odin report
run: ./odin report
timeout-minutes: 1
- name: Compile needed Vendor
run: |
make -C $(./odin root)/vendor/stb/src
make -C $(./odin root)/vendor/cgltf/src
make -C $(./odin root)/vendor/miniaudio/src
timeout-minutes: 10
- name: Odin check
run: ./odin check examples/demo -vet
timeout-minutes: 10
@@ -115,6 +121,12 @@ jobs:
- name: Odin report
run: ./odin report
timeout-minutes: 1
- name: Compile needed Vendor
run: |
make -C $(./odin root)/vendor/stb/src
make -C $(./odin root)/vendor/cgltf/src
make -C $(./odin root)/vendor/miniaudio/src
timeout-minutes: 10
- name: Odin check
run: ./odin check examples/demo -vet
timeout-minutes: 10
@@ -159,6 +171,12 @@ jobs:
- name: Odin report
run: ./odin report
timeout-minutes: 1
- name: Compile needed Vendor
run: |
make -C $(./odin root)/vendor/stb/src
make -C $(./odin root)/vendor/cgltf/src
make -C $(./odin root)/vendor/miniaudio/src
timeout-minutes: 10
- name: Odin check
run: ./odin check examples/demo -vet
timeout-minutes: 10

View File

@@ -1079,7 +1079,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
return false;
}
gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String const &original_string, bool err_on_not_found, LoadFileCache **cache_) {
gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String const &original_string, bool err_on_not_found, LoadFileCache **cache_, LoadFileTier tier) {
ast_node(ce, CallExpr, call);
ast_node(bd, BasicDirective, ce->proc);
String builtin_name = bd->name.string;
@@ -1105,12 +1105,16 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String
gbFileError file_error = gbFileError_None;
String data = {};
bool exists = false;
LoadFileTier cache_tier = LoadFileTier_Invalid;
LoadFileCache **cache_ptr = string_map_get(&c->info->load_file_cache, path);
LoadFileCache *cache = cache_ptr ? *cache_ptr : nullptr;
if (cache) {
file_error = cache->file_error;
data = cache->data;
exists = cache->exists;
cache_tier = cache->tier;
}
defer ({
if (cache == nullptr) {
@@ -1118,60 +1122,78 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String
new_cache->path = path;
new_cache->data = data;
new_cache->file_error = file_error;
new_cache->exists = exists;
new_cache->tier = cache_tier;
string_map_init(&new_cache->hashes, 32);
string_map_set(&c->info->load_file_cache, path, new_cache);
if (cache_) *cache_ = new_cache;
} else {
cache->data = data;
cache->file_error = file_error;
cache->exists = exists;
cache->tier = cache_tier;
if (cache_) *cache_ = cache;
}
});
TEMPORARY_ALLOCATOR_GUARD();
char *c_str = alloc_cstring(temporary_allocator(), path);
if (tier > cache_tier) {
cache_tier = tier;
gbFile f = {};
if (cache == nullptr) {
TEMPORARY_ALLOCATOR_GUARD();
char *c_str = alloc_cstring(temporary_allocator(), path);
gbFile f = {};
file_error = gb_file_open(&f, c_str);
defer (gb_file_close(&f));
if (file_error == gbFileError_None) {
exists = true;
switch(tier) {
case LoadFileTier_Exists:
// Nothing to do.
break;
case LoadFileTier_Contents: {
isize file_size = cast(isize)gb_file_size(&f);
if (file_size > 0) {
u8 *ptr = cast(u8 *)gb_alloc(permanent_allocator(), file_size+1);
gb_file_read_at(&f, ptr, file_size, 0);
ptr[file_size] = '\0';
data.text = ptr;
data.len = file_size;
}
break;
}
default:
GB_PANIC("Unhandled LoadFileTier");
};
}
}
defer (gb_file_close(&f));
switch (file_error) {
default:
case gbFileError_Invalid:
if (err_on_not_found) {
error(ce->proc, "Failed to `#%.*s` file: %s; invalid file or cannot be found", LIT(builtin_name), c_str);
error(ce->proc, "Failed to `#%.*s` file: %.*s; invalid file or cannot be found", LIT(builtin_name), LIT(path));
}
call->state_flags |= StateFlag_DirectiveWasFalse;
return false;
case gbFileError_NotExists:
if (err_on_not_found) {
error(ce->proc, "Failed to `#%.*s` file: %s; file cannot be found", LIT(builtin_name), c_str);
error(ce->proc, "Failed to `#%.*s` file: %.*s; file cannot be found", LIT(builtin_name), LIT(path));
}
call->state_flags |= StateFlag_DirectiveWasFalse;
return false;
case gbFileError_Permission:
if (err_on_not_found) {
error(ce->proc, "Failed to `#%.*s` file: %s; file permissions problem", LIT(builtin_name), c_str);
error(ce->proc, "Failed to `#%.*s` file: %.*s; file permissions problem", LIT(builtin_name), LIT(path));
}
call->state_flags |= StateFlag_DirectiveWasFalse;
return false;
case gbFileError_None:
// Okay
break;
}
if (cache == nullptr) {
isize file_size = cast(isize)gb_file_size(&f);
if (file_size > 0) {
u8 *ptr = cast(u8 *)gb_alloc(permanent_allocator(), file_size+1);
gb_file_read_at(&f, ptr, file_size, 0);
ptr[file_size] = '\0';
data.text = ptr;
data.len = file_size;
}
}
};
return true;
}
@@ -1263,7 +1285,7 @@ gb_internal LoadDirectiveResult check_load_directive(CheckerContext *c, Operand
operand->mode = Addressing_Constant;
LoadFileCache *cache = nullptr;
if (cache_load_file_directive(c, call, o.value.value_string, err_on_not_found, &cache)) {
if (cache_load_file_directive(c, call, o.value.value_string, err_on_not_found, &cache, LoadFileTier_Contents)) {
operand->value = exact_value_string(cache->data);
return LoadDirective_Success;
}
@@ -1345,6 +1367,8 @@ gb_internal LoadDirectiveResult check_load_directory_directive(CheckerContext *c
map_set(&c->info->load_directory_map, call, new_cache);
} else {
cache->file_error = file_error;
map_set(&c->info->load_directory_map, call, cache);
}
});
@@ -1389,7 +1413,7 @@ gb_internal LoadDirectiveResult check_load_directory_directive(CheckerContext *c
for (FileInfo fi : list) {
LoadFileCache *cache = nullptr;
if (cache_load_file_directive(c, call, fi.fullpath, err_on_not_found, &cache)) {
if (cache_load_file_directive(c, call, fi.fullpath, err_on_not_found, &cache, LoadFileTier_Contents)) {
array_add(&file_caches, cache);
} else {
result = LoadDirective_Error;
@@ -1488,6 +1512,30 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
operand->type = t_source_code_location;
operand->mode = Addressing_Value;
} else if (name == "exists") {
if (ce->args.count != 1) {
error(ce->close, "'#exists' expects 1 argument, got %td", ce->args.count);
return false;
}
Operand o = {};
check_expr(c, &o, ce->args[0]);
if (o.mode != Addressing_Constant || !is_type_string(o.type)) {
error(ce->args[0], "'#exists' expected a constant string argument");
return false;
}
operand->type = t_untyped_bool;
operand->mode = Addressing_Constant;
String original_string = o.value.value_string;
LoadFileCache *cache = nullptr;
if (cache_load_file_directive(c, call, original_string, /* err_on_not_found=*/ false, &cache, LoadFileTier_Exists)) {
operand->value = exact_value_bool(cache->exists);
} else {
operand->value = exact_value_bool(false);
}
} else if (name == "load") {
return check_load_directive(c, operand, call, type_hint, true) == LoadDirective_Success;
} else if (name == "load_directory") {
@@ -1540,7 +1588,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
String hash_kind = o_hash.value.value_string;
LoadFileCache *cache = nullptr;
if (cache_load_file_directive(c, call, original_string, true, &cache)) {
if (cache_load_file_directive(c, call, original_string, true, &cache, LoadFileTier_Contents)) {
MUTEX_GUARD(&c->info->load_file_mutex);
// TODO(bill): make these procedures fast :P
u64 hash_value = 0;

View File

@@ -7420,6 +7420,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
String name = bd->name.string;
if (
name == "location" ||
name == "exists" ||
name == "assert" ||
name == "panic" ||
name == "defined" ||
@@ -8341,6 +8342,7 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A
name == "assert" ||
name == "defined" ||
name == "config" ||
name == "exists" ||
name == "load" ||
name == "load_hash" ||
name == "load_directory" ||

View File

@@ -336,7 +336,16 @@ struct ObjcMsgData {
ObjcMsgKind kind;
Type *proc_type;
};
enum LoadFileTier {
LoadFileTier_Invalid,
LoadFileTier_Exists,
LoadFileTier_Contents,
};
struct LoadFileCache {
LoadFileTier tier;
bool exists;
String path;
gbFileError file_error;
String data;

View File

@@ -1,9 +1,23 @@
package cgltf
when ODIN_OS == .Windows { foreign import lib "lib/cgltf.lib" }
else when ODIN_OS == .Linux { foreign import lib "lib/cgltf.a" }
else when ODIN_OS == .Darwin { foreign import lib "lib/darwin/cgltf.a" }
else { foreign import lib "system:cgltf" }
@(private)
LIB :: (
"lib/cgltf.lib" when ODIN_OS == .Windows
else "lib/cgltf.a" when ODIN_OS == .Linux
else "lib/darwin/cgltf.a" when ODIN_OS == .Darwin
else ""
)
when LIB != "" {
when !#exists(LIB) {
// Windows library is shipped with the compiler, so a Windows specific message should not be needed.
#panic("Could not find the compiled cgltf library, it can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/cgltf/src\"`")
}
foreign import lib { LIB }
} else {
foreign import lib "system:cgltf"
}
import "core:c"

View File

@@ -8,12 +8,16 @@ when MINIAUDIO_SHARED {
#panic("Shared linking for miniaudio is not supported yet")
}
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
@(private)
LIB :: "lib/miniaudio.lib" when ODIN_OS == .Windows else "lib/miniaudio.a"
when !#exists(LIB) {
// Windows library is shipped with the compiler, so a Windows specific message should not be needed.
#panic("Could not find the compiled miniaudio library, it can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/miniaudio/src\"`")
}
foreign import lib { LIB }
BINDINGS_VERSION_MAJOR :: 0
BINDINGS_VERSION_MINOR :: 11
BINDINGS_VERSION_REVISION :: 21

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/************************************************************************************************************************************************************
*************************************************************************************************************************************************************

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/************************************************************************************************************************************************************

View File

@@ -1,10 +1,6 @@
package miniaudio
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
import "core:c"

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/*
Delay

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/************************************************************************************************************************************************************

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/************************************************************************************************************************************************************

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/**************************************************************************************************************************************************************

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
waveform_type :: enum c.int {
sine,

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/*
Slot Allocator

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c/libc"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
MAX_LOG_CALLBACKS :: 4

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/************************************************************************************************************************************************************

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/************************************************************************************************************************************************************

View File

@@ -1,10 +1,6 @@
package miniaudio
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
@(default_calling_convention="c", link_prefix="ma_")
foreign lib {

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
@(default_calling_convention="c", link_prefix="ma_")
foreign lib {

View File

@@ -2,11 +2,7 @@ package miniaudio
import "core:c"
when ODIN_OS == .Windows {
foreign import lib "lib/miniaudio.lib"
} else {
foreign import lib "lib/miniaudio.a"
}
foreign import lib { LIB }
/************************************************************************************************************************************************************

View File

@@ -2,13 +2,26 @@ package stb_image
import c "core:c/libc"
@(private)
LIB :: (
"../lib/stb_image.lib" when ODIN_OS == .Windows
else "../lib/stb_image.a" when ODIN_OS == .Linux
else "../lib/darwin/stb_image.a" when ODIN_OS == .Darwin
else ""
)
when LIB != "" {
when !#exists(LIB) {
// The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed.
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
}
foreign import stbi { LIB }
} else {
foreign import stbi "system:stb_image"
}
#assert(size_of(c.int) == size_of(b32))
when ODIN_OS == .Windows { foreign import stbi "../lib/stb_image.lib" }
else when ODIN_OS == .Linux { foreign import stbi "../lib/stb_image.a" }
else when ODIN_OS == .Darwin { foreign import stbi "../lib/darwin/stb_image.a" }
else { foreign import stbi "system:stb_image" }
#assert(size_of(b32) == size_of(c.int))
//

View File

@@ -2,11 +2,24 @@ package stb_image
import c "core:c/libc"
when ODIN_OS == .Windows { foreign import lib "../lib/stb_image_resize.lib" }
else when ODIN_OS == .Linux { foreign import lib "../lib/stb_image_resize.a" }
else when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_image_resize.a" }
else { foreign import lib "system:stb_image_resize" }
@(private)
RESIZE_LIB :: (
"../lib/stb_image_resize.lib" when ODIN_OS == .Windows
else "../lib/stb_image_resize.a" when ODIN_OS == .Linux
else "../lib/darwin/stb_image_resize.a" when ODIN_OS == .Darwin
else ""
)
when RESIZE_LIB != "" {
when !#exists(RESIZE_LIB) {
// The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed.
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
}
foreign import lib { RESIZE_LIB }
} else {
foreign import lib "system:stb_image_resize"
}
//////////////////////////////////////////////////////////////////////////////
//

View File

@@ -2,11 +2,24 @@ package stb_image
import c "core:c/libc"
when ODIN_OS == .Windows { foreign import stbiw "../lib/stb_image_write.lib" }
else when ODIN_OS == .Linux { foreign import stbiw "../lib/stb_image_write.a" }
else when ODIN_OS == .Darwin { foreign import stbiw "../lib/darwin/stb_image_write.a" }
else { foreign import stbiw "system:stb_image_write" }
@(private)
WRITE_LIB :: (
"../lib/stb_image_write.lib" when ODIN_OS == .Windows
else "../lib/stb_image_write.a" when ODIN_OS == .Linux
else "../lib/darwin/stb_image_write.a" when ODIN_OS == .Darwin
else ""
)
when WRITE_LIB != "" {
when !#exists(WRITE_LIB) {
// The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed.
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
}
foreign import stbiw { WRITE_LIB }
} else {
foreign import stbiw "system:stb_image_write"
}
write_func :: proc "c" (ctx: rawptr, data: rawptr, size: c.int)

View File

@@ -4,10 +4,23 @@ import "core:c"
#assert(size_of(b32) == size_of(c.int))
when ODIN_OS == .Windows { foreign import lib "../lib/stb_rect_pack.lib" }
else when ODIN_OS == .Linux { foreign import lib "../lib/stb_rect_pack.a" }
else when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_rect_pack.a" }
else { foreign import lib "system:stb_rect_pack" }
@(private)
LIB :: (
"../lib/stb_rect_pack.lib" when ODIN_OS == .Windows
else "../lib/stb_rect_pack.a" when ODIN_OS == .Linux
else "../lib/darwin/stb_rect_pack.a" when ODIN_OS == .Darwin
else ""
)
when LIB != "" {
when !#exists(LIB) {
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
}
foreign import lib { LIB }
} else {
foreign import lib "system:stb_rect_pack"
}
Coord :: distinct c.int
_MAXVAL :: max(Coord)

View File

@@ -14,7 +14,7 @@ unix:
$(AR) rcs ../lib/stb_image_resize.a stb_image_resize.o
$(AR) rcs ../lib/stb_truetype.a stb_truetype.o
$(AR) rcs ../lib/stb_rect_pack.a stb_rect_pack.o
#$(AR) rcs ../lib/stb_vorbis_pack.a stb_vorbis_pack.o
$(AR) rcs ../lib/stb_vorbis.a stb_vorbis.o
#$(CC) -fPIC -shared -Wl,-soname=stb_image.so -o ../lib/stb_image.so stb_image.o
#$(CC) -fPIC -shared -Wl,-soname=stb_image_write.so -o ../lib/stb_image_write.so stb_image_write.o
#$(CC) -fPIC -shared -Wl,-soname=stb_image_resize.so -o ../lib/stb_image_resize.so stb_image_resize.o

View File

@@ -3,11 +3,23 @@ package stb_truetype
import c "core:c"
import stbrp "vendor:stb/rect_pack"
when ODIN_OS == .Windows { foreign import stbtt "../lib/stb_truetype.lib" }
else when ODIN_OS == .Linux { foreign import stbtt "../lib/stb_truetype.a" }
else when ODIN_OS == .Darwin { foreign import stbtt "../lib/darwin/stb_truetype.a" }
else { foreign import stbtt "system:stb_truetype" }
@(private)
LIB :: (
"../lib/stb_truetype.lib" when ODIN_OS == .Windows
else "../lib/stb_truetype.a" when ODIN_OS == .Linux
else "../lib/darwin/stb_truetype.a" when ODIN_OS == .Darwin
else ""
)
when LIB != "" {
when !#exists(LIB) {
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
}
foreign import stbtt { LIB }
} else {
foreign import stbtt "system:stb_truetype"
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

View File

@@ -2,13 +2,23 @@ package stb_vorbis
import c "core:c/libc"
@(private)
LIB :: (
"../lib/stb_vorbis.lib" when ODIN_OS == .Windows
else "../lib/stb_vorbis.a" when ODIN_OS == .Linux
else "../lib/darwin/stb_vorbis.a" when ODIN_OS == .Darwin
else ""
)
when ODIN_OS == .Windows { foreign import lib "../lib/stb_vorbis.lib" }
else when ODIN_OS == .Linux { foreign import lib "../lib/stb_vorbis.a" }
else when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_vorbis.a" }
else { foreign import lib "system:stb_vorbis" }
when LIB != "" {
when !#exists(LIB) {
#panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`")
}
foreign import lib { LIB }
} else {
foreign import lib "system:stb_vorbis"
}
/////////// THREAD SAFETY