Type-safe DSL for SwiftPM modular architecture

Hi everyone,

While working on a modular iOS project with Swift Package Manager, I ran into a common problem: as the number of modules grows, Package.swift quickly turns into a long list of string-based dependencies.
Example:

.target(

    name: "NewsPresentation",

    dependencies: [

        "NewsDomain",

        "Core",

        "UI",

        "Resources"

    ]

)

This approach works, but it has a few downsides in larger projects:

• dependencies are string-based

• architectural rules are not enforced

• manifests grow with a lot of repetition

• refactoring module names becomes fragile

Since SwiftPM manifests are just Swift files, I experimented with using Swift itself to model the architecture.

The idea is to treat Package.swift not just as configuration, but as a declarative description of the module architecture.

For example, feature modules can be generated from a small DSL:

featureTargets(module: { .News($0) })

Which produces:

with dependency rules encoded once.

Modules and dependencies are represented using enums instead of strings:

.module(.Core)

.module(.News(.Domain))

This gives compile-time safety for dependencies and allows encoding architectural rules directly in Swift.

In my demo project this approach generates 35 modules while keeping the manifest relatively compact.

I wrote a more detailed explanation here:

I would be curious to hear feedback from others using SwiftPM at scale.

Specifically:

• Do you see drawbacks in treating Package.swift as a small DSL for architecture?

• Have you used similar approaches in larger SwiftPM projects?

• Are there better patterns for encoding architectural rules in SwiftPM?

Thanks!

2 Likes