@@ -42,11 +42,30 @@ public final class UserToolchain: Toolchain {
4242 /// An array of paths to search for libraries at link time.
4343 public let librarySearchPaths : [ AbsolutePath ]
4444
45+ /// Lock for thread-safe access to lazy properties
46+ private let lazyPropertiesLock = NSLock ( )
47+
48+ /// Cached runtime library paths
49+ private var _runtimeLibraryPaths : [ AbsolutePath ] ? = nil
50+
4551 /// An array of paths to use with binaries produced by this toolchain at run time.
46- public lazy var runtimeLibraryPaths : [ AbsolutePath ] = {
47- guard let targetInfo else { return [ ] }
48- return ( try ? Self . computeRuntimeLibraryPaths ( targetInfo: targetInfo) ) ?? [ ]
49- } ( )
52+ public var runtimeLibraryPaths : [ AbsolutePath ] {
53+ lazyPropertiesLock. lock ( )
54+ defer { lazyPropertiesLock. unlock ( ) }
55+
56+ if let cached = _runtimeLibraryPaths {
57+ return cached
58+ }
59+
60+ guard let targetInfo = self . targetInfo else {
61+ _runtimeLibraryPaths = [ ]
62+ return [ ]
63+ }
64+
65+ let paths = ( try ? Self . computeRuntimeLibraryPaths ( targetInfo: targetInfo) ) ?? [ ]
66+ _runtimeLibraryPaths = paths
67+ return paths
68+ }
5069
5170 /// Path containing Swift resources for dynamic linking.
5271 public var swiftResourcesPath : AbsolutePath ? {
@@ -82,16 +101,47 @@ public final class UserToolchain: Toolchain {
82101 public let targetTriple : Basics . Triple
83102
84103 private let _targetInfo : JSON ?
85- private lazy var targetInfo : JSON ? = {
104+
105+ /// Cached target info, deliberately doublely optional, one
106+ /// for "not yet cached", one for "failed to get target info".
107+ private var _cachedTargetInfo : Optional < JSON ? > = nil
108+
109+ private var targetInfo : JSON ? {
110+ lazyPropertiesLock. lock ( )
111+ defer { lazyPropertiesLock. unlock ( ) }
112+
113+ if let cached = _cachedTargetInfo {
114+ return cached
115+ }
116+
86117 // Only call out to the swift compiler to fetch the target info when necessary
87- try ? _targetInfo ?? Self . getTargetInfo ( swiftCompiler: swiftCompilerPath)
88- } ( )
118+ let info = try ? _targetInfo ?? Self . getTargetInfo ( swiftCompiler: swiftCompilerPath)
119+ _cachedTargetInfo = info
120+ return info
121+ }
122+
123+ /// Cached swift compiler version, deliberately doublely optional, one
124+ /// for "not yet cached", one for "failed to get target info".
125+ private var _swiftCompilerVersion : Optional < String ? > = nil
89126
90127 // A version string that can be used to identify the swift compiler version
91- public lazy var swiftCompilerVersion : String ? = {
92- guard let targetInfo else { return nil }
93- return Self . computeSwiftCompilerVersion ( targetInfo: targetInfo)
94- } ( )
128+ public var swiftCompilerVersion : String ? {
129+ lazyPropertiesLock. lock ( )
130+ defer { lazyPropertiesLock. unlock ( ) }
131+
132+ if let cached = _swiftCompilerVersion {
133+ return cached
134+ }
135+
136+ guard let targetInfo = self . targetInfo else {
137+ _swiftCompilerVersion = nil
138+ return nil
139+ }
140+
141+ let version = Self . computeSwiftCompilerVersion ( targetInfo: targetInfo)
142+ _swiftCompilerVersion = version
143+ return version
144+ }
95145
96146 /// The list of CPU architectures to build for.
97147 public let architectures : [ String ] ?
0 commit comments