Skip to content

Commit 6782244

Browse files
johnno1962dmhtsCopilot
authored
Clear cache on failed link. (#116)
* Clear cache on failed link. * Simulator+Rosetta. * SwiftRegex5 performance. * Update README.md * Log failed compilation command. * "packageFrameworks" fallback using object file path. * Derived sources. * Rationalisation. * Proxy mode unhiding. * Tidy-up. * Move "Unhider" into InjectionLite. * Unhiding while Intercepting. * Basic check. * Update Sources/InjectionNext/InjectionNext.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update App/InjectionNext/MonitorXcode.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Dima Hutsuliak <doberq@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent d119ef4 commit 6782244

11 files changed

Lines changed: 117 additions & 210 deletions

File tree

App/InjectionNext.xcodeproj/project.pbxproj

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
BB4788972EB6B81A00464AB4 /* xt_forwarding_trampoline_x86.s in Sources */ = {isa = PBXBuildFile; fileRef = BB47888E2EB6B81A00464AB4 /* xt_forwarding_trampoline_x86.s */; };
8282
BB4788982EB6B81A00464AB4 /* fishhook.c in Sources */ = {isa = PBXBuildFile; fileRef = BB4788862EB6B81A00464AB4 /* fishhook.c */; };
8383
BB5155DA2CDED44F00704C7A /* InjectionHybrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5155D92CDED44400704C7A /* InjectionHybrid.swift */; };
84+
BB52AD552F1501F500297CD9 /* Unhider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22B6459F2C18DD9D00F99B61 /* Unhider.swift */; };
8485
BB6A56F02C50E73600C92112 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6A56EF2C50E73600C92112 /* Defaults.swift */; };
8586
BB6A56F12C50E79800C92112 /* copy_bundle.sh in Resources */ = {isa = PBXBuildFile; fileRef = BBDD84582C4FF0B9000F3124 /* copy_bundle.sh */; };
8687
BB85A42B2D6B9C7B00FA29D0 /* feedcommands in Resources */ = {isa = PBXBuildFile; fileRef = BB85A4242D6B9C5300FA29D0 /* feedcommands */; };
@@ -166,7 +167,7 @@
166167
224E57FC2C08BAE200B71C79 /* InjectionClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InjectionClient.h; path = ../../Sources/InjectionNextC/include/InjectionClient.h; sourceTree = "<group>"; };
167168
224E57FD2C08BBE300B71C79 /* InjectionServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InjectionServer.swift; sourceTree = "<group>"; };
168169
224E57FF2C08BC0E00B71C79 /* MonitorXcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonitorXcode.swift; sourceTree = "<group>"; };
169-
22B6459F2C18DD9D00F99B61 /* Unhider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Unhider.swift; sourceTree = "<group>"; };
170+
22B6459F2C18DD9D00F99B61 /* Unhider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Unhider.swift; path = ../../InjectionLite/Sources/InjectionImpl/Unhider.swift; sourceTree = "<group>"; };
170171
BB037DF31FAD808B004B267C /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
171172
BB037DF41FAD80D0004B267C /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
172173
BB16653925E9A5F0001407AE /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@@ -837,6 +838,7 @@
837838
BBDD84552C4FEC98000F3124 /* SimpleSocket.mm in Sources */,
838839
BB42F9382EB63C2900FDBBCC /* KeyPaths.swift in Sources */,
839840
BB42F9392EB63C2900FDBBCC /* Reloader.swift in Sources */,
841+
BB52AD552F1501F500297CD9 /* Unhider.swift in Sources */,
840842
BB42F93A2EB63C2900FDBBCC /* Generics.swift in Sources */,
841843
BB42F93B2EB63C2900FDBBCC /* Metadata.swift in Sources */,
842844
BB42F93C2EB63C2900FDBBCC /* Common.swift in Sources */,
@@ -926,7 +928,6 @@
926928
GCC_WARN_UNUSED_FUNCTION = YES;
927929
GCC_WARN_UNUSED_VARIABLE = YES;
928930
HEADER_SEARCH_PATHS = $SRCROOT/HotReloading/Sources/HotReloadingGuts/include;
929-
HELPER_MACH_ID = com.johnholdsworth.InjectionIII.Helper.mach;
930931
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
931932
LD_RUNPATH_SEARCH_PATHS = (
932933
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(SWIFT_PLATFORM_TARGET_PREFIX)",
@@ -992,7 +993,6 @@
992993
GCC_WARN_UNUSED_FUNCTION = YES;
993994
GCC_WARN_UNUSED_VARIABLE = YES;
994995
HEADER_SEARCH_PATHS = $SRCROOT/HotReloading/Sources/HotReloadingGuts/include;
995-
HELPER_MACH_ID = com.johnholdsworth.InjectionIII.Helper.mach;
996996
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
997997
LD_RUNPATH_SEARCH_PATHS = (
998998
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(SWIFT_PLATFORM_TARGET_PREFIX)",
@@ -1073,11 +1073,12 @@
10731073
INFOPLIST_FILE = InjectionNext/Info.plist;
10741074
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
10751075
MACOSX_DEPLOYMENT_TARGET = 10.13;
1076-
MARKETING_VERSION = 1.5.1;
1076+
MARKETING_VERSION = 1.5.2;
10771077
PRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionNext;
10781078
PRODUCT_NAME = "$(TARGET_NAME)";
10791079
PROVISIONING_PROFILE_SPECIFIER = "";
10801080
SDKROOT = macosx;
1081+
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) INJECTION_NEXT_APP";
10811082
SWIFT_OBJC_BRIDGING_HEADER = "InjectionNext/InjectionNext-Bridging-Header.h";
10821083
};
10831084
name = Debug;
@@ -1096,11 +1097,12 @@
10961097
INFOPLIST_FILE = InjectionNext/Info.plist;
10971098
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
10981099
MACOSX_DEPLOYMENT_TARGET = 10.13;
1099-
MARKETING_VERSION = 1.5.1;
1100+
MARKETING_VERSION = 1.5.2;
11001101
PRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionNext;
11011102
PRODUCT_NAME = "$(TARGET_NAME)";
11021103
PROVISIONING_PROFILE_SPECIFIER = "";
11031104
SDKROOT = macosx;
1105+
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) INJECTION_NEXT_APP";
11041106
SWIFT_OBJC_BRIDGING_HEADER = "InjectionNext/InjectionNext-Bridging-Header.h";
11051107
};
11061108
name = Release;
@@ -1255,7 +1257,7 @@
12551257
repositoryURL = "https://github.com/johnno1962/SwiftRegex5";
12561258
requirement = {
12571259
kind = upToNextMajorVersion;
1258-
minimumVersion = 6.1.3;
1260+
minimumVersion = 6.2.1;
12591261
};
12601262
};
12611263
22E3D9892C19009900BB234E /* XCRemoteSwiftPackageReference "DLKit" */ = {

App/InjectionNext/FrontendServer.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
import Cocoa
1414
import Popen
1515

16+
#if INJECTION_III_APP
17+
struct Unhider { static var packageFrameworks: String? }
18+
#endif
19+
1620
class FrontendServer: SimpleSocket {
1721
enum State: String {
1822
case unpatched = "Intercept Compiler"
@@ -85,7 +89,7 @@ class FrontendServer: SimpleSocket {
8589

8690
override func runInBackground() {
8791
guard validateConnection() && readString() == "1.0" else {
88-
return _ = Self.frontendRecompiler()
92+
return Self.frontendRecompiler()
8993
.error("Unpatch then repatch compiler to update script version")
9094
}
9195
do {
@@ -119,12 +123,21 @@ class FrontendServer: SimpleSocket {
119123
swiftFiles += source+"\n"
120124
}
121125
case "-o":
122-
_ = feed.readString()
126+
if let object = feed.readString(),
127+
Unhider.packageFrameworks == nil {
128+
var url = URL(fileURLWithPath: object)
129+
for _ in 1...4 {
130+
url.deleteLastPathComponent()
131+
}
132+
Unhider.packageFrameworks = url.path
133+
}
123134
default:
124135
if let sdkPlatform: String = arg[#"/([A-Za-z]+)[\d\.]+\.sdk$"#] {
125136
platform = sdkPlatform
126137
}
127-
if arg.hasSuffix(".swift") && args.last != "-F" {
138+
if args.last == "-F" && arg.hasSuffix("/PackageFrameworks") {
139+
Unhider.packageFrameworks = arg
140+
} else if arg.hasSuffix(".swift") && args.last != "-F" {
128141
swiftFiles += arg+"\n"
129142
} else if arg[Reloader.optionsToRemove] {
130143
_ = feed.readString()

App/InjectionNext/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleShortVersionString</key>
2020
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleVersion</key>
22-
<string>12988</string>
22+
<string>13280</string>
2323
<key>LSApplicationCategoryType</key>
2424
<string>public.app-category.developer-tools</string>
2525
<key>LSMinimumSystemVersion</key>

App/InjectionNext/InjectionHybrid.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ extension AppDelegate {
4343
watchDirectoryItem.state = Self.watchers.isEmpty ? .off : .on
4444
}
4545
static func alreadyWatching(_ projectRoot: String) -> String? {
46-
return watchers.keys.first { projectRoot.hasPrefix($0) }
46+
return Self.watchers[projectRoot] != nil ? projectRoot :
47+
watchers.keys.first { projectRoot.hasPrefix($0+"/") }
4748
}
4849
static func restartLastWatcher() {
4950
DispatchQueue.main.async {
@@ -144,10 +145,18 @@ class InjectionHybrid: InjectionBase {
144145

145146
class HybridCompiler: NextCompiler {
146147
/// Legacy log parsing version of recomilation
147-
var liteRecompiler = Recompiler()
148+
static var liteRecompiler = Recompiler()
148149

149150
override func recompile(source: String, platform: String) -> String? {
150-
return liteRecompiler.recompile(source: source, platformFilter:
151+
let cacheFile = Reloader.cacheFile
152+
Reloader.cacheFile[#"_(\w+)_builds"#, 1] = platform
153+
if cacheFile != Reloader.cacheFile { Self.liteRecompiler = Recompiler() }
154+
return Self.liteRecompiler.recompile(source: source, platformFilter:
151155
"SDKs/"+platform, dylink: false)
152156
}
157+
158+
override func link(object: String, dylib: String, arch: String) -> (String, Double)? {
159+
return super.link(object: object, dylib: dylib, arch: arch) ??
160+
Self.liteRecompiler.linkingFailed()
161+
}
153162
}

App/InjectionNext/MonitorXcode.swift

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,19 @@ class MonitorXcode {
3535
#if DEBUG
3636
args += " | tee \(recompiler.tmpbase).log"
3737
#endif
38-
if let xcodeStdout = Popen(cmd: "export SOURCEKIT_LOGGING=1; " +
39-
"'\(Defaults.xcodePath)/Contents/MacOS/Xcode' 2>&1\(args)") {
38+
if !FileManager.default.fileExists(atPath: Defaults.xcodePath) {
39+
InjectionServer.error("""
40+
No valid Xcode at path:
41+
\(Defaults.xcodePath)
42+
Use menu item "Select Xcode"
43+
to select a valid path.
44+
""")
45+
}
46+
else if let xcodeStdout = Popen(cmd: """
47+
export SOURCEKIT_LOGGING=1
48+
export RUNNING_VIA_INJECTION_NEXT=1
49+
'\(Defaults.xcodePath)/Contents/MacOS/Xcode' 2>&1 \(args)
50+
""") {
4051
Self.runningXcode = self
4152
AppDelegate.ui.launchXcodeItem.state = .on
4253
DispatchQueue.global().async {
@@ -55,7 +66,7 @@ class MonitorXcode {
5566
break // break on clean exit and EOF.
5667
} catch {
5768
// Continue processing on error
58-
_ = self.recompiler.error(error)
69+
self.recompiler.error(error)
5970
}
6071
}
6172
}
@@ -105,6 +116,7 @@ class MonitorXcode {
105116
}
106117

107118
let indexBuild = "/Index.noindex/Build/"
119+
let productDir = "-"+FrontendServer.clientPlatform.lowercased()
108120
while let line = xcodeStdout.readLine() {
109121
// debug(">>"+line+"<<")
110122
if line.hasPrefix(" key.request: source.request.") &&
@@ -115,33 +127,35 @@ class MonitorXcode {
115127
xcodeStdout.readLine() == " key.compilerargs: [" ||
116128
line == " key.compilerargs: [" {
117129
var swiftFiles = "", args = [String](), fileCount = 0,
118-
workingDir = "/tmp", configDirs = Set<String>()
130+
workingDir = "/tmp"
119131

120132
while var arg = readQuotedString() {
133+
/// Used if injecting the Swift compiler.
121134
let llvmIncs = "/llvm-macosx-arm64/lib"
122135
if arg.hasPrefix("-I"), arg.contains(llvmIncs) {
123136
arg = arg.replacingOccurrences(of: llvmIncs,
124137
with: "/../buildbot_osx"+llvmIncs)
125138
}
126-
if args.last == "-F" && arg.hasSuffix("/PackageFrameworks") {
127-
Unhider.packageFrameworks = arg
128-
#if DEFAULTS_PACKAGE_PROBLEM || false
129-
let frameworksURL = URL(fileURLWithPath: arg)
130-
let derivedData = frameworksURL.deletingLastPathComponent()
131-
.deletingLastPathComponent().deletingLastPathComponent()
132-
.deletingLastPathComponent().deletingLastPathComponent()
133-
let productsDir =
134-
derivedData.appendingPathComponent("Build/Products")
135-
let platform = InjectionServer
136-
.currentClient?.platform ?? "iPhoneSimulator"
137-
if let configs = Glob(pattern: productsDir.path +
138-
"/*-" + platform.lowercased()) {
139-
for other in configs
140-
where configDirs.insert(other).inserted {
141-
args += [other, "-F"]
142-
}
139+
140+
/// Arguments received from SourceKit while syntax highlighting the editor
141+
/// have their own "Intermediates" directory. Map it back to the main one.
142+
let alt = arg[indexBuild, "/Build/"]
143+
if !arg.hasSuffix(".yaml"), alt != arg,
144+
!arg.contains("/Intermediates.noindex/"),
145+
let path: String = alt[#"(?:-I)?(.*)"#],
146+
FileManager.default.fileExists(atPath: path) {
147+
arg = alt
148+
}
149+
150+
/// Determine path to DerivedData for "unhiding".
151+
if args.last == "-F" {
152+
if arg.hasSuffix("/PackageFrameworks") {
153+
Unhider.packageFrameworks = arg
154+
}
155+
else if Unhider.packageFrameworks == nil,
156+
arg.hasSuffix(productDir) {
157+
Unhider.packageFrameworks = arg+"/PackageFrameworks"
143158
}
144-
#endif
145159
}
146160

147161
if arg.hasSuffix(".swift") && args.last != "-F" {
@@ -159,35 +173,7 @@ class MonitorXcode {
159173
arg.contains(indexBuild) {
160174
// injecting tests without having run tests
161175
args.removeLast()
162-
// Xcode seems to maintain two sets of "build inputs"
163-
// i.e. .swiftmodule, .modulemap etc. files and it
164-
// seems the main build allows you to avoid "unhiding"
165-
// whereas the paths provided to SourceKit are for the
166-
// Index.noindex/Build tree of inputs. Switch them.
167-
} else if /*(args.last == "-I" || args.last == "-F" ||
168-
args.last == "-Xcc" && (arg.hasPrefix("-I") ||
169-
arg.hasPrefix("-fmodule-map-file="))) &&*/
170-
arg.contains(indexBuild) &&
171-
!arg.contains("/Intermediates.noindex/"),
172-
let _ = args.last {
173-
// expands out default argument generators
174-
let alt = arg.replacingOccurrences(
175-
of: indexBuild, with: "/Build/")
176-
var change = [alt]
177-
// alternate fix of Defaults problem
178-
// hopefully without causing unhides
179-
// InjectionNext/issues/#40 c.f. #78
180-
if let path: String = alt[#"(?:-I)?(.*)"#],
181-
!FileManager.default.fileExists(atPath: path) {
182-
// change += (arg.hasPrefix("-") ? [arg] :
183-
// option.hasPrefix("-") ? [option, arg] :
184-
// [])
185-
change = [arg]
186-
}
187-
// debug("CHANGE", change)
188-
args += change
189-
} else if !(arg == "-F" && args.last == "-F") &&
190-
arg != "-Xfrontend" && !arg.hasPrefix("-driver-") {
176+
} else if arg != "-Xfrontend" && !arg.hasPrefix("-driver-") {
191177
args.append(arg)
192178
}
193179
}

App/InjectionNext/NextCompiler.swift

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,12 @@ class NextCompiler {
8383
/// Default counter for Compilertron
8484
var compileNumber = 0
8585

86-
func error(_ msg: String) -> Bool {
86+
func error(_ msg: String) {
8787
let msg = "⚠️ "+msg
8888
NSLog(msg)
8989
log(msg)
90-
return false
9190
}
92-
func error(_ err: Error) -> Bool {
91+
func error(_ err: Error) {
9392
error("Internal app error: \(err)")
9493
}
9594

@@ -119,7 +118,8 @@ class NextCompiler {
119118
= prepare(source: source, connected: client),
120119
let data = codesign(dylib: dylib, platform: platform) else {
121120
AppDelegate.ui.setMenuIcon(.error)
122-
return error("Injection failed. Was your app connected?")
121+
error("Injection failed. Was your app connected?")
122+
return false
123123
}
124124

125125
InjectionServer.clientQueue.sync {
@@ -160,7 +160,8 @@ class NextCompiler {
160160
metrics.success = false
161161
sendMetrics(metrics)
162162
}
163-
return self.error(error)
163+
self.error(error)
164+
return false
164165
}
165166
}
166167

@@ -289,7 +290,7 @@ class NextCompiler {
289290
/// task and return the full path to the resulting object file.
290291
func recompile(source: String, platform: String) -> String? {
291292
guard let stored = compilations[source] else {
292-
_ = error("Postponing: \(source) Have you viewed it in Xcode?")
293+
error("Postponing: \(source) Have you viewed it in Xcode?")
293294
pendingSource = source
294295
return nil
295296
}
@@ -326,11 +327,17 @@ class NextCompiler {
326327
"-plugin-path", toolchain+"/usr/lib/swift/host/plugins",
327328
"-plugin-path", toolchain+"/usr/local/lib/swift/host/plugins"] :
328329
["-c", source, "-Xclang", "-fno-validate-pch"]) + baseOptionsToAdd
329-
330+
var arguments = stored.arguments
331+
if let target = InjectionServer.currentClient?.arch, target != "arm64" {
332+
// Simulator running in Rosetta.
333+
for i in 0..<arguments.count {
334+
arguments[i][#"^(\w+)-apple-ios"#] = target
335+
}
336+
}
330337
// Call compiler process with timing
331338
let compilationStartTime = Date.timeIntervalSinceReferenceDate
332339
let compile = Topen(exec: compiler,
333-
arguments: stored.arguments + languageSpecific,
340+
arguments: arguments + languageSpecific,
334341
cd: stored.workingDir)
335342
var errors = ""
336343
while let line = compile.readLine() {
@@ -340,9 +347,9 @@ class NextCompiler {
340347
errors += line+"\n"
341348
}
342349
if errors.contains(" error: ") {
343-
print(([compiler] + stored.arguments +
344-
languageSpecific).joined(separator: " "))
345-
_ = error("Recompile failed for: \(source)\n"+errors)
350+
error("Failed compilation: "+([compiler] + arguments +
351+
languageSpecific).joined(separator: " "))
352+
error("Recompile failed for: \(source)\n"+errors)
346353
Self.lastError = errors
347354
return nil
348355
}
@@ -352,7 +359,7 @@ class NextCompiler {
352359
let compilationTimeMs = (now - compilationStartTime) * 1000
353360
detail(String(format: "⚡ Compiled in %.0fms", compilationTimeMs))
354361

355-
let compilationCommand = (stored.arguments + languageSpecific)
362+
let compilationCommand = (arguments + languageSpecific)
356363
.map { $0[#"([ $()])"#, "\\\\$1"] }.joined(separator: " ")
357364
Reloader.extractLinkCommand(from: compilationCommand)
358365
return object
@@ -376,7 +383,7 @@ class NextCompiler {
376383
}
377384

378385
if let errors = Popen.system(linkCommand, errors: true) {
379-
_ = error("Linking failed:\n\(linkCommand)\nerrors:\n"+errors)
386+
error("Linking failed:\n\(linkCommand)\nerrors:\n"+errors)
380387
Self.lastError = errors
381388
return nil
382389
}
@@ -401,7 +408,7 @@ class NextCompiler {
401408
else exit 1; fi)
402409
"""
403410
if let errors = Popen.system(codesign, errors: true) {
404-
_ = error("Codesign failed \(codesign) errors:\n"+errors)
411+
error("Codesign failed \(codesign) errors:\n"+errors)
405412
Self.lastError = errors
406413
}
407414
}

0 commit comments

Comments
 (0)