I have a multi target project where every target relies on a built "web bundle" which is basically a collection of html, optimized images, and optimized javascript.
Right now that web bundle is built in a pre build step by running a script. The script takes awhile to run and outputs to a folder that is referenced into the project via a PBXFileReference which is then referenced in the Copy Bundle Resources step.
96516AC22BF928DD00576562 /* build */ = {isa = PBXFileReference; lastKnownFileType = folder; name = build; path = "../web-ui/build"; sourceTree = "<group>"; }
....
96516AC32BF928DD00576562 /* build in Resources */ = {isa = PBXBuildFile; fileRef = 96516AC22BF928DD00576562 /* build */; };
As a step, I wrote an aggregate target that can also run this script. I specified its input and output files and turned off sandboxing. It does exactly what I need it to. Critically it is ran based on dependency analysis. If I modify any file in web-ui it rebuilds, if I dont I can repeatedly build the aggregate target and it will not re-run the script. This is perfect.
A97590172E419CBA00741928 /* Build Web Bundle */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 12;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/xcodescripts/build-web-bundle.bash",
"$(SRCROOT)/web-ui/index.html",
"$(SRCROOT)/web-ui/vite-env.d.ts",
"$(SRCROOT)/web-ui/vite.config.ts",
"$(SRCROOT)/web-ui/tsconfig.json",
"$(SRCROOT)/web-ui/stats.html",
"$(SRCROOT)/web-ui/postcss.config.js",
"$(SRCROOT)/web-ui/package.json",
"$(SRCROOT)/web-ui/justfile",
"$(SRCROOT)/web-ui/src/",
);
name = "Build Web Bundle";
outputFileListPaths = (
);
outputPaths = (
"$(SRCROOT)/web-ui/build/",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "exec \"${SCRIPT_INPUT_FILE_0}\"\n";
};
You may notice I reference a src file. This is made possible via a flag USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES which allows Xcode to check folder dependencies recursively.
The problem is that my other targets do not automatically recognize that they need to run the "WebBundle" aggregate target in order to update a resource they copy in their "Copy bundle resources" phase.
So I tried adding it as a Target Dependency.
A9DE685B2E41C9A8005EF4E0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A97590132E419C1200741928 /* WebBundle */;
targetProxy = A9DE685A2E41C9A8005EF4E0 /* PBXContainerItemProxy */;
};
Unfortunately this breaks whatever magic was allowing the script to be run only when there are web bundle changes. Every build it runs the "Build Web Bundle" script.
I think what I am missing is a way to specify in these other targets that a resource they are used to copying from the Xcode PBXFileReference is produced by the aggregate target. This way they can start to reason about the dependencies.
Other possibilities are that I should be building the web bundle to a separate location. Or that these references are somehow broken in another way. To be clear the folder format is as thus
project/
iOS/
client.xcodeproj
web-ui/
build/ (web bundle build is output here and referenced relatively)
src/
index.html (and other things)
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
This question is a component of this question and an extension to this question which has been solved. This situation might feel a pinch constructed but it is a simplified version of one step of the original question.
Basically in my app I have a script that outputs a folder with a few files inside of it. This folder is output to $(BUILT_PRODUCTS_DIR)/build/ and is referenced via a PBXBuildFile. Because I put a wait in the script (to simulate a long build I have in my real project) it is very obvious when the script is or isn't run. The goal would be for it to run only when its dependencies have changed.
The trick is if I put this script as a "run script" phase within my final target dependency analysis works great. The script only runs when the dependencies are updated. However if I put the "run script" phase into an aggregate target then add it as a Target Dependency in the main target Xcode wants to run the script every time. Regardless of if the dependencies have changed. However if you build just the aggregate target alone everything goes just fine. It only builds when it has to.
To me this does not quite make sense. I thought that dependency analysis of the script within my aggregate target would be the same regardless of whether that script was within the aggregate target or the main target.
In my app I ideally need the aggregate target to be shared by multiple other targets. While I could put the script in each it would be more foolproof to have them share an aggregate target.
Why would dependency analysis come to a different conclusion when the script is within an aggregate target that is a target dependency of the main target?
If it helps here is the script and the entire project can be found here on GitHub if you would like to play with it.
mkdir -p "${SCRIPT_OUTPUT_FILE_0}/build/"
echo "Pausing for 10 seconds before creating files..."
sleep 10
cat "${SCRIPT_INPUT_FILE_0}"
cat > "${SCRIPT_OUTPUT_FILE_0}/build/index.html" << EOF
<!DOCTYPE html>
<html>
<head>
<title>Simple Page</title>
</head>
<body>
<h1>Welcome to Simple Page</h1>
<p>Generated at: $(date)</p>
</body>
</html>
EOF
cat > "${SCRIPT_OUTPUT_FILE_0}/build/page.html" << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Simple Page</title>
</head>
<body>
</body>
</html>
EOF
In my project I have an aggregate target that runs a script that generates a "web bundle" in a folder build/ with all the html/css/resources needed for the website. These resources are generated via a script. I use these resources in multiple targets so I have created an aggregate target to make this simple.
However, I have not found this simple. If I have the aggregate target output to $(DERIVED_FILE_DIR)/ then it outputs to a path that looks like this
DerivedData/BrowserApp-bla/Build/Intermediates.noindex/BrowserApp.build/Debug-iphonesimulator/WebBundle.build/DerivedSources/build/index.html
If I then drag that folder into Xcode and create a folder that references it. Then take that reference and make it relative to build products I get this
A9DE6A502E41E397005EF4E0 /* build */ = {
isa = PBXFileSystemSynchronizedRootGroup;
name = build;
path = "../../Intermediates.noindex/BrowserApp.build/Debug-iphonesimulator/WebBundle.build/DerivedSources/build";
sourceTree = BUILT_PRODUCTS_DIR;
};
This is because to the main BrowserApp target the BUILT_PRODUCTS_DIR is DerivedData/BrowserApp-bla/Build/Products/Debug-iphonesimulator.
You can see that the reference essentially has to maneuver out of the built products folder for the main BrowserApp target and into the built products directory for WebBundle.
This is ok for a debug build I suppose you can imagine that this is going to break down the moment you have a release build.
Now if we ignore that problem then comes the problem of getting it in Copy Bundle Resources. Xcode 16s PBXFileSystemSynchronizedRootGroup is a great improvement but does not help here. The only way I have found to get the folder copied is to hop into an earlier Xcode or make the following modifications.
Change the PBXFileSystemSynchronizedRootGroup into a PBXBuildFile
(In PBXFileReference section)
A9DE6A502E41E397005EF4E0 /* ../../Intermediates.noindex/client.build/Debug/WebBundle.build/DerivedSources/build */ = {isa = PBXFileReference; lastKnownFileType = text; path = ../../Intermediates.noindex/BrowserApp.build/Debug-iphonesimulator/WebBundle.build/DerivedSources/build; sourceTree = BUILT_PRODUCTS_DIR; };
(In the mainGroup PBXGroupSection)
A9DE6A502E41E397005EF4E0 /* ../../Intermediates.noindex/client.build/Debug/WebBundle.build/DerivedSources/build */,
Then remove any references for A9DE6A502E41E397005EF4E0 as a synchronized group
Create a PBXBuildFile using the previous PBXBuildFile as its fileRef then add it to the copy resources stage
(In PBXBuildFile section)
96516AC32BF928DD00576562 /* ../../Intermediates.noindex/BrowserApp.build/Debug-iphonesimulator/WebBundle.build/DerivedSources/build in Resources */ = {isa = PBXBuildFile; fileRef = A9DE6A502E41E397005EF4E0 /* ../../Intermediates.noindex/BrowserApp.build/Debug-iphonesimulator/WebBundle.build/DerivedSources/build */; };
(In the PBXBuildResources phase for the resources section of the main target)
96516AC32BF928DD00576562 /* ../../Intermediates.noindex/BrowserApp.build/Debug-iphonesimulator/WebBundle.build/
I do not know of a way to do this with a PBXFileSystemSynchronizedRootGroup so these manual changes seem necessary. After these changes I have the following:
And you can confirm the entire folder is accessible to the app. However if you try to build for release/Archive you get
lstat(/Users/calebkierum/Library/Developer/Xcode/DerivedData/BrowserApp-bla/Build/Intermediates.noindex/ArchiveIntermediates/BrowserApp/Intermediates.noindex/BrowserApp.build/Debug-iphonesimulator/WebBundle.build/DerivedSources/build): No such file or directory (2)
Which makes sense. The file reference has a relative path that explicitly mentions "debug" however because this path is based on an aggregate target I am not sure how you really update this reference for release.
I have an auto-renewable subscription. I have two methods helping me keep track of when they are expired
@MainActor public func isPurchased(product: Product) async -> Bool {
guard let state = await product.currentEntitlement else {
return false
}
switch state {
case .unverified(_, _):
return false
case .verified(let transaction):
await transaction.finish()
return isTransactionRelevant(transaction)
}
}
private func isTransactionRelevant(_ transaction: Transaction) -> Bool {
if let revocationDate = transaction.revocationDate {
logger.error("Transaction verification failed: Transaction was revoked on \(revocationDate)")
return false
}
if let expirationDate = transaction.expirationDate,
expirationDate < Date()
{
logger.error("Transaction verification failed: Transaction expired on \(expirationDate)")
return false
}
if transaction.isUpgraded {
logger.error("Transaction verification failed: Transaction was upgraded")
return false
}
logger.info("Transaction verification succeeded")
return true
}
I also have this that I can call to get the latest state of purchases
@MainActor public func updateStoreKitSubscriptionStatus() async {
var currentProductsPurchased: [Product] = []
for await result in Transaction.currentEntitlements {
if case .verified(let transaction) = result {
if isTransactionRelevant(transaction) {
if let product = products.first(
where: { $0.id == transaction.productID
})
{
currentProductsPurchased.append(product)
}
}
await transaction.finish()
}
}
self.purchasedProducts = currentProductsPurchased
}
Right now when a subscription expires the user needs to manually do some action that triggers updateStoreKitSubscriptionStatus() as it appears that expirations do not come through in Transaction.updates.
I am surprised there does not seem to be a better way. Does StoreKit not notify you somewhere that an auto-renewable subscription has expired? Can you observe it in an ObservableObject? Or do I need to just frequently poll Transaction.currentEntitlements even if I dont expect frequent updates?
Topic:
App & System Services
SubTopic:
StoreKit
I am sort of trying to do the opposite of what others are doing. I have a target called CopyFramework that creates a CopyFramework.framework within my main xcproj file.
I set up this target because a specific framework (we can call it Tools.xcframework) is distributed as a binary. That framework file lives within the code.
Tools.xcframework is structured like so
Tools.xcframework (Coding/testBuild/DynamicToolFrameworks/Tools.xcframework)
info.plist
ios-arm64/
Tools.xcframework/
Tools (executable file)
Tools.bundle
Headers/
Info.plist
Modules/
Tools.swiftmodule/
arm64-apple-ios.abi.json
arm64-apple-ios.private.swiftinterface
arm64-apple-ios.swiftdoc
arm64-apple-ios.swiftinterface
module.modulemap
module.private.modulemap
PrivateHeaders/
ios-arm64_x86_64-simulator/
When the CopyFramework target is run xcode does a few steps which copy the correct version of this framework to derived data.
Process Tools.xcframework (iOS)
Coding/testBuild/DynamicToolFrameworks/Tools.xcframework
/Library/Developer/Xcode/DerivedData/testBuild-sha/Build/Products/Debug-iphoneos/Tools.framework ios
cd /Users/calebkierum/Coding/testBuild
builtin-process-xcframework --xcframework Coding/testBuild/DynamicToolFrameworks/Tools.xcframework --platform ios --target-path Library/Developer/Xcode/DerivedData/testBuild-sha/Build/Products/Debug-iphoneos
Meaning essentially that the Tools.xcframework for the proper platform is taken from Tools.xcframework/ios-arm64 and copied to Library/Developer/Xcode/DerivedData/testBuild-sha/Build/Products/Debug-iphoneos/Tools.xcframework
I am writing a Swift Package that needs to be able to reference the correct Tools.xcframework. I have set it up like so:
let package = Package(
name: "CoreObjC",
platforms: [.iOS(.v17), .macCatalyst(.v17)],
products: [
.library(name: "CoreObjC", targets: ["CoreObjC"]),
],
dependencies: [
// Does something to here ???
//.package(path: "../testBuild")
],
targets: [
.target(
name: "CoreObjC",
dependencies: [
// Here I would like to be referencing the CopyFramework.framework target within my buildTest.xcproj file
.product(name: "CopyFramework", package: /*??? its not in a swift package its a part of an xcproj file*/)
],
path: "CoreObjC",
publicHeadersPath: "Headers",
linkerSettings: [
.linkedFramework("Tools", .when(platforms: [.iOS])),
.linkedLibrary("c++")
]
),
],
cxxLanguageStandard: CXXLanguageStandard.gnucxx14
)
Now obviously this does not work. I do not know how to communicate to the Package.swift file that the binary dependency is a framework target within my xcproj file. If I do run the target CopyFramework followed by building CoreObjC it works though (so long as you comment out the bits trying to reference CopyFramework). Running the CopyFramework target processes the Tools.xcframework and copies the proper xcframework sub folder to Derived data and the Swift Package build system seems to be able to see it.
Is there a way I can get rid of this manual step? Make it so that when I build the CoreObjC target (swift package) that either CopyFramework is run or some other process is run to get the proper xcframework out of Coding/testBuild/DynamicToolFrameworks/Tools.xcframework and into DerivedData?
Is it even theoretically possible to have a Swift Package reference a target in a normal xcproj file?
I am a bit confused. My understanding previously was that a modulemap was required in order to have a bridging header be generated. Now it has come to my attention that a modulemap is both a build input and something you can put in the Modules folder of the built product if you so choose.
I have tried reading the clang modulemap documentation, but am really struggling to connect most of what it says to the problem at hand.
In a project I am working on, the generation of the modulemap file is quite problematic. The framework imports C++ libraries and itself writes Objective-C++ wrappers for them. Currently, the modulemap file is both set as the Module Map File in "Build Settings" and presumably used when the Swift project later imports it.
In this project the modulemap is a list of the objective-c++ header files then export *
I am trying to understand what I would lose if I do one or both of two things:
What happens if I dont set this module map file in the build settings for the objective-c++ framework?
What happens if I dont have a modulemap involved whatsoever in this objective-c++ framework and then it is imported into Swift?
And does any of this change if its compiled as a static vs dynamic library? What if I embed it vs not embed it?
Because the build in the real project is so complicated its hard to isolate what is going on. So I built a smaller sample app.
There is CFramework which has an objective-c++ class. There is SwiftProject which imports that framework and is purely Swift. It imports the module and uses it.
I did not write a modulemap file, and the Swift project builds just fine. In the timeline it:
Prepares packages
Computes target dependency graph
Builds static cache for iPhoneSimulator18.2sdk
As near as I can tell even though the objective-c++ framework is not built with a modulemap in its build settings and there is not a modulemap included in the framework everything works. So then the modulemap file is useless? Perhaps it speeds things up but what step would theoretically be skippable?
I have two targets:
Library
and
Generate-Library-Modulemap
I use a modulemap to help bridge the Objective-C++ code to Swift.
Generate-Library-Modulemap is set up to run only when new headers are added (this is done reliably through some trickery). This seems to work, but the problem is that if I add Generate-Library-Modulemap as a dependency of Library, it seems that by the time Library Generate-Library-Modulemap is run, the Library target has already loaded up an outdated modulemap file.
The result is my first attempt to build after adding headers is that the framework fails, as even though the modulemap was generated, it was not attached to the framework. The second attempt succeeds as it reads the updated modulemap.
Is there any way to force Xcode to run the Generate-Library-Modulemap step before starting on Library? Or perhaps attach the modulemap after the fact?
Topic:
Developer Tools & Services
SubTopic:
Xcode
I have a project which is set up like so
App.xcproject
App target { Dependency on Bridges.framework }
Bridges.xcproject
Bridges.framework
Bridges.framework has a bunch of Objective-c++ headers that import c++ headers/frameworks etc. It has a modulemap that allows it to generate bridging headers for the App target which is Swift only.
I have noticed that every single build Planning Swift module App is run for 1 second, then Precompile bridging header is run for a moment, then every single swift file that imports Bridges recompiles regardless of if it had any edits taking about 2-3 seconds.
It feels like since nothing has changed inside of Bridges that this bridging header precompile should not be necessary every single run.
Bridges.framework is in General/Frameworks as "Do not
embed"
Bridges is in build phases "Target dependencies" and "Link binary with libraries"
Is this just normal and I should let this slide or is there a way to avoid this?
I have an Xcproject that I am using to define a .framework target that includes Objective-C++ bridges for a whole slew of C++ libraries.
To bridge Objective-C++ to Swift code in a separate target, I am using a .modulemap file that I generate in a script.
So we've essentially got
App.xcproject
App target { Dependency on Bridges.framework }
Bridges.xcproject
Bridges.framework { Dependency on generate-modulemap + a whole slough of c++ libraries }
generate-modulemap
It is VERY expensive for the Bridges framework to need to compile each build. The generation of the bridge static library takes 21 seconds, and the signing of it takes 32 seconds.
I would like to get generate-module to have its RunScript phase run based on dependency analysis. This way a new modulemap is only made when there is a new header and I can avoid compiling the whole framework each build. Normally, I would just list all of the headers in the input list to the script, but in this case, the goal is more to have it be any file within that folder. However, it is very unclear how to do so. Is there a way to get the "based on dependency analysis" to go based on any file within a folder?
A filelist does not work here because the filelist does not get updated automatically when you add a new header into that folder.
Hello! I am trying to get my app set up to support external payments. The snag I am hitting at the moment is it seems that relevant pages are not accessible?
There is this old EU doc
https://developer.apple.com/support/apps-using-alternative-payment-providers-in-the-eu/
But the more updated US doc titled "Distributing apps in the U.S. that provide an external purchase link - Support" is not available where it should be https://developer.apple.com/support/storekit-external-entitlement-us/
In addition the link for requesting the entitlement seems to be broken
https://developer.apple.com/contact/request/storekit-external-entitlement-us/
Any idea how one can access these? Perhaps this is just a temporary error?
My personal project is a bit further along however after not being able to get this to work in my app I fell back to a much simpler/proven implementation out there. There is this project on GitHub with a guide that implements a barebones app extension with packet tunneling. I figure this can give us common ground.
After changing the bundle and group identifiers to all end with -Caleb and or match up I tried running the app. The app extension does not work whatsoever and seemingly for reasons that are similar to my personal project.
If I pull up the console and filter for the subsystem (com.github.kean.vpn-client-caleb.vpn-tunnel) I see the following.
First you see installd installing it
0x16ba5f000 -[MIUninstaller _uninstallBundleWithIdentity:linkedToChildren:waitForDeletion:uninstallReason:temporaryReference:deleteDataContainers:wasLastReference:error:]: Destroying container com.github.kean.vpn-client-caleb.vpn-tunnel with persona 54D15361-A614-4E0D-931A-0953CDB50CE8 at /private/var/mobile/Containers/Data/PluginKitPlugin/2D0AE485-BB56-4E3E-B59E-48424CD4FD65
And then installd says this (No idea what it means)
0x16b9d3000 -[MIInstallationJournalEntry _refreshUUIDForContainer:withError:]: Data container for com.github.kean.vpn-client-caleb.vpn-tunnel is now at /private/var/mobile/Containers/Data/PluginKitPlugin/2D0AE485-BB56-4E3E-B59E-48424CD4FD65
Concerningly runningboardd seems to immediately try and stop it?
Executing termination request for: <RBSProcessPredicate <RBSProcessBundleIdentifiersPredicate| {(
"com.github.kean.vpn-client-caleb",
"com.github.kean.vpn-client-caleb.vpn-tunnel"
)}>>
[app<com.github.kean.vpn-client-caleb(54D15361-A614-4E0D-931A-0953CDB50CE8)>:1054] Terminating with context: <RBSTerminateContext| explanation:installcoordinationd app:[com.github.kean.vpn-client-caleb/54D15361-A614-4E0D-931A-0953CDB50CE8] uuid:963149FA-F712-460B-9B5C-5CE1C309B2FC isPlaceholder:Y reportType:None maxTerminationResistance:Absolute attrs:[
<RBSPreventLaunchLimitation| <RBSProcessPredicate <RBSProcessBundleIdentifiersPredicate| {(
"com.github.kean.vpn-client-caleb",
"com.github.kean.vpn-client-caleb.vpn-tunnel"
)}>> allow:(null)>
]>
Then runningboardd leaves a cryptic message
Acquiring assertion targeting system from originator [osservice<com.apple.installcoordinationd>:244] with description <RBSAssertionDescriptor| "installcoordinationd app:[com.github.kean.vpn-client-caleb/54D15361-A614-4E0D-931A-0953CDB50CE8] uuid:963149FA-F712-460B-9B5C-5CE1C309B2FC isPlaceholder:Y" ID:33-244-5222 target:system attributes:[
<RBSPreventLaunchLimitation| <RBSProcessPredicate <RBSProcessBundleIdentifiersPredicate| {(
"com.github.kean.vpn-client-caleb",
"com.github.kean.vpn-client-caleb.vpn-tunnel"
)}>> allow:(null)>
]>
And that seems to be all I have to go off of.... If I widen my search a bit I can see backboardd saying things like
Connection removed: IOHIDEventSystemConnection uuid:57E97E5D-8CDE-467B-81CA-36A93C7684AD pid:1054 process:vpn-client type:Passive entitlements:0x0 caller:BackBoardServices: <redacted> + 280 attributes:{
HighFrequency = 1;
bundleID = "com.github.kean.vpn-client-caleb";
pid = 1054;
} state:0x1 events:119 mask:0x800 dropped:0 dropStatus:0 droppedMask:0x0 lastDroppedTime:NONE
Or
Removing client connection <BKHIDClientConnection: 0xbf9828cd0; IOHIDEventSystemConnectionRef: 0xbf96d9600; vpid: 1054(vAF7); taskPort: 0x5D777; bundleID: com.github.kean.vpn-client-caleb> for client: IOHIDEventSystemConnection uuid:57E97E5D-8CDE-467B-81CA-36A93C7684AD pid:1054 process:vpn-client type:Passive entitlements:0x0 caller:BackBoardServices: <redacted> + 280 attributes:{
HighFrequency = 1;
bundleID = "com.github.kean.vpn-client-caleb";
pid = 1054;
} state:0x1 events:119 mask:0x800 dropped:0 dropStatus:0 droppedMask:0x0 lastDroppedTime:NONE source:HID
There's really nothing in the sysdiagnose either. No crash no nothing.
I am stumped. Any idea what might be going wrong for me here? Has something about the way app extensions or sandbox rules work changed in later OSes?
It only seems to happen in the real app I am working on and not within any of the test apps I make.
Its lasted a few Xcode versions. Don't know if this is widespread to the point of having a name?
I can certainly see how many devices hit it but its a but is there enough data here to know if this was a fluke vs "every time x" thing that may be more annoying?
Given at this point my app is only rolled out to a few users the number of devices isn't as useful for telling me which crashes to prioritize. In this screenshot I can tell two devices hit it. But did they only hit it once? Daily?
Topic:
Developer Tools & Services
SubTopic:
Xcode
Hello,
I have an old app that was pulled from the App Store after my developer account expired (was a free app, wasn't going to pay 99$ a year to keep it up). I would like to revitalize it porting it mostly to swift.
This would be much easier if I could just create a new Xcode project.
However I do want people who previously owned the app to receive it as as a free update/download given they have already purchased it.
If I create a new project. Can I set it to the same bundle identifier and not encounter any problems uploading it to the App Store this way? Or is there some reason this is a bad idea?
It is fairly hard to test this given I am not currently a part of the paid developer program. And additionally I don't want to "test" publishing the app for review.
Does anyone know if this will work out ok? Has anyone done this themselves?
Topic:
App Store Distribution & Marketing
SubTopic:
App Store Connect
Tags:
App Review
App Store
App Store Connect
Xcode
I am trying to create a cross platform application where some of the code is shared among the Android and iOS version and is written in c++ however I am not really sure where to begin with the XCode/iOS/Swift side of things. I can write c++ code but I am not sure where to put it. Most of the tutorials I can find show how to include already compiled c++ code into your project but I want to be able to write it alongside my swift code just like I might do with a bridging header in objective-c.How can I set up XCode so I can edit and compile my c++ code alongside my Swift code?