4545#![ cfg_attr( docsrs, deny( broken_intra_doc_links) ) ]
4646#![ cfg_attr( docsrs, feature( doc_cfg) ) ]
4747
48-
49- use std:: borrow:: Cow ;
5048use std:: env:: consts:: { DLL_PREFIX , DLL_SUFFIX } ;
51- use std:: ffi:: OsStr ;
49+ use std:: ffi:: { OsStr , OsString } ;
5250use std:: fmt;
53- use std:: ops:: { self , Deref } ;
51+ use std:: ops;
5452use std:: marker;
5553
5654#[ cfg( unix) ]
@@ -89,13 +87,15 @@ impl Library {
8987 /// [`SetErrorMode`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
9088 ///
9189 /// Calling this function from multiple threads is not safe if used in conjunction with
92- /// path-less filename and library search path is modified (`SetDllDirectory` function on
90+ /// relative filenames and the library search path is modified (`SetDllDirectory` function on
9391 /// Windows, `{DY,}LD_LIBRARY_PATH` environment variable on UNIX).
9492 ///
9593 /// # Platform-specific behaviour
9694 ///
9795 /// When a plain library filename is supplied, locations where library is searched for is
98- /// platform specific and cannot be adjusted in a portable manner.
96+ /// platform specific and cannot be adjusted in a portable manner. See documentation for
97+ /// the platform specific [`os::unix::Library::new`] and [`os::windows::Library::new`] methods
98+ /// for further information on library lookup behaviour.
9999 ///
100100 /// ## Windows
101101 ///
@@ -113,9 +113,10 @@ impl Library {
113113 /// `awesome.module`) allows to avoid code which has to account for platform’s conventional
114114 /// library filenames.
115115 ///
116- /// Strive to specify absolute or relative path to your library, unless system-wide libraries
117- /// are being loaded. Platform-dependent library search locations combined with various quirks
118- /// related to path-less filenames may cause flaky code.
116+ /// Strive to specify an absolute or at least a relative path to your library, unless
117+ /// system-wide libraries are being loaded. Platform-dependent library search locations
118+ /// combined with various quirks related to path-less filenames may cause flakiness in
119+ /// programs.
119120 ///
120121 /// # Examples
121122 ///
@@ -130,35 +131,6 @@ impl Library {
130131 imp:: Library :: new ( filename) . map ( From :: from)
131132 }
132133
133- fn resolve_name < ' a > ( name : & ' a str ) -> Cow < ' a , str > {
134- match ( name. starts_with ( DLL_PREFIX ) , name. ends_with ( DLL_SUFFIX ) ) {
135- ( true , true ) => Cow :: Borrowed ( name) ,
136- ( true , false ) => Cow :: Owned ( format ! ( "{}{}" , name, DLL_SUFFIX ) ) ,
137- ( false , true ) => Cow :: Owned ( format ! ( "{}{}" , DLL_PREFIX , name) ) ,
138- ( false , false ) => Cow :: Owned ( format ! ( "{}{}{}" , DLL_PREFIX , name, DLL_SUFFIX ) ) ,
139- }
140- }
141-
142- /// Loads a library and does resolve it's name to match platform-specific
143- /// naming schemes.
144- ///
145- /// For a given library called `engine`, this method will resolve the name
146- /// to the following:
147- /// - `Linux`: `libengine.so`
148- /// - `macOS`: `libengine.dylib`
149- /// - `Windows`: `engine.dll`
150- ///
151- /// # Note
152- ///
153- /// This function does only work with library names and does not work when
154- /// supplying a path to a library. The function assumes that the library is
155- /// already present inside a path that is detectable and searchable by the
156- /// OS during runtime.
157- pub fn with_name_resolve < T : AsRef < str > > ( libname : T ) -> Result < Library , Error > {
158- let resolved_name = Self :: resolve_name ( libname. as_ref ( ) ) ;
159- Self :: new ( resolved_name. deref ( ) )
160- }
161-
162134 /// Get a pointer to function or static variable by symbol name.
163135 ///
164136 /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
@@ -369,109 +341,26 @@ impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
369341unsafe impl < ' lib , T : Send > Send for Symbol < ' lib , T > { }
370342unsafe impl < ' lib , T : Sync > Sync for Symbol < ' lib , T > { }
371343
372- #[ cfg( test) ]
373- mod tests {
374- use super :: Library ;
375-
376- #[ cfg( target_os = "windows" ) ]
377- #[ test]
378- fn test_resolve_name_none ( ) {
379- let name = "audioengine" ;
380- let resolved = Library :: resolve_name ( name) ;
381- assert_eq ! ( & resolved, "audioengine.dll" ) ;
382- }
383-
384- #[ cfg( target_os = "linux" ) ]
385- #[ test]
386- fn test_resolve_name_none ( ) {
387- let name = "audioengine" ;
388- let resolved = Library :: resolve_name ( name) ;
389- assert_eq ! ( & resolved, "libaudioengine.so" ) ;
390- }
391-
392- #[ cfg( target_os = "macos" ) ]
393- #[ test]
394- fn test_resolve_name_none ( ) {
395- let name = "audioengine" ;
396- let resolved = Library :: resolve_name ( name) ;
397- assert_eq ! ( & resolved, "libaudioengine.dylib" ) ;
398- }
399-
400- // prefix only
401-
402- #[ cfg( target_os = "windows" ) ]
403- #[ test]
404- fn test_resolve_name_prefix ( ) {
405- let name = "audioengine" ;
406- let resolved = Library :: resolve_name ( name) ;
407- assert_eq ! ( & resolved, "audioengine.dll" ) ;
408- }
409-
410- #[ cfg( target_os = "linux" ) ]
411- #[ test]
412- fn test_resolve_name_prefix ( ) {
413- let name = "libaudioengine" ;
414- let resolved = Library :: resolve_name ( name) ;
415- assert_eq ! ( & resolved, "libaudioengine.so" ) ;
416- }
417-
418- #[ cfg( target_os = "macos" ) ]
419- #[ test]
420- fn test_resolve_name_prefix ( ) {
421- let name = "libaudioengine" ;
422- let resolved = Library :: resolve_name ( name) ;
423- assert_eq ! ( & resolved, "libaudioengine.dylib" ) ;
424- }
425-
426- // suffix only
427-
428- #[ cfg( target_os = "windows" ) ]
429- #[ test]
430- fn test_resolve_name_suffix ( ) {
431- let name = "audioengine.dll" ;
432- let resolved = Library :: resolve_name ( name) ;
433- assert_eq ! ( & resolved, "audioengine.dll" ) ;
434- }
435-
436- #[ cfg( target_os = "linux" ) ]
437- #[ test]
438- fn test_resolve_name_suffix ( ) {
439- let name = "audioengine.so" ;
440- let resolved = Library :: resolve_name ( name) ;
441- assert_eq ! ( & resolved, "libaudioengine.so" ) ;
442- }
443-
444- #[ cfg( target_os = "macos" ) ]
445- #[ test]
446- fn test_resolve_name_suffix ( ) {
447- let name = "audioengine.dylib" ;
448- let resolved = Library :: resolve_name ( name) ;
449- assert_eq ! ( & resolved, "libaudioengine.dylib" ) ;
450- }
451-
452- // both
453-
454- #[ cfg( target_os = "windows" ) ]
455- #[ test]
456- fn test_resolve_name_prefix_and_suffix ( ) {
457- let name = "audioengine.dll" ;
458- let resolved = Library :: resolve_name ( name) ;
459- assert_eq ! ( & resolved, "audioengine.dll" ) ;
460- }
461-
462- #[ cfg( target_os = "linux" ) ]
463- #[ test]
464- fn test_resolve_name_prefix_and_suffix ( ) {
465- let name = "libaudioengine.so" ;
466- let resolved = Library :: resolve_name ( name) ;
467- assert_eq ! ( & resolved, "libaudioengine.so" ) ;
468- }
469-
470- #[ cfg( target_os = "macos" ) ]
471- #[ test]
472- fn test_resolve_name_prefix_and_suffix ( ) {
473- let name = "libaudioengine.dylib" ;
474- let resolved = Library :: resolve_name ( name) ;
475- assert_eq ! ( & resolved, "libaudioengine.dylib" ) ;
476- }
344+ /// Converts a library name to a filename generally appropriate for use on the system.
345+ ///
346+ /// The function will prepend prefixes (such as `lib`) and suffixes (such as `.so`) to the library
347+ /// `name` to construct the filename.
348+ ///
349+ /// # Examples
350+ ///
351+ /// It can be used to load global libraries in a platform independent manner:
352+ ///
353+ /// ```
354+ /// use libloading::{Library, library_filename};
355+ /// // Will attempt to load `libLLVM.so` on Linux, `libLLVM.dylib` on macOS and `LLVM.dll` on
356+ /// // Windows.
357+ /// let library = Library::new(library_filename("LLVM"));
358+ /// ```
359+ pub fn library_filename < S : AsRef < OsStr > > ( name : S ) -> OsString {
360+ let name = name. as_ref ( ) ;
361+ let mut string = OsString :: with_capacity ( name. len ( ) + DLL_PREFIX . len ( ) + DLL_SUFFIX . len ( ) ) ;
362+ string. push ( DLL_PREFIX ) ;
363+ string. push ( name) ;
364+ string. push ( DLL_SUFFIX ) ;
365+ string
477366}
0 commit comments