Skip to content
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

Enforce .NET 8 SDK for new C# modules #2046

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Enforce .NET 8 SDK for new C# modules
This fixes an issue where users with .NET 9 SDK installed can't build C# modules even if .NET 8 SDK is installed as well.

Unfortunately, this covers only new projects created with `spacetime init` as that's the only place where we control the project directory. For everyone else, we print instructions with a link to the official configuration docs.
  • Loading branch information
RReverser committed Dec 16, 2024
commit f4fa645df7eee1b9aac7c0e656fac869d5c4e404
2 changes: 2 additions & 0 deletions crates/cli/src/subcommands/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ 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"),
// Reuse global.json from modules instead of a separate template to ensure that we stay in sync.
(include_str!("../../../../modules/global.json"), "global.json"),
RReverser marked this conversation as resolved.
Show resolved Hide resolved
];

// Check all dependencies
Expand Down
35 changes: 21 additions & 14 deletions crates/cli/src/tasks/csharp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use anyhow::Context;
use duct::cmd;
use std::fs;
use std::path::{Path, PathBuf};

Expand All @@ -8,27 +7,37 @@ fn parse_major_version(version: &str) -> Option<u8> {
}

pub(crate) fn build_csharp(project_path: &Path, build_debug: bool) -> anyhow::Result<PathBuf> {
// 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",
Expand All @@ -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}"),
};
Expand All @@ -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") {
Expand Down
6 changes: 6 additions & 0 deletions modules/global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"sdk": {
"version": "8.0.400",
"rollForward": "latestMinor"
}
}