@@ -212,7 +212,7 @@ private final class IndexStoreAPIImpl {
212212 private let path : AbsolutePath
213213
214214 /// Handle of the dynamic library.
215- private let dylib : DLHandle
215+ private let dylib : _DLHandle
216216
217217 /// The index store API functions.
218218 fileprivate let fn : indexstore_functions_t
@@ -234,14 +234,14 @@ private final class IndexStoreAPIImpl {
234234 public init ( dylib path: AbsolutePath ) throws {
235235 self . path = path
236236#if os(Windows)
237- let flags : DLOpenFlags = [ ]
237+ let flags : _DLOpenFlags = [ ]
238238#else
239- let flags : DLOpenFlags = [ . lazy, . local, . first, . deepBind]
239+ let flags : _DLOpenFlags = [ . lazy, . local, . first, . deepBind]
240240#endif
241- self . dylib = try dlopen ( path. pathString, mode: flags)
241+ self . dylib = try _dlopen ( path. pathString, mode: flags)
242242
243- func dlsym_required< T> ( _ handle: DLHandle , symbol: String ) throws -> T {
244- guard let sym: T = dlsym ( handle, symbol: symbol) else {
243+ func dlsym_required< T> ( _ handle: _DLHandle , symbol: String ) throws -> T {
244+ guard let sym: T = _dlsym ( handle, symbol: symbol) else {
245245 throw StringError ( " Missing required symbol: \( symbol) " )
246246 }
247247 return sym
@@ -285,3 +285,124 @@ extension indexstore_string_ref_t {
285285 ) !
286286 }
287287}
288+
289+ // Private, non-deprecated copy of the dlopen code in `dlopen.swift` as we are planning to remove the public API in the next version.
290+
291+ import protocol Foundation. CustomNSError
292+ import var Foundation. NSLocalizedDescriptionKey
293+ import TSCLibc
294+
295+ private final class _DLHandle {
296+ #if os(Windows)
297+ typealias Handle = HMODULE
298+ #else
299+ typealias Handle = UnsafeMutableRawPointer
300+ #endif
301+ var rawValue : Handle ? = nil
302+
303+ init ( rawValue: Handle ) {
304+ self . rawValue = rawValue
305+ }
306+
307+ deinit {
308+ precondition ( rawValue == nil , " DLHandle must be closed or explicitly leaked before destroying " )
309+ }
310+
311+ public func close( ) throws {
312+ if let handle = rawValue {
313+ #if os(Windows)
314+ guard FreeLibrary ( handle) else {
315+ throw _DLError. close ( " Failed to FreeLibrary: \( GetLastError ( ) ) " )
316+ }
317+ #else
318+ guard dlclose ( handle) == 0 else {
319+ throw _DLError. close ( _dlerror ( ) ?? " unknown error " )
320+ }
321+ #endif
322+ }
323+ rawValue = nil
324+ }
325+
326+ public func leak( ) {
327+ rawValue = nil
328+ }
329+ }
330+
331+ private struct _DLOpenFlags : RawRepresentable , OptionSet {
332+
333+ #if !os(Windows)
334+ public static let lazy : _DLOpenFlags = _DLOpenFlags ( rawValue: RTLD_LAZY)
335+ public static let now : _DLOpenFlags = _DLOpenFlags ( rawValue: RTLD_NOW)
336+ public static let local : _DLOpenFlags = _DLOpenFlags ( rawValue: RTLD_LOCAL)
337+ public static let global : _DLOpenFlags = _DLOpenFlags ( rawValue: RTLD_GLOBAL)
338+
339+ // Platform-specific flags.
340+ #if canImport(Darwin)
341+ public static let first : _DLOpenFlags = _DLOpenFlags ( rawValue: RTLD_FIRST)
342+ public static let deepBind : _DLOpenFlags = _DLOpenFlags ( rawValue: 0 )
343+ #else
344+ public static let first : _DLOpenFlags = _DLOpenFlags ( rawValue: 0 )
345+ #if os(Linux)
346+ public static let deepBind : _DLOpenFlags = _DLOpenFlags ( rawValue: RTLD_DEEPBIND)
347+ #else
348+ public static let deepBind : _DLOpenFlags = _DLOpenFlags ( rawValue: 0 )
349+ #endif
350+ #endif
351+ #endif
352+
353+ public var rawValue : Int32
354+
355+ public init ( rawValue: Int32 ) {
356+ self . rawValue = rawValue
357+ }
358+ }
359+
360+ private enum _DLError : Error {
361+ case `open`( String )
362+ case close( String )
363+ }
364+
365+ extension _DLError : CustomNSError {
366+ public var errorUserInfo : [ String : Any ] {
367+ return [ NSLocalizedDescriptionKey: " \( self ) " ]
368+ }
369+ }
370+
371+ private func _dlsym< T> ( _ handle: _DLHandle , symbol: String ) -> T ? {
372+ #if os(Windows)
373+ guard let ptr = GetProcAddress ( handle. rawValue!, symbol) else {
374+ return nil
375+ }
376+ #else
377+ guard let ptr = dlsym ( handle. rawValue!, symbol) else {
378+ return nil
379+ }
380+ #endif
381+ return unsafeBitCast ( ptr, to: T . self)
382+ }
383+
384+ private func _dlopen( _ path: String ? , mode: _DLOpenFlags ) throws -> _DLHandle {
385+ #if os(Windows)
386+ guard let handle = path? . withCString ( encodedAs: UTF16 . self, LoadLibraryW) else {
387+ throw _DLError. open ( " LoadLibraryW failed: \( GetLastError ( ) ) " )
388+ }
389+ #else
390+ guard let handle = TSCLibc . dlopen ( path, mode. rawValue) else {
391+ throw _DLError. open ( _dlerror ( ) ?? " unknown error " )
392+ }
393+ #endif
394+ return _DLHandle ( rawValue: handle)
395+ }
396+
397+ private func _dlclose( _ handle: _DLHandle ) throws {
398+ try handle. close ( )
399+ }
400+
401+ #if !os(Windows)
402+ private func _dlerror( ) -> String ? {
403+ if let err: UnsafeMutablePointer < Int8 > = dlerror ( ) {
404+ return String ( cString: err)
405+ }
406+ return nil
407+ }
408+ #endif
0 commit comments