-
Notifications
You must be signed in to change notification settings - Fork 71
Add quick pick to set Xcode DEVELOPER_DIR #384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
import * as vscode from "vscode"; | ||
import * as fs from "fs/promises"; | ||
import * as path from "path"; | ||
import configuration from "./configuration"; | ||
import { FolderEvent, WorkspaceContext } from "./WorkspaceContext"; | ||
import { createSwiftTask, SwiftTaskProvider } from "./SwiftTaskProvider"; | ||
import { FolderContext } from "./FolderContext"; | ||
|
@@ -23,7 +24,6 @@ import { withQuickPick } from "./ui/QuickPick"; | |
import { execSwift } from "./utilities/utilities"; | ||
import { Version } from "./utilities/version"; | ||
import { DarwinCompatibleTarget, SwiftToolchain } from "./toolchain/toolchain"; | ||
import configuration from "./configuration"; | ||
|
||
/** | ||
* References: | ||
|
@@ -431,31 +431,68 @@ function openInExternalEditor(packageNode: PackageNode) { | |
} | ||
} | ||
|
||
interface DarwinQuickPickTarget extends vscode.QuickPickItem { | ||
value: DarwinCompatibleTarget; | ||
label: string; | ||
} | ||
|
||
/** | ||
* Switches the target SDK to the platform selected in a QuickPick UI. | ||
*/ | ||
async function switchPlatform() { | ||
const onSelect = async (picked: DarwinQuickPickTarget) => { | ||
const sdkForTarget = await SwiftToolchain.getSdkForTarget(picked.value); | ||
if (sdkForTarget) { | ||
configuration.sdk = sdkForTarget; | ||
} else { | ||
vscode.window.showErrorMessage("Unable to obtain requested SDK path"); | ||
} | ||
}; | ||
|
||
await withQuickPick<DarwinQuickPickTarget>( | ||
await withQuickPick( | ||
"Select a new target", | ||
[ | ||
{ value: DarwinCompatibleTarget.macOS, label: "macOS" }, | ||
{ value: DarwinCompatibleTarget.iOS, label: "iOS" }, | ||
], | ||
onSelect | ||
async picked => { | ||
const sdkForTarget = await SwiftToolchain.getSdkForTarget(picked.value); | ||
if (sdkForTarget) { | ||
configuration.sdk = sdkForTarget; | ||
} else { | ||
vscode.window.showErrorMessage("Unable to obtain requested SDK path"); | ||
} | ||
} | ||
); | ||
} | ||
|
||
/** | ||
* Choose DEVELOPER_DIR | ||
* @param workspaceContext | ||
*/ | ||
async function selectXcodeDeveloperDir() { | ||
const defaultXcode = await SwiftToolchain.getXcodeDeveloperDir(); | ||
const selectedXcode = configuration.swiftEnvironmentVariables.DEVELOPER_DIR; | ||
const xcodes = await SwiftToolchain.getXcodeInstalls(); | ||
await withQuickPick( | ||
selectedXcode ?? defaultXcode, | ||
xcodes.map(xcode => { | ||
const developerDir = `${xcode}/Contents/Developer`; | ||
return { | ||
label: developerDir === defaultXcode ? `${xcode} (default)` : xcode, | ||
folder: developerDir === defaultXcode ? undefined : developerDir, | ||
}; | ||
}), | ||
async selected => { | ||
let swiftEnv = configuration.swiftEnvironmentVariables; | ||
const previousDeveloperDir = swiftEnv.DEVELOPER_DIR ?? defaultXcode; | ||
if (selected.folder) { | ||
swiftEnv.DEVELOPER_DIR = selected.folder; | ||
} else if (swiftEnv.DEVELOPER_DIR) { | ||
// if DEVELOPER_DIR was set and the new folder is the default then | ||
// delete variable | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const { DEVELOPER_DIR, ...rest } = swiftEnv; | ||
swiftEnv = rest; | ||
} | ||
configuration.swiftEnvironmentVariables = swiftEnv; | ||
// if SDK is inside previous DEVELOPER_DIR then move to new DEVELOPER_DIR | ||
if ( | ||
configuration.sdk.length > 0 && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is convenient enough but I'm wondering if it's possible for the setting of swift.SDK could be like either way
a bit out of scope here. you may find some ideas here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DEVELOPER_DIR doesn't exist on Linux or Windows. Also the SDK can exist outside the DEVELOPER_DIR if you are cross compiling for another platform. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for your answer |
||
configuration.sdk.startsWith(previousDeveloperDir) | ||
) { | ||
configuration.sdk = configuration.sdk.replace( | ||
previousDeveloperDir, | ||
selected.folder ?? defaultXcode | ||
); | ||
} | ||
} | ||
); | ||
} | ||
|
||
|
@@ -510,6 +547,9 @@ export function register(ctx: WorkspaceContext) { | |
if (item instanceof PackageNode) { | ||
openInExternalEditor(item); | ||
} | ||
}) | ||
}), | ||
vscode.commands.registerCommand("swift.selectXcodeDeveloperDir", () => | ||
selectXcodeDeveloperDir() | ||
) | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
|
||
import * as fs from "fs/promises"; | ||
import * as path from "path"; | ||
import { normalize } from "path"; | ||
import * as plist from "plist"; | ||
import * as vscode from "vscode"; | ||
import configuration from "../configuration"; | ||
|
@@ -95,6 +96,49 @@ export class SwiftToolchain { | |
); | ||
} | ||
|
||
/** | ||
* Get active developer dir for Xcode | ||
*/ | ||
public static async getXcodeDeveloperDir(): Promise<string> { | ||
const { stdout } = await execFile("xcode-select", ["-p"]); | ||
return stdout.trimEnd(); | ||
} | ||
|
||
/** | ||
* @param target Target to obtain the SDK path for | ||
* @returns path to the SDK for the target | ||
*/ | ||
public static async getSdkForTarget( | ||
target: DarwinCompatibleTarget | ||
): Promise<string | undefined> { | ||
let sdkType: string; | ||
switch (target) { | ||
case DarwinCompatibleTarget.macOS: | ||
// macOS is the default target, so lets not update the SDK | ||
return undefined; | ||
case DarwinCompatibleTarget.iOS: | ||
sdkType = "iphoneos"; | ||
break; | ||
} | ||
|
||
// Include custom variables so that non-standard XCode installs can be better supported. | ||
const { stdout } = await execFile("xcrun", ["--sdk", sdkType, "--show-sdk-path"], { | ||
env: { ...process.env, ...configuration.swiftEnvironmentVariables }, | ||
}); | ||
return path.join(stdout.trimEnd()); | ||
} | ||
|
||
/** | ||
* Get list of Xcode versions intalled on mac | ||
* @returns Folders for each Xcode install | ||
*/ | ||
public static async getXcodeInstalls(): Promise<string[]> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nits] |
||
const { stdout: xcodes } = await execFile("mdfind", [ | ||
`kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'`, | ||
]); | ||
return xcodes.trimEnd().split("\n"); | ||
} | ||
|
||
logDiagnostics(channel: SwiftOutputChannel) { | ||
channel.logDiagnostic(`Swift Path: ${this.swiftFolderPath}`); | ||
channel.logDiagnostic(`Toolchain Path: ${this.toolchainPath}`); | ||
|
@@ -214,30 +258,6 @@ export class SwiftToolchain { | |
return undefined; | ||
} | ||
|
||
/** | ||
* @param target Target to obtain the SDK path for | ||
* @returns path to the SDK for the target | ||
*/ | ||
public static async getSdkForTarget( | ||
target: DarwinCompatibleTarget | ||
): Promise<string | undefined> { | ||
let sdkType: string; | ||
switch (target) { | ||
case DarwinCompatibleTarget.macOS: | ||
sdkType = "macosx"; | ||
break; | ||
case DarwinCompatibleTarget.iOS: | ||
sdkType = "iphoneos"; | ||
break; | ||
} | ||
|
||
// Include custom variables so that non-standard XCode installs can be better supported. | ||
const { stdout } = await execFile("xcrun", ["--sdk", sdkType, "--show-sdk-path"], { | ||
env: { ...process.env, ...configuration.swiftEnvironmentVariables }, | ||
}); | ||
return path.join(stdout.trimEnd()); | ||
} | ||
|
||
/** | ||
* @returns path to custom SDK | ||
*/ | ||
|
@@ -260,8 +280,8 @@ export class SwiftToolchain { | |
): Promise<string | undefined> { | ||
switch (process.platform) { | ||
case "darwin": { | ||
const { stdout } = await execFile("xcode-select", ["-p"]); | ||
return path.join(stdout.trimEnd(), "usr", "bin"); | ||
const developerDir = await this.getXcodeDeveloperDir(); | ||
return path.join(developerDir, "usr", "bin"); | ||
} | ||
case "win32": { | ||
// look up runtime library directory for XCTest alternatively | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nits] the UI and the actual value is a bit different
the list in UI is Xcode paths
but the actual values are the developer paths
it's a little bit different, not sure if engineers would get confused