Skip to content

Commit 7554e86

Browse files
Saadnajmiclaude
andcommitted
feat: add Apple framework CI to Azure Pipelines
Add Apple build stage to the 1ES pipeline template and a standalone Apple pipeline for environments without 1ES macOS support. Structure (3 phases, matching the Windows matrix pattern): 1. Build host hermesc compiler (single macOS job) 2. Build platform slices in parallel (8 slices x 2 flavors = 16 jobs) 3. Assemble universal xcframework per flavor (2 jobs) Each job calls build-apple.mts with selective --no-* flags. YAML handles only artifact orchestration, Xcode setup, and pool config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8c222e5 commit 7554e86

2 files changed

Lines changed: 352 additions & 0 deletions

File tree

.ado/apple-pipeline.yml

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#
2+
# Standalone pipeline for building Hermes Apple frameworks (macOS, iOS, tvOS, visionOS).
3+
# This pipeline runs outside the 1ES template since 1ES shared pools
4+
# do not currently offer macOS images.
5+
#
6+
7+
trigger: none
8+
pr: none
9+
10+
pool:
11+
vmImage: macos-15
12+
13+
variables:
14+
IOS_DEPLOYMENT_TARGET: "15.1"
15+
XROS_DEPLOYMENT_TARGET: "1.0"
16+
MAC_DEPLOYMENT_TARGET: "10.15"
17+
18+
parameters:
19+
- name: AppleSliceMatrix
20+
type: object
21+
default:
22+
- Name: macosx
23+
- Name: iphoneos
24+
- Name: iphonesimulator
25+
- Name: appletvos
26+
- Name: appletvsimulator
27+
- Name: catalyst
28+
- Name: xros
29+
- Name: xrsimulator
30+
31+
- name: AppleFlavorMatrix
32+
type: object
33+
default:
34+
- Name: Debug
35+
- Name: Release
36+
37+
stages:
38+
- stage: build_apple
39+
displayName: Build Apple Frameworks
40+
jobs:
41+
42+
#=========================================================================
43+
# Step 1: Build the host HermesC compiler.
44+
#=========================================================================
45+
- job: Build_HermesC_Apple
46+
displayName: Build HermesC (Apple host)
47+
steps:
48+
- checkout: self
49+
- task: UseNode@1
50+
displayName: Use Node.js 22.x
51+
inputs:
52+
version: 22.x
53+
- script: |
54+
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
55+
xcodebuild -version
56+
displayName: Setup Xcode
57+
- script: >
58+
node .ado/scripts/build-apple.mts
59+
--no-build
60+
--no-build-xcframework
61+
displayName: Build host hermesc
62+
- publish: $(Build.SourcesDirectory)/build_host_hermesc
63+
artifact: hermesc-apple
64+
displayName: Publish HermesC artifact
65+
66+
#=========================================================================
67+
# Step 2: Build each Apple platform slice (matrix: slice x flavor).
68+
#=========================================================================
69+
- ${{ each flavor in parameters.AppleFlavorMatrix }}:
70+
- ${{ each slice in parameters.AppleSliceMatrix }}:
71+
- job: Build_Apple_${{ slice.Name }}_${{ flavor.Name }}
72+
displayName: Build Apple ${{ slice.Name }} (${{ flavor.Name }})
73+
dependsOn: Build_HermesC_Apple
74+
timeoutInMinutes: 120
75+
steps:
76+
- checkout: self
77+
- task: UseNode@1
78+
displayName: Use Node.js 22.x
79+
inputs:
80+
version: 22.x
81+
- script: |
82+
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
83+
displayName: Setup Xcode
84+
- download: current
85+
artifact: hermesc-apple
86+
displayName: Download HermesC artifact
87+
- script: |
88+
cp -R $(Pipeline.Workspace)/hermesc-apple $(Build.SourcesDirectory)/build_host_hermesc
89+
chmod +x ./build_host_hermesc/bin/hermesc
90+
91+
node .ado/scripts/build-apple.mts \
92+
--no-build-hermesc \
93+
--slice ${{ slice.Name }} \
94+
--configuration ${{ flavor.Name }} \
95+
--no-build-xcframework
96+
97+
# Rename for artifact uniqueness and compress to preserve symlinks
98+
mv "build_${{ slice.Name }}" "build_${{ slice.Name }}_${{ flavor.Name }}"
99+
tar -czf "build_${{ slice.Name }}_${{ flavor.Name }}.tar.gz" "build_${{ slice.Name }}_${{ flavor.Name }}"
100+
displayName: Build ${{ slice.Name }} ${{ flavor.Name }} framework
101+
- publish: $(Build.SourcesDirectory)/build_${{ slice.Name }}_${{ flavor.Name }}.tar.gz
102+
artifact: apple-slice-${{ slice.Name }}-${{ flavor.Name }}
103+
displayName: Publish ${{ slice.Name }} ${{ flavor.Name }} artifact
104+
105+
#=========================================================================
106+
# Step 3: Assemble universal xcframework from all slices (per flavor).
107+
#=========================================================================
108+
- ${{ each flavor in parameters.AppleFlavorMatrix }}:
109+
- job: Build_Apple_XCFramework_${{ flavor.Name }}
110+
displayName: Build Apple XCFramework (${{ flavor.Name }})
111+
dependsOn:
112+
- ${{ each slice in parameters.AppleSliceMatrix }}:
113+
- Build_Apple_${{ slice.Name }}_${{ flavor.Name }}
114+
timeoutInMinutes: 60
115+
steps:
116+
- checkout: self
117+
- task: UseNode@1
118+
displayName: Use Node.js 22.x
119+
inputs:
120+
version: 22.x
121+
- script: |
122+
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
123+
displayName: Setup Xcode
124+
125+
# Download all slice artifacts for this flavor.
126+
- ${{ each slice in parameters.AppleSliceMatrix }}:
127+
- download: current
128+
artifact: apple-slice-${{ slice.Name }}-${{ flavor.Name }}
129+
displayName: Download ${{ slice.Name }} ${{ flavor.Name }} slice
130+
131+
# Untar and rename all slices back to build_<slice> for the script.
132+
- script: |
133+
set -euo pipefail
134+
SLICES="macosx iphoneos iphonesimulator appletvos appletvsimulator catalyst xros xrsimulator"
135+
for SLICE in $SLICES; do
136+
cp "$(Pipeline.Workspace)/apple-slice-${SLICE}-${{ flavor.Name }}/build_${SLICE}_${{ flavor.Name }}.tar.gz" .
137+
tar -xzf "build_${SLICE}_${{ flavor.Name }}.tar.gz"
138+
mv "build_${SLICE}_${{ flavor.Name }}" "build_${SLICE}"
139+
done
140+
displayName: Unpack slice artifacts
141+
142+
# Assemble universal xcframework and create dSYM archive.
143+
- script: >
144+
node .ado/scripts/build-apple.mts
145+
--no-build-hermesc
146+
--no-build
147+
--configuration ${{ flavor.Name }}
148+
--create-dsym-archive
149+
displayName: Create universal xcframework
150+
151+
- publish: $(Build.SourcesDirectory)/destroot
152+
artifact: apple-hermes-xcframework-${{ flavor.Name }}
153+
displayName: Publish xcframework artifact
154+
- publish: $(Build.SourcesDirectory)/hermes-dSYM-${{ flavor.Name }}.tar.gz
155+
artifact: apple-hermes-dsym-${{ flavor.Name }}
156+
displayName: Publish dSYM artifact

