Skip to content

Commit 079a811

Browse files
committed
Init template cleanup
Improve the `swift package init` experience using the following criteria: - Simplify the templates to include only the minimum necessary to get started without making assumptions. - Use documentation links instead of arbitrary template content to teach people about Swift. - Improve the "front door" experience with the help usage. Detailed list of changes: - Remove the `system-module` template. - Remove the `manifest` template - it's emptier than `empty` and isn't providing a lot of value on its own. Make the `empty` template only generate a manifest instead. - Remove README generation. - Don't generate empty directories. - Don't emit empty dependencies array in manifests. - Update `library` template content: - Remove struct definition, use a simple public function instead. - Include documentation links for TSPL and the Standard Library. - Include documentation links for XCTest in the generated test case. - Update `executable` template content - Use simpler top-level code instead of an `@main` struct. - Remove executable tests. - Put sources directly in `./Sources`. - Clean up and align `type` argument help text - Update Usage.md documentation - Update CHANGELOG to reflect init template changes in #6144 rdar://98999734
1 parent 2d90cc8 commit 079a811

File tree

5 files changed

+49
-202
lines changed

5 files changed

+49
-202
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ Swift Next
1717
}
1818
```
1919

20-
2120
Swift 5.9
2221
-----------
2322

@@ -29,6 +28,9 @@ Swift 5.9
2928

3029
Support for building plugin dependencies for the host when cross-compiling.
3130

31+
* [#6144]
32+
33+
Remove the `system-module` and `manifest` templates and clean up the remaining `empty`, `library`, and `executable` templates so they include the minimum information needed to get started, with links to documentation in the generated library, executable, and test content.
3234

3335
Swift 5.8
3436
-----------

Documentation/Usage.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ initialize it as a package that builds a system module:
158158
example$ cd ..
159159
$ mkdir Clibgit
160160
$ cd Clibgit
161-
Clibgit$ swift package init --type system-module
161+
Clibgit$ swift package init --type empty
162162

163-
This creates `Package.swift` and `module.modulemap` files in the directory.
163+
This creates a `Package.swift` file in the directory.
164164
Edit `Package.swift` and add `pkgConfig` parameter:
165165

166166
```swift
@@ -181,7 +181,7 @@ parameter you can pass the path of a directory containing the library using the
181181

182182
example$ swift build -Xlinker -L/usr/local/lib/
183183

184-
Edit `module.modulemap` so it consists of the following:
184+
Create a `module.modulemap` file so it consists of the following:
185185

