Rust: Add support for Rust editions with Rust_EDITION target property

This commit is contained in:
Baudouin Feildel
2026-03-26 23:15:58 +01:00
parent d0e39096b6
commit 313769e766
18 changed files with 149 additions and 0 deletions
+1
View File
@@ -405,6 +405,7 @@ Properties on Targets
/prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG
/prop_tgt/RUNTIME_OUTPUT_NAME
/prop_tgt/RUNTIME_OUTPUT_NAME_CONFIG
/prop_tgt/Rust_EDITION
/prop_tgt/SKIP_BUILD_RPATH
/prop_tgt/SKIP_LINTING
/prop_tgt/SOURCE_DIR
+1
View File
@@ -579,6 +579,7 @@ Variables that Control the Build
/variable/CMAKE_POSITION_INDEPENDENT_CODE
/variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY
/variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY_CONFIG
/variable/CMAKE_Rust_EDITION
/variable/CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS
/variable/CMAKE_SHARED_LINKER_FLAGS
/variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG
+25
View File
@@ -0,0 +1,25 @@
Rust_EDITION
------------
.. versionadded:: 4.4
.. note::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_RUST``.
The Rust edition required to build this target. It is initialized from the
:variable:`CMAKE_Rust_EDITION` variable if defined. Setting this property
results in adding a flag such as ``--edition=2018`` to the compile line.
Supported values are:
``2015``
Rust 2015, the default edition, started with Rust 1.0.
``2018``
Rust 2018, available since Rust 1.31.
``2021``
Rust 2021, available since Rust 1.56.
``2024``
Rust 2024, available since Rust 1.85.
+10
View File
@@ -0,0 +1,10 @@
CMAKE_Rust_EDITION
------------------
.. versionadded:: 4.4
.. note::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_RUST``.
Default value for :prop_tgt:`Rust_EDITION` target property if set when a target
is created.
+8
View File
@@ -2795,6 +2795,14 @@ void cmGeneratorTarget::AddHIPArchitectureFlags(cmBuildStep compileOrLink,
}
}
void cmGeneratorTarget::AddRustTargetFlags(std::string& flags) const
{
cmValue const edition = this->GetProperty("Rust_EDITION");
if (edition && !edition->empty()) {
flags += " --edition=" + *edition;
}
}
void cmGeneratorTarget::AddCUDAToolkitFlags(std::string& flags) const
{
std::string const& compiler =
+2
View File
@@ -626,6 +626,8 @@ public:
void AddISPCTargetFlags(std::string& flags) const;
void AddRustTargetFlags(std::string& flags) const;
std::string GetFeatureSpecificLinkRuleVariable(
std::string const& var, std::string const& lang,
std::string const& config) const;
+2
View File
@@ -2140,6 +2140,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
}
} else if (lang == "HIP") {
target->AddHIPArchitectureFlags(compileOrLink, config, flags);
} else if (lang == "Rust") {
target->AddRustTargetFlags(flags);
}
// Add VFS Overlay for Clang compilers
+1
View File
@@ -381,6 +381,7 @@ TargetProperty const StaticTargetProperties[] = {
{ "Swift_MODULE_DIRECTORY"_s, IC::CanCompileSources },
{ "Swift_COMPILATION_MODE"_s, IC::CanCompileSources },
// ---- Rust
{ "Rust_EDITION"_s, IC::CanCompileSources },
{ "Rust_MAIN_CRATE_ROOT"_s, IC::CanCompileSources },
// ---- moc
{ "AUTOMOC"_s, IC::CanCompileSources },
@@ -0,0 +1,5 @@
\[1/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
\[2/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
\[3/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
\[4/5\] Building Rust object CMakeFiles[\\/]Edition\.20[0-9][0-9]\.dir[\\/](Debug[\\/])?libedition_20[0-9][0-9]\.rs\.rlib
\[5/5\] Linking Rust executable (Debug[\\/])?Editions
+6
View File
@@ -0,0 +1,6 @@
^CMake Warning \(dev\) at Editions\.cmake:[0-9]+ \(enable_language\):
CMake's support for the Rust programming language is experimental\. It is
meant only for experimentation and feedback to CMake developers\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.$
+4
View File
@@ -0,0 +1,4 @@
Not searching for unused variables given on the command line.
-- Configuring done \([.0-9]+s\)
-- Generating done \([.0-9]+s\)
-- Build files have been written to: .*[\\/]Editions-build
+32
View File
@@ -0,0 +1,32 @@
set(CMAKE_EXPERIMENTAL_RUST "6b6e613b-f6cb-402d-8aea-59034fa8c65b")
enable_language(Rust)
# No Edition set, rustc defaults to 2015.
add_library(Edition.2015 OBJECT edition_2015.rs)
set_target_properties(Edition.2015 PROPERTIES Rust_EDITION 2015)
# Explicitly set edition on target, without default value from variable.
add_library(Edition.2018 OBJECT edition_2018.rs)
set_target_properties(Edition.2018 PROPERTIES Rust_EDITION 2018)
# Implicitly set edition on target from variable
set(CMAKE_Rust_EDITION 2021)
add_library(Edition.2021 OBJECT edition_2021.rs)
# Explicitly override the edition.
add_library(Edition.2024 OBJECT edition_2024.rs)
set_target_properties(Edition.2024 PROPERTIES Rust_EDITION 2024)
# Rust guarantees that we can link multiple crates with different editions
# together. We specify explicitly the edition to make sure CMake properly pass
# the edition in the linking step too.
unset(CMAKE_Rust_EDITION)
add_executable(Editions editions.rs)
set_target_properties(Editions PROPERTIES Rust_EDITION 2018)
target_link_libraries(
Editions PRIVATE
Edition.2015
Edition.2018
Edition.2021
Edition.2024
)
+7
View File
@@ -2,3 +2,10 @@ include(RunCMake)
run_cmake(Enable)
run_cmake(EnableExperimental)
block()
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Editions-build)
run_cmake(Editions)
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(Editions-build ${CMAKE_COMMAND} --build . --config Debug)
endblock()
+2
View File
@@ -0,0 +1,2 @@
// dyn is as an identifier is only allowed in Rust 2015
pub fn dyn() {}
+18
View File
@@ -0,0 +1,18 @@
#![allow(rust_2021_compatibility)]
pub trait Foo {}
struct FooA {}
impl Foo for FooA {}
struct FooB {}
impl Foo for FooB {}
// dyn keyword is available in 2018+
pub fn make_foo(value: i32) -> Box<dyn Foo> {
match value {
// Unsupported in 2021+, should be 0..=42
0...42 => Box::new(FooA{}),
_ => Box::new(FooB{}),
}
}
+5
View File
@@ -0,0 +1,5 @@
// gen is becoming a keyword in 2024
pub fn gen() -> i32 {
// This does not compile before Rust 2021
[1, 2, 3].into_iter().reduce(|acc, n| acc + n).unwrap_or(0)
}
+8
View File
@@ -0,0 +1,8 @@
pub fn add_options(a: Option<i32>, b: Option<i32>) -> Option<i32> {
// let chains only allowed in Rust 2024
if let Some(a) = a && let Some(b) = b {
Some(a + b)
} else {
None
}
}
+12
View File
@@ -0,0 +1,12 @@
use edition_2015;
use edition_2018;
use edition_2021;
use edition_2024;
fn main() {
edition_2015::r#dyn();
let _ = edition_2018::make_foo(1337);
let _ = edition_2021::r#gen();
let _ = edition_2024::add_options(None, None);
}