.ado/build-template.yml

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@ parameters:
1313
type: boolean
1414
default: false
1515

16+
# Matrix with Apple platform slices for Hermes xcframework.
17+
- name: AppleSliceMatrix
18+
type: object
19+
default:
20+
- Name: macosx
21+
- Name: iphoneos
22+
- Name: iphonesimulator
23+
- Name: appletvos
24+
- Name: appletvsimulator
25+
- Name: catalyst
26+
- Name: xros
27+
- Name: xrsimulator
28+
29+
- name: AppleFlavorMatrix
30+
type: object
31+
default:
32+
- Name: Debug
33+
- Name: Release
34+
1635
# Matrix with target platforms for Hermes binaries.
1736
- name: BuildMatrix
1837
type: object
@@ -44,6 +63,7 @@ parameters:
4463
TargetCPU: arm64ec
4564
BuildUWP: --no-uwp
4665

66+
4767
resources:
4868
repositories:
4969
# The repo for the Office compliant build pipeline templates.
@@ -355,3 +375,179 @@ extends:
355375
"ToolVersion" : "1.0"
356376
}
357377
]
378+
379+
#=============================================================================
380+
# Apple framework builds
381+
# Builds Hermes for all Apple platforms (macOS, iOS, tvOS, visionOS, catalyst)
382+
# and assembles them into a universal xcframework.
383+
#=============================================================================
384+
- stage: apple
385+
dependsOn: [] # Run in parallel with the Windows 'main' stage
386+
jobs:
387+
388+
# Step 1: Build the host HermesC compiler on macOS.
389+
- job: Build_HermesC_Apple
390+
displayName: Build HermesC (Apple host)
391+
392+
pool:
393+
name: Azure Pipelines
394+
vmImage: macos-15
395+
os: macOS
396+
397+
variables:
398+
- name: skipComponentGovernanceDetection
399+
value: true
400+
- name: ONEES_ENFORCED_CODEQL_ENABLED
401+
value: false
402+
403+
templateContext:
404+
outputs:
405+
- output: pipelineArtifact
406+
artifactName: hermesc-apple
407+
targetPath: $(Build.SourcesDirectory)/build_host_hermesc
408+
409+
steps:
410+
- checkout: self
411+
- task: UseNode@1
412+
displayName: Use Node.js 22.x
413+
inputs:
414+
version: 22.x
415+
- script: |
416+
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
417+
xcodebuild -version
418+
displayName: Setup Xcode
419+
- script: >
420+
node .ado/scripts/build-apple.mts
421+
--no-build
422+
--no-build-xcframework
423+
displayName: Build host hermesc
424+
425+
# Step 2: Build each Apple platform slice (matrix: slice x flavor).
426+
- ${{ each flavor in parameters.AppleFlavorMatrix }}:
427+
- ${{ each slice in parameters.AppleSliceMatrix }}:
428+
- job: Build_Apple_${{ slice.Name }}_${{ flavor.Name }}
429+
displayName: Build Apple ${{ slice.Name }} (${{ flavor.Name }})
430+
431+
dependsOn:
432+
- Build_HermesC_Apple
433+
434+
pool:
435+
name: Azure Pipelines
436+
vmImage: macos-15
437+
os: macOS
438+
439+
timeoutInMinutes: 120
440+
441+
variables:
442+
- name: skipComponentGovernanceDetection
443+
value: true
444+
- name: ONEES_ENFORCED_CODEQL_ENABLED
445+
value: false
446+
447+
templateContext:
448+
outputs:
449+
- output: pipelineArtifact
450+
artifactName: apple-slice-${{ slice.Name }}-${{ flavor.Name }}
451+
targetPath: $(Build.SourcesDirectory)/build_${{ slice.Name }}_${{ flavor.Name }}.tar.gz
452+
453+
steps:
454+
- checkout: self
455+
456+
- task: UseNode@1
457+
displayName: Use Node.js 22.x
458+
inputs:
459+
version: 22.x
460+
461+
- script: |
462+
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
463+
displayName: Setup Xcode
464+
465+
- task: DownloadPipelineArtifact@2
466+
displayName: Download HermesC artifact
467+
inputs:
468+
artifact: hermesc-apple
469+
path: $(Build.SourcesDirectory)/build_host_hermesc
470+
471+
- script: |
472+
chmod +x ./build_host_hermesc/bin/hermesc
473+
474+
node .ado/scripts/build-apple.mts \
475+
--no-build-hermesc \
476+
--slice ${{ slice.Name }} \
477+
--configuration ${{ flavor.Name }} \
478+
--no-build-xcframework
479+
480+
# Rename for artifact uniqueness and compress to preserve symlinks
481+
mv "build_${{ slice.Name }}" "build_${{ slice.Name }}_${{ flavor.Name }}"
482+
tar -czf "build_${{ slice.Name }}_${{ flavor.Name }}.tar.gz" "build_${{ slice.Name }}_${{ flavor.Name }}"
483+
displayName: Build ${{ slice.Name }} ${{ flavor.Name }} framework
484+
485+
# Step 3: Assemble universal xcframework from all slices (per flavor).
486+
- ${{ each flavor in parameters.AppleFlavorMatrix }}:
487+
- job: Build_Apple_XCFramework_${{ flavor.Name }}
488+
displayName: Build Apple XCFramework (${{ flavor.Name }})
489+
490+
dependsOn:
491+
- ${{ each slice in parameters.AppleSliceMatrix }}:
492+
- Build_Apple_${{ slice.Name }}_${{ flavor.Name }}
493+
494+
pool:
495+
name: Azure Pipelines
496+
vmImage: macos-15
497+
os: macOS
498+
499+
timeoutInMinutes: 60
500+
501+
variables:
502+
- name: skipComponentGovernanceDetection
503+
value: true
504+
- name: ONEES_ENFORCED_CODEQL_ENABLED
505+
value: false
506+
507+
templateContext:
508+
outputs:
509+
- output: pipelineArtifact
510+
artifactName: apple-hermes-xcframework-${{ flavor.Name }}
511+
targetPath: $(Build.SourcesDirectory)/destroot
512+
- output: pipelineArtifact
513+
artifactName: apple-hermes-dsym-${{ flavor.Name }}
514+
targetPath: $(Build.SourcesDirectory)/hermes-dSYM-${{ flavor.Name }}.tar.gz
515+
516+
steps:
517+
- checkout: self
518+
519+
- task: UseNode@1
520+
displayName: Use Node.js 22.x
521+
inputs:
522+
version: 22.x
523+
524+
- script: |
525+
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
526+
displayName: Setup Xcode
527+
528+
# Download all slice artifacts for this flavor.
529+
- ${{ each slice in parameters.AppleSliceMatrix }}:
530+
- task: DownloadPipelineArtifact@2
531+
displayName: Download ${{ slice.Name }} ${{ flavor.Name }} slice
532+
inputs:
533+
artifact: apple-slice-${{ slice.Name }}-${{ flavor.Name }}
534+
path: $(Build.SourcesDirectory)
535+
536+
# Untar and rename all slices back to build_<slice> for the script.
537+
- script: |
538+
set -euo pipefail
539+
SLICES="macosx iphoneos iphonesimulator appletvos appletvsimulator catalyst xros xrsimulator"
540+
for SLICE in $SLICES; do
541+
tar -xzf "build_${SLICE}_${{ flavor.Name }}.tar.gz"
542+
mv "build_${SLICE}_${{ flavor.Name }}" "build_${SLICE}"
543+
done
544+
displayName: Unpack slice artifacts
545+
546+
# Assemble universal xcframework and create dSYM archive.
547+
- script: >
548+
node .ado/scripts/build-apple.mts
549+
--no-build-hermesc
550+
--no-build
551+
--configuration ${{ flavor.Name }}
552+
--create-dsym-archive
553+
displayName: Create universal xcframework

0 commit comments

Comments
 (0)