1111 * - Standardizing response formatting for build results
1212 * - Managing build-specific error handling and reporting
1313 * - Supporting various build actions (build, clean, showBuildSettings, etc.)
14+ * - Supporting xcodemake as an alternative build strategy for faster incremental builds
1415 *
1516 * This file depends on the lower-level utilities in xcode.ts for command execution
1617 * while adding build-specific behavior, formatting, and error handling.
@@ -20,6 +21,14 @@ import { log } from './logger.js';
2021import { executeXcodeCommand , XcodePlatform , constructDestinationString } from './xcode.js' ;
2122import { ToolResponse , SharedBuildParams , PlatformBuildOptions } from '../types/common.js' ;
2223import { createTextResponse } from './validation.js' ;
24+ import {
25+ isXcodemakeEnabled ,
26+ isXcodemakeAvailable ,
27+ executeXcodemakeCommand ,
28+ executeMakeCommand ,
29+ doesMakefileExist ,
30+ } from './xcodemake.js' ;
31+ import path from 'path' ;
2332
2433/**
2534 * Common function to execute an Xcode build command across platforms
@@ -48,6 +57,27 @@ export async function executeXcodeBuild(
4857
4958 log ( 'info' , `Starting ${ platformOptions . logPrefix } ${ buildAction } for scheme ${ params . scheme } ` ) ;
5059
60+ // Check if xcodemake is enabled and available
61+ const useXcodemake = isXcodemakeEnabled ( ) ;
62+ let xcodemakeAvailable = false ;
63+
64+ if ( useXcodemake && buildAction === 'build' ) {
65+ xcodemakeAvailable = await isXcodemakeAvailable ( ) ;
66+ if ( ! xcodemakeAvailable ) {
67+ log ( 'warning' , 'xcodemake is enabled but not available. Falling back to xcodebuild.' ) ;
68+ buildMessages . push ( {
69+ type : 'text' ,
70+ text : '⚠️ xcodemake is enabled but not found in PATH. Falling back to xcodebuild.' ,
71+ } ) ;
72+ } else {
73+ log ( 'info' , 'Using xcodemake for faster incremental builds.' ) ;
74+ buildMessages . push ( {
75+ type : 'text' ,
76+ text : 'ℹ️ Using xcodemake for faster incremental builds.' ,
77+ } ) ;
78+ }
79+ }
80+
5181 try {
5282 const command = [ 'xcodebuild' ] ;
5383
@@ -116,13 +146,48 @@ export async function executeXcodeBuild(
116146 command . push ( '-derivedDataPath' , params . derivedDataPath ) ;
117147 }
118148
119- if ( params . extraArgs ) {
149+ if ( params . extraArgs && params . extraArgs . length > 0 ) {
120150 command . push ( ...params . extraArgs ) ;
121151 }
122152
123153 command . push ( buildAction ) ;
124154
125- const result = await executeXcodeCommand ( command , platformOptions . logPrefix ) ;
155+ // Determine project directory for xcodemake
156+ let projectDir = '' ;
157+ if ( params . workspacePath ) {
158+ projectDir = path . dirname ( params . workspacePath ) ;
159+ } else if ( params . projectPath ) {
160+ projectDir = path . dirname ( params . projectPath ) ;
161+ }
162+
163+ // Execute the command using xcodemake or xcodebuild
164+ let result ;
165+ if ( useXcodemake && xcodemakeAvailable && buildAction === 'build' ) {
166+ // Check if Makefile already exists
167+ const makefileExists = doesMakefileExist ( projectDir ) ;
168+
169+ if ( makefileExists ) {
170+ // Use make for incremental builds
171+ log ( 'info' , 'Makefile exists, using make for incremental build' ) ;
172+ buildMessages . push ( {
173+ type : 'text' ,
174+ text : 'ℹ️ Using make for incremental build' ,
175+ } ) ;
176+ result = await executeMakeCommand ( projectDir , platformOptions . logPrefix ) ;
177+ } else {
178+ // Generate Makefile using xcodemake
179+ log ( 'info' , 'Generating Makefile with xcodemake' ) ;
180+ buildMessages . push ( {
181+ type : 'text' ,
182+ text : 'ℹ️ Generating Makefile with xcodemake (first build may take longer)' ,
183+ } ) ;
184+ // Remove 'xcodebuild' from the command array before passing to executeXcodemakeCommand
185+ result = await executeXcodemakeCommand ( command . slice ( 1 ) , platformOptions . logPrefix ) ;
186+ }
187+ } else {
188+ // Use standard xcodebuild
189+ result = await executeXcodeCommand ( command , platformOptions . logPrefix ) ;
190+ }
126191
127192 // Grep warnings and errors from stdout (build output)
128193 const warningOrErrorLines = grepWarningsAndErrors ( result . output ) ;
@@ -163,6 +228,14 @@ export async function executeXcodeBuild(
163228 // Create additional info based on platform and action
164229 let additionalInfo = '' ;
165230
231+ // Add xcodemake info if relevant
232+ if ( useXcodemake && xcodemakeAvailable && buildAction === 'build' ) {
233+ additionalInfo += `xcodemake: Using faster incremental builds with xcodemake.
234+ Future builds will use the generated Makefile for improved performance.
235+
236+ ` ;
237+ }
238+
166239 // Only show next steps for 'build' action
167240 if ( buildAction === 'build' ) {
168241 if ( platformOptions . platform === XcodePlatform . macOS ) {
0 commit comments