@@ -408,12 +408,32 @@ public final class PackageBuilder {
408408 // Check for a modulemap file, which indicates a system target.
409409 let moduleMapPath = packagePath. appending ( component: moduleMapFilename)
410410 if fileSystem. isFile ( moduleMapPath) {
411+
412+ // Warn about any declared targets.
413+ let targets = manifest. package . targets
414+ if !targets. isEmpty {
415+ diagnostics. emit (
416+ data: PackageBuilderDiagnostics . SystemPackageDeclaresTargetsDiagnostic ( targets: targets. map ( { $0. name } ) ) ,
417+ location: PackageLocation . Local ( name: manifest. name, packagePath: packagePath)
418+ )
419+ }
420+
421+ // Emit deprecation notice.
422+ switch manifest. manifestVersion {
423+ case . v3, . v4: break
424+ case . v4_2:
425+ diagnostics. emit (
426+ data: PackageBuilderDiagnostics . SystemPackageDeprecatedDiagnostic ( ) ,
427+ location: PackageLocation . Local ( name: manifest. name, packagePath: packagePath)
428+ )
429+ }
430+
411431 // Package contains a modulemap at the top level, so we assuming
412432 // it's a system library target.
413433 return [
414434 SystemLibraryTarget (
415435 name: manifest. name,
416- path: packagePath,
436+ path: packagePath, isImplicit : true ,
417437 pkgConfig: manifest. package . pkgConfig,
418438 providers: manifest. package . providers)
419439 ]
@@ -493,7 +513,7 @@ public final class PackageBuilder {
493513 let potentialTargets : [ PotentialModule ]
494514 potentialTargets = try manifest. package . targets. map ( { target in
495515 let path = try findPath ( for: target)
496- return PotentialModule ( name: target. name, path: path, isTest : target. isTest )
516+ return PotentialModule ( name: target. name, path: path, type : target. type )
497517 } )
498518 return try createModules ( potentialTargets)
499519 }
@@ -543,9 +563,9 @@ public final class PackageBuilder {
543563 if potentialModulePaths. isEmpty {
544564 // There are no directories that look like targets, so try to create a target for the source directory
545565 // itself (with the name coming from the name in the manifest).
546- potentialModules = [ PotentialModule ( name: manifest. name, path: srcDir, isTest : false ) ]
566+ potentialModules = [ PotentialModule ( name: manifest. name, path: srcDir, type : . regular ) ]
547567 } else {
548- potentialModules = potentialModulePaths. map ( { PotentialModule ( name: $0. basename, path: $0, isTest : false ) } )
568+ potentialModules = potentialModulePaths. map ( { PotentialModule ( name: $0. basename, path: $0, type : . regular ) } )
549569 }
550570 return try createModules ( potentialModules + potentialTestModules( ) )
551571 }
@@ -691,6 +711,19 @@ public final class PackageBuilder {
691711 productDeps: [ ( name: String , package : String ? ) ]
692712 ) throws -> Target ? {
693713
714+ // Create system library target.
715+ if potentialModule. type == . system {
716+ let moduleMapPath = potentialModule. path. appending ( component: moduleMapFilename)
717+ guard fileSystem. isFile ( moduleMapPath) else {
718+ return nil
719+ }
720+ return SystemLibraryTarget (
721+ name: potentialModule. name,
722+ path: potentialModule. path, isImplicit: false ,
723+ pkgConfig: manifestTarget? . pkgConfig,
724+ providers: manifestTarget? . providers)
725+ }
726+
694727 // Compute the path to public headers directory.
695728 let publicHeaderComponent = manifestTarget? . publicHeadersPath ?? ClangTarget . defaultPublicHeadersComponent
696729 let publicHeadersPath = potentialModule. path. appending ( RelativePath ( publicHeaderComponent) )
@@ -882,7 +915,7 @@ public final class PackageBuilder {
882915
883916 return testsDirContents
884917 . filter ( shouldConsiderDirectory)
885- . map ( { PotentialModule ( name: $0. basename, path: $0, isTest : true ) } )
918+ . map ( { PotentialModule ( name: $0. basename, path: $0, type : . test ) } )
886919 }
887920
888921 /// Find the linux main file for the package.
@@ -1054,6 +1087,19 @@ public final class PackageBuilder {
10541087 case nil : type = . library( . automatic)
10551088 }
10561089 let targets = try modulesFrom ( targetNames: p. targets, product: p. name)
1090+
1091+ // Peform special validations if this product is exporting
1092+ // a system library target.
1093+ if targets. contains ( where: { $0 is SystemLibraryTarget } ) {
1094+ if type != . library( . automatic) || targets. count != 1 {
1095+ diagnostics. emit (
1096+ data: PackageBuilderDiagnostics . SystemPackageProductValidationDiagnostic ( product: p. name) ,
1097+ location: PackageLocation . Local ( name: manifest. name, packagePath: packagePath)
1098+ )
1099+ continue
1100+ }
1101+ }
1102+
10571103 append ( Product ( name: p. name, type: type, targets: targets) )
10581104 default :
10591105 fatalError ( " Unreachable " )
@@ -1076,12 +1122,17 @@ private struct PotentialModule: Hashable {
10761122 let path : AbsolutePath
10771123
10781124 /// If this should be a test target.
1079- let isTest : Bool
1125+ var isTest : Bool {
1126+ return type == . test
1127+ }
1128+
1129+ /// The target type.
1130+ let type : PackageDescription4 . Target . TargetType
10801131
10811132 /// The base prefix for the test target, used to associate with the target it tests.
10821133 public var basename : String {
10831134 guard isTest else {
1084- fatalError ( " \( type ( of: self ) ) should be a test target to access basename. " )
1135+ fatalError ( " \( Swift . type ( of: self ) ) should be a test target to access basename. " )
10851136 }
10861137 precondition ( name. hasSuffix ( Target . testModuleNameSuffix) )
10871138 let endIndex = name. index ( name. endIndex, offsetBy: - Target. testModuleNameSuffix. count)
0 commit comments