From 35be2d8bfcc1f44f6de22bc44c09899f2f2ae53f Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 5 Sep 2024 17:30:03 +0100 Subject: [PATCH 1/7] Allow using msys2 instead of cygwin --- action.yml | 3 + dist/index.js | 95 ++++++++++++++++++++++++--- dist/post/index.js | 13 ++++ packages/setup-ocaml/src/constants.ts | 17 +++++ packages/setup-ocaml/src/installer.ts | 25 +++++-- packages/setup-ocaml/src/opam.ts | 9 ++- packages/setup-ocaml/src/windows.ts | 55 ++++++++++++++++ 7 files changed, 197 insertions(+), 20 deletions(-) diff --git a/action.yml b/action.yml index e0ba3271..db00a1b1 100644 --- a/action.yml +++ b/action.yml @@ -37,6 +37,9 @@ inputs: description: The prefix of the cache keys. required: false default: v1 + windows-environment: + description: Whether to use `cygwin` (default) or `msys2` for windows installs. + required: false github-token: description: DO NOT SET THIS. required: false diff --git a/dist/index.js b/dist/index.js index b2b7e958..aa497c76 100644 --- a/dist/index.js +++ b/dist/index.js @@ -147223,6 +147223,19 @@ const ALLOW_PRERELEASE_OPAM = lib_core.getBooleanInput("allow-prerelease-opam", required: false, trimWhitespace: true, }); +const WINDOWS_ENVIRONMENT = (() => { + const input = lib_core.getInput("windows-environment"); + if (!(PLATFORM === "windows" || input === "")) { + lib_core.error("windows-environment is only supported on windows"); + } + if (input === "msys2" || input === "cygwin") { + return input; + } + if (input !== "") { + lib_core.error("unrecognized value for windows-environment"); + } + return "cygwin"; +})(); const CACHE_PREFIX = lib_core.getInput("cache-prefix", { required: false, trimWhitespace: true, @@ -147399,7 +147412,7 @@ async function acquireOpam() { } }); } -async function initializeOpam() { +async function initializeOpam(prefix) { await lib_core.group("Initialise opam state", async () => { if (PLATFORM !== "windows") { try { @@ -147416,7 +147429,7 @@ async function initializeOpam() { const extraOptions = []; if (PLATFORM === "windows") { extraOptions.push("--cygwin-local-install"); - extraOptions.push(`--cygwin-location=${CYGWIN_ROOT}`); + extraOptions.push(`--cygwin-location=${prefix}`); } if (OPAM_DISABLE_SANDBOXING) { extraOptions.push("--disable-sandboxing"); @@ -147430,9 +147443,9 @@ async function initializeOpam() { ]); }); } -async function setupOpam() { +async function setupOpam(prefix) { await acquireOpam(); - await initializeOpam(); + await initializeOpam(prefix); } async function installOcaml(ocamlCompiler) { await lib_core.group("Install OCaml", async () => { @@ -166041,6 +166054,58 @@ async function setupCygwin() { await io.cp(setup, CYGWIN_ROOT); }); } +function getPacmanPath(msys2Root) { + return external_node_path_namespaceObject.join(msys2Root, "usr", "bin", "pacman"); +} +async function testMsys2Installation(path) { + try { + await promises_namespaceObject.access(path); + } + catch { + throw new Error(`No msys2 installation found at: ${path}.`); + } +} +async function getMsys2Install() { + const msys2Root = process.env.MSYS2_ROOT; + // MSYS2_ROOT takes priority + if (msys2Root) { + await testMsys2Installation(msys2Root); + return [msys2Root, getPacmanPath(msys2Root)]; + } + try { + // check for pacman from PATH + const pacmanPath = await io.which("pacman", true); + return [external_node_path_namespaceObject.dirname(external_node_path_namespaceObject.dirname(external_node_path_namespaceObject.dirname(pacmanPath))), pacmanPath]; + } + catch { + // finally check the default msys directory + const defaultRoot = "C:\\msys64"; + testMsys2Installation(defaultRoot); + return [defaultRoot, getPacmanPath(defaultRoot)]; + } +} +async function prepareMsys2() { + return await lib_core.group("Install needed Msys2 packages", async () => { + const [root, pacmanPath] = await getMsys2Install(); + // core update + await (0,lib_exec.exec)(pacmanPath, ["-Syu", "--noconfirm"]); + // packages needed for opam + const packages = [ + "curl", + "diffutils", + "m4", + "make", + "mingw-w64-i686-gcc", + "mingw-w64-x86_64-gcc", + "patch", + "perl", + "rsync", + "unzip", + ]; + await (0,lib_exec.exec)(pacmanPath, ["-Syu", "--noconfirm", ...packages]); + return root; + }); +} ;// CONCATENATED MODULE: ./src/cache.ts @@ -166336,13 +166401,25 @@ async function installer() { } const { opamCacheHit, cygwinCacheHit } = await restoreOpamCaches(); if (PLATFORM === "windows") { - await setupCygwin(); - if (!cygwinCacheHit) { - await saveCygwinCache(); + switch (WINDOWS_ENVIRONMENT) { + case "msys2": { + const msys2Root = await prepareMsys2(); + await setupOpam(msys2Root); + break; + } + case "cygwin": + await setupCygwin(); + if (!cygwinCacheHit) { + await saveCygwinCache(); + } + lib_core.addPath(CYGWIN_ROOT_BIN); + await setupOpam(CYGWIN_ROOT); + break; } - lib_core.addPath(CYGWIN_ROOT_BIN); } - await setupOpam(); + else { + await setupOpam(); + } if (!opamCacheHit) { await repositoryRemoveAll(); await repositoryAddAll(OPAM_REPOSITORIES); diff --git a/dist/post/index.js b/dist/post/index.js index 157a8030..f08b0556 100644 --- a/dist/post/index.js +++ b/dist/post/index.js @@ -112200,6 +112200,19 @@ const ALLOW_PRERELEASE_OPAM = lib_core.getBooleanInput("allow-prerelease-opam", required: false, trimWhitespace: true, }); +const WINDOWS_ENVIRONMENT = (() => { + const input = lib_core.getInput("windows-environment"); + if (!(constants_PLATFORM === "windows" || input === "")) { + lib_core.error("windows-environment is only supported on windows"); + } + if (input === "msys2" || input === "cygwin") { + return input; + } + if (input !== "") { + lib_core.error("unrecognized value for windows-environment"); + } + return "cygwin"; +})(); const constants_CACHE_PREFIX = lib_core.getInput("cache-prefix", { required: false, trimWhitespace: true, diff --git a/packages/setup-ocaml/src/constants.ts b/packages/setup-ocaml/src/constants.ts index 23890d47..dbdeb72d 100644 --- a/packages/setup-ocaml/src/constants.ts +++ b/packages/setup-ocaml/src/constants.ts @@ -86,6 +86,23 @@ export const ALLOW_PRERELEASE_OPAM = core.getBooleanInput( }, ); +export const WINDOWS_ENVIRONMENT: "cygwin" | "msys2" = (() => { + const input = core.getInput("windows-environment"); + + if (!(PLATFORM === "windows" || input === "")) { + core.error("windows-environment is only supported on windows"); + } + + if (input === "msys2" || input === "cygwin") { + return input; + } + + if (input !== "") { + core.error("unrecognized value for windows-environment"); + } + return "cygwin"; +})(); + export const CACHE_PREFIX = core.getInput("cache-prefix", { required: false, trimWhitespace: true, diff --git a/packages/setup-ocaml/src/installer.ts b/packages/setup-ocaml/src/installer.ts index f6fc53e7..0d14032f 100644 --- a/packages/setup-ocaml/src/installer.ts +++ b/packages/setup-ocaml/src/installer.ts @@ -10,6 +10,7 @@ import { saveOpamCache, } from "./cache.js"; import { + CYGWIN_ROOT, CYGWIN_ROOT_BIN, DUNE_CACHE, DUNE_CACHE_ROOT, @@ -18,6 +19,7 @@ import { OPAM_ROOT, PLATFORM, RESOLVED_COMPILER, + WINDOWS_ENVIRONMENT, } from "./constants.js"; import { installDune } from "./dune.js"; import { @@ -29,7 +31,7 @@ import { update, } from "./opam.js"; import { retrieveOpamLocalPackages } from "./packages.js"; -import { setupCygwin } from "./windows.js"; +import { prepareMsys2, setupCygwin } from "./windows.js"; export async function installer() { if (core.isDebug()) { @@ -64,13 +66,24 @@ export async function installer() { } const { opamCacheHit, cygwinCacheHit } = await restoreOpamCaches(); if (PLATFORM === "windows") { - await setupCygwin(); - if (!cygwinCacheHit) { - await saveCygwinCache(); + switch (WINDOWS_ENVIRONMENT) { + case "msys2": { + const msys2Root = await prepareMsys2(); + await setupOpam(msys2Root); + break; + } + case "cygwin": + await setupCygwin(); + if (!cygwinCacheHit) { + await saveCygwinCache(); + } + core.addPath(CYGWIN_ROOT_BIN); + await setupOpam(CYGWIN_ROOT); + break; } - core.addPath(CYGWIN_ROOT_BIN); + } else { + await setupOpam(); } - await setupOpam(); if (!opamCacheHit) { await repositoryRemoveAll(); await repositoryAddAll(OPAM_REPOSITORIES); diff --git a/packages/setup-ocaml/src/opam.ts b/packages/setup-ocaml/src/opam.ts index 1a215271..b0ae6964 100644 --- a/packages/setup-ocaml/src/opam.ts +++ b/packages/setup-ocaml/src/opam.ts @@ -8,7 +8,6 @@ import * as semver from "semver"; import { ALLOW_PRERELEASE_OPAM, ARCHITECTURE, - CYGWIN_ROOT, GITHUB_TOKEN, OPAM_DISABLE_SANDBOXING, PLATFORM, @@ -86,7 +85,7 @@ async function acquireOpam() { }); } -async function initializeOpam() { +async function initializeOpam(prefix?: string) { await core.group("Initialise opam state", async () => { if (PLATFORM !== "windows") { try { @@ -104,7 +103,7 @@ async function initializeOpam() { const extraOptions = []; if (PLATFORM === "windows") { extraOptions.push("--cygwin-local-install"); - extraOptions.push(`--cygwin-location=${CYGWIN_ROOT}`); + extraOptions.push(`--cygwin-location=${prefix}`); } if (OPAM_DISABLE_SANDBOXING) { extraOptions.push("--disable-sandboxing"); @@ -119,9 +118,9 @@ async function initializeOpam() { }); } -export async function setupOpam() { +export async function setupOpam(prefix?: string) { await acquireOpam(); - await initializeOpam(); + await initializeOpam(prefix); } export async function installOcaml(ocamlCompiler: string) { diff --git a/packages/setup-ocaml/src/windows.ts b/packages/setup-ocaml/src/windows.ts index d519878c..a5551cc1 100644 --- a/packages/setup-ocaml/src/windows.ts +++ b/packages/setup-ocaml/src/windows.ts @@ -115,3 +115,58 @@ export async function setupCygwin() { await io.cp(setup, CYGWIN_ROOT); }); } + +function getPacmanPath(msys2Root: string): string { + return path.join(msys2Root, "usr", "bin", "pacman"); +} + +async function testMsys2Installation(path: string): Promise { + try { + await fs.access(path); + } catch { + throw new Error(`No msys2 installation found at: ${path}.`); + } +} + +async function getMsys2Install(): Promise<[root: string, pacmanPath: string]> { + const msys2Root = process.env.MSYS2_ROOT; + + // MSYS2_ROOT takes priority + if (msys2Root) { + await testMsys2Installation(msys2Root); + return [msys2Root, getPacmanPath(msys2Root)]; + } + try { + // check for pacman from PATH + const pacmanPath = await io.which("pacman", true); + return [path.dirname(path.dirname(path.dirname(pacmanPath))), pacmanPath]; + } catch { + // finally check the default msys directory + const defaultRoot = "C:\\msys64"; + testMsys2Installation(defaultRoot); + return [defaultRoot, getPacmanPath(defaultRoot)]; + } +} + +export async function prepareMsys2(): Promise { + return await core.group("Install needed Msys2 packages", async () => { + const [root, pacmanPath] = await getMsys2Install(); + // core update + await exec(pacmanPath, ["-Syu", "--noconfirm"]); + // packages needed for opam + const packages = [ + "curl", + "diffutils", + "m4", + "make", + "mingw-w64-i686-gcc", + "mingw-w64-x86_64-gcc", + "patch", + "perl", + "rsync", + "unzip", + ]; + await exec(pacmanPath, ["-Syu", "--noconfirm", ...packages]); + return root; + }); +} From c1f32ec7efd14583e1ab28979d10f8bb268790a8 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 5 Sep 2024 13:32:57 +0100 Subject: [PATCH 2/7] Do not install cygwin cache for msys2 --- dist/index.js | 2 +- dist/post/index.js | 4 ++-- packages/setup-ocaml/src/cache.ts | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dist/index.js b/dist/index.js index aa497c76..7040f26b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -166266,7 +166266,7 @@ async function restoreOpamCache() { } async function restoreOpamCaches() { return await lib_core.group("Retrieve the opam cache", async () => { - const [opamCacheHit, cygwinCacheHit] = await Promise.all(PLATFORM === "windows" + const [opamCacheHit, cygwinCacheHit] = await Promise.all(PLATFORM === "windows" && WINDOWS_ENVIRONMENT === "cygwin" ? [restoreOpamCache(), restoreCygwinCache()] : [restoreOpamCache()]); return { opamCacheHit, cygwinCacheHit }; diff --git a/dist/post/index.js b/dist/post/index.js index f08b0556..2286febe 100644 --- a/dist/post/index.js +++ b/dist/post/index.js @@ -112200,7 +112200,7 @@ const ALLOW_PRERELEASE_OPAM = lib_core.getBooleanInput("allow-prerelease-opam", required: false, trimWhitespace: true, }); -const WINDOWS_ENVIRONMENT = (() => { +const constants_WINDOWS_ENVIRONMENT = (() => { const input = lib_core.getInput("windows-environment"); if (!(constants_PLATFORM === "windows" || input === "")) { lib_core.error("windows-environment is only supported on windows"); @@ -112416,7 +112416,7 @@ async function restoreOpamCache() { } async function restoreOpamCaches() { return await core.group("Retrieve the opam cache", async () => { - const [opamCacheHit, cygwinCacheHit] = await Promise.all(PLATFORM === "windows" + const [opamCacheHit, cygwinCacheHit] = await Promise.all(PLATFORM === "windows" && WINDOWS_ENVIRONMENT === "cygwin" ? [restoreOpamCache(), restoreCygwinCache()] : [restoreOpamCache()]); return { opamCacheHit, cygwinCacheHit }; diff --git a/packages/setup-ocaml/src/cache.ts b/packages/setup-ocaml/src/cache.ts index 13313250..2b55f724 100644 --- a/packages/setup-ocaml/src/cache.ts +++ b/packages/setup-ocaml/src/cache.ts @@ -18,6 +18,7 @@ import { OPAM_ROOT, PLATFORM, RESOLVED_COMPILER, + WINDOWS_ENVIRONMENT, } from "./constants.js"; import { retrieveLatestOpamRelease } from "./opam.js"; import { retrieveCygwinVersion } from "./windows.js"; @@ -203,7 +204,7 @@ async function restoreOpamCache() { export async function restoreOpamCaches() { return await core.group("Retrieve the opam cache", async () => { const [opamCacheHit, cygwinCacheHit] = await Promise.all( - PLATFORM === "windows" + PLATFORM === "windows" && WINDOWS_ENVIRONMENT === "cygwin" ? [restoreOpamCache(), restoreCygwinCache()] : [restoreOpamCache()], ); From ef2134f3e439247248b3abe7e0fc449aac390c5e Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 5 Sep 2024 13:33:15 +0100 Subject: [PATCH 3/7] Use separate opam cache for msys2 installs --- dist/index.js | 5 ++++- dist/post/index.js | 5 ++++- packages/setup-ocaml/src/cache.ts | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dist/index.js b/dist/index.js index 7040f26b..fe4da66c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -166145,6 +166145,7 @@ async function composeOpamCacheKeys() { const ocamlCompiler = await RESOLVED_COMPILER; const repositoryUrls = OPAM_REPOSITORIES.map(([_, value]) => value).join(); const osInfo = await lib.osInfo(); + const msys2 = WINDOWS_ENVIRONMENT === "msys2" ? "msys2" : undefined; const plainKey = [ PLATFORM, osInfo.release, @@ -166153,7 +166154,9 @@ async function composeOpamCacheKeys() { ocamlCompiler, repositoryUrls, sandbox, - ].join(); + ] + .concat(msys2 ?? []) + .join(); const hash = external_node_crypto_.createHash("sha256").update(plainKey).digest("hex"); const key = `${CACHE_PREFIX}-setup-ocaml-opam-${hash}`; const restoreKeys = [key]; diff --git a/dist/post/index.js b/dist/post/index.js index 2286febe..0b3e6e6d 100644 --- a/dist/post/index.js +++ b/dist/post/index.js @@ -112295,6 +112295,7 @@ async function composeOpamCacheKeys() { const ocamlCompiler = await RESOLVED_COMPILER; const repositoryUrls = OPAM_REPOSITORIES.map(([_, value]) => value).join(); const osInfo = await system.osInfo(); + const msys2 = WINDOWS_ENVIRONMENT === "msys2" ? "msys2" : undefined; const plainKey = [ PLATFORM, osInfo.release, @@ -112303,7 +112304,9 @@ async function composeOpamCacheKeys() { ocamlCompiler, repositoryUrls, sandbox, - ].join(); + ] + .concat(msys2 ?? []) + .join(); const hash = crypto.createHash("sha256").update(plainKey).digest("hex"); const key = `${CACHE_PREFIX}-setup-ocaml-opam-${hash}`; const restoreKeys = [key]; diff --git a/packages/setup-ocaml/src/cache.ts b/packages/setup-ocaml/src/cache.ts index 2b55f724..4432fd26 100644 --- a/packages/setup-ocaml/src/cache.ts +++ b/packages/setup-ocaml/src/cache.ts @@ -51,6 +51,7 @@ async function composeOpamCacheKeys() { const ocamlCompiler = await RESOLVED_COMPILER; const repositoryUrls = OPAM_REPOSITORIES.map(([_, value]) => value).join(); const osInfo = await system.osInfo(); + const msys2 = WINDOWS_ENVIRONMENT === "msys2" ? "msys2" : undefined; const plainKey = [ PLATFORM, osInfo.release, @@ -59,7 +60,9 @@ async function composeOpamCacheKeys() { ocamlCompiler, repositoryUrls, sandbox, - ].join(); + ] + .concat(msys2 ?? []) + .join(); const hash = crypto.createHash("sha256").update(plainKey).digest("hex"); const key = `${CACHE_PREFIX}-setup-ocaml-opam-${hash}`; const restoreKeys = [key]; From 1dd04e90c100c02e8865ecabcbf1dd9c214955ff Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 5 Sep 2024 13:47:06 +0100 Subject: [PATCH 4/7] [test] Add windows msys2 workflow --- .github/workflows/workflow.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 89b47ada..60111a1c 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -53,6 +53,8 @@ jobs: - windows-latest ocaml-compiler: - "5.2" + windows-environment: + - "" allow-prerelease-opam: - false include: @@ -62,6 +64,9 @@ jobs: - os: ubuntu-latest ocaml-compiler: "5.2" allow-prerelease-opam: true + - os: windows-latest + ocaml-compiler: "5.2" + windows-environment: msys2 runs-on: ${{ matrix.os }} @@ -74,5 +79,6 @@ jobs: with: ocaml-compiler: ${{ matrix.ocaml-compiler }} allow-prerelease-opam: ${{ matrix.allow-prerelease-opam }} + windows-environment: ${{ matrix.windows-environment }} - run: opam install ssl From ce75b2eef5f7c76869d935c77237be3935eae150 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Sat, 7 Dec 2024 19:49:45 +0000 Subject: [PATCH 5/7] Set missing input parameter on windows msys2 test --- .github/workflows/workflow.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 60111a1c..162c1dfe 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -67,6 +67,7 @@ jobs: - os: windows-latest ocaml-compiler: "5.2" windows-environment: msys2 + allow-prerelease-opam: false runs-on: ${{ matrix.os }} From 62676603a9c6477a656f71828e707734a7ed9017 Mon Sep 17 00:00:00 2001 From: tobil4sk Date: Wed, 1 Jan 2025 13:06:10 +0000 Subject: [PATCH 6/7] Add missing await when testing msys install Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/setup-ocaml/src/windows.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/setup-ocaml/src/windows.ts b/packages/setup-ocaml/src/windows.ts index a5551cc1..44520c3d 100644 --- a/packages/setup-ocaml/src/windows.ts +++ b/packages/setup-ocaml/src/windows.ts @@ -143,7 +143,7 @@ async function getMsys2Install(): Promise<[root: string, pacmanPath: string]> { } catch { // finally check the default msys directory const defaultRoot = "C:\\msys64"; - testMsys2Installation(defaultRoot); + await testMsys2Installation(defaultRoot); return [defaultRoot, getPacmanPath(defaultRoot)]; } } From 520a4f950aa9811dcabb170ec2e9660ddad9390b Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Wed, 1 Jan 2025 14:01:03 +0000 Subject: [PATCH 7/7] Recompile dist file --- dist/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/index.js b/dist/index.js index fe4da66c..7a50acb3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -166080,7 +166080,7 @@ async function getMsys2Install() { catch { // finally check the default msys directory const defaultRoot = "C:\\msys64"; - testMsys2Installation(defaultRoot); + await testMsys2Installation(defaultRoot); return [defaultRoot, getPacmanPath(defaultRoot)]; } }