Skip to content

Commit

Permalink
fix: fixed latest toolchain(> 5.6) setup failure on Windows (#3)
Browse files Browse the repository at this point in the history
* fix: fixed latest toolchain(> 5.6) setup failure on Windows

* wip: log path

* fix: added fix for development snapshots
  • Loading branch information
soumyamahunt authored Aug 30, 2023
1 parent a1e6eac commit da27e5b
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 64 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,19 @@ jobs:
cancel-in-progress: true
strategy:
matrix:
os: [ubuntu-latest, macos-latest, macos-13]
os: [ubuntu-latest, macos-latest, windows-latest]
swift: ['latest']
development: [false, true]
include:
- os: macos-latest
swift: '5.0.0'
development: false
- os: macos-13
swift: 'latest'
development: false
- os: ubuntu-latest
swift: '5.3.0'
development: false
- os: windows-latest
swift: '5.6'
development: false
- os: windows-latest
swift: '5.3'
development: false
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Setup Swift

[![GitHub Action](https://img.shields.io/github/v/tag/SwiftyLab/setup-swift?logo=github&label=GitHub)](https://badge.fury.io/gh/SwiftyLab%2Fsetup-swift)
[![GitHub Action](https://img.shields.io/github/v/tag/SwiftyLab/setup-swift?logo=github&label=GitHub)](https://github.com/marketplace/actions/setup-swift-environment-for-macos-linux-and-windows)
[![Supports macOS, Linux & Windows](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-blue?label=platform)](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources)
[![Swift 5.9](https://img.shields.io/badge/Swift-5.9-orange?logo=swift&logoColor=white)](https://swift.org)
[![CI/CD](https://github.com/SwiftyLab/setup-swift/actions/workflows/main.yml/badge.svg)](https://github.com/SwiftyLab/setup-swift/actions/workflows/main.yml)
Expand All @@ -24,7 +24,8 @@ Or use the latest development snapshots by enabling the `development` flag:

```yml
- uses: SwiftyLab/setup-swift@latest
development: true
with:
development: true
```

After the environment is configured you can run swift and xcode commands using the standard [`run`](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsrun) step:
Expand Down
22 changes: 21 additions & 1 deletion __tests__/installer/windows.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,37 @@ describe('windows toolchain installation verification', () => {
expect(installer['visualStudio']).toStrictEqual(visualStudio)
})

it('tests unpack', async () => {
it('tests unpack for default toolchains', async () => {
const installer = new WindowsToolchainInstaller(toolchain)
const exe = path.resolve('tool', 'downloaded', 'toolchain.exe')
const extracted = path.resolve('tool', 'extracted', 'path')
process.env.SystemDrive = 'C:'
jest.spyOn(toolCache, 'extractTar').mockResolvedValue(extracted)
jest.spyOn(exec, 'exec').mockResolvedValue(0)
jest.spyOn(fs, 'access').mockRejectedValueOnce(new Error())
jest.spyOn(fs, 'access').mockResolvedValue()
jest.spyOn(fs, 'cp').mockResolvedValue()
const toolPath = path.join(process.env.SystemDrive, 'Library')
await expect(installer['unpack'](exe)).resolves.toBe(toolPath)
})

it('tests unpack for development snapshots', async () => {
const installer = new WindowsToolchainInstaller(toolchain)
const exe = path.resolve('tool', 'downloaded', 'toolchain.exe')
const extracted = path.resolve('tool', 'extracted', 'path')
process.env.SystemDrive = 'C:'
jest.spyOn(toolCache, 'extractTar').mockResolvedValue(extracted)
jest.spyOn(exec, 'exec').mockResolvedValue(0)
jest.spyOn(fs, 'access').mockResolvedValue()
jest.spyOn(fs, 'cp').mockResolvedValue()
const toolPath = path.join(
process.env.SystemDrive,
'Program Files',
'Swift'
)
await expect(installer['unpack'](exe)).resolves.toBe(toolPath)
})

it('tests add to PATH', async () => {
const installer = new WindowsToolchainInstaller(toolchain)
installer['visualStudio'] = visualStudio
Expand Down
93 changes: 77 additions & 16 deletions dist/index.js

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

139 changes: 98 additions & 41 deletions src/installer/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,52 +45,29 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller<Windo
protected async unpack(exe: string) {
core.debug(`Installing toolchain from "${exe}"`)
const code = await exec(`"${exe}"`, ['-q'])
const installation = path.join(process.env.SystemDrive ?? 'C:', 'Library')
const toolchain = path.join(
installation,
'Developer',
'Toolchains',
'unknown-Asserts-development.xctoolchain'
)
const sdkroot = path.join(
installation,
'Developer',
'Platforms',
'Windows.platform',
'Developer',
'SDKs',
'Windows.sdk'
)
if (code !== 0) {
throw new Error(`Swift installer failed with exit code: "${code}"`)
}
core.debug(`Toolchain installed at "${toolchain}"`)
core.debug(`SDK installed at "${sdkroot}"`)
return installation
const installation = await Installation.detect()
return installation.location
}

protected async add(installation: string) {
const toolchain = path.join(
installation,
'Developer',
'Toolchains',
'unknown-Asserts-development.xctoolchain'
)
const sdkroot = path.join(
installation,
'Developer',
'Platforms',
'Windows.platform',
'Developer',
'SDKs',
'Windows.sdk'
)
core.debug(`Adding toolchain "${toolchain}" to path`)
const swiftPath = path.join(toolchain, 'usr', 'bin')
core.exportVariable('SDKROOT', sdkroot)
const swiftDev = path.join(installation, 'Swift-development', 'bin')
const icu67 = path.join(installation, 'icu-67', 'usr', 'bin')
for (const envPath of [swiftPath, swiftDev, icu67]) {
protected async add(installLocation: string) {
const installation = await Installation.get(installLocation)
core.exportVariable('SDKROOT', installation.sdkroot)
if (installation.devdir) {
core.exportVariable('DEVELOPER_DIR', installation.devdir)
}
const location = installation.location
const swiftPath = path.join(installation.toolchain, 'usr', 'bin')
const swiftDev = path.join(location, 'Swift-development', 'bin')
const icu67 = path.join(location, 'icu-67', 'usr', 'bin')
const tools = path.join(location, 'Tools')
const runtimePath = path.join(installation.runtime, 'usr', 'bin')
const requirePaths = [swiftPath, swiftDev, icu67, tools, runtimePath]

for (const envPath of requirePaths) {
core.debug(`Adding "${envPath}" to PATH`)
core.addPath(envPath)
}
core.debug(`Swift installed at "${swiftPath}"`)
Expand All @@ -104,3 +81,83 @@ export class WindowsToolchainInstaller extends VerifyingToolchainInstaller<Windo
core.exportVariable('SWIFTFLAGS', swiftFlags)
}
}

class Installation {
readonly location: string
readonly toolchain: string
readonly sdkroot: string
readonly runtime: string
readonly devdir?: string

private constructor(
location: string,
toolchain: string,
sdkroot: string,
runtime: string,
devdir?: string
) {
this.location = location
this.toolchain = toolchain
this.sdkroot = sdkroot
this.runtime = runtime
this.devdir = devdir
}

static async get(location: string, fallback?: string) {
let toolchain: string
let sdkroot: string
let runtime: string
let devdir: string | undefined

try {
core.debug(`Checking for development snapshot installation`)
toolchain = path.join(location, 'Toolchains', '0.0.0+Asserts')
sdkroot = path.join(location, 'Toolchains', '0.0.0+Asserts')
runtime = path.join(location, 'Runtimes', '0.0.0')
await fs.access(toolchain)
} catch (error) {
core.debug(`Switching to default installation due to "${error}"`)
if (fallback) {
location = fallback
}
devdir = path.join(location, 'Developer')
toolchain = path.join(
devdir,
'Toolchains',
'unknown-Asserts-development.xctoolchain'
)
sdkroot = path.join(
devdir,
'Platforms',
'Windows.platform',
'Developer',
'SDKs',
'Windows.sdk'
)
runtime = path.join(location, 'Swift', 'runtime-development')
}
return new Installation(location, toolchain, sdkroot, runtime, devdir)
}

static async detect() {
const systemDrive = process.env.SystemDrive ?? 'C:'
const defaultPath = path.join(systemDrive, 'Library')
const devPath = path.join(systemDrive, 'Program Files', 'Swift')
const installation = await Installation.get(devPath, defaultPath)
if (path.relative(devPath, installation.location)) {
const runtimeRoot = path.join(installation.location, 'Swift')
try {
await fs.access(devPath)
await fs.cp(devPath, runtimeRoot, {recursive: true})
} catch (error) {
core.debug(`Runtime check failed with "${error}"`)
}
}
core.debug(`Installation location at "${installation.location}"`)
core.debug(`Toolchain installed at "${installation.toolchain}"`)
core.debug(`SDK installed at "${installation.sdkroot}"`)
core.debug(`Runtime installed at "${installation.runtime}"`)
core.debug(`Development directory at "${installation.devdir}"`)
return installation
}
}

0 comments on commit da27e5b

Please sign in to comment.