From 763ba5ef5c005310da076389531120efdb5c9ae8 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 7 Jan 2025 20:40:56 +0000 Subject: [PATCH] Enforce .NET 8 SDK for new C# modules (#2046) --- .github/workflows/benchmarks.yml | 2 +- .github/workflows/ci.yml | 6 ++-- crates/cli/src/subcommands/init.rs | 1 + .../subcommands/project/csharp/global._json | 6 ++++ crates/cli/src/tasks/csharp.rs | 35 +++++++++++-------- modules/global.json | 6 ++++ 6 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 crates/cli/src/subcommands/project/csharp/global._json create mode 100644 modules/global.json diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index cf8332655e4..4ea8e367611 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -88,7 +88,7 @@ jobs: - name: Install .NET toolchain uses: actions/setup-dotnet@v3 with: - dotnet-version: "8.x" + global-json-file: modules/global.json env: DOTNET_INSTALL_DIR: ~/.dotnet diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed34802f604..6e340e55428 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - uses: dsherret/rust-toolchain-file@v1 - uses: actions/setup-dotnet@v3 with: - dotnet-version: "8.x" + global-json-file: modules/global.json - name: Start containers run: docker compose up -d - name: Run smoketests @@ -70,7 +70,7 @@ jobs: - uses: actions/setup-dotnet@v3 with: - dotnet-version: "8.x" + global-json-file: modules/global.json - name: Create /stdb dir run: | @@ -114,7 +114,7 @@ jobs: - uses: actions/setup-dotnet@v3 with: - dotnet-version: "8.x" + global-json-file: modules/global.json - name: Create /stdb dir run: | diff --git a/crates/cli/src/subcommands/init.rs b/crates/cli/src/subcommands/init.rs index 111bcd189f8..e018c3849a0 100644 --- a/crates/cli/src/subcommands/init.rs +++ b/crates/cli/src/subcommands/init.rs @@ -178,6 +178,7 @@ pub async fn exec_init_csharp(args: &ArgMatches) -> anyhow::Result<()> { (include_str!("project/csharp/StdbModule._csproj"), "StdbModule.csproj"), (include_str!("project/csharp/Lib._cs"), "Lib.cs"), (include_str!("project/csharp/_gitignore"), ".gitignore"), + (include_str!("project/csharp/global._json"), "global.json"), ]; // Check all dependencies diff --git a/crates/cli/src/subcommands/project/csharp/global._json b/crates/cli/src/subcommands/project/csharp/global._json new file mode 100644 index 00000000000..4e550c173fd --- /dev/null +++ b/crates/cli/src/subcommands/project/csharp/global._json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.400", + "rollForward": "latestMinor" + } +} diff --git a/crates/cli/src/tasks/csharp.rs b/crates/cli/src/tasks/csharp.rs index 5a35f4cd374..7fbccdb9944 100644 --- a/crates/cli/src/tasks/csharp.rs +++ b/crates/cli/src/tasks/csharp.rs @@ -1,5 +1,4 @@ use anyhow::Context; -use duct::cmd; use std::fs; use std::path::{Path, PathBuf}; @@ -8,27 +7,37 @@ fn parse_major_version(version: &str) -> Option { } pub(crate) fn build_csharp(project_path: &Path, build_debug: bool) -> anyhow::Result { + // All `dotnet` commands must execute in the project directory, otherwise + // global.json won't have any effect and wrong .NET SDK might be picked. + macro_rules! dotnet { + ($($arg:expr),*) => { + duct::cmd!("dotnet", $($arg),*).dir(project_path) + }; + } + // Check if the `wasi-experimental` workload is installed. Unfortunately, we // have to do this by inspecting the human-readable output. There is a // hidden `--machine-readable` flag but it also mixes in human-readable // output as well as unnecessarily updates various unrelated manifests. - match cmd!("dotnet", "workload", "list").read() { + match dotnet!("workload", "list").read() { Ok(workloads) if workloads.contains("wasi-experimental") => {} Ok(_) => { // If wasi-experimental is not found, first check if we're running - // on .NET 8.0. We can't even install that workload on older - // versions, so this helps to provide a nicer message than "Workload - // ID wasi-experimental is not recognized.". - let version = cmd!("dotnet", "--version").read().unwrap_or_default(); - if parse_major_version(&version) < Some(8) { - anyhow::bail!(".NET 8.0 is required, but found {version}."); + // on .NET SDK 8.0. We can't even install that workload on older + // versions, and we don't support .NET 9.0 yet, so this helps to + // provide a nicer message than "Workload ID wasi-experimental is not recognized.". + let version = dotnet!("--version").read().unwrap_or_default(); + if parse_major_version(&version) != Some(8) { + anyhow::bail!(concat!( + ".NET SDK 8.0 is required, but found {version}.\n", + "If you have multiple versions of .NET SDK installed, configure your project using https://learn.microsoft.com/en-us/dotnet/core/tools/global-json." + )); } // Finally, try to install the workload ourselves. On some systems // this might require elevated privileges, so print a nice error // message if it fails. - cmd!( - "dotnet", + dotnet!( "workload", "install", "wasi-experimental", @@ -41,7 +50,7 @@ pub(crate) fn build_csharp(project_path: &Path, build_debug: bool) -> anyhow::Re ))?; } Err(error) if error.kind() == std::io::ErrorKind::NotFound => { - anyhow::bail!("dotnet not found in PATH. Please install .NET 8.0.") + anyhow::bail!("dotnet not found in PATH. Please install .NET SDK 8.0.") } Err(error) => anyhow::bail!("{error}"), }; @@ -57,9 +66,7 @@ pub(crate) fn build_csharp(project_path: &Path, build_debug: bool) -> anyhow::Re })?; // run dotnet publish using cmd macro - cmd!("dotnet", "publish", "-c", config_name, "-v", "quiet") - .dir(project_path) - .run()?; + dotnet!("publish", "-c", config_name, "-v", "quiet").run()?; // check if file exists let subdir = if std::env::var_os("EXPERIMENTAL_WASM_AOT").map_or(false, |v| v == "1") { diff --git a/modules/global.json b/modules/global.json new file mode 100644 index 00000000000..4e550c173fd --- /dev/null +++ b/modules/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.400", + "rollForward": "latestMinor" + } +}