From 6f824e4b09dcf4ecb4f311d6cce6e38d28aee663 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Thu, 3 Sep 2026 17:18:51 -0700 Subject: [PATCH] minor cleanups * updated the comments * simplified the test --- src/linker/lnk.c | 11 ++++----- src/linker/tests/linker_tests.c | 41 +++++++++++++-------------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index aedaa99e..d5d0c38a 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -921,17 +921,16 @@ lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSou LNK_Input *input = 0; - // default libraries may omit extension if (input_source == LNK_InputSource_Default || input_source == LNK_InputSource_Obj) { + // default libraries may omit extension if (!str8_ends_with(path, str8_lit(".lib"), StringMatchFlag_CaseInsensitive)) { path = push_str8f(scratch.arena, "%S.lib", path); } if (lnk_is_lib_disallowed(config, path)) { goto exit; } - // An explicitly supplied library also satisfies a bare /DEFAULTLIB name, - // even when its directory is not on LIBPATH. Do not strip directory parts - // from the request: path-qualified defaults still name distinct libraries. + + // default libraries may duplicate libs that are specified using full path input = hash_table_search_path_raw(inputer->cmd_lib_names_ht, path); if (input) { goto exit; @@ -973,8 +972,8 @@ lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSou exit:; if (input && input_source == LNK_InputSource_CmdLine) { - // Keep basename aliases separate from path identity so two explicitly - // supplied libraries with the same basename can both be linked. + // store command-line libraries by basename; keep only the first mapping because + // /DEFAULTLIB only needs to know whether a matching library was explicitly supplied String8 name = str8_skip_last_slash(input->path); if (!hash_table_search_path(inputer->cmd_lib_names_ht, name)) { hash_table_push_path_raw(inputer->arena, inputer->cmd_lib_names_ht, name, input); diff --git a/src/linker/tests/linker_tests.c b/src/linker/tests/linker_tests.c index 2a60c78b..edaa55b9 100644 --- a/src/linker/tests/linker_tests.c +++ b/src/linker/tests/linker_tests.c @@ -2665,16 +2665,15 @@ TEST(base_relocs) TEST(default_lib_matches_explicit_path) { - COFF_ObjWriter *entry = coff_obj_writer_alloc(0, COFF_MachineType_X64); - COFF_ObjSection *text = coff_obj_writer_push_section(entry, str8_lit(".text"), - COFF_SectionFlag_CntCode|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_Align1Bytes, - str8_lit("\x31\xc0\xc3")); + COFF_ObjWriter *entry = coff_obj_writer_alloc(0, COFF_MachineType_X64); + COFF_ObjSection *text = coff_obj_writer_push_section(entry, str8_lit(".text"), PE_TEXT_SECTION_FLAGS, str8_lit("\x31\xc0\xc3")); coff_obj_writer_push_symbol_extern_func(entry, str8_lit("entry"), 0, text); T_Ok(t_write_file(str8_lit("entry.obj"), coff_obj_writer_serialize(arena, entry))); coff_obj_writer_release(&entry); - char *dirs[] = {"sdk libs", "other libs"}; + + char *dirs[] = {"sdk libs", "other libs"}; char *symbols[] = {"first_provider", "second_provider"}; - for EachIndex(i, ArrayCount(dirs)) { + for EachElement(i, dirs) { T_Ok(make_directory(t_make_file_path(arena, str8_cstring(dirs[i])))); COFF_ObjWriter *obj = coff_obj_writer_alloc(0, COFF_MachineType_X64); coff_obj_writer_push_symbol_abs(obj, str8_cstring(symbols[i]), 1, COFF_SymStorageClass_External); @@ -2685,14 +2684,13 @@ TEST(default_lib_matches_explicit_path) coff_obj_writer_release(&obj); } - char *args = "/subsystem:console /entry:entry /out:default.exe entry.obj /include:first_provider"; - String8 paths[] = {str8_lit("sdk libs/provider.lib"), t_make_file_path(arena, str8_lit("sdk libs/provider.lib"))}; // Debug builds also write normal progress to stderr; reject only the missing-library diagnostic. - char *names[] = {"provider.lib", "PROVIDER.LIB", "provider"}; - // RAD accepts an omitted extension; LLD checks visited names before adding it. - U64 name_count = t_id_linker() == Linker_radlink ? ArrayCount(names) : 2; - for EachIndex(path_idx, ArrayCount(paths)) { - for EachIndex(name_idx, name_count) { + char *names[] = {"provider.lib", "PROVIDER.LIB", "provider"}; + char *args = "/subsystem:console /entry:entry /out:default.exe entry.obj /include:first_provider"; + String8 paths[] = {str8_lit("sdk libs/provider.lib"), t_make_file_path(arena, str8_lit("sdk libs/provider.lib"))}; + + for EachElement(path_idx, paths) { + for EachElement(name_idx, names) { t_invoke_linkerf("%s \"%S\" /defaultlib:%s", args, paths[path_idx], names[name_idx]); T_Ok(g_last_exit_code == 0); T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library"), 0) == g_errors.size); @@ -2719,19 +2717,12 @@ TEST(default_lib_matches_explicit_path) // Missing defaults must still warn; explicit bare paths are not defaults. t_invoke_linkerf("%s \"%S\" /defaultlib:missing_provider.lib", args, paths[1]); - if (t_id_linker() == Linker_radlink) { - T_Ok(g_last_exit_code == 0); - T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library `missing_provider.lib`"), 0) < g_errors.size); - } else { - T_Ok(g_last_exit_code != 0); - } + T_Ok(g_last_exit_code == 0); + T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library `missing_provider.lib`"), 0) < g_errors.size); + t_invoke_linkerf("%s \"%S\" provider.lib", args, paths[1]); - if (t_id_linker() == Linker_radlink) { - T_Ok(g_last_exit_code == 0); - T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library `provider.lib`"), 0) < g_errors.size); - } else { - T_Ok(g_last_exit_code != 0); - } + T_Ok(g_last_exit_code == 0); + T_Ok(str8_find_needle(g_errors, 0, str8_lit("unable to find library `provider.lib`"), 0) < g_errors.size); } TEST(simple_lib_test)