SourceKitten icon indicating copy to clipboard operation
SourceKitten copied to clipboard

App Store App

Open mredig opened this issue 5 years ago • 7 comments

Is it possible to use the sourcekitten framework in an app submitted to the App Store?

Obviously, App Store apps need to be sandboxed. Unfortunately, simply turning that on doesn't work. I get xcrun: error: cannot be used within an App Sandbox.

So I found this issue that suggested wrapping SourceKitten in an XPC Service. I did so, turned sandboxing on in my app, and it worked as intended! So I submitted to the App Store and it failed upon upload because The XPC Service needs to be sandboxed too...

So I turned sandboxing on for the XPC Service and was confronted with xcrun: error: cannot be used within an App Sandbox again.

Is this just impossible? Or is there more to it to get it to work?

mredig avatar Jul 28 '19 03:07 mredig

I think the sandbox issues are due to loading external dynamic libraries (namely libclang and sourcekitd). You may be able to avoid those sandbox issues by including copies of those libraries in your app bundle, re-signed by you.

jpsim avatar Jul 28 '19 17:07 jpsim

Interesting... I had assumed it was related to running a Process command in the sandbox, but googling a bit about that, I haven't found anything to explicitly say that's not allowed.

mredig avatar Jul 28 '19 22:07 mredig

So I turned sandboxing on for the XPC Service and was confronted with xcrun: error: cannot be used within an App Sandbox again.

Ah yes sorry I didn't pay close enough attention to this sentence. That's definitely a Process invocation. We do this to dynamically determine where to look for sourcekitd.framework and libclang.dylib. If you set the TOOLCHAIN_DIR environment variable to the location where SourceKitten should look to load these libraries, you can avoid running xcrun.

Check out library_wrapper.swift for the implementation details.

jpsim avatar Jul 28 '19 22:07 jpsim

I tried both hardcoding private let toolchainDir = env("TOOLCHAIN_DIR") to private let toolchainDir = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib" (and /Applications/Xcode.app/Contents/Developer/Toolchains/ cuz I wasn't sure which was correct) and setting the scheme to set the TOOLCHAIN_DIR to both of those values. Breakpoints confirm the value passed through, but the issue persists.

What's odd though is that xcrun is running before those breakpoints ever hit. (I put the breakpoint on the return statement of the env function in library_wrapper.swift)

If it clarifies anything at all, I'm extracting documentation through the following code:

		let module = Module(xcodeBuildArguments: [], inPath: url.path)

		guard let docs = module?.docs else {
			completion(nil)
			return
		}
		let docString = docs.description
		guard let jsonData = docString.data(using: .utf8) else {
			completion(nil)
			return
		}

When sandboxing is off, the first thing I see printed in the console is Running xcodebuild, otherwise the first thing I see is the xcrun: error: cannot be used within an App Sandbox error when it's on.

mredig avatar Jul 29 '19 23:07 mredig

Ah, yeah that still invokes a separate Process instance.

If you find another way to get swiftc arguments, you could use a different Module initializer.

jpsim avatar Jul 30 '19 16:07 jpsim

Hi @mredig , did you find solution for this problem? :<

Moriquendi avatar Feb 09 '20 18:02 Moriquendi

Unfortunately I have not had time to try the suggestion and the project has been sitting on the back burner. Some day though....

mredig avatar Feb 09 '20 19:02 mredig