@@ -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 externalExecutablesCache = [ BinaryTarget: [ ExecutableInfo] ] ( )
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,15 @@ 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) {
1632
- libraryBinaryPaths. insert ( library. binaryPath)
1641
+ switch binaryTarget. kind {
1642
+ case . xcframework:
1643
+ let libraries = try self . parseXCFramework ( for: binaryTarget)
1644
+ for library in libraries {
1645
+ libraryBinaryPaths. insert ( library. libraryPath)
1646
+ }
1647
+ case . artifactsArchive:
1648
+ let tools = try self . parseArtifactsArchive ( for: binaryTarget)
1649
+ tools. forEach { availableTools [ $0. name] = $0. executablePath }
1633
1650
}
1634
1651
case . extension:
1635
1652
continue
@@ -1650,7 +1667,7 @@ public class BuildPlan {
1650
1667
}
1651
1668
}
1652
1669
1653
- return ( linkLibraries, staticTargets, systemModules, libraryBinaryPaths)
1670
+ return ( linkLibraries, staticTargets, systemModules, libraryBinaryPaths, availableTools )
1654
1671
}
1655
1672
1656
1673
/// Plan a Clang target.
@@ -1678,11 +1695,14 @@ public class BuildPlan {
1678
1695
clangTarget. additionalFlags += [ " -fmodule-map-file= \( target. moduleMapPath. pathString) " ]
1679
1696
clangTarget. additionalFlags += pkgConfig ( for: target) . cFlags
1680
1697
case let target as BinaryTarget :
1681
- if let library = xcFrameworkLibrary ( for: target) {
1682
- if let headersPath = library. headersPath {
1683
- clangTarget. additionalFlags += [ " -I " , headersPath. pathString]
1698
+ if case . xcframework = target. kind {
1699
+ let libraries = try self . parseXCFramework ( for: target)
1700
+ for library in libraries {
1701
+ if let headersPath = library. headersPath {
1702
+ clangTarget. additionalFlags += [ " -I " , headersPath. pathString]
1703
+ }
1704
+ clangTarget. libraryBinaryPaths. insert ( library. libraryPath)
1684
1705
}
1685
- clangTarget. libraryBinaryPaths. insert ( library. binaryPath)
1686
1706
}
1687
1707
default : continue
1688
1708
}
@@ -1712,11 +1732,14 @@ public class BuildPlan {
1712
1732
swiftTarget. additionalFlags += [ " -Xcc " , " -fmodule-map-file= \( target. moduleMapPath. pathString) " ]
1713
1733
swiftTarget. additionalFlags += pkgConfig ( for: target) . cFlags
1714
1734
case let target as BinaryTarget :
1715
- if let library = xcFrameworkLibrary ( for: target) {
1716
- if let headersPath = library. headersPath {
1717
- swiftTarget. additionalFlags += [ " -Xcc " , " -I " , " -Xcc " , headersPath. pathString]
1735
+ if case . xcframework = target. kind {
1736
+ let libraries = try self . parseXCFramework ( for: target)
1737
+ for library in libraries {
1738
+ if let headersPath = library. headersPath {
1739
+ swiftTarget. additionalFlags += [ " -Xcc " , " -I " , " -Xcc " , headersPath. pathString]
1740
+ }
1741
+ swiftTarget. libraryBinaryPaths. insert ( library. libraryPath)
1718
1742
}
1719
- swiftTarget. libraryBinaryPaths. insert ( library. binaryPath)
1720
1743
}
1721
1744
default :
1722
1745
break
@@ -1835,53 +1858,69 @@ public class BuildPlan {
1835
1858
return result
1836
1859
}
1837
1860
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
- }
1861
+ /// Extracts the library information from an XCFramework.
1862
+ private func parseXCFramework( for target: BinaryTarget ) throws -> [ LibraryInfo ] {
1863
+ try self . externalLibrariesCache. memoize ( key: target) {
1864
+ let metadata = try XCFrameworkMetadata . parse ( fileSystem: self . fileSystem, rootPath: target. artifactPath)
1846
1865
1847
1866
// 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)
1867
+ guard let library = metadata . libraries. first ( where: {
1868
+ $0. platform == buildParameters. triple. os. asXCFrameworkPlatformString && $0. architectures. contains ( buildParameters. triple. arch. rawValue)
1850
1869
} ) else {
1851
- diagnostics . emit ( error : """
1870
+ throw StringError ( """
1852
1871
artifact ' \( target. name) ' does not support the target platform and architecture \
1853
1872
(' \( buildParameters. triple) ')
1854
1873
""" )
1855
- return nil
1856
1874
}
1857
1875
1858
1876
let libraryDirectory = target. artifactPath. appending ( component: library. libraryIdentifier)
1859
- let binaryPath = libraryDirectory. appending ( component: library. libraryPath)
1860
- let headersPath = library. headersPath. map ( { libraryDirectory. appending ( component: $0) } )
1861
- return LibraryInfo ( binaryPath: binaryPath, headersPath: headersPath)
1862
- }
1877
+ let libraryPath = libraryDirectory. appending ( RelativePath ( library. libraryPath) )
1878
+ let headersPath = library. headersPath. map ( { libraryDirectory. appending ( RelativePath ( $0) ) } )
1863
1879
1864
- // If we don't have the library information yet, calculate it.
1865
- if let xcFramework = xcFrameworkCache [ target] {
1866
- return xcFramework
1880
+ return [ LibraryInfo ( libraryPath: libraryPath, headersPath: headersPath) ]
1867
1881
}
1882
+ }
1883
+
1884
+ /// Extracts the artifacts from an artifactsArchive
1885
+ private func parseArtifactsArchive( for target: BinaryTarget ) throws -> [ ExecutableInfo ] {
1886
+ try self . externalExecutablesCache. memoize ( key: target) {
1887
+ let metadata = try ArtifactsArchiveMetadata . parse ( fileSystem: self . fileSystem, rootPath: target. artifactPath)
1868
1888
1869
- let xcFramework = calculateLibraryInfo ( )
1870
- xcFrameworkCache [ target] = xcFramework
1871
- return xcFramework
1889
+ // filter the artifacts that are relevant to the triple
1890
+ // FIXME: this filter needs to become more sophisticated
1891
+ let supportedArtifacts = metadata. artifacts. filter { $0. value. variants. contains ( where: { $0. supportedTriples. contains ( buildParameters. triple) } ) }
1892
+ // TODO: add support for libraries
1893
+ let executables = supportedArtifacts. filter { $0. value. type == . executable }
1894
+
1895
+ // flatten the results for easy access
1896
+ return executables. reduce ( into: [ ExecutableInfo] ( ) , { partial, entry in
1897
+ let executables = entry. value. variants. map {
1898
+ ExecutableInfo ( name: entry. key, executablePath: target. artifactPath. appending ( RelativePath ( $0. path) ) )
1899
+ }
1900
+ partial. append ( contentsOf: executables)
1901
+ } )
1902
+ }
1872
1903
}
1873
1904
}
1874
1905
1875
- /// Information about a library.
1906
+ /// Information about a library from a binary dependency .
1876
1907
private struct LibraryInfo : Equatable {
1877
-
1878
1908
/// The path to the binary.
1879
- let binaryPath : AbsolutePath
1909
+ let libraryPath : AbsolutePath
1880
1910
1881
1911
/// The path to the headers directory, if one exists.
1882
1912
let headersPath : AbsolutePath ?
1883
1913
}
1884
1914
1915
+ /// Information about an executable from a binary dependency.
1916
+ private struct ExecutableInfo : Equatable {
1917
+ /// The tool name
1918
+ let name : String
1919
+
1920
+ /// The path to the executable.
1921
+ let executablePath : AbsolutePath
1922
+ }
1923
+
1885
1924
private extension Diagnostic . Message {
1886
1925
static var swiftBackDeployError : Diagnostic . Message {
1887
1926
. 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/ " )
0 commit comments