Skip to content

Commit

Permalink
Merge pull request #6 from giginet/static-linking
Browse files Browse the repository at this point in the history
Support Static Framework
  • Loading branch information
giginet authored Oct 20, 2022
2 parents b4aacfd + 29c6548 commit 88d79ab
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 16 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ All XCFrameworks are generated into `MyAppDependencies/XCFramework` in default.
|-\-configuration, -c|Build configuration for generated frameworks (debug / release)|release|
|-\-output, -o|Path indicates a XCFrameworks output directory|$PACKAGE_ROOT/XCFrameworks|
|-\-embed-debug-symbols|Whether embed debug symbols to frameworks or not|-|
|-\--static|Whether generated frameworks are Static Frameworks or not|-|
|-\-support-simulators|Whether also building for simulators of each SDKs or not|-|
|-\-cache-policy|How to reuse built frameworks|project|

Expand Down Expand Up @@ -120,6 +121,7 @@ They are stored on `$OUTPUT_DIR/.$FRAMEWORK_NAME.version` as a JSON file.
"buildOptions" : {
"buildConfiguration" : "release",
"isDebugSymbolsEmbedded" : false,
"frameworkType" : "dynamic",
"sdks" : [
"iOS"
],
Expand Down
6 changes: 6 additions & 0 deletions Sources/ScipioKit/BuildOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ struct BuildOptions: Hashable, Codable {
var buildConfiguration: BuildConfiguration
var isSimulatorSupported: Bool
var isDebugSymbolsEmbedded: Bool
var frameworkType: FrameworkType
var sdks: [SDK]
}

Expand All @@ -19,6 +20,11 @@ public enum BuildConfiguration: String, Codable {
}
}

public enum FrameworkType: String, Codable {
case dynamic
case `static`
}

enum SDK: String, Codable {
case macOS
case macCatalyst
Expand Down
68 changes: 54 additions & 14 deletions Sources/ScipioKit/ProjectGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,34 @@ import Xcodeproj
import TSCBasic
import Basics

struct XCConfigValue {
let rawString: String
}

extension XCConfigValue: ExpressibleByBooleanLiteral {
init(booleanLiteral value: BooleanLiteralType) {
self.rawString = value ? "YES" : "NO"
}
}

extension XCConfigValue: ExpressibleByStringLiteral {
init(stringLiteral value: StringLiteralType) {
self.rawString = value
}
}

struct XCConfigEncoder {
func generate(configs: [String: XCConfigValue]) -> Data {
configs
.sorted { $0.key < $1.key }
.map { pair -> String in
"\(pair.key) = \(pair.value.rawString)"
}
.joined(separator: "\n")
.data(using: .utf8)!
}
}

struct ProjectGenerator {
private let fileSystem: any FileSystem

Expand All @@ -16,7 +44,11 @@ struct ProjectGenerator {
}

@discardableResult
func generate(for package: Package, embedDebugSymbols isDebugSymbolsEmbedded: Bool) throws -> Result {
func generate(
for package: Package,
embedDebugSymbols isDebugSymbolsEmbedded: Bool,
frameworkType: FrameworkType
) throws -> Result {
let projectPath = package.projectPath

let project = try pbxproj(
Expand All @@ -29,8 +61,14 @@ struct ProjectGenerator {
observabilityScope: observabilitySystem.topScope)

let distributionXCConfigPath = package.workspaceDirectory.appending(component: "Distribution.xcconfig")

let isStaticFramework = frameworkType == .static
let xcConfigData = makeXCConfigData(
isDebugSymbolsEmbedded: isDebugSymbolsEmbedded,
isStaticFramework: isStaticFramework
)
try fileSystem.writeFileContents(distributionXCConfigPath,
string: buildDistributionXCConfigContents(embedDebugSymbols: isDebugSymbolsEmbedded))
data: xcConfigData)

let group = createOrGetConfigsGroup(project: project)
let reference = group.addFileReference (
Expand Down Expand Up @@ -62,19 +100,21 @@ struct ProjectGenerator {
return .init(project: project, projectPath: projectPath)
}

private func buildDistributionXCConfigContents(embedDebugSymbols: Bool) -> String {
let base = """
BUILD_LIBRARY_FOR_DISTRIBUTION = YES
ENABLE_BITCODE = YES
OTHER_CFLAGS = -fembed-bitcode
"""
if embedDebugSymbols {
let debugSymbol = """
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
"""
return [base, debugSymbol].joined(separator: "\n")
private func makeXCConfigData(isDebugSymbolsEmbedded: Bool, isStaticFramework: Bool) -> Data {
var configs: [String: XCConfigValue] = [
"BUILD_LIBRARY_FOR_DISTRIBUTION": true,
]

if isDebugSymbolsEmbedded {
configs["DEBUG_INFORMATION_FORMAT"] = "dwarf-with-dsym"
}

if isStaticFramework {
configs["MACH_O_TYPE"] = "staticlib"
}
return base

let encoder = XCConfigEncoder()
return encoder.generate(configs: configs)
}

private var infoPlist: String {
Expand Down
9 changes: 7 additions & 2 deletions Sources/ScipioKit/Runner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ public struct Runner {
}

public struct Options {
public init(buildConfiguration: BuildConfiguration, isSimulatorSupported: Bool, isDebugSymbolsEmbedded: Bool, outputDirectory: URL? = nil, cacheMode: CacheMode, verbose: Bool) {
public init(buildConfiguration: BuildConfiguration, isSimulatorSupported: Bool, isDebugSymbolsEmbedded: Bool, frameworkType: FrameworkType, outputDirectory: URL? = nil, cacheMode: CacheMode, verbose: Bool) {
self.buildConfiguration = buildConfiguration
self.isSimulatorSupported = isSimulatorSupported
self.isDebugSymbolsEmbedded = isDebugSymbolsEmbedded
self.frameworkType = frameworkType
self.outputDirectory = outputDirectory
self.cacheMode = cacheMode
self.verbose = verbose
Expand All @@ -45,6 +46,7 @@ public struct Runner {
public var buildConfiguration: BuildConfiguration
public var isSimulatorSupported: Bool
public var isDebugSymbolsEmbedded: Bool
public var frameworkType: FrameworkType
public var outputDirectory: URL?
public var cacheMode: CacheMode
public var verbose: Bool
Expand Down Expand Up @@ -121,14 +123,17 @@ public struct Runner {
let buildOptions = BuildOptions(buildConfiguration: options.buildConfiguration,
isSimulatorSupported: options.isSimulatorSupported,
isDebugSymbolsEmbedded: options.isDebugSymbolsEmbedded,
frameworkType: options.frameworkType,
sdks: sdks)
try fileSystem.createDirectory(package.workspaceDirectory, recursive: true)

let resolver = Resolver(package: package)
try await resolver.resolve()

let generator = ProjectGenerator()
try generator.generate(for: package, embedDebugSymbols: buildOptions.isDebugSymbolsEmbedded)
try generator.generate(for: package,
embedDebugSymbols: buildOptions.isDebugSymbolsEmbedded,
frameworkType: buildOptions.frameworkType)

let outputDir = frameworkOutputDir.resolve(packageDirectory: packageDirectory)

Expand Down
1 change: 1 addition & 0 deletions Sources/scipio/CreateCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ extension Scipio {
buildConfiguration: buildOptions.buildConfiguration,
isSimulatorSupported: buildOptions.supportSimulators,
isDebugSymbolsEmbedded: buildOptions.embedDebugSymbols,
frameworkType: buildOptions.frameworkType,
cacheMode: .disabled,
verbose: globalOptions.verbose)
)
Expand Down
10 changes: 10 additions & 0 deletions Sources/scipio/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,14 @@ struct BuildOptionGroup: ParsableArguments {
@Flag(name: .customLong("support-simulators"),
help: "Whether also building for simulators of each SDKs or not.")
var supportSimulators = false

@Flag(name: [.customLong("static")],
help: "Whether generated frameworks are Static Frameworks or not")
var shouldBuildStaticFramework = false
}

extension BuildOptionGroup {
var frameworkType: FrameworkType {
shouldBuildStaticFramework ? .static : .dynamic
}
}
1 change: 1 addition & 0 deletions Sources/scipio/PrepareCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ extension Scipio {
buildConfiguration: buildOptions.buildConfiguration,
isSimulatorSupported: buildOptions.supportSimulators,
isDebugSymbolsEmbedded: buildOptions.embedDebugSymbols,
frameworkType: buildOptions.frameworkType,
cacheMode: runnerCacheMode,
verbose: globalOptions.verbose)
)
Expand Down
2 changes: 2 additions & 0 deletions Tests/ScipioKitTests/CacheSystemTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault
buildOptions: .init(buildConfiguration: .release,
isSimulatorSupported: false,
isDebugSymbolsEmbedded: false,
frameworkType: .dynamic,
sdks: [.iOS]),
clangVersion: "clang-1400.0.29.102")
let encoder = JSONEncoder()
Expand All @@ -38,6 +39,7 @@ InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault
"buildOptions" : {
"buildConfiguration" : "release",
"isDebugSymbolsEmbedded" : false,
"frameworkType" : "dynamic",
"sdks" : [
"iOS"
],
Expand Down
4 changes: 4 additions & 0 deletions Tests/ScipioKitTests/PrepareTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ final class PrepareTests: XCTestCase {
buildConfiguration: .release,
isSimulatorSupported: false,
isDebugSymbolsEmbedded: false,
frameworkType: .dynamic,
cacheMode: .disabled,
verbose: true))
do {
Expand Down Expand Up @@ -65,6 +66,7 @@ final class PrepareTests: XCTestCase {
buildOptions: .init(buildConfiguration: .release,
isSimulatorSupported: false,
isDebugSymbolsEmbedded: false,
frameworkType: .dynamic,
sdks: [.iOS]),
outputDirectory: frameworkOutputDir,
storage: nil)
Expand All @@ -87,6 +89,7 @@ final class PrepareTests: XCTestCase {
buildConfiguration: .release,
isSimulatorSupported: false,
isDebugSymbolsEmbedded: false,
frameworkType: .dynamic,
cacheMode: .project,
verbose: false)
)
Expand Down Expand Up @@ -126,6 +129,7 @@ final class PrepareTests: XCTestCase {
buildConfiguration: .release,
isSimulatorSupported: false,
isDebugSymbolsEmbedded: false,
frameworkType: .dynamic,
cacheMode: .storage(storage),
verbose: false)
)
Expand Down
21 changes: 21 additions & 0 deletions Tests/ScipioKitTests/XCConfigEncoderTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Foundation
@testable import ScipioKit
import XCTest

final class XCConfigEncoderTests: XCTestCase {
func testEncode() {
let encoder = XCConfigEncoder()
let configs: [String: XCConfigValue] = [
"MACH_O_TYPE": "staticlib",
"BUILD_LIBRARY_FOR_DISTRIBUTION": true,
]
let data = encoder.generate(configs: configs)
XCTAssertEqual(
String(data: data, encoding: .utf8),
"""
BUILD_LIBRARY_FOR_DISTRIBUTION = YES
MACH_O_TYPE = staticlib
"""
)
}
}

0 comments on commit 88d79ab

Please sign in to comment.