Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f10c6a3a0 | |||
| c7cd649aab | |||
| 8201f7778b | |||
| 504393c3e3 |
+9
-1
@@ -33,9 +33,13 @@ let package = Package(
|
||||
dependencies: ["XCRemoteCache"]
|
||||
),
|
||||
.target(
|
||||
name: "xclibtool",
|
||||
name: "xclibtoolSupport",
|
||||
dependencies: ["XCRemoteCache"]
|
||||
),
|
||||
.target(
|
||||
name: "xclibtool",
|
||||
dependencies: ["XCRemoteCache", "xclibtoolSupport"]
|
||||
),
|
||||
.target(
|
||||
name: "xcpostbuild",
|
||||
dependencies: ["XCRemoteCache"]
|
||||
@@ -65,5 +69,9 @@ let package = Package(
|
||||
dependencies: ["XCRemoteCache"],
|
||||
resources: [.copy("TestData")]
|
||||
),
|
||||
.testTarget(
|
||||
name: "xclibtoolSupportTests",
|
||||
dependencies: ["xclibtoolSupport"]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
import Foundation
|
||||
|
||||
/// Represents a mode that libtool was called
|
||||
public enum XCLibtoolMode {
|
||||
public enum XCLibtoolMode: Equatable {
|
||||
/// Creating a static library (ar format) from a set of .o input files
|
||||
case createLibrary(output: String, filelist: String, dependencyInfo: String)
|
||||
/// Creating a universal library (multiple-architectures) from a set of input .a static libraries
|
||||
|
||||
@@ -18,53 +18,24 @@
|
||||
// under the License.
|
||||
|
||||
import Foundation
|
||||
import xclibtoolSupport
|
||||
import XCRemoteCache
|
||||
|
||||
public enum XCLibtoolMainError: Error {
|
||||
case missingOutput
|
||||
case unsupportedMode
|
||||
}
|
||||
|
||||
/// Wrapper for a `libtool` program that copies the build executable (e.g. .a) from a cached-downloaded location
|
||||
/// Fallbacks to a standard `libtool` when the Ramote cache is not applicable (e.g. modified sources)
|
||||
public class XCLibtoolMain {
|
||||
public init() { }
|
||||
|
||||
public func main() {
|
||||
let args = ProcessInfo().arguments
|
||||
var output: String?
|
||||
// all input arguments library '.a'. Used to create an universal binary
|
||||
var inputLibraries: [String] = []
|
||||
var filelist: String?
|
||||
var dependencyInfo: String?
|
||||
var i = 0
|
||||
while i < args.count {
|
||||
switch args[i] {
|
||||
case "-o":
|
||||
output = args[i + 1]
|
||||
i += 1
|
||||
case "-filelist":
|
||||
filelist = args[i + 1]
|
||||
i += 1
|
||||
case "-dependency_info":
|
||||
dependencyInfo = args[i + 1]
|
||||
i += 1
|
||||
case let input where input.hasSuffix(".a"):
|
||||
inputLibraries.append(input)
|
||||
default:
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
guard let outputInput = output else {
|
||||
exit(1, "Missing 'output' argument. Args: \(args)")
|
||||
}
|
||||
|
||||
let mode: XCLibtoolMode
|
||||
if let filelistInput = filelist, let dependencyInfoInput = dependencyInfo {
|
||||
// libtool is creating a library
|
||||
mode = .createLibrary(output: outputInput, filelist: filelistInput, dependencyInfo: dependencyInfoInput)
|
||||
} else if !inputLibraries.isEmpty {
|
||||
// multiple input libraries suggest creating an universal binary
|
||||
mode = .createUniversalBinary(output: outputInput, inputs: inputLibraries)
|
||||
} else {
|
||||
// unknown mode
|
||||
exit(1, "Unsupported mode. Args: \(args)")
|
||||
}
|
||||
do {
|
||||
let mode = try XCLibtoolHelper.buildMode(args: args)
|
||||
try XCLibtool(mode).run()
|
||||
} catch {
|
||||
exit(1, "Failed with: \(error). Args: \(args)")
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2023 Spotify AB.
|
||||
//
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
import Foundation
|
||||
import XCRemoteCache
|
||||
|
||||
public enum XCLibtoolHelperError: Error {
|
||||
case missingOutput
|
||||
case unsupportedMode
|
||||
}
|
||||
|
||||
public class XCLibtoolHelper {
|
||||
public static func buildMode(args: [String]) throws -> XCLibtoolMode {
|
||||
var output: String?
|
||||
// all input arguments are '*.a' or no path extension. Used to create an universal binary
|
||||
var inputLibraries: [String] = []
|
||||
var filelist: String?
|
||||
var dependencyInfo: String?
|
||||
var i = 0
|
||||
while i < args.count {
|
||||
switch args[i] {
|
||||
case "-o":
|
||||
output = args[i + 1]
|
||||
i += 1
|
||||
case "-filelist":
|
||||
filelist = args[i + 1]
|
||||
i += 1
|
||||
case "-dependency_info":
|
||||
dependencyInfo = args[i + 1]
|
||||
i += 1
|
||||
case let input where ["", "a"].contains(URL(string: args[i])?.pathExtension):
|
||||
// Support for static frameworks (no extension) and static libraries (.a)
|
||||
inputLibraries.append(input)
|
||||
default:
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
guard let outputInput = output else {
|
||||
throw XCLibtoolHelperError.missingOutput
|
||||
}
|
||||
|
||||
let mode: XCLibtoolMode
|
||||
if let filelistInput = filelist, let dependencyInfoInput = dependencyInfo {
|
||||
// libtool is creating a library
|
||||
mode = .createLibrary(output: outputInput, filelist: filelistInput, dependencyInfo: dependencyInfoInput)
|
||||
} else if !inputLibraries.isEmpty {
|
||||
// multiple input libraries suggest creating an universal binary
|
||||
mode = .createUniversalBinary(output: outputInput, inputs: inputLibraries)
|
||||
} else {
|
||||
// unknown mode
|
||||
throw XCLibtoolHelperError.unsupportedMode
|
||||
}
|
||||
return mode
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2023 Spotify AB.
|
||||
//
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you 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.
|
||||
|
||||
@testable import xclibtoolSupport
|
||||
import XCTest
|
||||
|
||||
class XCLibtoolHelperTests: XCTestCase {
|
||||
func testStaticFrameworkUniversalBinary() throws {
|
||||
let mode = try XCLibtoolHelper.buildMode(
|
||||
args: ["-o", "/universal/static", "/arch1/static", "arch2/static"]
|
||||
)
|
||||
|
||||
XCTAssertEqual(mode, .createUniversalBinary(
|
||||
output: "/universal/static",
|
||||
inputs: ["/arch1/static", "arch2/static"]
|
||||
))
|
||||
}
|
||||
|
||||
func testStaticLibraryUniversalBinary() throws {
|
||||
let mode = try XCLibtoolHelper.buildMode(
|
||||
args: ["-o", "/universal/static.a", "/arch1/static.a", "arch2/static.a"]
|
||||
)
|
||||
|
||||
XCTAssertEqual(mode, .createUniversalBinary(
|
||||
output: "/universal/static.a",
|
||||
inputs: ["/arch1/static.a", "arch2/static.a"]
|
||||
))
|
||||
}
|
||||
|
||||
func testUnknownExtensionInputThrowsUnsupportedMode() throws {
|
||||
XCTAssertThrowsError(
|
||||
try XCLibtoolHelper.buildMode(args: ["-o", "/universal/static.a", "/arch1/static.unknown"])) { error in
|
||||
switch error {
|
||||
case XCLibtoolHelperError.unsupportedMode: break
|
||||
default:
|
||||
XCTFail("Not expected error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testMissingOutputThrowsMissingOutput() throws {
|
||||
XCTAssertThrowsError(try XCLibtoolHelper.buildMode(args: ["/arch1/static"])) { error in
|
||||
switch error {
|
||||
case XCLibtoolHelperError.missingOutput: break
|
||||
default:
|
||||
XCTFail("Not expected error")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
36201A2A2843B3D3002FF70F /* MixedTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36201A292843B3D3002FF70F /* MixedTarget.swift */; };
|
||||
36201A362843B435002FF70F /* libMixedTarget.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 36201A272843B3D3002FF70F /* libMixedTarget.a */; };
|
||||
36201A392843BDDC002FF70F /* StandaloneObjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 36201A382843BDDC002FF70F /* StandaloneObjc.m */; };
|
||||
4EE6CF4929B6C1A000AEE1B4 /* StaticFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 4EE6CF4829B6C1A000AEE1B4 /* StaticFramework.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4EE6CF5329B6C1AF00AEE1B4 /* StaticFrameworkFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EE6CF5229B6C1AF00AEE1B4 /* StaticFrameworkFile.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -38,6 +40,16 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
4EE6CF4E29B6C1A000AEE1B4 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -55,6 +67,12 @@
|
||||
36201A302843B414002FF70F /* SomeObjC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SomeObjC.h; sourceTree = "<group>"; };
|
||||
36201A372843BDDC002FF70F /* StandaloneObjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StandaloneObjc.h; sourceTree = "<group>"; };
|
||||
36201A382843BDDC002FF70F /* StandaloneObjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StandaloneObjc.m; sourceTree = "<group>"; };
|
||||
4E628CA229B8066500AF2DB0 /* SandaloneWatchAppExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SandaloneWatchAppExtension.swift; sourceTree = "<group>"; };
|
||||
4E628CA429B8066500AF2DB0 /* SandaloneWatchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SandaloneWatchApp.swift; sourceTree = "<group>"; };
|
||||
4E628CA629B8066500AF2DB0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
4EE6CF4629B6C1A000AEE1B4 /* StaticFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StaticFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4EE6CF4829B6C1A000AEE1B4 /* StaticFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StaticFramework.h; sourceTree = "<group>"; };
|
||||
4EE6CF5229B6C1AF00AEE1B4 /* StaticFrameworkFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StaticFrameworkFile.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -73,6 +91,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
4EE6CF4329B6C1A000AEE1B4 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@@ -81,6 +106,8 @@
|
||||
children = (
|
||||
36201A0E2843B3C3002FF70F /* StandaloneApp */,
|
||||
36201A282843B3D3002FF70F /* MixedTarget */,
|
||||
4EE6CF4729B6C1A000AEE1B4 /* StaticFramework */,
|
||||
4E628CA129B8066500AF2DB0 /* SandaloneWatchApp */,
|
||||
36201A0D2843B3C3002FF70F /* Products */,
|
||||
36201A352843B435002FF70F /* Frameworks */,
|
||||
);
|
||||
@@ -91,6 +118,7 @@
|
||||
children = (
|
||||
36201A0C2843B3C3002FF70F /* StandaloneApp.app */,
|
||||
36201A272843B3D3002FF70F /* libMixedTarget.a */,
|
||||
4EE6CF4629B6C1A000AEE1B4 /* StaticFramework.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -128,8 +156,38 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4E628CA129B8066500AF2DB0 /* SandaloneWatchApp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4E628CA229B8066500AF2DB0 /* SandaloneWatchAppExtension.swift */,
|
||||
4E628CA429B8066500AF2DB0 /* SandaloneWatchApp.swift */,
|
||||
4E628CA629B8066500AF2DB0 /* Info.plist */,
|
||||
);
|
||||
path = SandaloneWatchApp;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4EE6CF4729B6C1A000AEE1B4 /* StaticFramework */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4EE6CF5229B6C1AF00AEE1B4 /* StaticFrameworkFile.swift */,
|
||||
4EE6CF4829B6C1A000AEE1B4 /* StaticFramework.h */,
|
||||
);
|
||||
path = StaticFramework;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
4EE6CF4129B6C1A000AEE1B4 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4EE6CF4929B6C1A000AEE1B4 /* StaticFramework.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
36201A0B2843B3C3002FF70F /* StandaloneApp */ = {
|
||||
isa = PBXNativeTarget;
|
||||
@@ -138,6 +196,7 @@
|
||||
36201A082843B3C3002FF70F /* Sources */,
|
||||
36201A092843B3C3002FF70F /* Frameworks */,
|
||||
36201A0A2843B3C3002FF70F /* Resources */,
|
||||
4EE6CF4E29B6C1A000AEE1B4 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -167,6 +226,24 @@
|
||||
productReference = 36201A272843B3D3002FF70F /* libMixedTarget.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
4EE6CF4529B6C1A000AEE1B4 /* StaticFramework */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 4EE6CF5129B6C1A000AEE1B4 /* Build configuration list for PBXNativeTarget "StaticFramework" */;
|
||||
buildPhases = (
|
||||
4EE6CF4129B6C1A000AEE1B4 /* Headers */,
|
||||
4EE6CF4229B6C1A000AEE1B4 /* Sources */,
|
||||
4EE6CF4329B6C1A000AEE1B4 /* Frameworks */,
|
||||
4EE6CF4429B6C1A000AEE1B4 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = StaticFramework;
|
||||
productName = StaticFramework;
|
||||
productReference = 4EE6CF4629B6C1A000AEE1B4 /* StaticFramework.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@@ -174,7 +251,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1320;
|
||||
LastSwiftUpdateCheck = 1420;
|
||||
LastUpgradeCheck = 1320;
|
||||
TargetAttributes = {
|
||||
36201A0B2843B3C3002FF70F = {
|
||||
@@ -185,6 +262,10 @@
|
||||
CreatedOnToolsVersion = 13.2.1;
|
||||
LastSwiftMigration = 1320;
|
||||
};
|
||||
4EE6CF4529B6C1A000AEE1B4 = {
|
||||
CreatedOnToolsVersion = 14.2;
|
||||
LastSwiftMigration = 1420;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 36201A072843B3C3002FF70F /* Build configuration list for PBXProject "StandaloneApp" */;
|
||||
@@ -202,6 +283,7 @@
|
||||
targets = (
|
||||
36201A0B2843B3C3002FF70F /* StandaloneApp */,
|
||||
36201A262843B3D3002FF70F /* MixedTarget */,
|
||||
4EE6CF4529B6C1A000AEE1B4 /* StaticFramework */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -217,6 +299,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
4EE6CF4429B6C1A000AEE1B4 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
@@ -264,6 +353,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
4EE6CF4229B6C1A000AEE1B4 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4EE6CF5329B6C1AF00AEE1B4 /* StaticFrameworkFile.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
@@ -413,6 +510,7 @@
|
||||
36201A212843B3C7002FF70F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -443,6 +541,7 @@
|
||||
36201A222843B3C7002FF70F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -508,6 +607,79 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
4EE6CF4F29B6C1A000AEE1B4 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MARKETING_VERSION = 1.0;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.StaticFramework;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4EE6CF5029B6C1A000AEE1B4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MARKETING_VERSION = 1.0;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.squareup.StaticFramework;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@@ -538,6 +710,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4EE6CF5129B6C1A000AEE1B4 /* Build configuration list for PBXNativeTarget "StaticFramework" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4EE6CF4F29B6C1A000AEE1B4 /* Debug */,
|
||||
4EE6CF5029B6C1A000AEE1B4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 36201A042843B3C3002FF70F /* Project object */;
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1420"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4EE6CF4529B6C1A000AEE1B4"
|
||||
BuildableName = "StaticFramework.framework"
|
||||
BlueprintName = "StaticFramework"
|
||||
ReferencedContainer = "container:StandaloneApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "4EE6CF4529B6C1A000AEE1B4"
|
||||
BuildableName = "StaticFramework.framework"
|
||||
BlueprintName = "StaticFramework"
|
||||
ReferencedContainer = "container:StandaloneApp.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for StaticFramework.
|
||||
FOUNDATION_EXPORT double StaticFrameworkVersionNumber;
|
||||
|
||||
//! Project version string for StaticFramework.
|
||||
FOUNDATION_EXPORT const unsigned char StaticFrameworkVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <StaticFramework/PublicHeader.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import Foundation
|
||||
|
||||
public class SomeClass {
|
||||
public init() {}
|
||||
}
|
||||
+18
-15
@@ -15,7 +15,7 @@ namespace :e2e do
|
||||
NGINX_ROOT_DIR = '/tmp/cache'
|
||||
XCRC_BINARIES = 'XCRC'
|
||||
SHARED_COCOAPODS_CONFIG = {
|
||||
'cache_addresses' => ['http://localhost:8080/cache/pods'],
|
||||
'cache_addresses' => ['http://localhost:8080/cache/pods'],
|
||||
'primary_repo' => GIT_REMOTE_ADDRESS,
|
||||
'primary_branch' => GIT_BRANCH,
|
||||
'mode' => 'consumer',
|
||||
@@ -58,6 +58,7 @@ namespace :e2e do
|
||||
system("pwd")
|
||||
system("#{XCRC_BINARIES}/xcprepare integrate --input StandaloneApp.xcodeproj --mode producer --final-producer-target StandaloneApp")
|
||||
# Build the project to fill in the cache
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StaticFramework', 'watch', 'watchOS')
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StandaloneApp')
|
||||
system("#{XCRC_BINARIES}/xcprepare stats --reset --format json")
|
||||
end
|
||||
@@ -73,13 +74,15 @@ namespace :e2e do
|
||||
prepare_for_standalone(consumer_srcroot)
|
||||
Dir.chdir(consumer_srcroot) do
|
||||
system("#{XCRC_BINARIES}/xcprepare integrate --input StandaloneApp.xcodeproj --mode consumer")
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StandaloneApp', {'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer"})
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StaticFramework', 'watch', 'watchOS', {'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer"})
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StandaloneApp', 'iphone', 'iOS', {'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer"})
|
||||
valide_hit_rate
|
||||
|
||||
puts 'Building standalone consumer with local change...'
|
||||
# Extra: validate local compilation of the Standalone ObjC code
|
||||
system("echo '' >> StandaloneApp/StandaloneObjc.m")
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StandaloneApp', {'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer_local"})
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StaticFramework', 'watch', 'watchOS', {'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer_local"})
|
||||
build_project(nil, "StandaloneApp.xcodeproj", 'StandaloneApp', 'iphone', 'iOS', {'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer_local"})
|
||||
end
|
||||
|
||||
# Revert all side effects
|
||||
@@ -103,7 +106,7 @@ namespace :e2e do
|
||||
at_exit { puts('resetting ngingx'); system('nginx -s stop') }
|
||||
end
|
||||
|
||||
# Create a new branch out of a current commit and
|
||||
# Create a new branch out of a current commit and
|
||||
# add remote that points to itself
|
||||
def self.configure_git
|
||||
system("git checkout -B #{GIT_BRANCH}")
|
||||
@@ -144,7 +147,7 @@ namespace :e2e do
|
||||
def self.cocoapods_configuration_string(extra_configs = {})
|
||||
configuration_lines = ['xcremotecache({']
|
||||
all_properties = SHARED_COCOAPODS_CONFIG.merge(extra_configs)
|
||||
config_lines = all_properties.map {|key, value| " \"#{key}\" => #{value.inspect},"}
|
||||
config_lines = all_properties.map {|key, value| " \"#{key}\" => #{value.inspect},"}
|
||||
configuration_lines.push(*config_lines)
|
||||
configuration_lines << '})'
|
||||
configuration_lines.join("\n")
|
||||
@@ -159,20 +162,20 @@ namespace :e2e do
|
||||
end
|
||||
end
|
||||
|
||||
def self.build_project(workspace, project, scheme, extra_args = {})
|
||||
def self.build_project(workspace, project, scheme, sdk = 'iphone', platform = 'iOS', extra_args = {})
|
||||
xcodebuild_args = {
|
||||
'workspace' => workspace,
|
||||
'project' => project,
|
||||
'scheme' => scheme,
|
||||
'configuration' => 'Debug',
|
||||
'sdk' => 'iphonesimulator',
|
||||
'destination' => 'generic/platform=iOS Simulator',
|
||||
'sdk' => "#{sdk}simulator",
|
||||
'destination' => "generic/platform=#{platform} Simulator",
|
||||
'derivedDataPath' => DERIVED_DATA_PATH,
|
||||
}.merge(extra_args).compact
|
||||
xcodebuild_vars = {
|
||||
'EXCLUDED_ARCHS' => 'arm64 i386'
|
||||
'EXCLUDED_ARCHS' => 'arm64'
|
||||
}
|
||||
args = ['xcodebuild']
|
||||
args = ['set -o pipefail;', 'xcodebuild']
|
||||
args.push(*xcodebuild_args.map {|k,v| "-#{k} '#{v}'"})
|
||||
args.push(*xcodebuild_vars.map {|k,v| "#{k}='#{v}'"})
|
||||
args.push('clean build')
|
||||
@@ -185,12 +188,12 @@ namespace :e2e do
|
||||
end
|
||||
end
|
||||
|
||||
def self.build_project_cocoapods(extra_args = {})
|
||||
def self.build_project_cocoapods(sdk = 'iphone', platform = 'iOS', extra_args = {})
|
||||
system('pod install')
|
||||
build_project('XCRemoteCacheSample.xcworkspace', nil, 'XCRemoteCacheSample', extra_args)
|
||||
build_project('XCRemoteCacheSample.xcworkspace', nil, 'XCRemoteCacheSample', sdk, platform, extra_args)
|
||||
end
|
||||
|
||||
def self.read_stats
|
||||
def self.read_stats
|
||||
stats_json_string = JSON.parse(`#{XCRC_BINARIES}/xcprepare stats --format json`)
|
||||
misses = stats_json_string.fetch('miss_count', 0)
|
||||
hits = stats_json_string.fetch('hit_count', 0)
|
||||
@@ -213,7 +216,7 @@ namespace :e2e do
|
||||
consumer_configuration = cocoapods_configuration_string()
|
||||
|
||||
puts("****** Scenario: #{template_path}")
|
||||
|
||||
|
||||
# Run producer build
|
||||
pre_producer_setup
|
||||
dump_podfile(producer_configuration, template_path)
|
||||
@@ -229,7 +232,7 @@ namespace :e2e do
|
||||
dump_podfile(consumer_configuration, template_path)
|
||||
puts('Building consumer ...')
|
||||
Dir.chdir(E2E_COCOAPODS_SAMPLE_DIR) do
|
||||
build_project_cocoapods({'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer"})
|
||||
build_project_cocoapods('iphone', 'iOS', {'derivedDataPath' => "#{DERIVED_DATA_PATH}_consumer"})
|
||||
valide_hit_rate
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user