Skip to content

Conversation

@jbelkins
Copy link
Contributor

@jbelkins jbelkins commented Nov 9, 2025

Description of changes

Adds the framework for a native-Swift code generator, in the form of a Swift build tool plugin plus a CLI tool.

The plugin is added to the service client target by adding it to the service client target's plugins param. (For aws-sdk-swift, this is performed in companion PR awslabs/aws-sdk-swift#2053).

Using existing code generation, the smithy-model-info.json is added to the Sources in each service client. That file contains the path in the project to the Smithy JSON model for that service. Example contents of smithy-model-info.json:

{"path":"codegen/sdk-codegen/aws-models/sts.json"}

The code generator:

  • Loads the smithy-model-info.json file for that client, then uses the path from that file to load the model.
  • Creates a generated Swift file ModelCount.swift with a global variable modelCount holding the size of the model file in bytes (this proves that the code generator can access the model.)
  • The modelCount var has a documentation comment, to show that doc comments in generated Swift files get picked up.

Example of generated code (for AWSSTS):

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

// Code generated by SmithyCodegenCLI. DO NOT EDIT!

/// The count of bytes in the model.
public let modelCount = 287051

This example code generation is trivial, but it does prove that code generation from a model is possible using Swift build plugins.

Dependency changes:

  • Adds https://github.com/apple/swift-argument-parser as a dependency.
    • This allows the code generator executable (target SmithyCodegenCLI, defined below) to benefit from the utility swift-argument-parser provides.
    • This dependency is already present because it is required by aws-crt-swift, so no change in development footprint.

Scope

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

import software.amazon.smithy.aws.traits.ServiceTrait
import software.amazon.smithy.swift.codegen.integration.ProtocolGenerator
import software.amazon.smithy.swift.codegen.model.getTrait

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just generates a very simple JSON file named smithy-model-info.json into the directory where the Swift source files go. Its purpose is to tell the Swift code generator where it can find the JSON model file for this service client, relative to project root. Example contents:

{"path":"codegen/sdk-codegen/aws-models/s3.json"}

import ArgumentParser
import Foundation
import SmithyCodegenCore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very simple code generator that:

  • Reads the Smithy JSON model file into memory.
  • Generates a Swift source file with a public variable modelCount: Int that contains the number of bytes in the model file.
  • Adds a simple doc comment to the variable.

While this example codegen is trivial and not useful in itself, it does prove that:

  • A Swift build plugin code generator can read from our model files elsewhere in the project.
  • It can generate a Swift file that is added to the target.
  • Doc comments in generated code get picked up with the rest of the target's doc comments.

Follow-on development would code-generate more substantial content from the model.


import struct Foundation.Data
import struct Foundation.URL

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this type does right now is record the number of bytes in the model file. In the future it would read the model into an in-memory tree for use during code generation.

dependencies: {
var dependencies: [Package.Dependency] = [
.package(url: "https://github.com/awslabs/aws-crt-swift.git", exact: "0.54.2"),
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swift-argument-parser is added as a dependency because the SmithyCodegenCLI target is essentially a command-line tool, and argument-parser makes the API for that tool easier to manage & use.

aws-crt-swift already imports this dependency so the effect on customers' dependencies at compile time is zero add.

.library(name: "SmithyCBOR", targets: ["SmithyCBOR"]),
.library(name: "SmithyWaitersAPI", targets: ["SmithyWaitersAPI"]),
.library(name: "SmithyTestUtil", targets: ["SmithyTestUtil"]),
.plugin(name: "SmithyCodeGenerator", targets: ["SmithyCodeGenerator"]),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SmithyCodeGenerator plugin is exported so that service clients in aws-sdk-swift can add it to their target definitions.

),
.target(
name: "SmithyCodegenCore"
),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 targets are added above:

  • SmithyCodeGenerator which is the build plugin that directs code generation at build time.
  • SmithyCodegenCLI which is the executable that performs code generation.
  • SmithyCodegenCore which contains components for reading the Smithy model. In the future it will provide features comparable to existing Smithy codegen.


LOGGER.info("Generating Smithy model file info")
SmithyModelFileInfoGenerator(ctx).writeSmithyModelFileInfo()

Copy link
Contributor Author

@jbelkins jbelkins Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initiates generation of the smithy-model-info.json file.

import class Foundation.JSONDecoder
import struct Foundation.URL
import PackagePlugin

Copy link
Contributor Author

@jbelkins jbelkins Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type implements the Swift build tool plugin.

Essentially, all the build plugin does is:

  • Receives a list of all files in this target, and a "working directory" it can write its output to.
  • Iterates over the files to decide what executable tool(s) to run on each of them.
    • All source files except for smithy-model-info.json are ignored & no action is taken on them.
    • smithy-model-info.json is read to get the model file location, then the code generator SmithyCodegenCLI is run with the model as the input.
  • Code-generated Swift files are written to the working directory, and after the build plugin finishes all its work, the Swift compiler compiles generated Swift files along with the rest of the target.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant