Skip to content

Commit 7e70eea

Browse files
dpogueArcTanSusan
andcommitted
feat!: Remove some Xcode build dir overrides
Once upon a time, Xcode's default directory values had issues when there were spaces in project names, so we override the CONFIGURATION_BUILD_DIR and SHARED_PRECOMPS_DIR variables with our own paths. However, this can interfere with Cocoapods, and Xcode should be able to handle things sensibly nowadays. Unfortunately, that results in our build artifacts living somewhere in a randomly-named Xcode DerivedData directory, and then we can't do things like run the app in a simulator or on a device because we don't know the path to it. Setting SYMROOT allows us to control the output directory of the built products, with the caveat that Xcode always creates a subdirectory named with the current configuration. So instead of `build/emulator`, we'll have `build/Debug-iphonesimulator` and instead of `build/device`, we'll have `build/Release-iphoneos`. Hypothetically this is better because now we are sure that debug and release files never get mixed up in the same output directory. The downside is that this is a breaking change because it alters the path for the output .ipa files. Closes #617. Closes #659. Closes #671. Co-Authored-By: Susan Tan <[email protected]>
1 parent 3d6c71a commit 7e70eea

File tree

3 files changed

+75
-33
lines changed

3 files changed

+75
-33
lines changed

lib/build.js

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ module.exports.run = function (buildOpts) {
219219
events.emit('log', `\tPlatform: ${buildOpts.device ? 'device' : 'emulator'}`);
220220
events.emit('log', `\tTarget: ${emulatorTarget}`);
221221

222-
const buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator'));
222+
const buildOutputDir = path.join(projectPath, 'build', `${configuration}-${(buildOpts.device ? 'iphoneos' : 'iphonesimulator')}`);
223223

224-
// remove the build/device folder before building
224+
// remove the build output folder before building
225225
fs.removeSync(buildOutputDir);
226226

227227
const xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, emulatorTarget, buildOpts);
@@ -264,7 +264,8 @@ module.exports.run = function (buildOpts) {
264264
const exportOptionsPlist = plist.build(exportOptions);
265265
const exportOptionsPath = path.join(projectPath, 'exportOptions.plist');
266266

267-
const buildOutputDir = path.join(projectPath, 'build', 'device');
267+
const configuration = buildOpts.release ? 'Release' : 'Debug';
268+
const buildOutputDir = path.join(projectPath, 'build', `${configuration}-iphoneos`);
268269

269270
function checkSystemRuby () {
270271
const ruby_cmd = which.sync('ruby', { nothrow: true });
@@ -346,10 +347,16 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, emulatorTar
346347
'-archivePath', customArgs.archivePath || `${projectName}.xcarchive`
347348
];
348349
buildActions = ['archive'];
349-
settings = [
350-
customArgs.configuration_build_dir || `CONFIGURATION_BUILD_DIR=${path.join(projectPath, 'build', 'device')}`,
351-
customArgs.shared_precomps_dir || `SHARED_PRECOMPS_DIR=${path.join(projectPath, 'build', 'sharedpch')}`
352-
];
350+
settings = [`SYMROOT=${path.join(projectPath, 'build')}`];
351+
352+
if (customArgs.configuration_build_dir) {
353+
settings.push(customArgs.configuration_build_dir);
354+
}
355+
356+
if (customArgs.shared_precomps_dir) {
357+
settings.push(customArgs.shared_precomps_dir);
358+
}
359+
353360
// Add other matched flags to otherFlags to let xcodebuild present an appropriate error.
354361
// This is preferable to just ignoring the flags that the user has passed in.
355362
if (customArgs.sdk) {
@@ -370,17 +377,23 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, emulatorTar
370377
}
371378
} else { // emulator
372379
options = [
373-
'-workspace', customArgs.project || `${projectName}.xcworkspace`,
380+
'-workspace', customArgs.workspace || `${projectName}.xcworkspace`,
374381
'-scheme', customArgs.scheme || projectName,
375382
'-configuration', customArgs.configuration || configuration,
376383
'-sdk', customArgs.sdk || 'iphonesimulator',
377384
'-destination', customArgs.destination || `platform=iOS Simulator,name=${emulatorTarget}`
378385
];
379386
buildActions = ['build'];
380-
settings = [
381-
customArgs.configuration_build_dir || `CONFIGURATION_BUILD_DIR=${path.join(projectPath, 'build', 'emulator')}`,
382-
customArgs.shared_precomps_dir || `SHARED_PRECOMPS_DIR=${path.join(projectPath, 'build', 'sharedpch')}`
383-
];
387+
settings = [`SYMROOT=${path.join(projectPath, 'build')}`];
388+
389+
if (customArgs.configuration_build_dir) {
390+
settings.push(customArgs.configuration_build_dir);
391+
}
392+
393+
if (customArgs.shared_precomps_dir) {
394+
settings.push(customArgs.shared_precomps_dir);
395+
}
396+
384397
// Add other matched flags to otherFlags to let xcodebuild present an appropriate error.
385398
// This is preferable to just ignoring the flags that the user has passed in.
386399
if (customArgs.archivePath) {

lib/run.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ module.exports.run = function (runOptions) {
4242
}
4343

4444
let useDevice = !!runOptions.device;
45+
const configuration = runOptions.release ? 'Release' : 'Debug';
4546

4647
return require('./listDevices').run()
4748
.then(devices => {
@@ -60,7 +61,7 @@ module.exports.run = function (runOptions) {
6061
}
6162
}).then(() => build.findXCodeProjectIn(projectPath))
6263
.then(projectName => {
63-
let appPath = path.join(projectPath, 'build', 'emulator', `${projectName}.app`);
64+
let appPath = path.join(projectPath, 'build', `${configuration}-iphonesimulator`, `${projectName}.app`);
6465
const buildOutputDir = path.join(projectPath, 'build', 'device');
6566

6667
// select command to run and arguments depending whether
@@ -91,7 +92,7 @@ module.exports.run = function (runOptions) {
9192
})
9293
.then(
9394
() => {
94-
appPath = path.join(projectPath, 'build', 'device', `${projectName}.app`);
95+
appPath = path.join(projectPath, 'build', `${configuration}-iphoneos`, `${projectName}.app`);
9596
let extraArgs = [];
9697
if (runOptions.argv) {
9798
// argv.slice(2) removes node and run.js, filterSupportedArgs removes the run.js args

tests/spec/unit/build.spec.js

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,9 @@ describe('build', () => {
4444
'-archivePath',
4545
'TestProjectName.xcarchive',
4646
'archive',
47-
`CONFIGURATION_BUILD_DIR=${path.join(testProjectPath, 'build', 'device')}`,
48-
`SHARED_PRECOMPS_DIR=${path.join(testProjectPath, 'build', 'sharedpch')}`
47+
`SYMROOT=${path.join(testProjectPath, 'build')}`
4948
]);
50-
expect(args.length).toEqual(13);
49+
expect(args.length).toEqual(12);
5150
});
5251

5352
it('should generate appropriate args if buildFlags are passed in', () => {
@@ -74,10 +73,11 @@ describe('build', () => {
7473
'-archivePath',
7574
'TestArchivePathFlag',
7675
'archive',
76+
`SYMROOT=${path.join(testProjectPath, 'build')}`,
7777
'CONFIGURATION_BUILD_DIR=TestConfigBuildDirFlag',
7878
'SHARED_PRECOMPS_DIR=TestSharedPrecompsDirFlag'
7979
]);
80-
expect(args.length).toEqual(13);
80+
expect(args.length).toEqual(14);
8181
});
8282

8383
it('should generate appropriate args for device', () => {
@@ -94,10 +94,9 @@ describe('build', () => {
9494
'-archivePath',
9595
'TestProjectName.xcarchive',
9696
'archive',
97-
`CONFIGURATION_BUILD_DIR=${path.join(testProjectPath, 'build', 'device')}`,
98-
`SHARED_PRECOMPS_DIR=${path.join(testProjectPath, 'build', 'sharedpch')}`
97+
`SYMROOT=${path.join(testProjectPath, 'build')}`
9998
]);
100-
expect(args.length).toEqual(13);
99+
expect(args.length).toEqual(12);
101100
});
102101

103102
it('should generate appropriate args for simulator', () => {
@@ -114,10 +113,42 @@ describe('build', () => {
114113
'-destination',
115114
'platform=iOS Simulator,name=iPhone 5s',
116115
'build',
117-
`CONFIGURATION_BUILD_DIR=${path.join(testProjectPath, 'build', 'emulator')}`,
118-
`SHARED_PRECOMPS_DIR=${path.join(testProjectPath, 'build', 'sharedpch')}`
116+
`SYMROOT=${path.join(testProjectPath, 'build')}`
119117
]);
120-
expect(args.length).toEqual(13);
118+
expect(args.length).toEqual(12);
119+
});
120+
121+
it('should generate appropriate args for simulator if buildFlags are passed in', () => {
122+
const buildFlags = [
123+
'-workspace TestWorkspaceFlag',
124+
'-scheme TestSchemeFlag',
125+
'-configuration TestConfigurationFlag',
126+
'-destination TestDestinationFlag',
127+
'-archivePath TestArchivePathFlag',
128+
'CONFIGURATION_BUILD_DIR=TestConfigBuildDirFlag',
129+
'SHARED_PRECOMPS_DIR=TestSharedPrecompsDirFlag'
130+
];
131+
132+
const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', 'iPhone 5s', { device: false, buildFlag: buildFlags });
133+
expect(args).toEqual([
134+
'-workspace',
135+
'TestWorkspaceFlag',
136+
'-scheme',
137+
'TestSchemeFlag',
138+
'-configuration',
139+
'TestConfigurationFlag',
140+
'-sdk',
141+
'iphonesimulator',
142+
'-destination',
143+
'TestDestinationFlag',
144+
'build',
145+
`SYMROOT=${path.join(testProjectPath, 'build')}`,
146+
'CONFIGURATION_BUILD_DIR=TestConfigBuildDirFlag',
147+
'SHARED_PRECOMPS_DIR=TestSharedPrecompsDirFlag',
148+
'-archivePath',
149+
'TestArchivePathFlag'
150+
]);
151+
expect(args.length).toEqual(16);
121152
});
122153

123154
it('should add matched flags that are not overriding for device', () => {
@@ -136,12 +167,11 @@ describe('build', () => {
136167
'-archivePath',
137168
'TestProjectName.xcarchive',
138169
'archive',
139-
`CONFIGURATION_BUILD_DIR=${path.join(testProjectPath, 'build', 'device')}`,
140-
`SHARED_PRECOMPS_DIR=${path.join(testProjectPath, 'build', 'sharedpch')}`,
170+
`SYMROOT=${path.join(testProjectPath, 'build')}`,
141171
'-sdk',
142172
'TestSdkFlag'
143173
]);
144-
expect(args.length).toEqual(15);
174+
expect(args.length).toEqual(14);
145175
});
146176

147177
it('should add matched flags that are not overriding for simulator', () => {
@@ -160,12 +190,11 @@ describe('build', () => {
160190
'-destination',
161191
'platform=iOS Simulator,name=iPhone 5s',
162192
'build',
163-
`CONFIGURATION_BUILD_DIR=${path.join(testProjectPath, 'build', 'emulator')}`,
164-
`SHARED_PRECOMPS_DIR=${path.join(testProjectPath, 'build', 'sharedpch')}`,
193+
`SYMROOT=${path.join(testProjectPath, 'build')}`,
165194
'-archivePath',
166195
'TestArchivePathFlag'
167196
]);
168-
expect(args.length).toEqual(15);
197+
expect(args.length).toEqual(14);
169198
});
170199

171200
it('should generate appropriate args for automatic provisioning', () => {
@@ -197,10 +226,9 @@ describe('build', () => {
197226
'-authenticationKeyIssuerID',
198227
'00000000-0000-0000-0000-000000000000',
199228
'archive',
200-
`CONFIGURATION_BUILD_DIR=${path.join(testProjectPath, 'build', 'device')}`,
201-
`SHARED_PRECOMPS_DIR=${path.join(testProjectPath, 'build', 'sharedpch')}`
229+
`SYMROOT=${path.join(testProjectPath, 'build')}`
202230
]);
203-
expect(args.length).toEqual(20);
231+
expect(args.length).toEqual(19);
204232
});
205233
});
206234

0 commit comments

Comments
 (0)