Add `TokamakShim` module to simplify imports (#192)

Adding this module as a dependency, Tokamak users would only need to add a single import regardless of the platform they're targeting. Thus, instead of

```swift
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
```

a single `import TokamakShim` is enough. `TokamakShim` re-exports correct modules based on a target platform.

I've also renamed the `TokamakDemo Native` directory to `NativeDemo` for brevity.

`xcodebuild` output in the `macos_demo_build` job is now passed to `xcpretty` for more readable build logs.
This commit is contained in:
Max Desiatov 2020-07-19 20:53:27 +01:00 committed by GitHub
parent 743d9a0de8
commit 5f3822257d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 199 additions and 81 deletions

View File

@ -27,6 +27,7 @@ jobs:
set -ex
sudo xcode-select --switch /Applications/Xcode_12_beta.app/Contents/Developer/
xcodebuild -version
cd "TokamakDemo Native"
cd "NativeDemo"
xcodebuild -scheme iOS -destination 'generic/platform=iOS' \
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO | \
xcpretty --color

View File

@ -35,10 +35,42 @@
D1B4229124B3B9BB00682F74 /* ListDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B4228E24B3B9BB00682F74 /* ListDemo.swift */; };
D1B4229224B3B9BB00682F74 /* OutlineGroupDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B4228F24B3B9BB00682F74 /* OutlineGroupDemo.swift */; };
D1B4229324B3B9BB00682F74 /* OutlineGroupDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B4228F24B3B9BB00682F74 /* OutlineGroupDemo.swift */; };
D1E5FDAD24C1D57000E7485E /* TokamakShim.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1E5FDAC24C1D57000E7485E /* TokamakShim.swift */; };
D1E5FDAF24C1D58E00E7485E /* libTokamakShim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D1E5FDA424C1D54B00E7485E /* libTokamakShim.a */; };
D1E5FDB224C1D59400E7485E /* libTokamakShim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D1E5FDA424C1D54B00E7485E /* libTokamakShim.a */; };
D1EE7EA724C0DD2100C0D127 /* PickerDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1EE7EA624C0DD2100C0D127 /* PickerDemo.swift */; };
D1EE7EA824C0DD2100C0D127 /* PickerDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1EE7EA624C0DD2100C0D127 /* PickerDemo.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
D1E5FDB024C1D58E00E7485E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 85ED183E24AD37970085DFA0 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D1E5FDA324C1D54B00E7485E;
remoteInfo = TokamakShim;
};
D1E5FDB324C1D59400E7485E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 85ED183E24AD37970085DFA0 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D1E5FDA324C1D54B00E7485E;
remoteInfo = TokamakShim;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
D1E5FDA224C1D54B00E7485E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
85ED184A24AD379A0085DFA0 /* TokamakDemo Native.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TokamakDemo Native.app"; sourceTree = BUILT_PRODUCTS_DIR; };
85ED185224AD379A0085DFA0 /* TokamakDemo Native.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TokamakDemo Native.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -60,6 +92,8 @@
B56F22E224BD1C26001738DF /* GridDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridDemo.swift; sourceTree = "<group>"; };
D1B4228E24B3B9BB00682F74 /* ListDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListDemo.swift; sourceTree = "<group>"; };
D1B4228F24B3B9BB00682F74 /* OutlineGroupDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutlineGroupDemo.swift; sourceTree = "<group>"; };
D1E5FDA424C1D54B00E7485E /* libTokamakShim.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTokamakShim.a; sourceTree = BUILT_PRODUCTS_DIR; };
D1E5FDAC24C1D57000E7485E /* TokamakShim.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokamakShim.swift; sourceTree = "<group>"; };
D1EE7EA624C0DD2100C0D127 /* PickerDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerDemo.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -68,10 +102,19 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D1E5FDAF24C1D58E00E7485E /* libTokamakShim.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
85ED184F24AD379A0085DFA0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D1E5FDB224C1D59400E7485E /* libTokamakShim.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D1E5FDA124C1D54B00E7485E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
@ -84,6 +127,7 @@
85ED183D24AD37970085DFA0 = {
isa = PBXGroup;
children = (
D1E5FDAB24C1D57000E7485E /* TokamakShim */,
85ED188B24AD3CF10085DFA0 /* LaunchScreen.storyboard */,
85ED186924AD38F20085DFA0 /* UIAppDelegate.swift */,
85ED189424AD41B90085DFA0 /* NSAppDelegate.swift */,
@ -92,6 +136,7 @@
85ED18BD24AD46340085DFA0 /* Info.plist */,
85ED189924AD425E0085DFA0 /* TokamakDemo */,
85ED184B24AD379A0085DFA0 /* Products */,
D1E5FDAE24C1D58E00E7485E /* Frameworks */,
);
sourceTree = "<group>";
};
@ -100,6 +145,7 @@
children = (
85ED184A24AD379A0085DFA0 /* TokamakDemo Native.app */,
85ED185224AD379A0085DFA0 /* TokamakDemo Native.app */,
D1E5FDA424C1D54B00E7485E /* libTokamakShim.a */,
);
name = Products;
sourceTree = "<group>";
@ -125,6 +171,22 @@
path = ../Sources/TokamakDemo;
sourceTree = "<group>";
};
D1E5FDAB24C1D57000E7485E /* TokamakShim */ = {
isa = PBXGroup;
children = (
D1E5FDAC24C1D57000E7485E /* TokamakShim.swift */,
);
name = TokamakShim;
path = ../Sources/TokamakShim;
sourceTree = "<group>";
};
D1E5FDAE24C1D58E00E7485E /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -139,6 +201,7 @@
buildRules = (
);
dependencies = (
D1E5FDB124C1D58E00E7485E /* PBXTargetDependency */,
);
name = iOS;
productName = iOS;
@ -156,12 +219,30 @@
buildRules = (
);
dependencies = (
D1E5FDB424C1D59400E7485E /* PBXTargetDependency */,
);
name = macOS;
productName = macOS;
productReference = 85ED185224AD379A0085DFA0 /* TokamakDemo Native.app */;
productType = "com.apple.product-type.application";
};
D1E5FDA324C1D54B00E7485E /* TokamakShim */ = {
isa = PBXNativeTarget;
buildConfigurationList = D1E5FDA824C1D54B00E7485E /* Build configuration list for PBXNativeTarget "TokamakShim" */;
buildPhases = (
D1E5FDA024C1D54B00E7485E /* Sources */,
D1E5FDA124C1D54B00E7485E /* Frameworks */,
D1E5FDA224C1D54B00E7485E /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = TokamakShim;
productName = TokamakShim;
productReference = D1E5FDA424C1D54B00E7485E /* libTokamakShim.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -179,6 +260,9 @@
CreatedOnToolsVersion = 12.0;
LastSwiftMigration = 1200;
};
D1E5FDA324C1D54B00E7485E = {
CreatedOnToolsVersion = 12.0;
};
};
};
buildConfigurationList = 85ED184124AD37970085DFA0 /* Build configuration list for PBXProject "TokamakDemo Native" */;
@ -196,6 +280,7 @@
targets = (
85ED184924AD379A0085DFA0 /* iOS */,
85ED185124AD379A0085DFA0 /* macOS */,
D1E5FDA324C1D54B00E7485E /* TokamakShim */,
);
};
/* End PBXProject section */
@ -262,8 +347,29 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
D1E5FDA024C1D54B00E7485E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D1E5FDAD24C1D57000E7485E /* TokamakShim.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
D1E5FDB124C1D58E00E7485E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D1E5FDA324C1D54B00E7485E /* TokamakShim */;
targetProxy = D1E5FDB024C1D58E00E7485E /* PBXContainerItemProxy */;
};
D1E5FDB424C1D59400E7485E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D1E5FDA324C1D54B00E7485E /* TokamakShim */;
targetProxy = D1E5FDB324C1D59400E7485E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
85ED185C24AD379B0085DFA0 /* Debug */ = {
isa = XCBuildConfiguration;
@ -469,6 +575,35 @@
};
name = Release;
};
D1E5FDA924C1D54B00E7485E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
D1E5FDAA24C1D54B00E7485E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -499,6 +634,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D1E5FDA824C1D54B00E7485E /* Build configuration list for PBXNativeTarget "TokamakShim" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D1E5FDA924C1D54B00E7485E /* Debug */,
D1E5FDAA24C1D54B00E7485E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 85ED183E24AD37970085DFA0 /* Project object */;

