Compare commits

..

16 Commits

Author SHA1 Message Date
Bartosz Polaczyk 2f10c6a3a0 Merge pull request #185 from polac24/bartosz/20230306-watch-library
Support universal binary framework
2023-03-08 15:21:10 -05:00
Bartosz Polaczyk c7cd649aab Fix formatting 2023-03-08 06:02:24 -05:00
Bartosz Polaczyk 8201f7778b Fix for static frameworks 2023-03-08 05:33:39 -05:00
Bartosz Polaczyk 504393c3e3 Bundle optional private.swiftinterface 2023-03-08 05:29:02 -05:00
Aleksander Grzyb 82334dda04 Merge pull request #181 from polac24/lddplus-automatic
Add LDPLUSPLUS in automatic integration mode
2023-01-09 09:24:34 +01:00
Bartosz Polaczyk 1072979479 Fix formatting 2023-01-08 10:14:38 -08:00
Bartosz Polaczyk d741b3f6df Add unit tests 2023-01-08 09:59:44 -08:00
Bartosz Polaczyk a0f20b4da3 Add LDPLUSPLUS in automatic mode 2023-01-08 09:53:03 -08:00
Aleksander Grzyb f325b74796 Merge pull request #177 from polac24/pch-c-header
Compile locally PCH for c-header
2023-01-06 06:40:12 +01:00
Aleksander Grzyb a50eae615c Merge pull request #178 from polac24/xcode-1420
Switch to Xcode 14.2
2023-01-02 10:46:23 +01:00
Bartosz Polaczyk 3c8f062e95 Remove whitespaces 2022-12-30 10:59:16 -08:00
Bartosz Polaczyk 1cf685e197 Switch to Xcode 14.2 2022-12-30 10:57:49 -08:00
Bartosz Polaczyk d2ba874079 Compile locally PCH for c-header 2022-12-30 10:52:11 -08:00
Bartosz Polaczyk b439674378 Merge pull request #164 from polac24/20220831-optional-public-headers-folder
Make PUBLIC_HEADERS_FOLDER_PATH ENV optional
2022-11-24 05:27:57 +01:00
Bartosz Polaczyk b1507b6e60 Fix linting 2022-08-31 13:42:30 +02:00
Bartosz Polaczyk c76c8a7672 Make PUBLIC_HEADERS_FOLDER_PATH optional 2022-08-31 13:22:13 +02:00
19 changed files with 480 additions and 64 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
macOS:
runs-on: macos-12
env:
XCODE_VERSION: ${{ '13.3.1' }}
XCODE_VERSION: ${{ '14.2' }}
steps:
- name: Select Xcode
run: "sudo xcode-select -s /Applications/Xcode_$XCODE_VERSION.app"
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
docs:
runs-on: macos-12
env:
XCODE_VERSION: ${{ '13.3.1' }}
XCODE_VERSION: ${{ '14.2' }}
steps:
- uses: actions/checkout@v2
- name: Select Xcode
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
name: Add macOS binaries to release
runs-on: macos-12
env:
XCODE_VERSION: ${{ '13.3.1' }}
XCODE_VERSION: ${{ '14.2' }}
steps:
- name: Select Xcode
run: "sudo xcode-select -s /Applications/Xcode_$XCODE_VERSION.app"
+9 -1
View File
@@ -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
@@ -140,8 +140,8 @@ extension PostbuildContext {
/// Note: The file has yaml extension, even it is in the json format
overlayHeadersPath = targetTempDir.appendingPathComponent("all-product-headers.yaml")
irrelevantDependenciesPaths = config.irrelevantDependenciesPaths
let publicHeadersPath: String = try env.readEnv(key: "PUBLIC_HEADERS_FOLDER_PATH")
if publicHeadersPath != "/usr/local/include" {
let publicHeadersPathEnv: String? = env.readEnv(key: "PUBLIC_HEADERS_FOLDER_PATH")
if let publicHeadersPath = publicHeadersPathEnv, publicHeadersPathEnv != "/usr/local/include" {
// '/usr/local/include' is a value of PUBLIC_HEADERS_FOLDER_PATH when no public headers are automatically
// generated and it is up to a project configuration to place it in a common location (e.g. static library)
publicHeadersFolderPath = builtProductsDir.appendingPathComponent(publicHeadersPath)
@@ -396,7 +396,8 @@ class TemplateBasedCCWrapperBuilder: CCWrapperBuilder {
const char *output_arg_name = "-o";
const char *serialize_diagnostics_arg_name = "--serialize-diagnostics";
const char *language_mode_arg_name = "-x";
const char *precompile_header_arg_value = "objective-c-header";
const char *precompile_objc_header_arg_value = "objective-c-header";
const char *precompile_c_header_arg_value = "c-header";
const char *clang_cmd = "\(clangCommand)";
const char *markerFile = "\(markerFilename)";
const char *compilationHistoryFile = "\(compilationHistoryFilename)";
@@ -464,7 +465,7 @@ class TemplateBasedCCWrapperBuilder: CCWrapperBuilder {
clang_args[argc] = NULL;
// Verify mode. Even a target is cached, pch mode is not supported. Fallback to the local compilation
if (language_mode != NULL && strcmp(language_mode, precompile_header_arg_value) == 0) {
if (language_mode != NULL && (strcmp(language_mode, precompile_objc_header_arg_value) == 0 || strcmp(language_mode, precompile_c_header_arg_value) == 0)) {
return execvp(clang_cmd, (char *const*) clang_args);
}
@@ -50,6 +50,7 @@ class XcodeProjBuildSettingsIntegrateAppender: BuildSettingsIntegrateAppender {
result["CC"] = wrappers.cc.path
result["LD"] = wrappers.ld.path
result["LIBTOOL"] = wrappers.libtool.path
result["LDPLUSPLUS"] = wrappers.ldplusplus.path
}
let existingSwiftFlags = result["OTHER_SWIFT_FLAGS"] as? String
+9 -38
View File
@@ -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
}
}
@@ -150,4 +150,13 @@ class PostbuildContextTests: FileXCTestCase {
XCTAssertEqual(context.publicHeadersFolderPath, "/MyBuiltProductsDir/MyModule.grameworks/Headers")
}
func testPublicHeaderFolderPathEnvIsOptional() throws {
var envs = Self.SampleEnvs
envs.removeValue(forKey: "PUBLIC_HEADERS_FOLDER_PATH")
let context = try PostbuildContext(config, env: envs)
XCTAssertNil(context.publicHeadersFolderPath)
}
}
@@ -60,4 +60,14 @@ class XcodeProjBuildSettingsIntegrateAppenderTests: XCTestCase {
XCTAssertEqual(resultURL, fakeRootURL.path)
}
func testConsumerSettingLdPlusPlus() throws {
let mode: Mode = .consumer
let fakeRootURL: URL = "/xxxxxxxxxxC"
let appender = XcodeProjBuildSettingsIntegrateAppender(mode: mode, repoRoot: rootURL, fakeSrcRoot: fakeRootURL)
let result = appender.appendToBuildSettings(buildSettings: buildSettings, wrappers: binaries)
let ldPlusPlus: String = try XCTUnwrap(result["LDPLUSPLUS"] as? String)
XCTAssertEqual(ldPlusPlus, binaries.ldplusplus.path)
}
}
@@ -333,7 +333,7 @@ class TemplateBasedCCWrapperBuilderTests: FileXCTestCase {
XCTAssertNotEqual(newFileOutputData, Data())
}
func testPCHCompilationFallbacks() throws {
func testPCHObjCCompilationFallbacks() throws {
// Marker is empty to mimic the new file scenario
let pchFile = directory.appendingPathComponent("input.pch")
createValidPCHFile(pchFile)
@@ -344,6 +344,17 @@ class TemplateBasedCCWrapperBuilderTests: FileXCTestCase {
XCTAssertTrue(fileManager.fileExists(atPath: outputFile.path))
}
func testPCHCCompilationFallbacks() throws {
// Marker is empty to mimic the new file scenario
let pchFile = directory.appendingPathComponent("input.pch")
createValidPCHFile(pchFile)
arguments = ["-x", "c-header", "-MF", dependencyFile.path, "-o", outputFile.path, pchFile.path]
try shellExec(Self.xccc.path, args: arguments, inDir: directory.path)
XCTAssertTrue(fileManager.fileExists(atPath: outputFile.path))
}
/// Creates a simple C code in the location
private func createValidCFile(_ location: URL) {
fileManager.createFile(atPath: location.path, contents: "int main(){}".data(using: .utf8), attributes: nil)
@@ -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 */;
@@ -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
View File
@@ -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