@@ -2663,6 +2663,77 @@ TEST(base_relocs)
26632663 }
26642664}
26652665
2666+ TEST (default_lib_matches_explicit_path )
2667+ {
2668+ COFF_ObjWriter * entry = coff_obj_writer_alloc (0 , COFF_MachineType_X64 );
2669+ COFF_ObjSection * text = coff_obj_writer_push_section (entry , str8_lit (".text" ),
2670+ COFF_SectionFlag_CntCode |COFF_SectionFlag_MemRead |COFF_SectionFlag_MemExecute |COFF_SectionFlag_Align1Bytes ,
2671+ str8_lit ("\x31\xc0\xc3" ));
2672+ coff_obj_writer_push_symbol_extern_func (entry , str8_lit ("entry" ), 0 , text );
2673+ T_Ok (t_write_file (str8_lit ("entry.obj" ), coff_obj_writer_serialize (arena , entry )));
2674+ coff_obj_writer_release (& entry );
2675+ char * dirs [] = {"sdk libs" , "other libs" };
2676+ char * symbols [] = {"first_provider" , "second_provider" };
2677+ for EachIndex (i , ArrayCount (dirs )) {
2678+ T_Ok (make_directory (t_make_file_path (arena , str8_cstring (dirs [i ]))));
2679+ COFF_ObjWriter * obj = coff_obj_writer_alloc (0 , COFF_MachineType_X64 );
2680+ coff_obj_writer_push_symbol_abs (obj , str8_cstring (symbols [i ]), 1 , COFF_SymStorageClass_External );
2681+ COFF_LibWriter * lib = coff_lib_writer_alloc ();
2682+ coff_lib_writer_push_obj (lib , str8_lit ("provider.obj" ), coff_obj_writer_serialize (arena , obj ));
2683+ T_Ok (t_write_file (str8f (arena , "%s/provider.lib" , dirs [i ]), coff_lib_writer_serialize (arena , lib , 0 , 0 , 1 )));
2684+ coff_lib_writer_release (& lib );
2685+ coff_obj_writer_release (& obj );
2686+ }
2687+
2688+ char * args = "/subsystem:console /entry:entry /out:default.exe entry.obj /include:first_provider" ;
2689+ String8 paths [] = {str8_lit ("sdk libs/provider.lib" ), t_make_file_path (arena , str8_lit ("sdk libs/provider.lib" ))};
2690+ // Debug builds also write normal progress to stderr; reject only the missing-library diagnostic.
2691+ char * names [] = {"provider.lib" , "PROVIDER.LIB" , "provider" };
2692+ // RAD accepts an omitted extension; LLD checks visited names before adding it.
2693+ U64 name_count = t_id_linker () == Linker_radlink ? ArrayCount (names ) : 2 ;
2694+ for EachIndex (path_idx , ArrayCount (paths )) {
2695+ for EachIndex (name_idx , name_count ) {
2696+ t_invoke_linkerf ("%s \"%S\" /defaultlib:%s" , args , paths [path_idx ], names [name_idx ]);
2697+ T_Ok (g_last_exit_code == 0 );
2698+ T_Ok (str8_find_needle (g_errors , 0 , str8_lit ("unable to find library" ), 0 ) == g_errors .size );
2699+ }
2700+ }
2701+
2702+ // Embedded directives use a separate input-source queue from /DEFAULTLIB.
2703+ COFF_ObjWriter * directive = coff_obj_writer_alloc (0 , COFF_MachineType_X64 );
2704+ coff_obj_writer_push_directive (directive , str8_lit ("/DEFAULTLIB:provider.lib" ));
2705+ T_Ok (t_write_file (str8_lit ("directive.obj" ), coff_obj_writer_serialize (arena , directive )));
2706+ coff_obj_writer_release (& directive );
2707+ t_invoke_linkerf ("%s \"%S\" directive.obj" , args , paths [1 ]);
2708+ T_Ok (g_last_exit_code == 0 );
2709+ T_Ok (str8_find_needle (g_errors , 0 , str8_lit ("unable to find library" ), 0 ) == g_errors .size );
2710+
2711+ // A basename match must not swallow another explicitly named library, or a
2712+ // path-qualified default, with the same basename but a different provider.
2713+ t_invoke_linkerf ("%s \"%S\" \"other libs/provider.lib\" /include:second_provider" , args , paths [1 ]);
2714+ T_Ok (g_last_exit_code == 0 );
2715+ T_Ok (str8_find_needle (g_errors , 0 , str8_lit ("unable to find library" ), 0 ) == g_errors .size );
2716+ t_invoke_linkerf ("%s \"%S\" /defaultlib:\"other libs/provider.lib\" /include:second_provider" , args , paths [1 ]);
2717+ T_Ok (g_last_exit_code == 0 );
2718+ T_Ok (str8_find_needle (g_errors , 0 , str8_lit ("unable to find library" ), 0 ) == g_errors .size );
2719+
2720+ // Missing defaults must still warn; explicit bare paths are not defaults.
2721+ t_invoke_linkerf ("%s \"%S\" /defaultlib:missing_provider.lib" , args , paths [1 ]);
2722+ if (t_id_linker () == Linker_radlink ) {
2723+ T_Ok (g_last_exit_code == 0 );
2724+ T_Ok (str8_find_needle (g_errors , 0 , str8_lit ("unable to find library `missing_provider.lib`" ), 0 ) < g_errors .size );
2725+ } else {
2726+ T_Ok (g_last_exit_code != 0 );
2727+ }
2728+ t_invoke_linkerf ("%s \"%S\" provider.lib" , args , paths [1 ]);
2729+ if (t_id_linker () == Linker_radlink ) {
2730+ T_Ok (g_last_exit_code == 0 );
2731+ T_Ok (str8_find_needle (g_errors , 0 , str8_lit ("unable to find library `provider.lib`" ), 0 ) < g_errors .size );
2732+ } else {
2733+ T_Ok (g_last_exit_code != 0 );
2734+ }
2735+ }
2736+
26662737TEST (simple_lib_test )
26672738{
26682739 String8 test_payload = str8_lit ("The quick brown fox jumps over the lazy dog" );
0 commit comments