Skip to content

Commit 9980f36

Browse files
authored
Merge pull request #397 from dennisameling/windows-arm64
Add ARM64/aarch64 support
2 parents 8ccb0df + 3072056 commit 9980f36

File tree

6 files changed

+163
-8
lines changed

6 files changed

+163
-8
lines changed

.vscode/settings.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
{
22
"cSpell.ignoreRegExpList": [
3+
"--noconfirm",
34
"CHERE_INVOKING",
45
"LC_CTYPE",
56
"SDK's",
7+
"aarch64",
8+
"base-devel",
9+
"clangarm64",
610
"makepkg-git",
711
"mingw-w64-git",
812
"mingw32",
913
"mingw64",
14+
"pcre2",
1015
"vstfs://.*"
1116
],
1217
"cSpell.words": [
1318
"artifactsize",
1419
"autodrain",
1520
"Backoff",
1621
"bitness",
22+
"Cygwin",
23+
"libiconv",
24+
"libssp",
1725
"mqueue",
26+
"MSYS",
1827
"MSYSTEM",
1928
"Pacman",
2029
"unzipper",

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ The supported flavors are:
5151

5252
### CPU architecture support
5353

54-
Git for Windows SDK comes in variants targeting `x86_64` (AKA "64-bit") and `i686` (AKA 32-bit). The default is `x86_64` and can be overridden like this:
54+
Git for Windows SDK comes in variants targeting `x86_64` (AKA "64-bit") and `i686` (AKA 32-bit). The default is `x86_64` and can be overridden like this:
5555

5656
```yaml
5757
- uses: git-for-windows/setup-git-for-windows-sdk
@@ -62,6 +62,8 @@ Git for Windows SDK comes in variants targeting `x86_64` (AKA "64-bit") and `i6
6262

6363
Please note that only the `build-installers` and the `full` flavors are available for `i686`.
6464

65+
As a special case, the architecture `aarch64` (AKA "ARM64") is also handled, even if there is no SDK fully targeting Windows/ARM64 (due to missing Cygwin/MSYS support for that architecture); Selecting this architecture will install the `x86_64` flavor of Git for Windows' SDK and then add the MINGW toolchain targeting Windows/ARM64.
66+
6567
### Verbosity
6668

6769
By default, this Action prints a line whenever 250 items were extracted (this does not work for the `full` flavor, where this Action is silent by default). It can be overridden by setting the input parameter `verbose`; setting it to a number will show updates whenever that many items were extracted. Setting it to `false` will suppress progress updates. Setting it to `true` will print every extracted file (this also works for the `full` flavor).

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ inputs:
1111
default: 'minimal'
1212
architecture:
1313
required: false
14-
description: 'The architecture of the SDK: x86_64 or i686'
14+
description: 'The architecture of the SDK: x86_64, i686 or aarch64. Note that "aarch64" uses the x86_64 SDK, but adds "clangarm64" to the path.'
1515
default: 'x86_64'
1616
msys:
1717
required: false

dist/index.js

Lines changed: 61 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

main.ts

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as core from '@actions/core'
22
import {mkdirp} from './src/downloader'
33
import {restoreCache, saveCache} from '@actions/cache'
44
import process from 'process'
5-
import {spawnSync} from 'child_process'
5+
import {spawn, spawnSync} from 'child_process'
66
import {
77
getArtifactMetadata,
88
getViaGit,
@@ -14,6 +14,61 @@ import * as coreCommand from '@actions/core/lib/command'
1414
const flavor = core.getInput('flavor')
1515
const architecture = core.getInput('architecture')
1616

17+
async function installArm64Dependencies(
18+
outputDirectory: string
19+
): Promise<void> {
20+
if (flavor === 'minimal') {
21+
throw new Error(`ARM64 not yet supported with flavor '${flavor}`)
22+
}
23+
24+
mkdirp(`${outputDirectory}/clangarm64`)
25+
fs.appendFileSync(
26+
`${outputDirectory}/etc/pacman.conf`,
27+
`
28+
[clangarm64]
29+
Server = https://mirror.msys2.org/mingw/clangarm64/`
30+
)
31+
32+
const packages = [
33+
'base-devel',
34+
'mingw-w64-clang-aarch64-openssl',
35+
'mingw-w64-clang-aarch64-zlib',
36+
'mingw-w64-clang-aarch64-curl',
37+
'mingw-w64-clang-aarch64-expat',
38+
'mingw-w64-clang-aarch64-libiconv',
39+
'mingw-w64-clang-aarch64-pcre2',
40+
'mingw-w64-clang-aarch64-libssp'
41+
]
42+
if (flavor === 'full' || flavor === 'makepkg-git') {
43+
packages.push(
44+
'mingw-w64-clang-aarch64-toolchain',
45+
'mingw-w64-clang-aarch64-asciidoc'
46+
)
47+
}
48+
49+
const child = spawn('pacman.exe', ['-Sy', '--noconfirm', ...packages])
50+
51+
child.stdout.setEncoding('utf-8')
52+
child.stderr.setEncoding('utf-8')
53+
54+
child.stdout.on('data', data => {
55+
core.info(data)
56+
})
57+
58+
child.stderr.on('data', data => {
59+
core.error(data)
60+
})
61+
62+
return new Promise((resolve, reject) => {
63+
child.on('error', error => reject(error))
64+
child.on('close', status =>
65+
status === 0
66+
? resolve()
67+
: reject(new Error(`Process exited with status code ${status}`))
68+
)
69+
})
70+
}
71+
1772
async function run(): Promise<void> {
1873
try {
1974
if (process.platform !== 'win32') {
@@ -22,10 +77,16 @@ async function run(): Promise<void> {
2277
)
2378
return
2479
}
80+
81+
const architectureToDownload =
82+
architecture === 'aarch64' ? 'x86_64' : architecture
2583
const verbose = core.getInput('verbose')
2684
const msysMode = core.getInput('msys') === 'true'
2785

28-
const {artifactName, download, id} = await getViaGit(flavor, architecture)
86+
const {artifactName, download, id} = await getViaGit(
87+
flavor,
88+
architectureToDownload
89+
)
2990
const outputDirectory = core.getInput('path') || `C:/${artifactName}`
3091
let useCache: boolean
3192
switch (core.getInput('cache')) {
@@ -68,7 +129,17 @@ async function run(): Promise<void> {
68129
}
69130
}
70131

71-
const mingw = architecture === 'i686' ? 'MINGW32' : 'MINGW64'
132+
const mingw = {
133+
i686: 'MINGW32',
134+
x86_64: 'MINGW64',
135+
aarch64: 'CLANGARM64'
136+
}[architecture]
137+
138+
if (mingw === undefined) {
139+
core.setFailed(`Invalid architecture ${architecture} specified`)
140+
return
141+
}
142+
72143
const msystem = msysMode ? 'MSYS' : mingw
73144

74145
const binPaths = [
@@ -77,6 +148,13 @@ async function run(): Promise<void> {
77148
'/usr/bin',
78149
`/${mingw.toLocaleLowerCase()}/bin`
79150
]
151+
152+
if (architecture === 'aarch64') {
153+
// Some binaries aren't available yet in the /clangarm64/bin folder, but Windows 11 ARM64
154+
// has support for x64 emulation, so let's add /mingw64/bin as a fallback.
155+
binPaths.splice(binPaths.length - 1, 0, '/mingw64/bin')
156+
}
157+
80158
for (const binPath of msysMode ? binPaths.reverse() : binPaths) {
81159
core.addPath(`${outputDirectory}${binPath}`)
82160
}
@@ -116,6 +194,13 @@ async function run(): Promise<void> {
116194
})) {
117195
ln(`/dev/${linkPath}`, `/proc/self/${target}`)
118196
}
197+
198+
if (msystem === 'CLANGARM64') {
199+
// ARM64 dependencies aren't included yet in the Git for Windows SDK. Ask Pacman to install them.
200+
core.startGroup(`Installing CLANGARM64 dependencies`)
201+
await installArm64Dependencies(outputDirectory)
202+
core.endGroup()
203+
}
119204
} catch (error) {
120205
core.setFailed(error instanceof Error ? error.message : `${error}`)
121206
}

0 commit comments

Comments
 (0)