Created
October 27, 2021 01:46
-
-
Save thomasvidas/1bdc37c1220f20ab3bdc18a224af0778 to your computer and use it in GitHub Desktop.
Typescript wrapper for xcodebuild
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { execSync, spawn, SpawnOptions } from 'child_process' | |
type XCodebuildOptions = { | |
/** | |
* Build the project specified by projectname. | |
* Required if there are multiple project files in the same directory. | |
*/ | |
project: string, | |
/** | |
* Build the target specified by targetname. | |
*/ | |
target: string, | |
/** | |
* Build all the targets in the specified project. | |
*/ | |
alltargets: boolean, | |
/** | |
* Build the workspace specified by workspacename. | |
*/ | |
workspace: string, | |
/** | |
* Build the scheme specified by schemename. | |
* Required if building aworkspace. | |
*/ | |
scheme: string, | |
/** | |
* Use the build configuration specified by "configurationname" when building each target. | |
*/ | |
configuration: string, | |
/** | |
* Use the architecture specified by architecture when building each target. | |
*/ | |
arch: string, | |
/** | |
* Build an Xcode project or workspace against the specified SDK, | |
* using build tools appropriate for that SDK. The argument may be an | |
* absolute path to an SDK, or the canonical name of an SDK. | |
*/ | |
sdk: string, | |
/** | |
* Lists all available SDKs that Xcode knows about, including their | |
* canonical names suitable for use with -sdk. Does not initiate a build. | |
*/ | |
showsdks: boolean, | |
/** | |
* Lists the targets and configurations in a project, or the schemes | |
* in a workspace. Does not initiate a build. | |
*/ | |
list: boolean, | |
} | |
class XCodebuild { | |
private commands: string[] | |
constructor() { | |
this.commands = [] | |
} | |
/** | |
* Archive a scheme from the build root (SYMROOT). This requires specifying a scheme. | |
*/ | |
public archive(): XCodebuild { | |
this.commands.push('archive') | |
return this; | |
} | |
/** | |
* Build the target in the build root (SYMROOT). This is the default build action. | |
*/ | |
public build(): XCodebuild { | |
this.commands.push('build') | |
return this; | |
} | |
/** | |
* Test a scheme from the build root (SYMROOT). This requires specifying a scheme. | |
*/ | |
public test(): XCodebuild { | |
this.commands.push('test') | |
return this; | |
} | |
/** | |
* Copy the source of the project to the source root (SRCROOT). | |
*/ | |
public installsrc(): XCodebuild { | |
this.commands.push('installsrc') | |
return this; | |
} | |
/** | |
* Build the target and install it into the target's installation directory in the distribution root | |
*/ | |
public install(): XCodebuild { | |
this.commands.push('install') | |
return this; | |
} | |
/** | |
* Remove build products and intermediate files from the build root (SYMROOT). | |
*/ | |
public clean(): XCodebuild { | |
this.commands.push('clean') | |
return this; | |
} | |
/** | |
* Execute the xcodebuild command. Will execute based on the order of the functions. | |
* @param options CLI options for xcodebuild | |
* @param spawnOptions Options to pass into child_process.spawn() | |
*/ | |
public run(options: Partial<XCodebuildOptions>, spawnOptions: SpawnOptions): Promise<void> { | |
let flags = ""; | |
(Object.keys(options) as Array<keyof XCodebuildOptions>).forEach(key => { | |
const value = options[key]; | |
if (typeof options[key] === 'boolean') { | |
if (value) { | |
flags += `-${key} ` | |
} | |
} else { | |
flags += `-${key} ${value} ` | |
} | |
}) | |
flags = flags.trim(); | |
let action = ""; | |
this.commands.forEach(cmd => action += `${cmd} `) | |
action = action.trim(); | |
const command = `xcodebuild ${flags} ${action}`; | |
return new Promise((resolve, reject) => { | |
const p = spawn(command, spawnOptions) | |
p.on('close', () => resolve()) | |
p.on('error', err => reject(err)) | |
}) | |
} | |
} | |
export const xcodebuild = new XCodebuild() | |
/** | |
* Silently runs a POSIX command synchronously to check if "xcodebuild" is in your path. | |
* @returns true if "xcodebuild" is in your path | |
*/ | |
export const isXcodeAvailable = (): boolean => { | |
// Auto-fail if running on Windows or WSL | |
if(process.platform === 'win32') { | |
return false | |
} | |
// POSIX compatible command that checks if xcodebuild exists in path | |
const exists = ` | |
#!/bin/sh | |
if command -v xcodebuild >/dev/null; then | |
echo true | |
else | |
echo false | |
fi | |
`.trim(); | |
try { | |
const stdout = execSync(exists, { stdio: [] }) | |
return JSON.parse(stdout.toString().trim()) | |
} catch (err) { | |
// command failed or couldn't parse output so probably can't use xcodebuild | |
return false | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment