Skip to content

Commit 96aa6fd

Browse files
authored
Merge pull request #565 from abertelrud/prep-for-se-0129
Add comments and clear up some of the code in preparation for SE-0021…
2 parents 2737eea + 27ec9c0 commit 96aa6fd

File tree

2 files changed

+57
-29
lines changed

2 files changed

+57
-29
lines changed

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,25 @@ import Utility
1414

1515
import class PackageDescription.Target
1616

17+
/// An error in the structure or layout of a package.
1718
public enum ModuleError: Swift.Error {
19+
20+
/// One or more referenced modules could not be found.
1821
case modulesNotFound([String])
22+
23+
/// Package layout is invalid.
1924
case invalidLayout(InvalidLayoutType)
25+
26+
/// Describes a way in which a package layout is invalid.
27+
public enum InvalidLayoutType {
28+
case multipleSourceRoots([String])
29+
case invalidLayout([String])
30+
}
31+
32+
/// A module was marked as being dependent on an executable.
2033
case executableAsDependency(module: String, dependency: String)
2134
}
2235

23-
public enum InvalidLayoutType {
24-
case multipleSourceRoots([String])
25-
case invalidLayout([String])
26-
}
27-
2836
extension ModuleError: FixableError {
2937
public var error: String {
3038
switch self {
@@ -49,7 +57,7 @@ extension ModuleError: FixableError {
4957
}
5058
}
5159

52-
extension InvalidLayoutType: FixableError {
60+
extension ModuleError.InvalidLayoutType: FixableError {
5361
public var error: String {
5462
switch self {
5563
case .multipleSourceRoots(let paths):
@@ -208,10 +216,12 @@ public struct PackageBuilder {
208216
}
209217

210218
/// Returns path to all the items in a directory.
219+
/// FIXME: This is generic functionality, and should move to FileSystem.
211220
func directoryContents(_ path: AbsolutePath) throws -> [AbsolutePath] {
212221
return try fileSystem.getDirectoryContents(path).map { path.appending(component: $0) }
213222
}
214223

224+
/// Returns the path of the source directory, throwing an error in case of an invalid layout (such as the presence of both `Sources` and `src` directories).
215225
func sourceRoot() throws -> AbsolutePath {
216226
let viableRoots = try fileSystem.getDirectoryContents(packagePath).filter { basename in
217227
let entry = packagePath.appending(component: basename)
@@ -234,48 +244,59 @@ public struct PackageBuilder {
234244
}
235245
}
236246

237-
/// Collects the modules which are defined by a package.
247+
/// Private function that creates and returns a list of non-test Modules defined by a package.
238248
private func constructModules() throws -> [Module] {
249+
250+
// Check for a modulemap file, which indicates a system module.
239251
let moduleMapPath = packagePath.appending(component: "module.modulemap")
240252
if fileSystem.isFile(moduleMapPath) {
253+
// Package contains a modulemap at the top level, so we assuming it's a system module.
241254
let sources = Sources(paths: [moduleMapPath], root: packagePath)
242255
return [try CModule(name: manifest.name, sources: sources, path: packagePath, pkgConfig: pkgConfigPath, providers: manifest.package.providers)]
243256
}
244257

258+
// If everything is excluded, just return an empty array.
245259
if manifest.package.exclude.contains(".") {
246260
return []
247261
}
248-
249-
let srcroot = try sourceRoot()
250-
251-
if srcroot != packagePath {
262+
263+
// Locate the source directory inside the package.
264+
let srcDir = try sourceRoot()
265+
266+
// If there is a source directory, we expect all source files to be located in it.
267+
if srcDir != packagePath {
252268
let invalidRootFiles = try directoryContents(packagePath).filter(isValidSource)
253269
guard invalidRootFiles.isEmpty else {
254270
throw ModuleError.invalidLayout(.invalidLayout(invalidRootFiles.map{ $0.asString }))
255271
}
256272
}
257-
258-
let maybeModules = try directoryContents(srcroot).filter(shouldConsiderDirectory)
259-
260-
if maybeModules.count == 1 && maybeModules[0] != srcroot {
261-
let invalidModuleFiles = try directoryContents(srcroot).filter(isValidSource)
273+
274+
// Locate any directories that might be the roots of modules inside the source directory.
275+
let potentialModulePaths = try directoryContents(srcDir).filter(shouldConsiderDirectory)
276+
277+
// If there's a single module inside the source directory, make sure there are no loose source files in the sources directory.
278+
if potentialModulePaths.count == 1 && potentialModulePaths[0] != srcDir {
279+
let invalidModuleFiles = try directoryContents(srcDir).filter(isValidSource)
262280
guard invalidModuleFiles.isEmpty else {
263281
throw ModuleError.invalidLayout(.invalidLayout(invalidModuleFiles.map{ $0.asString }))
264282
}
265283
}
266-
284+
285+
// With preliminary checks done, we can start creating modules.
267286
let modules: [Module]
268-
if maybeModules.isEmpty {
269-
// If there are no sources subdirectories, we have at most a one target package.
287+
if potentialModulePaths.isEmpty {
288+
// There are no directories that look like modules, so try to create a module for the source directory itself (with the name coming from the name in the manifest).
270289
do {
271-
modules = [try modulify(srcroot, name: manifest.name, isTest: false)]
272-
} catch Module.Error.noSources {
290+
modules = [try createModule(srcDir, name: manifest.name, isTest: false)]
291+
}
292+
catch Module.Error.noSources {
273293
// Completely empty packages are allowed as a special case.
274294
modules = []
275295
}
276296
} else {
277-
modules = try maybeModules.map { path in
278-
try modulify(path, name: path.basename, isTest: false)
297+
// We have at least one directory that looks like a module, so we try to create a module for each one.
298+
modules = try potentialModulePaths.map { path in
299+
try createModule(path, name: path.basename, isTest: false)
279300
}
280301
}
281302

@@ -320,19 +341,25 @@ public struct PackageBuilder {
320341
return modules
321342
}
322343

323-
private func modulify(_ path: AbsolutePath, name: String, isTest: Bool) throws -> Module {
344+
/// Private function that constructs a single Module object for the moduel at `path`, having the name `name`. If `isTest` is true, the module is constructed as a test module; if false, it is a regular module.
345+
private func createModule(_ path: AbsolutePath, name: String, isTest: Bool) throws -> Module {
346+
// Find all the files under the module path.
324347
let walked = try walk(path, fileSystem: fileSystem, recursing: shouldConsiderDirectory).map{ $0 }
325348

349+
// Select any source files for the C-based languages and for Swift.
326350
let cSources = walked.filter{ isValidSource($0, validExtensions: SupportedLanguageExtension.cFamilyExtensions) }
327351
let swiftSources = walked.filter{ isValidSource($0, validExtensions: SupportedLanguageExtension.swiftExtensions) }
328352

329-
if !cSources.isEmpty {
353+
// Create and return the right kind of module depending on what kind of sources we found.
354+
if cSources.isEmpty {
355+
// No C sources, so we expect to have Swift sources, and we create a Swift module.
356+
guard !swiftSources.isEmpty else { throw Module.Error.noSources(path.asString) }
357+
return try SwiftModule(name: name, isTest: isTest, sources: Sources(paths: swiftSources, root: path))
358+
} else {
359+
// No Swift sources, so we expect to have C sources, and we create a C module.
330360
guard swiftSources.isEmpty else { throw Module.Error.mixedSources(path.asString) }
331361
return try ClangModule(name: name, isTest: isTest, sources: Sources(paths: cSources, root: path))
332362
}
333-
334-
guard !swiftSources.isEmpty else { throw Module.Error.noSources(path.asString) }
335-
return try SwiftModule(name: name, isTest: isTest, sources: Sources(paths: swiftSources, root: path))
336363
}
337364

338365
/// Collects the products defined by a package.
@@ -416,7 +443,7 @@ public struct PackageBuilder {
416443

417444
// Create the test modules
418445
let testModules = try directoryContents(testsPath).filter(shouldConsiderDirectory).flatMap { dir in
419-
return [try modulify(dir, name: dir.basename, isTest: true)]
446+
return [try createModule(dir, name: dir.basename, isTest: true)]
420447
}
421448

422449
// Populate the test module dependencies.

Sources/PackageModel/Sources.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import Basic
1212
import Utility
1313

14+
/// A grouping of related source files.
1415
public struct Sources {
1516
public let relativePaths: [RelativePath]
1617
public let root: AbsolutePath

0 commit comments

Comments
 (0)