Skip to content

Commit c073793

Browse files
authored
Optionally provide build tasks for library products (#1741)
* Optionally provide build tasks for library products * Add documentation * Add CHANGELOG entry * Add link to Product documentation
1 parent dce35f4 commit c073793

File tree

9 files changed

+97
-5
lines changed

9 files changed

+97
-5
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
## {{releaseVersion}} - {{releaseDate}}
44

5+
### Added
6+
7+
- New `swift.createTasksForLibraryProducts` setting that when enabled causes the extension to automatically create and provide tasks for library products ([#1741](https://github.com/swiftlang/vscode-swift/pull/1741))
8+
59
## 2.10.0 - 2025-07-28
610

711
### Added
812

9-
- Added Swiftly toolchain management support `.swift-version` files, and integration with the toolchain selection UI ([#1717](https://github.com/swiftlang/vscode-swift/pull/1717)
13+
- Added Swiftly toolchain management support `.swift-version` files, and integration with the toolchain selection UI ([#1717](https://github.com/swiftlang/vscode-swift/pull/1717))
1014
- Added code lenses to run suites/tests, configurable with the `swift.showTestCodeLenses` setting ([#1698](https://github.com/swiftlang/vscode-swift/pull/1698))
1115
- New `swift.excludePathsFromActivation` setting to ignore specified sub-folders from being activated as projects ([#1693](https://github.com/swiftlang/vscode-swift/pull/1693))
1216
- New `swift.recordTestDuration` setting to disable capturing test durations, which can improve performance of heavy test runs ([#1745](https://github.com/swiftlang/vscode-swift/pull/1745))

assets/test/defaultPackage/Package.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ let package = Package(
99
.library(
1010
name: "PackageLib",
1111
targets: ["PackageLib"]),
12+
.library(
13+
name: "PackageLib2",
14+
type: .dynamic,
15+
targets: ["PackageLib"]),
1216
],
1317
targets: [
1418
// Targets are the basic building blocks of a package. A target can define a module or a test suite.

assets/test/defaultPackage/[email protected]

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ let package = Package(
1212
.library(
1313
name: "PackageLib",
1414
targets: ["PackageLib"]),
15+
.library(
16+
name: "PackageLib2",
17+
type: .dynamic,
18+
targets: ["PackageLib"]),
1519
],
1620
targets: [
1721
// Targets are the basic building blocks of a package. A target can define a module or a test suite.

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,12 @@
657657
],
658658
"scope": "application"
659659
},
660+
"swift.createTasksForLibraryProducts": {
661+
"type": "boolean",
662+
"default": false,
663+
"markdownDescription": "When enabled, the extension will create \"swift\" build tasks for library products in the package manifest. Note that automatic library products will not be included.",
664+
"scope": "machine-overridable"
665+
},
660666
"swift.showCreateSwiftProjectInWelcomePage": {
661667
"type": "boolean",
662668
"default": true,

src/SwiftPackage.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ export interface Product {
3737
type: { executable?: null; library?: string[] };
3838
}
3939

40+
export function isAutomatic(product: Product): boolean {
41+
return (product.type.library || []).includes("automatic");
42+
}
43+
4044
/** Swift Package Manager target */
4145
export interface Target {
4246
name: string;

src/configuration.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,12 @@ const configuration = {
402402
.getConfiguration("swift")
403403
.get<ShowBuildStatusOptions>("showBuildStatus", "swiftStatus");
404404
},
405+
/** create build tasks for the library products of the package(s) */
406+
get createTasksForLibraryProducts(): boolean {
407+
return vscode.workspace
408+
.getConfiguration("swift")
409+
.get<boolean>("createTasksForLibraryProducts", false);
410+
},
405411
/** background compilation */
406412
get backgroundCompilation(): boolean {
407413
return vscode.workspace

src/tasks/SwiftTaskProvider.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import * as vscode from "vscode";
1616
import { WorkspaceContext } from "../WorkspaceContext";
1717
import { FolderContext } from "../FolderContext";
18-
import { Product } from "../SwiftPackage";
18+
import { isAutomatic, Product } from "../SwiftPackage";
1919
import configuration, {
2020
ShowBuildStatusOptions,
2121
substituteVariablesInString,
@@ -425,6 +425,16 @@ export class SwiftTaskProvider implements vscode.TaskProvider {
425425
for (const executable of executables) {
426426
tasks.push(...createBuildTasks(executable, folderContext));
427427
}
428+
429+
if (configuration.createTasksForLibraryProducts) {
430+
const libraries = await folderContext.swiftPackage.libraryProducts;
431+
for (const lib of libraries) {
432+
if (isAutomatic(lib)) {
433+
continue;
434+
}
435+
tasks.push(...createBuildTasks(lib, folderContext));
436+
}
437+
}
428438
}
429439
return tasks;
430440
}

test/integration-tests/tasks/SwiftTaskProvider.test.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ import { executeTaskAndWaitForResult, waitForEndTaskProcess } from "../../utilit
2626
import { Version } from "../../../src/utilities/version";
2727
import { FolderContext } from "../../../src/FolderContext";
2828
import { mockGlobalObject } from "../../MockUtils";
29-
import { activateExtensionForSuite, folderInRootWorkspace } from "../utilities/testutilities";
29+
import {
30+
activateExtensionForSuite,
31+
folderInRootWorkspace,
32+
updateSettings,
33+
} from "../utilities/testutilities";
3034

3135
suite("SwiftTaskProvider Test Suite", () => {
3236
let workspaceContext: WorkspaceContext;
@@ -92,6 +96,13 @@ suite("SwiftTaskProvider Test Suite", () => {
9296
});
9397

9498
suite("provideTasks", () => {
99+
let resetSettings: (() => Promise<void>) | undefined;
100+
teardown(async () => {
101+
if (resetSettings) {
102+
await resetSettings();
103+
}
104+
});
105+
95106
suite("includes build all task from extension", () => {
96107
let task: vscode.Task | undefined;
97108

@@ -150,6 +161,41 @@ suite("SwiftTaskProvider Test Suite", () => {
150161
expect(task?.detail).to.include("swift build --product PackageExe");
151162
});
152163

164+
test("includes library build tasks task", async () => {
165+
const taskProvider = workspaceContext.taskProvider;
166+
let tasks = await taskProvider.provideTasks(new vscode.CancellationTokenSource().token);
167+
let task = tasks.find(t => t.name === "Build Debug PackageLib2 (defaultPackage)");
168+
expect(task).to.be.undefined;
169+
task = tasks.find(t => t.name === "Build Release PackageLib2 (defaultPackage)");
170+
expect(task).to.be.undefined;
171+
172+
resetSettings = await updateSettings({
173+
"swift.createTasksForLibraryProducts": true,
174+
});
175+
176+
tasks = await taskProvider.provideTasks(new vscode.CancellationTokenSource().token);
177+
task = tasks.find(t => t.name === "Build Debug PackageLib2 (defaultPackage)");
178+
expect(
179+
task,
180+
'expected to find a task named "Build Debug PackageLib2 (defaultPackage)", instead found ' +
181+
tasks.map(t => t.name)
182+
).to.not.be.undefined;
183+
expect(task?.detail).to.include("swift build --product PackageLib2");
184+
task = tasks.find(t => t.name === "Build Release PackageLib2 (defaultPackage)");
185+
expect(
186+
task,
187+
'expected to find a task named "Build Release PackageLib2 (defaultPackage)", instead found ' +
188+
tasks.map(t => t.name)
189+
).to.not.be.undefined;
190+
expect(task?.detail).to.include("swift build -c release --product PackageLib2");
191+
192+
// Don't include automatic products
193+
task = tasks.find(t => t.name === "Build Debug PackageLib (defaultPackage)");
194+
expect(task).to.be.undefined;
195+
task = tasks.find(t => t.name === "Build Release PackageLib (defaultPackage)");
196+
expect(task).to.be.undefined;
197+
});
198+
153199
test("includes product release task", async () => {
154200
const taskProvider = workspaceContext.taskProvider;
155201
const tasks = await taskProvider.provideTasks(

userdocs/userdocs.docc/Articles/Features/automatic-task-creation.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,17 @@ Add tasks for common operations with your Package.
55
For workspaces that contain a `Package.swift` file, the Swift extension adds the following tasks:
66

77
- **Build All**: Build all targets in the Package.
8-
- **Build Debug <Executable>**: Each executable in a Package.swift get a task for building a debug build.
9-
- **Build Release <Executable>**: Each executable in a Package.swift get a task for building a release build.
8+
- **Build Debug \<Executable\>**: Each executable product in a Package.swift get a task for building a debug build.
9+
- **Build Release \<Executable\>**: Each executable product in a Package.swift get a task for building a release build.
1010

1111
> 💡 Tip: Tasks use workflows common to all VS Code extensions. For more information see [the VS Code documentation for tasks](https://code.visualstudio.com/docs/editor/tasks).
1212
1313
These tasks are available via the commands **Terminal ▸ Run Task...** and **Terminal ▸ Run Build Task...** in the command palette.
14+
15+
## Create tasks for library targets
16+
17+
By default build tasks are only automatically created for executable products. If you set the `swift.createTasksForLibraryProducts` setting to true, then additional tasks will be created:
18+
- **Build Debug \<Library\>**: Each library product in a Package.swift get a task for building a debug build.
19+
- **Build Release \<Library\>**: Each library product in a Package.swift get a task for building a release build.
20+
21+
> ⚠️ Important: Tasks will not be created for automatic library products, as you cannot specify a `--product` option for automatic products when building. For more information see the [Swift Package Manager documentation for Product definitions](https://docs.swift.org/package-manager/PackageDescription/PackageDescription.html#product).

0 commit comments

Comments
 (0)