-USING:
- alien.libraries
- arrays
- assocs
- combinators
- formatting
- io io.encodings.utf8 io.launcher io.pathnames
- kernel
- sequences
- splitting
- system ;
-IN: alien.libraries.finder
-
-! Util
-: vsprintf1 ( obj fmt -- str )
- [ 1array ] dip vsprintf ;
-
-CONSTANT: name-formats {
- { windows { "%s.dll" "lib%s.dll" } }
- { linux { "lib%s.so" } }
- { unix { "lib%s.so" } }
- { macosx { "lib%s.dylib" } }
-}
-
-! On Windows, bundled dlls are shipped in a directory named "dlls" in
-! the Factor distribution. On other operating systems, the dynamic
-! linker can itself figure out where libraries are located.
-: path-formats ( -- path-formats )
- { "" } os windows? [ "dlls" suffix ] when name-formats os of
- [ append-path ] cartesian-map concat ;
-! Find lib using ldconfig
-CONSTANT: mach-map {
- { ppc.64 "libc6,64bit" }
- { x86.32 "libc6,x86-32" }
- { x86.64 "libc6,x86-64" }
-}
+USING: combinators system vocabs ;
-: ldconfig-cache ( -- seq )
- "/sbin/ldconfig -p" utf8 [ lines ] with-process-reader rest
- [ "=>" "" replace "\t " split harvest ] map ;
-
-: ldconfig-filter ( -- str )
- mach-map cpu of dup "libc6" ? "(" ")" surround ;
-
-: ldconfig-matches? ( lib this-lib this-arch -- ? )
- [ start 0 = ] [ ldconfig-filter = ] bi* and ;
-
-: ldconfig-find-soname ( lib -- seq )
- ldconfig-cache [ first2 ldconfig-matches? ] with filter [ first ] map ;
+IN: alien.libraries.finder
-: candidate-paths ( name -- paths )
- path-formats [ vsprintf1 ] with map
- os [ unix? ] [ linux? ] bi or [ first ldconfig-find-soname ] when ;
+HOOK: find-library os ( name -- path/f )
-: find-library ( name -- path/f )
- candidate-paths [ dlopen dll-valid? ] map-find nip ;
+{
+ { [ os macosx? ] [ "alien.libraries.finder.macosx" ] }
+ { [ os linux? ] [ "alien.libraries.finder.linux" ] }
+ { [ os windows? ] [ "alien.libraries.finder.windows" ] }
+} cond require
--- /dev/null
+! Copyright (C) 2013 Björn Lindqvist
+! See http://factorcode.org/license.txt for BSD license
+
+USING: alien.libraries alien.libraries.finder assocs io
+io.encodings.utf8 io.launcher kernel sequences splitting system
+;
+
+IN: alien.libraries.finder.linux
+
+<PRIVATE
+
+CONSTANT: mach-map {
+ { ppc.64 "libc6,64bit" }
+ { x86.32 "libc6,x86-32" }
+ { x86.64 "libc6,x86-64" }
+}
+
+: ldconfig-cache ( -- seq )
+ "/sbin/ldconfig -p" utf8 [ lines ] with-process-reader rest
+ [ "=>" "" replace "\t " split harvest ] map ;
+
+: ldconfig-filter ( -- str )
+ mach-map cpu of "libc6" or "(" ")" surround ;
+
+: ldconfig-matches? ( lib this-lib this-arch -- ? )
+ [ start 0 = ] [ ldconfig-filter = ] bi* and ;
+
+: ldconfig-find-soname ( lib -- seq )
+ ldconfig-cache [ first2 ldconfig-matches? ] with filter [ first ] map ;
+
+PRIVATE>
+
+M: linux find-library
+ "lib" ".so" surround ldconfig-find-soname
+ [ dlopen dll-valid? ] map-find nip ;
+
--- /dev/null
+
+USING: sequences tools.test ;
+
+IN: alien.libraries.finder.macosx
+
+{
+ {
+ f
+ f
+ f
+ f
+ T{ framework-info f "Location" "Name.framework/Name" "Name" f f }
+ T{ framework-info f "Location" "Name.framework/Name_suffix" "Name" f "suffix" }
+ f
+ f
+ T{ framework-info f "Location" "Name.framework/Versions/A/Name" "Name" "A" f }
+ T{ framework-info f "Location" "Name.framework/Versions/A/Name_suffix" "Name" "A" "suffix" }
+ }
+} [
+ {
+ "broken/path"
+ "broken/path/_suffix"
+ "Location/Name.framework"
+ "Location/Name.framework/_suffix"
+ "Location/Name.framework/Name"
+ "Location/Name.framework/Name_suffix"
+ "Location/Name.framework/Versions"
+ "Location/Name.framework/Versions/A"
+ "Location/Name.framework/Versions/A/Name"
+ "Location/Name.framework/Versions/A/Name_suffix"
+ } [ <framework-info> ] map
+] unit-test
+
+{
+ {
+ "/usr/lib/libSystem.dylib"
+ "/System/Library/Frameworks/System.framework/System"
+ }
+} [
+ {
+ "libSystem.dylib"
+ "System.framework/System"
+ } [ dyld-find ] map
+] unit-test
--- /dev/null
+! Copyright (C) 2013 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors alien.libraries.finder arrays assocs
+combinators.short-circuit environment io.files io.files.info
+io.pathnames kernel locals make namespaces sequences splitting
+system ;
+
+IN: alien.libraries.finder.macosx
+
+<PRIVATE
+
+TUPLE: framework-info location name shortname version suffix ;
+
+: make-framework-info ( filename -- info/f )
+ [ framework-info new ] dip
+ "/" split dup [ ".framework" tail? ] find drop [
+ cut [
+ [ "/" join ] bi@ [ >>location ] [ >>name ] bi*
+ ] keep [
+ rest dup ?first "Versions" = [
+ rest dup empty? [
+ unclip swap [ >>version ] dip
+ ] unless
+ ] when ?first "_" split1 [ >>shortname ] [ >>suffix ] bi*
+ ] unless-empty
+ ] [ drop ] if* dup shortname>> empty? [ drop f ] when ;
+
+CONSTANT: default-framework-fallback {
+ "~/Library/Frameworks"
+ "/Library/Frameworks"
+ "/Network/Library/Frameworks"
+ "/System/Library/Frameworks"
+}
+
+CONSTANT: default-library-fallback {
+ "~/lib"
+ "/usr/local/lib"
+ "/lib"
+ "/usr/lib"
+}
+
+SYMBOL: dyld-environment
+
+: dyld-env ( name -- seq )
+ dyld-environment get [ at ] [ os-env ] if* ;
+
+: dyld-paths ( name -- seq )
+ dyld-env [ ":" split ] [ f ] if* ;
+
+: paths% ( name seq -- )
+ [ prepend-path , ] with each ;
+
+: dyld-override-search ( name -- seq )
+ [
+ dup make-framework-info [
+ name>> "DYLD_FRAMEWORK_PATH" dyld-paths paths%
+ ] when*
+
+ file-name "DYLD_LIBRARY_PATH" dyld-paths paths%
+ ] { } make ;
+
+SYMBOL: dyld-executable-path
+
+: dyld-executable-path-search ( name -- seq )
+ "@executable_path/" ?head dyld-executable-path get and [
+ dyld-executable-path get prepend-path
+ ] [
+ drop f
+ ] if ;
+
+:: dyld-default-search ( name -- seq )
+ name make-framework-info :> framework
+ name file-name :> basename
+ "DYLD_FALLBACK_FRAMEWORK_PATH" dyld-paths :> fallback-framework-path
+ "DYLD_FALLBACK_LIBRARY_PATH" dyld-paths :> fallback-library-path
+ [
+ name ,
+
+ framework [
+ name>> fallback-framework-path paths%
+ ] when*
+
+ basename fallback-library-path paths%
+
+ framework fallback-framework-path empty? and [
+ framework name>> default-framework-fallback paths%
+ ] when
+
+ fallback-library-path empty? [
+ basename default-library-fallback paths%
+ ] when
+ ] { } make ;
+
+: dyld-image-suffix-search ( seq -- str )
+ "DYLD_IMAGE_SUFFIX" dyld-env [
+ swap [
+ [
+ [
+ ".dylib" ?tail [ prepend ] dip
+ [ ".dylib" append ] when ,
+ ] [
+ ,
+ ] bi
+ ] with each
+ ] { } make
+ ] when* ;
+
+: dyld-search-paths ( name -- paths )
+ [ dyld-override-search ]
+ [ dyld-executable-path-search ]
+ [ dyld-default-search ] tri 3append
+ dyld-image-suffix-search ;
+
+PRIVATE>
+
+: dyld-find ( name -- path/f )
+ dyld-search-paths
+ [ { [ exists? ] [ file-info regular-file? ] } 1&& ] find
+ [ nip ] when* ;
+
+: framework-find ( name -- path )
+ dup dyld-find [ nip ] [
+ ".framework" over start [
+ dupd head
+ ] [
+ [ ".framework" append ] keep
+ ] if* file-name append-path dyld-find
+ ] if* ;
+
+M: macosx find-library
+ [ "lib" ".dylib" surround ]
+ [ ".dylib" append ]
+ [ ".framework/" over 3append ] tri 3array
+ [ dyld-find ] map-find drop ;
--- /dev/null
+! Copyright (C) 2013 Björn Lindqvist
+! See http://factorcode.org/license.txt for BSD license
+
+USING: alien.libraries alien.libraries.finder arrays combinators
+kernel sequences system ;
+
+IN: alien.libraries.finder.windows
+
+<PRIVATE
+
+: candidate-paths ( name -- paths )
+ {
+ [ ".dll" append ]
+ [ "lib" ".dll" surround ]
+ [ "dlls/" ".dll" surround ]
+ [ "dlls/lib" ".dll" surround ]
+ } cleave 4array ;
+
+PRIVATE>
+
+M: windows find-library
+ candidate-paths [ dlopen dll-valid? ] map-find nip ;