diff --git a/basis/alien/libraries/finder/finder.factor b/basis/alien/libraries/finder/finder.factor index 24f86b3904..574e00ad4b 100644 --- a/basis/alien/libraries/finder/finder.factor +++ b/basis/alien/libraries/finder/finder.factor @@ -1,57 +1,12 @@ -USING: - alien.libraries - arrays - assocs - combinators - formatting - io io.encodings.utf8 io.launcher io.pathnames - kernel - sequences - splitting - system ; + +USING: combinators system vocabs ; + IN: alien.libraries.finder -! Util -: vsprintf1 ( obj fmt -- str ) - [ 1array ] dip vsprintf ; +HOOK: find-library os ( name -- path/f ) -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" } -} - -: 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 ; - -: candidate-paths ( name -- paths ) - path-formats [ vsprintf1 ] with map - os [ unix? ] [ linux? ] bi or [ first ldconfig-find-soname ] when ; - -: 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 diff --git a/basis/alien/libraries/finder/linux/linux.factor b/basis/alien/libraries/finder/linux/linux.factor new file mode 100644 index 0000000000..97c8e1c3c8 --- /dev/null +++ b/basis/alien/libraries/finder/linux/linux.factor @@ -0,0 +1,36 @@ +! 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 + +" "" 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 ; + diff --git a/basis/alien/libraries/finder/macosx/macosx-tests.factor b/basis/alien/libraries/finder/macosx/macosx-tests.factor new file mode 100644 index 0000000000..6388eb58af --- /dev/null +++ b/basis/alien/libraries/finder/macosx/macosx-tests.factor @@ -0,0 +1,44 @@ + +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" + } [ ] map +] unit-test + +{ + { + "/usr/lib/libSystem.dylib" + "/System/Library/Frameworks/System.framework/System" + } +} [ + { + "libSystem.dylib" + "System.framework/System" + } [ dyld-find ] map +] unit-test diff --git a/basis/alien/libraries/finder/macosx/macosx.factor b/basis/alien/libraries/finder/macosx/macosx.factor new file mode 100644 index 0000000000..63da9a3ff0 --- /dev/null +++ b/basis/alien/libraries/finder/macosx/macosx.factor @@ -0,0 +1,135 @@ +! 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 + +>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 ; diff --git a/basis/alien/libraries/finder/windows/windows.factor b/basis/alien/libraries/finder/windows/windows.factor new file mode 100644 index 0000000000..cef5b54a05 --- /dev/null +++ b/basis/alien/libraries/finder/windows/windows.factor @@ -0,0 +1,22 @@ +! 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 + + + +M: windows find-library + candidate-paths [ dlopen dll-valid? ] map-find nip ;