@@ -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 " )
@@ -1292,8 +1295,11 @@ public class BuildPlan {
1292
1295
/// Cache for pkgConfig flags.
1293
1296
private var pkgConfigCache = [ SystemLibraryTarget: ( cFlags: [ String] , libs: [ String] ) ] ( )
1294
1297
1295
- /// Cache for xcframework library information.
1296
- private var xcFrameworkCache = [ BinaryTarget: LibraryInfo? ] ( )
1298
+ /// Cache for library information.
1299
+ private var externalLibrariesCache = [ BinaryTarget: LibraryInfo] ( )
1300
+
1301
+ /// Cache for tools information.
1302
+ private var externalToolsCache = [ BinaryTarget: [ ToolInfo] ] ( )
1297
1303
1298
1304
private static func makeTestManifestTargets(
1299
1305
_ buildParameters: BuildParameters ,
@@ -1497,7 +1503,7 @@ public class BuildPlan {
1497
1503
// Add flags for system targets.
1498
1504
for systemModule in dependencies. systemModules {
1499
1505
guard case let target as SystemLibraryTarget = systemModule. underlyingTarget else {
1500
- fatalError ( " This should not be possible. " )
1506
+ throw InternalError ( " This should not be possible. " )
1501
1507
}
1502
1508
// Add pkgConfig libs arguments.
1503
1509
buildProduct. additionalFlags += pkgConfig ( for: target) . libs
@@ -1567,6 +1573,8 @@ public class BuildPlan {
1567
1573
// FIXME: We should write this as a custom llbuild task once we adopt it
1568
1574
// as a library.
1569
1575
try buildProduct. writeLinkFilelist ( fileSystem)
1576
+
1577
+ buildProduct. availableTools = dependencies. availableTools
1570
1578
}
1571
1579
1572
1580
/// Computes the dependencies of a product.
@@ -1576,7 +1584,8 @@ public class BuildPlan {
1576
1584
dylibs: [ ResolvedProduct ] ,
1577
1585
staticTargets: [ ResolvedTarget ] ,
1578
1586
systemModules: [ ResolvedTarget ] ,
1579
- libraryBinaryPaths: Set < AbsolutePath >
1587
+ libraryBinaryPaths: Set < AbsolutePath > ,
1588
+ availableTools: [ String : AbsolutePath ]
1580
1589
) {
1581
1590
1582
1591
// Sort the product targets in topological order.
@@ -1604,6 +1613,7 @@ public class BuildPlan {
1604
1613
var staticTargets = [ ResolvedTarget] ( )
1605
1614
var systemModules = [ ResolvedTarget] ( )
1606
1615
var libraryBinaryPaths : Set < AbsolutePath > = [ ]
1616
+ var availableTools = [ String: AbsolutePath] ( )
1607
1617
1608
1618
for dependency in allTargets {
1609
1619
switch dependency {
@@ -1626,8 +1636,13 @@ public class BuildPlan {
1626
1636
guard let binaryTarget = target. underlyingTarget as? BinaryTarget else {
1627
1637
throw InternalError ( " invalid binary target ' \( target. name) ' " )
1628
1638
}
1629
- if case . xcframework = binaryTarget. kind, let library = self . xcFrameworkLibrary ( for: binaryTarget) {
1639
+ switch binaryTarget. kind {
1640
+ case . xcframework:
1641
+ let library = try self . parseXCFramework ( for: binaryTarget)
1630
1642
libraryBinaryPaths. insert ( library. binaryPath)
1643
+ case . toolsArchive:
1644
+ let tools = try self . parseToolsArchive ( for: binaryTarget)
1645
+ tools. forEach { availableTools [ $0. name] = $0. binaryPath }
1631
1646
}
1632
1647
case . extension:
1633
1648
continue
@@ -1648,7 +1663,7 @@ public class BuildPlan {
1648
1663
}
1649
1664
}
1650
1665
1651
- return ( linkLibraries, staticTargets, systemModules, libraryBinaryPaths)
1666
+ return ( linkLibraries, staticTargets, systemModules, libraryBinaryPaths, availableTools )
1652
1667
}
1653
1668
1654
1669
/// Plan a Clang target.
@@ -1676,7 +1691,8 @@ public class BuildPlan {
1676
1691
clangTarget. additionalFlags += [ " -fmodule-map-file= \( target. moduleMapPath. pathString) " ]
1677
1692
clangTarget. additionalFlags += pkgConfig ( for: target) . cFlags
1678
1693
case let target as BinaryTarget :
1679
- if let library = xcFrameworkLibrary ( for: target) {
1694
+ if case . xcframework = target. kind {
1695
+ let library = try self . parseXCFramework ( for: target)
1680
1696
if let headersPath = library. headersPath {
1681
1697
clangTarget. additionalFlags += [ " -I " , headersPath. pathString]
1682
1698
}
@@ -1710,7 +1726,8 @@ public class BuildPlan {
1710
1726
swiftTarget. additionalFlags += [ " -Xcc " , " -fmodule-map-file= \( target. moduleMapPath. pathString) " ]
1711
1727
swiftTarget. additionalFlags += pkgConfig ( for: target) . cFlags
1712
1728
case let target as BinaryTarget :
1713
- if let library = xcFrameworkLibrary ( for: target) {
1729
+ if case . xcframework = target. kind {
1730
+ let library = try self . parseXCFramework ( for: target)
1714
1731
if let headersPath = library. headersPath {
1715
1732
swiftTarget. additionalFlags += [ " -Xcc " , " -I " , " -Xcc " , headersPath. pathString]
1716
1733
}
@@ -1833,53 +1850,64 @@ public class BuildPlan {
1833
1850
return result
1834
1851
}
1835
1852
1836
- /// Extracts the library to building against from a XCFramework.
1837
- private func xcFrameworkLibrary( for target: BinaryTarget ) -> LibraryInfo ? {
1838
- func calculateLibraryInfo( ) -> LibraryInfo ? {
1839
- // Parse the XCFramework's Info.plist.
1840
- let infoPath = target. artifactPath. appending ( component: " Info.plist " )
1841
- guard let info = XCFrameworkInfo ( path: infoPath, diagnostics: diagnostics, fileSystem: fileSystem) else {
1842
- return nil
1843
- }
1853
+ /// Extracts the library information from an XCFramework.
1854
+ private func parseXCFramework( for target: BinaryTarget ) throws -> LibraryInfo {
1855
+ try self . externalLibrariesCache. memoize ( key: target) {
1856
+ let metadata = try XCFrameworkMetadata . parse ( fileSystem: self . fileSystem, rootPath: target. artifactPath)
1844
1857
1845
1858
// Check that it supports the target platform and architecture.
1846
- guard let library = info . libraries. first ( where: {
1847
- return $0. platform == buildParameters. triple. os. asXCFrameworkPlatformString && $0. architectures. contains ( buildParameters. triple. arch. rawValue)
1859
+ guard let library = metadata . libraries. first ( where: {
1860
+ $0. platform == buildParameters. triple. os. asXCFrameworkPlatformString && $0. architectures. contains ( buildParameters. triple. arch. rawValue)
1848
1861
} ) else {
1849
- diagnostics . emit ( error : """
1862
+ throw StringError ( """
1850
1863
artifact ' \( target. name) ' does not support the target platform and architecture \
1851
1864
(' \( buildParameters. triple) ')
1852
1865
""" )
1853
- return nil
1854
1866
}
1855
1867
1856
1868
let libraryDirectory = target. artifactPath. appending ( component: library. libraryIdentifier)
1857
1869
let binaryPath = libraryDirectory. appending ( component: library. libraryPath)
1858
1870
let headersPath = library. headersPath. map ( { libraryDirectory. appending ( component: $0) } )
1871
+
1859
1872
return LibraryInfo ( binaryPath: binaryPath, headersPath: headersPath)
1860
1873
}
1874
+ }
1861
1875
1862
- // If we don't have the library information yet, calculate it.
1863
- if let xcFramework = xcFrameworkCache [ target ] {
1864
- return xcFramework
1865
- }
1876
+ /// Extracts the executables info from an executablesArchive
1877
+ private func parseToolsArchive ( for target : BinaryTarget ) throws -> [ ToolInfo ] {
1878
+ try self . externalToolsCache . memoize ( key : target ) {
1879
+ let metadata = try ToolsArchiveMetadata . parse ( fileSystem : self . fileSystem , rootPath : target . artifactPath )
1866
1880
1867
- let xcFramework = calculateLibraryInfo ( )
1868
- xcFrameworkCache [ target] = xcFramework
1869
- return xcFramework
1881
+ // filter the tools that are relevant to the triple
1882
+ let supportedTools = metadata. tools. filter { $0. value. contains ( where: { $0. supportedTriplets. contains ( buildParameters. triple) } ) }
1883
+ // flatten the tools for each access
1884
+ return supportedTools. reduce ( into: [ ToolInfo] ( ) , { partial, entry in
1885
+ let tools = entry. value. map {
1886
+ ToolInfo ( name: entry. key, binaryPath: target. artifactPath. appending ( RelativePath ( $0. path) ) )
1887
+ }
1888
+ partial. append ( contentsOf: tools)
1889
+ } )
1890
+ }
1870
1891
}
1871
1892
}
1872
1893
1873
- /// Information about a library.
1894
+ /// Information about a library from a binary dependency .
1874
1895
private struct LibraryInfo : Equatable {
1875
-
1876
1896
/// The path to the binary.
1877
1897
let binaryPath : AbsolutePath
1878
1898
1879
1899
/// The path to the headers directory, if one exists.
1880
1900
let headersPath : AbsolutePath ?
1881
1901
}
1882
1902
1903
+ /// Information about an executable from a binary dependency.
1904
+ private struct ToolInfo : Equatable {
1905
+ /// The tool name
1906
+ let name : String
1907
+ /// The path to the binary.
1908
+ let binaryPath : AbsolutePath
1909
+ }
1910
+
1883
1911
private extension Diagnostic . Message {
1884
1912
static var swiftBackDeployError : Diagnostic . Message {
1885
1913
. 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/ " )
@@ -1978,3 +2006,14 @@ fileprivate extension Triple {
1978
2006
isLinux ( ) || arch == . wasm32
1979
2007
}
1980
2008
}
2009
+
2010
+ // FIXME: move this to TSC
2011
+ extension Triple : Hashable {
2012
+ public func hash( into hasher: inout Hasher ) {
2013
+ hasher. combine ( self . tripleString)
2014
+ hasher. combine ( self . arch)
2015
+ hasher. combine ( self . vendor)
2016
+ hasher. combine ( self . os)
2017
+ hasher. combine ( self . abi)
2018
+ }
2019
+ }
0 commit comments