In modern Swift development, code generation is an essential technique for reducing boilerplate and improving code maintainability. Developers have a range of tools at their disposal to automate repetitive tasks, making their workows more efficient and their codebases easier to manage.
Among these tools, Swift Macros and Sourcery stand out as two popular options for generating code automatically. But how do they differ, and which one is best suited to your project? In this post, we’ll dive into both, compare their strengths, and help you determine which solution aligns with your development goals.
What Are Swift Macros?
Swift Macros are a new feature introduced in Swift 5.9, designed to perform compile time code generation. They allow developers to inject custom code into their projects by leveraging the Swift compiler’s internal mechanisms.
Use Cases for Swift Macros
Boilerplate reduction: Automatically conform to protocols like Codable or Equatable without manually implementing methods.
Compile time validation: Perform static checks and generate code based on compile time conditions.
Custom attribute handling: Add annotations to properties or methods and generate related code.
Advantages of Swift Macros
Integrated into the Swift compiler: No need to congure external tools or dependencies.
Typesafe and context aware: Macros have direct access to the compiler’s type system, reducing the risk of errors.
No additional dependencies: Built directly into the language, simplifying project setup and maintenance.
Limitations of Swift Macros
Swift version requirement: Only available in Swift 5.9 or later, limiting adoption in projects that support older versions.
Extensions: Currently no support for type extensions, Swift Macros omit them entirely.
New technology: As a relatively new feature, community adoption, third party support, and documentation are still evolving.
What Is Sourcery?
Sourcery is a third party metaprogramming tool that has been a staple of the Swift ecosystem for years. It reads your source code, processes custom annotations, and generates new code based on predefined templates.
Sourcery scans your Swift files for annotations and structural elements (e.g., classes, structs, protocols, extensions). It applies custom templates to generate code based on the parsed information. The generated code is written to specic files and integrated into your project.
Use Cases for Sourcery
Mock object generation: Automatically create mocks for unit tests.
Protocol conformance: Generate implementations for protocols like Codable or Equatable.
Custom logic: Create complex, reusable code structures using custom templates.
Advantages of Sourcery
Works with older Swift versions: Compatible with a wide range of Swift versions, making it a reliable choice for legacy projects.
Highly customisable: Developers can create and modify templates to fit specic project needs.
Large community and ecosystem: Extensive documentation, plugins, and community support are available.
Limitations of Sourcery
Requires setup and maintenance: Templates need to be created, and maintained alongside the project.
Not integrated into the toolchain: It operates as a separate tool, which can introduce additional build steps and complexity.
Choosing the Right Tool for Your Project
Swift Macros and Sourcery both offer powerful solutions for automating code generation, but their strengths lie in different areas, making the choice highly dependent on your project’s unique needs. Swift Macros excel in projects where simplicity, type safety, and native integration are top priorities. They are ideal for teams that value minimal setup and seamless integration with the Swift compiler. If your project involves standardised tasks like protocol conformances, attribute annotations, or compile time validations, Swift Macros offer a clean, efficient solution with immediate feedback during compilation. Moreover, the lack of external dependencies reduces maintenance overhead, making it easier to ensure consistency across teams, especially in environments where type safety and code correctness are critical.
However, their limited customisability and compatibility with only the latest Swift versions may pose challenges for more complex or legacy projects. If your project requires advanced code generation, such as creating dynamic data models, test mocks, or supporting multilayered architectures, Swift Macros may feel restrictive.
This is where Sourcery shines. As a mature, highly customisable tool, it allows developers to tailor templates for even the most intricate code generation needs. Sourcery’s exibility makes it particularly well suited for projects with diverse or evolving requirements, where boilerplate extends beyond simple protocol conformance. Additionally, Sourcery’s compatibility with older Swift versions ensures it remains a viable option for teams managing legacy codebases or working across multiple Swift versions.
When expanded with Sourcery Pro, it becomes even more powerful, adding features like enhanced template management and powerful template debugging, which streamline the development process. These capabilities make it easier to incorporate Sourcery into your workflow, reducing the time spent on troubleshooting and refining templates. This not only boosts productivity but also simplies the process of maintaining and scaling large codebases over time, making it a compelling choice for teams working on complex or longterm projects.
Ultimately, the decision comes down to your project’s specic demands. If you need a lightweight, compiler integrated solution for straightforward tasks, Swift Macros may be the best fit. But if your project requires flexibility, advanced customisation, and broad compatibility, Sourcery with its robust templating system and enhanced features through Sourcery Pro can offer the depth and adaptability you need. By understanding the strengths and limitations of both tools and considering factors like project complexity, and longterm maintenance, you can make a more informed decision that aligns with your development goals.
In many cases, experimenting with both tools can provide valuable insights and even highlight opportunities to use them together leveraging Swift Macros for simple, compile time tasks and Sourcery for more complex, template driven solutions.
Further Reading