View File

@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:../../Sources/TokamakDemo">
location = "self:">
</FileRef>
</Workspace>

View File

@ -1,4 +1,4 @@
// swift-tools-version:5.2
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to
// build this package.
@ -8,6 +8,7 @@ let package = Package(
name: "Tokamak",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
],
products: [
// Products define the executables and libraries produced by a package,
@ -20,6 +21,10 @@ let package = Package(
name: "TokamakDOM",
targets: ["TokamakDOM"]
),
.library(
name: "TokamakShim",
targets: ["TokamakShim"]
),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
@ -39,12 +44,16 @@ let package = Package(
),
.target(
name: "TokamakDemo",
dependencies: ["JavaScriptKit", "TokamakCore", "TokamakDOM"]
dependencies: ["JavaScriptKit", "TokamakShim"]
),
.target(
name: "TokamakDOM",
dependencies: ["JavaScriptKit", "TokamakCore"]
),
.target(
name: "TokamakShim",
dependencies: [.target(name: "TokamakDOM", condition: .when(platforms: [.wasi]))]
),
.target(
name: "TokamakTestRenderer",
dependencies: ["TokamakCore"]

View File

@ -34,14 +34,12 @@ dependencies and launch a development HTTP server. You can then open
### Example code
Tokamak API attempts to resemble SwiftUI API as much as possible. The main difference is
that you add `import TokamakDOM` instead of `import SwiftUI` in your files:
that you use `import TokamakShim` instead of `import SwiftUI` in your files. The former makes
your views compatible with Apple platforms, as well as platforms supported by Tokamak (currently
only WebAssembly/[WASI](https://wasi.dev/) with more coming in the future):
```swift
#if os(WASI)
import TokamakDOM
#else
import SwiftUI
#endif
import TokamakShim
struct Counter: View {
@State var count: Int
@ -133,10 +131,10 @@ can be formulated as these "rules":
1. If a symbol is restricted to a module and has no `public` access control, no need for an underscore.
2. If a symbol is part of a public renderer module API (e.g. `TokamakDOM`), no need for an underscore,
users may use those symbols directly, and it is re-exported from `TokamakCore` by the renderer module
via `public typealias`.
users may use those symbols directly, and it is re-exported from `TokamakCore` by the renderer module
via `public typealias`.
3. If a function or a type have `public` on them only by necessity to make them available in `TokamakDOM`,
but unavailable to users (or not intended for public use), underscore is needed to indicate that.
but unavailable to users (or not intended for public use), underscore is needed to indicate that.
The benefit of separate modules is that they allow us to provide separate renderers for different platforms.
Users can pick and choose what they want to use, e.g. purely static websites would use only `TokamakHTML`,

View File

@ -22,6 +22,7 @@ import TokamakCore
public typealias Environment = TokamakCore.Environment
public typealias EnvironmentObject = TokamakCore.EnvironmentObject
public typealias Binding = TokamakCore.Binding
public typealias ObservableObject = TokamakCore.ObservableObject
public typealias ObservedObject = TokamakCore.ObservedObject
public typealias Published = TokamakCore.Published

View File

@ -15,11 +15,7 @@
// Created by Carson Katri on 7/12/20.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
public struct ColorDemo: View {
var color: Color {

View File

@ -15,11 +15,7 @@
// Created by Max Desiatov on 14/02/2019.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
final class Count: ObservableObject {
@Published var value: Int

View File

@ -15,12 +15,7 @@
// Created by Carson Katri on 6/30/20.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import OpenCombine
import TokamakDOM
#endif
import TokamakShim
class TestEnvironment: ObservableObject {
@Published var envTest = "Hello, world!"

View File

@ -12,11 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
public struct ForEachDemo: View {
@State public var maxItem = 0

View File

@ -15,11 +15,7 @@
// Created by Carson Katri on 7/13/20.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
@available(OSX 10.16, iOS 14.0, *)
public struct GridDemo: View {

View File

@ -15,11 +15,7 @@
// Created by Carson Katri on 7/2/20.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
public struct ListDemo: View {
let fs: [File] = [

View File

@ -15,11 +15,7 @@
// Created by Carson Katri on 7/3/20.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
struct File: Identifiable {
let id: Int

View File

@ -12,11 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
struct Star: Shape {
func path(in rect: CGRect) -> Path {

View File

@ -12,11 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
struct PickerDemo: View {
var textStyles = Font.TextStyle.allCases

View File

@ -15,11 +15,7 @@
// Created by Carson Katri on 6/29/20.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
struct SpacerDemo: View {
var body: some View {

View File

@ -12,11 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
struct CustomModifier: ViewModifier {
func body(content: Content) -> some View {

View File

@ -12,12 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakCore
import TokamakDOM
#endif
import TokamakShim
struct TextFieldDemo: View {
@State var text = ""

View File

@ -15,11 +15,7 @@
// Created by Jed Fox on 07/01/2020.
//
#if canImport(SwiftUI)
import SwiftUI
#else
import TokamakDOM
#endif
import TokamakShim
struct TokamakDemoView: View {
var body: some View {

View File

@ -0,0 +1,19 @@
// Copyright 2020 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#if canImport(SwiftUI)
@_exported import SwiftUI
#elseif os(WASI)
@_exported import TokamakDOM
#endif