@@ -62,6 +62,7 @@ class Savi::Compiler::Binary
6262
6363 # Link a MachO executable for a MacOSX target.
6464 def link_for_macosx (ctx, target, obj_path, bin_path)
65+ lib_paths = [] of String
6566 link_args = %w{ld64.lld -execute}
6667
6768 # Specify the target architecture.
@@ -72,11 +73,13 @@ class Savi::Compiler::Binary
7273
7374 # Set up explicitly requested library paths.
7475 each_explicit_lib_path(ctx) { |lib_path |
76+ lib_paths << lib_path
7577 link_args << " -L#{ lib_path } "
7678 }
7779
7880 # Set up the main library paths.
7981 each_sysroot_lib_path(ctx, target) { |lib_path |
82+ lib_paths << lib_path
8083 link_args << " -L#{ lib_path } "
8184 }
8285
@@ -93,7 +96,7 @@ class Savi::Compiler::Binary
9396 link_args << " -lc++" if ctx.link_cpp_files.any?
9497
9598 # Link any additional libraries indicated by user code.
96- ctx.link_libraries.each { |name | link_args << " -l #{ name } " }
99+ ctx.link_libraries.each { |name , kind | add_unix_lib( link_args, lib_paths, name, kind) }
97100
98101 # Finally, specify the input object file and the output filename.
99102 link_args << obj_path
@@ -126,7 +129,7 @@ class Savi::Compiler::Binary
126129 add_windows_lib(link_args, lib_paths, " WS2_32" ) # used by runtime lang/socket.c
127130
128131 # Link any additional libraries indicated by user code.
129- ctx.link_libraries.each { |name | add_windows_lib(link_args, lib_paths, name) }
132+ ctx.link_libraries.each { |name , kind | add_windows_lib(link_args, lib_paths, name) }
130133
131134 # Finally, specify the input object file and the output filename.
132135 link_args << obj_path
@@ -136,20 +139,6 @@ class Savi::Compiler::Binary
136139 invoke_linker(" coff" , link_args)
137140 end
138141
139- private def add_windows_lib (link_args , lib_paths , name )
140- if lib_paths.any? { |lib_path |
141- File .exists?(File .join(lib_path, " #{ name } .Lib" ))
142- }
143- link_args << " -defaultlib:#{ name } .Lib"
144- elsif lib_paths.any? { |lib_path |
145- File .exists?(File .join(lib_path, " #{ name } .lib" ))
146- }
147- link_args << " -defaultlib:#{ name } .lib"
148- else
149- link_args << " -defaultlib:#{ name.downcase } .lib"
150- end
151- end
152-
153142 # Link an ELF executable for a Linux or FreeBSD target.
154143 def link_for_linux_or_bsd (ctx, target, obj_path, bin_path)
155144 link_args = %w{ld.lld}
@@ -172,13 +161,9 @@ class Savi::Compiler::Binary
172161 # Specify the dynamic linker library, based on the target platform.
173162 link_args << " -dynamic-linker" << dynamic_linker_for_linux_or_bsd(target)
174163
175- # Set up explicitly requested library paths.
176- each_explicit_lib_path(ctx) { |lib_path |
177- link_args << " -L#{ lib_path } "
178- }
179-
180- # Get the list of lib search paths within the sysroot.
164+ # Get the list of lib search paths.
181165 lib_paths = [] of String
166+ each_explicit_lib_path(ctx) { |lib_path | lib_paths << lib_path }
182167 each_sysroot_lib_path(ctx, target) { |path | lib_paths << path }
183168 lib_paths.each { |lib_path | link_args << " -L#{ lib_path } " }
184169
@@ -214,7 +199,7 @@ class Savi::Compiler::Binary
214199 end
215200
216201 # Link any additional libraries indicated by user code.
217- ctx.link_libraries.each { |name | link_args << " -l #{ name } " }
202+ ctx.link_libraries.each { |name , kind | add_unix_lib( link_args, lib_paths, name, kind) }
218203
219204 # Finally, specify the input object file and the output filename.
220205 link_args << obj_path
@@ -224,6 +209,32 @@ class Savi::Compiler::Binary
224209 invoke_linker(" elf" , link_args)
225210 end
226211
212+ private def add_unix_lib (link_args , lib_paths , name , kind )
213+ if kind == :prefer_static
214+ found_lib = maybe_find_in_paths(lib_paths, " lib#{ name } .a" )
215+ if found_lib
216+ link_args << found_lib
217+ return
218+ end
219+ end
220+
221+ link_args << " -l#{ name } "
222+ end
223+
224+ private def add_windows_lib (link_args , lib_paths , name )
225+ if lib_paths.any? { |lib_path |
226+ File .exists?(File .join(lib_path, " #{ name } .Lib" ))
227+ }
228+ link_args << " -defaultlib:#{ name } .Lib"
229+ elsif lib_paths.any? { |lib_path |
230+ File .exists?(File .join(lib_path, " #{ name } .lib" ))
231+ }
232+ link_args << " -defaultlib:#{ name } .lib"
233+ else
234+ link_args << " -defaultlib:#{ name.downcase } .lib"
235+ end
236+ end
237+
227238 # Get the path to the dynamic linker library for a Linux or FreeBSD target.
228239 def dynamic_linker_for_linux_or_bsd (target ) : String
229240 if target.linux?
@@ -363,12 +374,16 @@ class Savi::Compiler::Binary
363374 # Given a prioritized list of search paths and a file name, find the file.
364375 # Raises an error if the file couldn't be found in any of the paths
365376 def find_in_paths (paths, file_name) : String
377+ result = maybe_find_in_paths(paths, file_name)
378+ raise " failed to find #{ file_name } " if ! result
379+ result
380+ end
381+ def maybe_find_in_paths (paths, file_name) : String ?
366382 paths.each { |path |
367383 file_path = File .join(path, file_name)
368384 return file_path if File .exists?(file_path)
369385 }
370-
371- raise " failed to find #{ file_name } "
386+ nil
372387 end
373388
374389 def invoke_linker (flavor, link_args)
0 commit comments