186186
module Clibgit [system] {
187187
header "/usr/local/include/git2.h"
@@ -258,10 +258,10 @@ initialize it as a package that builds a system module:
258258
example$ cd ..
259259
$ mkdir CJPEG
260260
$ cd CJPEG
261-
CJPEG$ swift package init --type system-module
261+
CJPEG$ swift package init --type empty
262262

263-
This creates `Package.swift` and `module.modulemap` files in the directory.
264-
Edit `module.modulemap` so it consists of the following:
263+
This creates `Package.swift` file in the directory.
264+
Create a `module.modulemap` file so it consists of the following:
265265

266266
module CJPEG [system] {
267267
header "shim.h"

Sources/Commands/PackageTools/Init.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@ extension SwiftPackageTool {
2525

2626
@Option(
2727
name: .customLong("type"),
28-
help: ArgumentHelp("Package type: empty | library | executable | system-module | manifest", discussion: """
29-
empty - Create an empty package
30-
library - Create a package that contains a library
31-
executable - Create a package that contains a binary executable
32-
system-module - Create a package that contains a system module
33-
manifest - Create a Package.swift file
28+
help: ArgumentHelp("Package type:", discussion: """
29+
library - A package with a library.
30+
executable - A package with an executable.
31+
empty - An empty package with a Package.swift manifest.
3432
"""))
3533
var initMode: InitPackage.PackageType = .library
3634

Sources/Workspace/InitPackage.swift

Lines changed: 35 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ public final class InitPackage {
4343
case empty = "empty"
4444
case library = "library"
4545
case executable = "executable"
46-
case systemModule = "system-module"
47-
case manifest = "manifest"
4846
case `extension` = "extension"
4947

5048
public var description: String {
@@ -114,15 +112,8 @@ public final class InitPackage {
114112
// FIXME: We should form everything we want to write, then validate that
115113
// none of it exists, and then act.
116114
try writeManifestFile()
117-
118-
if packageType == .manifest {
119-
return
120-
}
121-
122-
try writeREADMEFile()
123115
try writeGitIgnore()
124116
try writeSources()
125-
try writeModuleMap()
126117
try writeTests()
127118
}
128119

@@ -177,51 +168,43 @@ public final class InitPackage {
177168
""")
178169
}
179170

180-
if packageType == .library || packageType == .manifest {
171+
if packageType == .library {
181172
pkgParams.append("""
182173
products: [
183-
// Products define the executables and libraries a package produces, and make them visible to other packages.
174+
// Products define the executables and libraries a package produces, making them visible to other packages.
184175
.library(
185176
name: "\(pkgname)",
186177
targets: ["\(pkgname)"]),
187178
]
188179
""")
189180
}
190181

191-
pkgParams.append("""
192-
dependencies: [
193-
// Dependencies declare other packages that this package depends on.
194-
// .package(url: /* package url */, from: "1.0.0"),
195-
]
196-
""")
197-
198-
if packageType == .library || packageType == .executable || packageType == .manifest {
182+
if packageType == .library || packageType == .executable {
199183
var param = ""
200184

201185
param += """
202186
targets: [
203-
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
204-
// Targets can depend on other targets in this package, and on products in packages this package depends on.
187+
// Targets are the basic building blocks of a package, defining a module or a test suite.
188+
// Targets can depend on other targets in this package and products from dependencies.
205189
206190
"""
207191
if packageType == .executable {
208192
param += """
209193
.executableTarget(
194+
name: "\(pkgname)",
195+
path: "Sources"),
196+
]
210197
"""
211198
} else {
212199
param += """
213200
.target(
201+
name: "\(pkgname)"),
202+
.testTarget(
203+
name: "\(pkgname)Tests",
204+
dependencies: ["\(pkgname)"]),
205+
]
214206
"""
215207
}
216-
param += """
217-
218-
name: "\(pkgname)",
219-
dependencies: []),
220-
.testTarget(
221-
name: "\(pkgname)Tests",
222-
dependencies: ["\(pkgname)"]),
223-
]
224-
"""
225208

226209
pkgParams.append(param)
227210
}
@@ -242,23 +225,10 @@ public final class InitPackage {
242225
)
243226
}
244227

245-
private func writeREADMEFile() throws {
246-
let readme = destinationPath.appending(component: "README.md")
247-
guard self.fileSystem.exists(readme) == false else {
228+
private func writeGitIgnore() throws {
229+
guard packageType != .empty else {
248230
return
249231
}
250-
251-
try writePackageFile(readme) { stream in
252-
stream <<< """
253-
# \(pkgname)
254-
255-
A description of this package.
256-
257-
"""
258-
}
259-
}
260-
261-
private func writeGitIgnore() throws {
262232
let gitignore = destinationPath.appending(component: ".gitignore")
263233
guard self.fileSystem.exists(gitignore) == false else {
264234
return
@@ -281,21 +251,20 @@ public final class InitPackage {
281251
}
282252

283253
private func writeSources() throws {
284-
if packageType == .systemModule || packageType == .manifest {
254+
if packageType == .empty {
285255
return
286256
}
257+
287258
let sources = destinationPath.appending(component: "Sources")
288259
guard self.fileSystem.exists(sources) == false else {
289260
return
290261
}
291262
progressReporter?("Creating \(sources.relative(to: destinationPath))/")
292263
try makeDirectories(sources)
293264

294-
if packageType == .empty {
295-
return
296-
}
297-
298-
let moduleDir = sources.appending(component: "\(pkgname)")
265+
let moduleDir = packageType == .executable
266+
? sources
267+
: sources.appending(component: "\(pkgname)")
299268
try makeDirectories(moduleDir)
300269

301270
let sourceFileName = "\(typeName).swift"
@@ -305,27 +274,19 @@ public final class InitPackage {
305274
switch packageType {
306275
case .library:
307276
content = """
308-
public struct \(typeName) {
309-
public private(set) var text = "Hello, World!"
310-
311-
public init() {
312-
}
313-
}
277+
// The Swift Programming Language
278+
// https://docs.swift.org/swift-book
314279
315280
"""
316281
case .executable:
317282
content = """
318-
@main
319-
struct \(typeName) {
320-
private(set) var text = "Hello, World!"
283+
// The Swift Programming Language
284+
// https://docs.swift.org/swift-book
321285
322-
static func main() {
323-
print(\(typeName)().text)
324-
}
325-
}
286+
print("Hello, world!")
326287
327288
"""
328-
case .systemModule, .empty, .manifest, .`extension`:
289+
case .empty, .`extension`:
329290
throw InternalError("invalid packageType \(packageType)")
330291
}
331292

@@ -334,43 +295,18 @@ public final class InitPackage {
334295
}
335296
}
336297

337-
private func writeModuleMap() throws {
338-
if packageType != .systemModule {
339-
return
340-
}
341-
let modulemap = destinationPath.appending(component: "module.modulemap")
342-
guard self.fileSystem.exists(modulemap) == false else {
343-
return
344-
}
345-
346-
try writePackageFile(modulemap) { stream in
347-
stream <<< """
348-
module \(moduleName) [system] {
349-
header "/usr/include/\(moduleName).h"
350-
link "\(moduleName)"
351-
export *
352-
}
353-
354-
"""
355-
}
356-
}
357-
358298
private func writeTests() throws {
359-
if packageType == .systemModule {
360-
return
299+
switch packageType {
300+
case .empty, .executable, .`extension`: return
301+
default: break
361302
}
362303
let tests = destinationPath.appending(component: "Tests")
363304
guard self.fileSystem.exists(tests) == false else {
364305
return
365306
}
366307
progressReporter?("Creating \(tests.relative(to: destinationPath))/")
367308
try makeDirectories(tests)
368-
369-
switch packageType {
370-
case .systemModule, .empty, .manifest, .`extension`: break
371-
case .library, .executable:
372-
try writeTestFileStubs(testsPath: tests)
373-
}
309+
try writeTestFileStubs(testsPath: tests)
374310
}
375311

376312
private func writeLibraryTestsFile(_ path: AbsolutePath) throws {
@@ -381,29 +317,11 @@ public final class InitPackage {
381317
382318
final class \(moduleName)Tests: XCTestCase {
383319
func testExample() throws {
384-
// This is an example of a functional test case.
385-
// Use XCTAssert and related functions to verify your tests produce the correct
386-
// results.
387-
XCTAssertEqual(\(typeName)().text, "Hello, World!")
388-
}
389-
}
390-
391-
"""
392-
}
393-
}
320+
// XCTest Documenation
321+
// https://developer.apple.com/documentation/xctest
394322
395-
private func writeExecutableTestsFile(_ path: AbsolutePath) throws {
396-
try writePackageFile(path) { stream in
397-
stream <<< """
398-
import XCTest
399-
@testable import \(moduleName)
400-
401-
final class \(moduleName)Tests: XCTestCase {
402-
func testExample() throws {
403-
// This is an example of a functional test case.
404-
// Use XCTAssert and related functions to verify your tests produce the correct
405-
// results.
406-
XCTAssertEqual(\(typeName)().text, "Hello, World!")
323+
// Defining Test Cases and Test Methods
324+
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
407325
}
408326
}
409327
@@ -418,11 +336,9 @@ public final class InitPackage {
418336

419337
let testClassFile = try AbsolutePath(validating: "\(moduleName)Tests.swift", relativeTo: testModule)
420338
switch packageType {
421-
case .systemModule, .empty, .manifest, .`extension`: break
339+
case .empty, .`extension`, .executable: break
422340
case .library:
423341
try writeLibraryTestsFile(testClassFile)
424-
case .executable:
425-
try writeExecutableTestsFile(testClassFile)
426342
}
427343
}
428344
}

0 commit comments

Comments
 (0)