@@ -1043,6 +1043,9 @@ public final class ProductBuildDescription {
1043
1043
/// Paths to the binary libraries the product depends on.
1044
1044
fileprivate var libraryBinaryPaths : Set < AbsolutePath > = [ ]
1045
1045
1046
+ /// Paths to tools shipped in binary dependencies
1047
+ var availableTools : [ String : AbsolutePath ] = [ : ]
1048
+
1046
1049
/// Path to the temporary directory for this product.
1047
1050
var tempsPath : AbsolutePath {
1048
1051
return buildParameters. buildPath. appending ( component: product. name + " .product " )
@@ -1294,8 +1297,11 @@ public class BuildPlan {
1294
1297
/// Cache for pkgConfig flags.
1295
1298
private var pkgConfigCache = [ SystemLibraryTarget: ( cFlags: [ String] , libs: [ String] ) ] ( )
1296
1299
1297
- /// Cache for xcframework library information.
1298
- private var xcFrameworkCache = [ BinaryTarget: LibraryInfo? ] ( )
1300
+ /// Cache for library information.
1301
+ private var externalLibrariesCache = [ BinaryTarget: LibraryInfo] ( )
1302
+
1303
+ /// Cache for tools information.
1304
+ private var externalToolsCache = [ BinaryTarget: [ ToolInfo] ] ( )
1299
1305
1300
1306
private static func makeTestManifestTargets(
1301
1307
_ buildParameters: BuildParameters ,
@@ -1499,7 +1505,7 @@ public class BuildPlan {
1499
1505
// Add flags for system targets.
1500
1506
for systemModule in dependencies. systemModules {
1501
1507
guard case let target as SystemLibraryTarget = systemModule. underlyingTarget else {
1502
- fatalError ( " This should not be possible. " )
1508
+ throw InternalError ( " This should not be possible. " )
1503
1509
}
1504
1510
// Add pkgConfig libs arguments.
1505
1511
buildProduct. additionalFlags += pkgConfig ( for: target) . libs
@@ -1569,6 +1575,8 @@ public class BuildPlan {
1569
1575
// FIXME: We should write this as a custom llbuild task once we adopt it
1570
1576
// as a library.
1571
1577
try buildProduct. writeLinkFilelist ( fileSystem)
1578
+
1579
+ buildProduct. availableTools = dependencies. availableTools
1572
1580
}
1573
1581
1574
1582
/// Computes the dependencies of a product.
@@ -1578,7 +1586,8 @@ public class BuildPlan {
1578
1586
dylibs: [ ResolvedProduct ] ,
1579
1587
staticTargets: [ ResolvedTarget ] ,
1580
1588
systemModules: [ ResolvedTarget ] ,
1581
- libraryBinaryPaths: Set < AbsolutePath >
1589
+ libraryBinaryPaths: Set < AbsolutePath > ,
1590
+ availableTools: [ String : AbsolutePath ]
1582
1591
) {
1583
1592
1584
1593
// Sort the product targets in topological order.
@@ -1606,6 +1615,7 @@ public class BuildPlan {
1606
1615
var staticTargets = [ ResolvedTarget] ( )
1607
1616
var systemModules = [ ResolvedTarget] ( )
1608
1617
var libraryBinaryPaths : Set < AbsolutePath > = [ ]
1618
+ var availableTools = [ String: AbsolutePath] ( )
1609
1619
1610
1620
for dependency in allTargets {
1611
1621
switch dependency {
@@ -1628,8 +1638,13 @@ public class BuildPlan {
1628
1638
guard let binaryTarget = target. underlyingTarget as? BinaryTarget else {
1629
1639
throw InternalError ( " invalid binary target ' \( target. name) ' " )
1630
1640
}
1631
- if case . xcframework = binaryTarget. kind, let library = self . xcFrameworkLibrary ( for: binaryTarget) {
1641
+ switch binaryTarget. kind {
1642
+ case . xcframework:
1643
+ let library = try self . parseXCFramework ( for: binaryTarget)
1632
1644
libraryBinaryPaths. insert ( library. binaryPath)
1645
+ case . toolsArchive:
1646
+ let tools = try self . parseToolsArchive ( for: binaryTarget)
1647
+ tools. forEach { availableTools [ $0. name] = $0. binaryPath }
1633
1648
}
1634
1649
case . extension:
1635
1650
continue
@@ -1650,7 +1665,7 @@ public class BuildPlan {
1650
1665
}
1651
1666
}
1652
1667
1653
- return ( linkLibraries, staticTargets, systemModules, libraryBinaryPaths)
1668
+ return ( linkLibraries, staticTargets, systemModules, libraryBinaryPaths, availableTools )
1654
1669
}
1655
1670
1656
1671
/// Plan a Clang target.
@@ -1678,7 +1693,8 @@ public class BuildPlan {
1678
1693
clangTarget. additionalFlags += [ " -fmodule-map-file= \( target. moduleMapPath. pathString) " ]
1679
1694
clangTarget. additionalFlags += pkgConfig ( for: target) . cFlags
1680
1695
case let target as BinaryTarget :
1681
- if let library = xcFrameworkLibrary ( for: target) {
1696
+ if case . xcframework = target. kind {
1697
+ let library = try self . parseXCFramework ( for: target)
1682
1698
if let headersPath = library. headersPath {
1683
1699
clangTarget. additionalFlags += [ " -I " , headersPath. pathString]
1684
1700
}
@@ -1712,7 +1728,8 @@ public class BuildPlan {
1712
1728
swiftTarget. additionalFlags += [ " -Xcc " , " -fmodule-map-file= \( target. moduleMapPath. pathString) " ]
1713
1729
swiftTarget. additionalFlags += pkgConfig ( for: target) . cFlags
1714
1730
case let target as BinaryTarget :
1715
- if let library = xcFrameworkLibrary ( for: target) {
1731
+ if case . xcframework = target. kind {
1732
+ let library = try self . parseXCFramework ( for: target)
1716
1733
if let headersPath = library. headersPath {
1717
1734
swiftTarget. additionalFlags += [ " -Xcc " , " -I " , " -Xcc " , headersPath. pathString]
1718
1735
}
@@ -1835,53 +1852,64 @@ public class BuildPlan {
1835
1852
return result
1836
1853
}
1837
1854
1838
- /// Extracts the library to building against from a XCFramework.
1839
- private func xcFrameworkLibrary( for target: BinaryTarget ) -> LibraryInfo ? {
1840
- func calculateLibraryInfo( ) -> LibraryInfo ? {
1841
- // Parse the XCFramework's Info.plist.
1842
- let infoPath = target. artifactPath. appending ( component: " Info.plist " )
1843
- guard let info = XCFrameworkInfo ( path: infoPath, diagnostics: diagnostics, fileSystem: fileSystem) else {
1844
- return nil
1845
- }
1855
+ /// Extracts the library information from an XCFramework.
1856
+ private func parseXCFramework( for target: BinaryTarget ) throws -> LibraryInfo {
1857
+ try self . externalLibrariesCache. memoize ( key: target) {
1858
+ let metadata = try XCFrameworkMetadata . parse ( fileSystem: self . fileSystem, rootPath: target. artifactPath)
1846
1859
1847
1860
// Check that it supports the target platform and architecture.
1848
- guard let library = info . libraries. first ( where: {
1849
- return $0. platform == buildParameters. triple. os. asXCFrameworkPlatformString && $0. architectures. contains ( buildParameters. triple. arch. rawValue)
1861
+ guard let library = metadata . libraries. first ( where: {
1862
+ $0. platform == buildParameters. triple. os. asXCFrameworkPlatformString && $0. architectures. contains ( buildParameters. triple. arch. rawValue)
1850
1863
} ) else {
1851
- diagnostics . emit ( error : """
1864
+ throw StringError ( """
1852
1865
artifact ' \( target. name) ' does not support the target platform and architecture \
1853
1866
(' \( buildParameters. triple) ')
1854
1867
""" )
1855
- return nil
1856
1868
}
1857
1869
1858
1870
let libraryDirectory = target. artifactPath. appending ( component: library. libraryIdentifier)
1859
1871
let binaryPath = libraryDirectory. appending ( component: library. libraryPath)
1860
1872
let headersPath = library. headersPath. map ( { libraryDirectory. appending ( component: $0) } )
1873
+
1861
1874
return LibraryInfo ( binaryPath: binaryPath, headersPath: headersPath)
1862
1875
}
1876
+ }
1863
1877
1864
- // If we don't have the library information yet, calculate it.
1865
- if let xcFramework = xcFrameworkCache [ target ] {
1866
- return xcFramework
1867
- }
1878
+ /// Extracts the executables info from an executablesArchive
1879
+ private func parseToolsArchive ( for target : BinaryTarget ) throws -> [ ToolInfo ] {
1880
+ try self . externalToolsCache . memoize ( key : target ) {
1881
+ let metadata = try ToolsArchiveMetadata . parse ( fileSystem : self . fileSystem , rootPath : target . artifactPath )
1868
1882
1869
- let xcFramework = calculateLibraryInfo ( )
1870
- xcFrameworkCache [ target] = xcFramework
1871
- return xcFramework
1883
+ // filter the tools that are relevant to the triple
1884
+ let supportedTools = metadata. tools. filter { $0. value. contains ( where: { $0. supportedTriplets. contains ( buildParameters. triple) } ) }
1885
+ // flatten the tools for each access
1886
+ return supportedTools. reduce ( into: [ ToolInfo] ( ) , { partial, entry in
1887
+ let tools = entry. value. map {
1888
+ ToolInfo ( name: entry. key, binaryPath: target. artifactPath. appending ( RelativePath ( $0. path) ) )
1889
+ }
1890
+ partial. append ( contentsOf: tools)
1891
+ } )
1892
+ }
1872
1893
}
1873
1894
}
1874
1895
1875
- /// Information about a library.
1896
+ /// Information about a library from a binary dependency .
1876
1897
private struct LibraryInfo : Equatable {
1877
-
1878
1898
/// The path to the binary.
1879
1899
let binaryPath : AbsolutePath
1880
1900
1881
1901
/// The path to the headers directory, if one exists.
1882
1902
let headersPath : AbsolutePath ?
1883
1903
}
1884
1904
1905
+ /// Information about an executable from a binary dependency.
1906
+ private struct ToolInfo : Equatable {
1907
+ /// The tool name
1908
+ let name : String
1909
+ /// The path to the binary.
1910
+ let binaryPath : AbsolutePath
1911
+ }
1912
+
1885
1913
private extension Diagnostic . Message {
1886
1914
static var swiftBackDeployError : Diagnostic . Message {
1887
1915
. warning( " Swift compiler no longer supports statically linking the Swift libraries. They're included in the OS by default starting with macOS Mojave 10.14.4 beta 3. For macOS Mojave 10.14.3 and earlier, there's an optional Swift library package that can be downloaded from \" More Downloads \" for Apple Developers at https://developer.apple.com/download/more/ " )
@@ -1980,3 +2008,14 @@ fileprivate extension Triple {
1980
2008
isLinux ( ) || arch == . wasm32
1981
2009
}
1982
2010
}
2011
+
2012
+ // FIXME: move this to TSC
2013
+ extension Triple : Hashable {
2014
+ public func hash( into hasher: inout Hasher ) {
2015
+ hasher. combine ( self . tripleString)
2016
+ hasher. combine ( self . arch)
2017
+ hasher. combine ( self . vendor)
2018
+ hasher. combine ( self . os)
2019
+ hasher. combine ( self . abi)
2020
+ }
2021
+ }
0 commit comments