Skip to content

Add ARM64/aarch64 support #397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
{
"cSpell.ignoreRegExpList": [
"--noconfirm",
"CHERE_INVOKING",
"LC_CTYPE",
"SDK's",
"aarch64",
"base-devel",
"clangarm64",
"makepkg-git",
"mingw-w64-git",
"mingw32",
"mingw64",
"pcre2",
"vstfs://.*"
],
"cSpell.words": [
"artifactsize",
"autodrain",
"Backoff",
"bitness",
"Cygwin",
"libiconv",
"libssp",
"mqueue",
"MSYS",
"MSYSTEM",
"Pacman",
"unzipper",
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The supported flavors are:

### CPU architecture support

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:
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:

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

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

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.

### Verbosity

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).
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ inputs:
default: 'minimal'
architecture:
required: false
description: 'The architecture of the SDK: x86_64 or i686'
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.'
default: 'x86_64'
msys:
required: false
Expand Down
63 changes: 61 additions & 2 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

91 changes: 88 additions & 3 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as core from '@actions/core'
import {mkdirp} from './src/downloader'
import {restoreCache, saveCache} from '@actions/cache'
import process from 'process'
import {spawnSync} from 'child_process'
import {spawn, spawnSync} from 'child_process'
import {
getArtifactMetadata,
getViaGit,
Expand All @@ -14,6 +14,61 @@ import * as coreCommand from '@actions/core/lib/command'
const flavor = core.getInput('flavor')
const architecture = core.getInput('architecture')

async function installArm64Dependencies(
outputDirectory: string
): Promise<void> {
if (flavor === 'minimal') {
throw new Error(`ARM64 not yet supported with flavor '${flavor}`)
}

mkdirp(`${outputDirectory}/clangarm64`)
fs.appendFileSync(
`${outputDirectory}/etc/pacman.conf`,
`
[clangarm64]
Server = https://mirror.msys2.org/mingw/clangarm64/`
)

const packages = [
'base-devel',
'mingw-w64-clang-aarch64-openssl',
'mingw-w64-clang-aarch64-zlib',
'mingw-w64-clang-aarch64-curl',
'mingw-w64-clang-aarch64-expat',
'mingw-w64-clang-aarch64-libiconv',
'mingw-w64-clang-aarch64-pcre2',
'mingw-w64-clang-aarch64-libssp'
]
if (flavor === 'full' || flavor === 'makepkg-git') {
packages.push(
'mingw-w64-clang-aarch64-toolchain',
'mingw-w64-clang-aarch64-asciidoc'
)
}

const child = spawn('pacman.exe', ['-Sy', '--noconfirm', ...packages])

child.stdout.setEncoding('utf-8')
child.stderr.setEncoding('utf-8')

child.stdout.on('data', data => {
core.info(data)
})

child.stderr.on('data', data => {
core.error(data)
})

return new Promise((resolve, reject) => {
child.on('error', error => reject(error))
child.on('close', status =>
status === 0
? resolve()
: reject(new Error(`Process exited with status code ${status}`))
)
})
}

async function run(): Promise<void> {
try {
if (process.platform !== 'win32') {
Expand All @@ -22,10 +77,16 @@ async function run(): Promise<void> {
)
return
}

const architectureToDownload =
architecture === 'aarch64' ? 'x86_64' : architecture
const verbose = core.getInput('verbose')
const msysMode = core.getInput('msys') === 'true'

const {artifactName, download, id} = await getViaGit(flavor, architecture)
const {artifactName, download, id} = await getViaGit(
flavor,
architectureToDownload
)
const outputDirectory = core.getInput('path') || `C:/${artifactName}`
let useCache: boolean
switch (core.getInput('cache')) {
Expand Down Expand Up @@ -68,7 +129,17 @@ async function run(): Promise<void> {
}
}

const mingw = architecture === 'i686' ? 'MINGW32' : 'MINGW64'
const mingw = {
i686: 'MINGW32',
x86_64: 'MINGW64',
aarch64: 'CLANGARM64'
}[architecture]

if (mingw === undefined) {
core.setFailed(`Invalid architecture ${architecture} specified`)
return
}

const msystem = msysMode ? 'MSYS' : mingw

const binPaths = [
Expand All @@ -77,6 +148,13 @@ async function run(): Promise<void> {
'/usr/bin',
`/${mingw.toLocaleLowerCase()}/bin`
]

if (architecture === 'aarch64') {
// Some binaries aren't available yet in the /clangarm64/bin folder, but Windows 11 ARM64
// has support for x64 emulation, so let's add /mingw64/bin as a fallback.
binPaths.splice(binPaths.length - 1, 0, '/mingw64/bin')
}

for (const binPath of msysMode ? binPaths.reverse() : binPaths) {
core.addPath(`${outputDirectory}${binPath}`)
}
Expand Down Expand Up @@ -116,6 +194,13 @@ async function run(): Promise<void> {
})) {
ln(`/dev/${linkPath}`, `/proc/self/${target}`)
}

if (msystem === 'CLANGARM64') {
// ARM64 dependencies aren't included yet in the Git for Windows SDK. Ask Pacman to install them.
core.startGroup(`Installing CLANGARM64 dependencies`)
await installArm64Dependencies(outputDirectory)
core.endGroup()
}
} catch (error) {
core.setFailed(error instanceof Error ? error.message : `${error}`)
}
Expand Down