I'm developing a design system that supports different themes.
Themes cannot be changed during runtime, so want to take advantage of that and do conditional imports.
The design system type is a generic one that looks like DS<Colors, Fonts>. This lives in the base design system target on the design system package. Then in the same package I have a separate target that depends on the base design system target for each theme that just provides the specialization of the generic type supplying its own colors and fonts.
Then I need to have a series of packages that will act as SDKs (are going to be used in the main app) that could easily be configured to be built using one theme or the other at compile time.
Ideally, how I envision this to work is main app imports the one theme it wants to use and packages are able to compile against the design system specialized type defined by that theme.
So I started to try some approaches to accomplish this on the first of these packages but with no success so far.
In MyTarget
source code which is where I want to use whatever design system is available, I do:
#if canImport(ThemeADesignSystem)
import ThemeADesignSystem
public typealias DS = ThemeADesignSystem.DS
#elseif canImport(ThemeBDesignSystem)
import ThemeBDesignSystem
public typealias DS = ThemeBDesignSystem.DS
#else
import DesignSystem
public typealias DS = DesignSystem.DS
#endif
Targets of that package are defined as
.target(
name: "MyTarget",
dependencies: [
.product(name: "DesignSystem", package: "iOSDesignSystem")
]
),
.target(
name: "MyTargetWithThemeA",
dependencies: [
.product(name: "ThemeADesignSystem", package: "iOSDesignSystem"),
.target(name: "MyTarget")
]
),
.target(
name: "MyTargetWithThemeB",
dependencies: [
.product(name: "ThemeBDesignSystem", package: "iOSDesignSystem"),
.target(name: "MyTarget")
]
)
And products for my package are static libraries built off MyTargetWithThemeA and MyTargetWithThemeB so clients can import the corresponding one matching their theme.
I was expecting that having a target the depends on MyTarget
and also on the appropriate theme product, would have made the canImport
directive to yield true at compile time and there MyTarget
is built using the corresponding design system type by that module. But it seems that's not the case.
Also wanted to mention that it would be as easy as if I could make something like
.target(
name: "MyTarget",
dependencies: [
.product(name: ProcessInfo.processInfo.environment("DESIGN_SYSTEM") ?? "DesignSystem", package: "iOSDesignSystem")
]
)
However that does not seem to be possible as environment variables seem to not be set by the time target is built.
Any ideas of why it may not be working like that and what could I do to achieve my goal?