Skip to content
Draft
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ It also performs the following actions:
- On macOS:
- Installing ROS and ROS 2 system dependencies using [Homebrew] and [pip]
- On Microsoft Windows:
- Installing ROS and ROS 2 system dependencies using [Chocolatey]
- Installing ROS 2 binaries and their dependencies using [pixi]

The dependencies installed by this package include ROS 2 DDS vendor packages, such as Eclipse Cyclone DDS, eProsima Fast DDS, and RTI Connext DDS.
See [`src/package_manager/*.ts`](./src/package_manager/) for the complete list.
Expand Down Expand Up @@ -294,7 +294,7 @@ The scripts and documentation in this project are released under the [Apache 2](
[ros2_latest_development_setup]: https://docs.ros.org/en/rolling/Installation/Alternatives/Latest-Development-Setup.html
[rep-2000]: https://www.ros.org/reps/rep-2000.html
[rep-3]: https://www.ros.org/reps/rep-0003.html
[chocolatey]: https://chocolatey.org/
[pixi]: https://pixi.sh/
[homebrew]: https://brew.sh/
[pip]: https://pip.pypa.io/en/stable/
[dockerhub_osrf]: https://hub.docker.com/r/osrf/ros/
Expand Down
95 changes: 0 additions & 95 deletions src/package_manager/chocolatey.ts

This file was deleted.

184 changes: 125 additions & 59 deletions src/setup-ros-windows.ts
Original file line number Diff line number Diff line change
@@ -1,92 +1,156 @@
import * as core from "@actions/core";
import * as tc from "@actions/tool-cache";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";

import * as chocolatey from "./package_manager/chocolatey";
import * as pip from "./package_manager/pip";
import * as utils from "./utils";

// Pixi-based binary releases; humble and iron are not supported.
const binaryReleases: { [index: string]: string } = {
humble:
"https://github.com/ros2/ros2/releases/download/humble-20250331/ros2-humble-20250331-windows-release-amd64.zip",
iron: "https://github.com/ros2/ros2/releases/download/release-iron-20241204/ros2-iron-20241204-windows-release-amd64.zip",
jazzy:
"https://github.com/ros2/ros2/releases/download/release-jazzy-20250430/ros2-jazzy-20250407-windows-release-amd64.zip",
kilted:
"https://github.com/ros2/ros2/releases/download/release-kilted-20250523/ros2-kilted-20250523-windows-release-amd64.zip",
lyrical:
"https://github.com/ros2/ros2/releases/download/release-lyrical-beta-20260430/ros2-lyrical-2026-04-30-windows-AMD64.zip",
rolling:
"https://github.com/ros2/ros2/releases/download/release-rolling-nightlies/ros2-rolling-nightly-windows-amd64.zip",
};

const pip3Packages: string[] = ["lxml", "netifaces"];
const pixiWorkspace = "C:\\pixi_ws";

/**
* Install ROS 2 build tools.
*/
async function prepareRos2BuildEnvironment() {
// Currently targeted Python version for Windows according to REP 2000
const python_dir = tc.find("Python", "3.8");
// Windows 11 starts at build 22000; GitHub-hosted runners are Windows Server and will warn.
function checkWindows11() {
const build = Number(os.release().split(".")[2]);
if (!(build >= 22000)) {
core.warning(`ROS 2 binaries only support Windows 11 (found ${os.release()})`);

Check failure on line 27 in src/setup-ros-windows.ts

View workflow job for this annotation

GitHub Actions / Lint sources and check build artifacts

Replace ``ROS·2·binaries·only·support·Windows·11·(found·${os.release()})`` with `⏎↹↹↹`ROS·2·binaries·only·support·Windows·11·(found·${os.release()})`,⏎↹↹`
}
}

async function findVs2022(): Promise<string> {
const vswhere = path.join(
process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)",
"Microsoft Visual Studio",
"Installer",
"vswhere.exe",
);
if (!fs.existsSync(vswhere)) {
return "";
}

let installPath = "";
await utils.exec(
path.join(python_dir, "python"),
vswhere,
[
"-c",
"import sysconfig; print(sysconfig.get_config_var('BINDIR')); print(sysconfig.get_path('scripts'))",
"-latest",
"-products",
"*",
"-version",
"[17.0,18.0)",
"-requires",
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
"-property",
"installationPath",
],
{
listeners: {
stdline: (data: string) => {
const p = data.trim();
if (p) {
core.info("Prepending to path: " + JSON.stringify(p));
core.addPath(p);
}
},
},
},
{ listeners: { stdout: (d: Buffer) => (installPath += d.toString()) } },
);
return installPath.trim();
}

core.addPath("c:\\program files\\cppcheck");
await chocolatey.installChocoDependencies();
await chocolatey.downloadAndInstallRos2NugetPackages();
/**
* Activate the Visual Studio 2022 (MSVC v143) toolchain, installing the Build Tools if missing.
* VS 18+ is not supported by ROS 2 yet.
*/
async function selectMsvc2022() {
let installPath = await findVs2022();
if (!installPath) {
const bootstrapper = await tc.downloadTool(
"https://aka.ms/vs/17/release/vs_BuildTools.exe",
path.join(process.env["RUNNER_TEMP"] || os.tmpdir(), "vs_BuildTools.exe"),
);
// 3010 means success, reboot pending.
const code = await utils.exec(
bootstrapper,
[
"--quiet",
"--wait",
"--norestart",
"--nocache",
"--add",
"Microsoft.VisualStudio.Workload.VCTools",
"--includeRecommended",
],
{ ignoreReturnCode: true },
);
if (code && code !== 3010) {
throw new Error(`VS 2022 Build Tools installation failed with exit code ${code}`);

Check failure on line 87 in src/setup-ros-windows.ts

View workflow job for this annotation

GitHub Actions / Lint sources and check build artifacts

Replace ``VS·2022·Build·Tools·installation·failed·with·exit·code·${code}`` with `⏎↹↹↹↹`VS·2022·Build·Tools·installation·failed·with·exit·code·${code}`,⏎↹↹↹`
}
installPath = await findVs2022();
}
if (!installPath) {
core.warning("Visual Studio 2022 C++ tools not found, skipping MSVC selection");

Check failure on line 92 in src/setup-ros-windows.ts

View workflow job for this annotation

GitHub Actions / Lint sources and check build artifacts

Replace `"Visual·Studio·2022·C++·tools·not·found,·skipping·MSVC·selection"` with `⏎↹↹↹"Visual·Studio·2022·C++·tools·not·found,·skipping·MSVC·selection",⏎↹↹`
return;
}

// Avoid version of pip that breaks Windows GitHub actions. See:
// * https://github.com/ros-tooling/action-ros-ci/pull/719#issuecomment-1030318146
// * https://github.com/actions/virtual-environments/issues/5027#issuecomment-1031113617
await utils.exec("python", ["-m", "pip", "install", "-U", "pip!=22.0.*"], {
cwd: path.sep,
const vcvars = path.join(installPath, "VC", "Auxiliary", "Build", "vcvars64.bat");

Check failure on line 96 in src/setup-ros-windows.ts

View workflow job for this annotation

GitHub Actions / Lint sources and check build artifacts

Replace `installPath,·"VC",·"Auxiliary",·"Build",·"vcvars64.bat"` with `⏎↹↹installPath,⏎↹↹"VC",⏎↹↹"Auxiliary",⏎↹↹"Build",⏎↹↹"vcvars64.bat",⏎↹`
let envDump = "";
await utils.exec("cmd", ["/d", "/s", "/c", `""${vcvars}" >nul && set"`], {
windowsVerbatimArguments: true,
listeners: { stdout: (d: Buffer) => (envDump += d.toString()) },
});
for (const line of envDump.split(/\r?\n/)) {
const i = line.indexOf("=");
if (i > 0 && process.env[line.slice(0, i)] !== line.slice(i + 1)) {
core.exportVariable(line.slice(0, i), line.slice(i + 1));
}
}
}

await pip.installPython3Dependencies(false);
await pip.runPython3PipInstall(pip3Packages, false);
await pip.runPython3PipInstall(["vcstool"], false);
// install "rosdistro" from master to include distutils fix:
// https://github.com/ros-infrastructure/rosdistro/pull/194
await pip.runPython3PipInstall(
["git+https://github.com/ros-infrastructure/rosdistro.git"],
false,
);
await pip.runPython3PipInstall(["rosdep"], false);
return utils.exec(`rosdep`, ["init"]);
async function installPixi() {
await utils.exec("powershell", [
"-ExecutionPolicy",
"ByPass",
"-Command",
"irm -useb https://pixi.sh/install.ps1 | iex",
]);
core.addPath(path.join(os.homedir(), ".pixi", "bin"));
}

/**
* Install ROS 2 binary releases.
* Install ROS 2 binary releases and their pixi environments.
*/
async function prepareRos2BinaryReleases() {
for (const rosDistro of utils.getRequiredRosDistributions()) {
if (rosDistro in binaryReleases) {
await utils.exec("wget", [
"--quiet",
binaryReleases[rosDistro],
"-O",
`${rosDistro}.zip`,
]);
await utils.exec("7z", [
"x",
`${rosDistro}.zip`,
"-y",
`-oC:\\dev\\${rosDistro}`,
if (!(rosDistro in binaryReleases)) {
core.warning(`No Windows binary release available for ${rosDistro}`);
continue;
}
const installDir = path.join(pixiWorkspace, rosDistro);
const manifestPath = path.join(installDir, "pixi.toml");
fs.mkdirSync(installDir, { recursive: true });

await tc.downloadTool(
`https://raw.githubusercontent.com/ros2/ros2/refs/heads/${rosDistro}/pixi.toml`,
manifestPath,
);
const zipPath = await tc.downloadTool(binaryReleases[rosDistro]);
await tc.extractZip(zipPath, installDir);

await utils.exec("pixi", ["install", "--manifest-path", manifestPath]);

const preinstallScript = path.join(
installDir,
"ros2-windows",
"preinstall_setup_windows.py",
);
if (fs.existsSync(preinstallScript)) {
await utils.exec("pixi", [
"run",
"--manifest-path",
manifestPath,
"python",
preinstallScript,
]);
}
}
Expand All @@ -96,6 +160,8 @@
* Install build environment on a Windows worker.
*/
export async function runWindows() {
await prepareRos2BuildEnvironment();
checkWindows11();
await selectMsvc2022();
await installPixi();
return await prepareRos2BinaryReleases();
}
Loading