Parcourir la source

feat(build, kernel): 添加内核版本信息生成与显示功能 (#1269)

添加了内核构建时自动生成版本信息的功能,包括版本号、构建时间、编译器信息、Git提交等。
在内核启动时打印版本信息,并可通过/proc/version文件查询。更新了about应用使用uname系统调用

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin il y a 2 mois
Parent
commit
a8e4a826a4

+ 1 - 0
.github/workflows/makefile.yml

@@ -28,6 +28,7 @@ jobs:
         shell: bash -ileo pipefail {0}
         run: |
           printf "\n" >> kernel/src/include/bindings/bindings.rs
+          printf "\n" >> kernel/src/init/version_info.rs
           sed -i 's/arch = ".*"/arch = "${{ matrix.arch }}"/' dadk-manifest.toml
           FMT_CHECK=1 make fmt
 

+ 240 - 0
build-scripts/Cargo.lock

@@ -11,6 +11,27 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
 [[package]]
 name = "bindgen"
 version = "0.61.0"
@@ -45,6 +66,12 @@ version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
 
+[[package]]
+name = "bumpalo"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
 [[package]]
 name = "cc"
 version = "1.1.10"
@@ -70,6 +97,21 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "chrono"
+version = "0.4.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "wasm-bindgen",
+ "windows-link",
+]
+
 [[package]]
 name = "clang-sys"
 version = "1.6.1"
@@ -81,6 +123,12 @@ dependencies = [
  "libloading",
 ]
 
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
 [[package]]
 name = "either"
 version = "1.9.0"
@@ -128,6 +176,30 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "iana-time-zone"
+version = "0.1.63"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "indexmap"
 version = "2.5.0"
@@ -138,6 +210,12 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "itoa"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+
 [[package]]
 name = "jobserver"
 version = "0.1.32"
@@ -147,13 +225,26 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "js-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "kernel_build"
 version = "0.1.0"
 dependencies = [
  "bindgen",
  "cc",
+ "chrono",
  "lazy_static",
+ "serde",
+ "serde_json",
  "toml",
 ]
 
@@ -219,6 +310,15 @@ dependencies = [
  "minimal-lexical",
 ]
 
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.18.0"
@@ -297,6 +397,18 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "ryu"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+
 [[package]]
 name = "serde"
 version = "1.0.193"
@@ -317,6 +429,17 @@ dependencies = [
  "syn 2.0.43",
 ]
 
+[[package]]
+name = "serde_json"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
 [[package]]
 name = "serde_spanned"
 version = "0.6.7"
@@ -394,6 +517,64 @@ version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.43",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.43",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
+
 [[package]]
 name = "which"
 version = "4.4.2"
@@ -428,6 +609,65 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "windows-core"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.43",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.43",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
+
+[[package]]
+name = "windows-result"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
+dependencies = [
+ "windows-link",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.48.0"

+ 4 - 1
build-scripts/kernel_build/Cargo.toml

@@ -9,4 +9,7 @@ edition = "2021"
 bindgen = "0.61.0"
 lazy_static = "1.4.0"
 cc = { version = "1.0.83", features = ["parallel"] }
-toml = "0.8.6"
+toml = "0.8.6"
+chrono = { version = "0.4", features = ["serde"] }
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"

+ 2 - 0
build-scripts/kernel_build/src/lib.rs

@@ -6,6 +6,7 @@ mod cfiles;
 mod constant;
 mod kconfig;
 mod utils;
+mod version_gen;
 
 /// 运行构建
 pub fn run() {
@@ -13,4 +14,5 @@ pub fn run() {
 
     crate::cfiles::CFilesBuilder::build();
     crate::kconfig::KConfigBuilder::build();
+    crate::version_gen::generate_version();
 }

+ 238 - 0
build-scripts/kernel_build/src/version_gen.rs

@@ -0,0 +1,238 @@
+use chrono::Utc;
+use std::env;
+use std::fs::{File, OpenOptions};
+use std::io::{Read, Write};
+use std::path::Path;
+use std::process::Command;
+
+#[derive(Debug, serde::Serialize)]
+struct KernelBuildInfo {
+    pub version: String,
+    pub release: String,
+    pub build_user: String,
+    pub build_host: String,
+    pub build_time: String,
+    pub compiler_info: String,
+    pub linker_info: String,
+    pub git_commit: String,
+    pub git_branch: String,
+    pub config_flags: String,
+}
+
+pub(super) fn generate_version() {
+    let out_dir = Path::new("./src/init/");
+    let version_file = Path::new(&out_dir).join("version_info.rs");
+
+    let build_info = collect_build_info();
+
+    let rust_code = generate_rust_code(&build_info);
+
+    let mut file = File::create(&version_file).unwrap();
+    file.write_all(rust_code.as_bytes()).unwrap();
+
+    println!("cargo:rerun-if-changed=../");
+}
+
+fn collect_build_info() -> KernelBuildInfo {
+    let release = "6.6.21-dragonos".to_string();
+
+    // 检查是否需要更新构建计数
+    let is_actual_build = env::var("DRAGONOS_ACTUAL_BUILD").map_or(false, |val| val.trim() == "1");
+
+    // 读取并更新构建计数器
+    let build_count = if is_actual_build {
+        get_or_update_build_count()
+    } else {
+        get_build_count(false)
+    };
+
+    let build_time = Utc::now().format("%a %b %d %H:%M:%S UTC %Y").to_string();
+
+    let build_user = env::var("USER").unwrap_or_else(|_| "dragonos".to_string());
+    let build_host = env::var("HOSTNAME").unwrap_or_else(|_| {
+        Command::new("hostname")
+            .output()
+            .ok()
+            .and_then(|o| String::from_utf8(o.stdout).ok())
+            .map(|s| s.trim().to_string())
+            .unwrap_or_else(|| "localhost".to_string())
+    });
+    let kernel_version = env::var("CARGO_PKG_VERSION").unwrap_or("unknown".to_string());
+    let version = format!(
+        "#{}-dragonos-{} {}",
+        build_count, kernel_version, build_time
+    );
+    let compiler_info = Command::new("rustc")
+        .arg("--version")
+        .output()
+        .ok()
+        .and_then(|o| String::from_utf8(o.stdout).ok())
+        .map(|s| s.lines().next().unwrap_or("").to_string())
+        .unwrap_or_else(|| "rustc (unknown)".to_string());
+    let linker_info = Command::new(env::var("LD").unwrap_or_else(|_| "ld".to_string()))
+        .arg("--version")
+        .output()
+        .ok()
+        .and_then(|o| String::from_utf8(o.stdout).ok())
+        .map(|s| s.lines().next().unwrap_or("").to_string())
+        .unwrap_or_else(|| "ld (unknown)".to_string());
+    let git_commit = Command::new("git")
+        .args(["rev-parse", "--short", "HEAD"])
+        .output()
+        .ok()
+        .and_then(|o| String::from_utf8(o.stdout).ok())
+        .map(|s| s.trim().to_string())
+        .unwrap_or_else(|| "unknown".to_string());
+
+    // 检查是否有未提交的更改
+    let is_dirty = Command::new("git")
+        .args(["status", "--porcelain"])
+        .output()
+        .ok()
+        .map(|o| !o.stdout.is_empty())
+        .unwrap_or(false);
+
+    // 如果有未提交的更改,添加-dirty后缀
+    let git_commit = if is_dirty && !git_commit.is_empty() {
+        format!("{}-dirty", git_commit)
+    } else {
+        git_commit
+    };
+    let git_branch = Command::new("git")
+        .args(["rev-parse", "--abbrev-ref", "HEAD"])
+        .output()
+        .ok()
+        .and_then(|o| String::from_utf8(o.stdout).ok())
+        .map(|s| s.trim().to_string())
+        .unwrap_or_else(|| "unknown".to_string());
+    let config_flags = env::var("CONFIG_FLAGS").unwrap_or_else(|_| "".to_string());
+
+    KernelBuildInfo {
+        version,
+        release,
+        build_user,
+        build_host,
+        build_time,
+        compiler_info,
+        linker_info,
+        git_commit,
+        git_branch,
+        config_flags,
+    }
+}
+
+fn generate_rust_code(build_info: &KernelBuildInfo) -> String {
+    format!(
+        r#"
+#![allow(dead_code)]
+// Auto-generated version information file, do not modify
+// Generated at: {}
+
+#[derive(Debug, Clone, Copy)]
+pub struct KernelBuildInfo {{
+    pub version: &'static str,
+    pub release: &'static str,
+    pub build_user: &'static str,
+    pub build_host: &'static str,
+    pub build_time: &'static str,
+    pub compiler_info: &'static str,
+    pub linker_info: &'static str,
+    pub git_commit: &'static str,
+    pub git_branch: &'static str,
+    pub config_flags: &'static str,
+}}
+
+pub static KERNEL_BUILD_INFO: KernelBuildInfo = KernelBuildInfo {{
+    version: "{}",
+    release: "{}",
+    build_user: "{}",
+    build_host: "{}",
+    build_time: "{}",
+    compiler_info: "{}",
+    linker_info: "{}",
+    git_commit: "{}",
+    git_branch: "{}",
+    config_flags: "{}",
+}};
+
+pub const fn get_kernel_build_info() -> &'static KernelBuildInfo {{
+    &KERNEL_BUILD_INFO
+}}
+"#,
+        Utc::now().format("%Y-%m-%d %H:%M:%S UTC"),
+        build_info.version,
+        build_info.release,
+        build_info.build_user,
+        build_info.build_host,
+        build_info.build_time,
+        build_info
+            .compiler_info
+            .replace('\\', "\\\\")
+            .replace('\"', "\\\""),
+        build_info
+            .linker_info
+            .replace('\\', "\\\\")
+            .replace('\"', "\\\""),
+        build_info.git_commit,
+        build_info.git_branch,
+        build_info.config_flags
+    )
+}
+
+/// 获取构建计数器(可选择是否更新)
+fn get_build_count(increment: bool) -> u32 {
+    let counter_file = Path::new(".build_count");
+
+    // 尝试读取现有计数器
+    let count = if counter_file.exists() {
+        let mut file = File::open(&counter_file).unwrap();
+        let mut content = String::new();
+        file.read_to_string(&mut content).unwrap();
+        content.trim().parse().unwrap_or(0)
+    } else {
+        0
+    };
+
+    if increment {
+        // 增加计数器
+        let new_count = count + 1;
+
+        // 写入新值
+        let mut file = OpenOptions::new()
+            .write(true)
+            .create(true)
+            .truncate(true)
+            .open(&counter_file)
+            .unwrap();
+
+        file.write_all(new_count.to_string().as_bytes()).unwrap();
+
+        // 将计数器文件添加到 .gitignore(如果还没添加)
+        let gitignore_path = Path::new(".gitignore");
+        if gitignore_path.exists() {
+            let mut gitignore_content = String::new();
+            if let Ok(mut gitignore_file) = File::open(gitignore_path) {
+                gitignore_file
+                    .read_to_string(&mut gitignore_content)
+                    .unwrap_or_default();
+            }
+
+            if !gitignore_content.lines().any(|line| line == ".build_count") {
+                if let Ok(mut gitignore_file) = OpenOptions::new().append(true).open(gitignore_path)
+                {
+                    writeln!(gitignore_file, "\n# Build counter\n.build_count").unwrap_or_default();
+                }
+            }
+        }
+
+        new_count
+    } else {
+        // 如果只是读取,返回当前计数+1(用于显示)
+        count + 1
+    }
+}
+
+/// 获取或更新构建计数器
+fn get_or_update_build_count() -> u32 {
+    get_build_count(true)
+}

+ 3 - 0
kernel/.gitignore

@@ -7,3 +7,6 @@ src/include/bindings/bindings.rs
 # 将自动生成的Rust-C FFI加到gitignore
 src/include/bindings/bindings.h
 
+
+# Build counter
+.build_count

+ 137 - 0
kernel/Cargo.lock

@@ -39,6 +39,21 @@ version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "another_ext4"
 version = "0.1.0"
@@ -135,6 +150,12 @@ checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
 name = "bitmap"
 version = "0.1.0"
 
+[[package]]
+name = "bumpalo"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
 [[package]]
 name = "byteorder"
 version = "1.5.0"
@@ -167,6 +188,21 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "chrono"
+version = "0.4.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits 0.2.19",
+ "serde",
+ "wasm-bindgen",
+ "windows-link",
+]
+
 [[package]]
 name = "clang-sys"
 version = "1.8.1"
@@ -197,6 +233,12 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
 [[package]]
 name = "crc"
 version = "0.1.0"
@@ -537,6 +579,30 @@ version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
 
+[[package]]
+name = "iana-time-zone"
+version = "0.1.63"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core 0.59.0",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "ida"
 version = "0.1.0"
@@ -609,6 +675,16 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "js-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "kcmdline_macros"
 version = "0.1.0"
@@ -631,7 +707,10 @@ version = "0.1.0"
 dependencies = [
  "bindgen",
  "cc",
+ "chrono",
  "lazy_static",
+ "serde",
+ "serde_json",
  "toml",
 ]
 
@@ -1537,6 +1616,64 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
+
 [[package]]
 name = "which"
 version = "4.4.2"

+ 1 - 1
kernel/src/Makefile

@@ -42,7 +42,7 @@ kernel_subdirs := debug
 TOOLCHAIN := +nightly-2025-08-10
 
 kernel_rust:
-	RUSTFLAGS="$(RUSTFLAGS)" cargo $(TOOLCHAIN) $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
+	DRAGONOS_ACTUAL_BUILD=1 RUSTFLAGS="$(RUSTFLAGS)" cargo $(TOOLCHAIN) $(CARGO_ZBUILD) build --release --target $(TARGET_JSON)
 
 
 all: kernel

+ 22 - 1
kernel/src/filesystem/procfs/mod.rs

@@ -39,6 +39,7 @@ use super::vfs::{
 pub mod kmsg;
 pub mod log;
 mod proc_mounts;
+mod proc_version;
 mod syscall;
 
 /// @brief 进程文件类型
@@ -59,6 +60,8 @@ pub enum ProcFileType {
     ProcFdDir = 5,
     ProcFdFile = 6,
     ProcMounts = 7,
+    /// /proc/version
+    ProcVersion = 8,
     //todo: 其他文件类型
     ///默认文件类型
     Default,
@@ -75,6 +78,7 @@ impl From<u8> for ProcFileType {
             5 => ProcFileType::ProcFdDir,
             6 => ProcFileType::ProcFdFile,
             7 => ProcFileType::ProcMounts,
+            8 => ProcFileType::ProcVersion,
             _ => ProcFileType::Default,
         }
     }
@@ -633,6 +637,19 @@ impl ProcFS {
             .create_proc_file(mounts_params)
             .unwrap_or_else(|_| panic!("create mounts error"));
 
+        // 创建 version 文件
+        let version_params = ProcFileCreationParams::builder()
+            .parent(result.root_inode())
+            .name("version")
+            .file_type(FileType::File)
+            .mode(ModeType::from_bits_truncate(0o444))
+            .ftype(ProcFileType::ProcVersion)
+            .build()
+            .unwrap();
+        result
+            .create_proc_file(version_params)
+            .unwrap_or_else(|_| panic!("create version error"));
+
         let self_dir = result
             .root_inode()
             .create("self", FileType::Dir, ModeType::from_bits_truncate(0o555))
@@ -780,6 +797,7 @@ impl IndexNode for LockedProcFSInode {
             ProcFileType::ProcMeminfo => inode.open_meminfo(&mut private_data)?,
             ProcFileType::ProcExe => inode.open_exe(&mut private_data)?,
             ProcFileType::ProcMounts => inode.open_mounts(&mut private_data)?,
+            ProcFileType::ProcVersion => inode.open_version(&mut private_data)?,
             ProcFileType::Default => inode.data.len() as i64,
             ProcFileType::ProcSelf => inode.open_self(&mut private_data)?,
             _ => 0,
@@ -838,7 +856,10 @@ impl IndexNode for LockedProcFSInode {
 
         // 根据文件类型读取相应数据
         match inode.fdata.ftype {
-            ProcFileType::ProcStatus | ProcFileType::ProcMeminfo | ProcFileType::ProcMounts => {
+            ProcFileType::ProcStatus
+            | ProcFileType::ProcMeminfo
+            | ProcFileType::ProcMounts
+            | ProcFileType::ProcVersion => {
                 // 获取数据信息
                 let mut private_data = match &*data {
                     FilePrivateData::Procfs(p) => p.clone(),

+ 29 - 0
kernel/src/filesystem/procfs/proc_version.rs

@@ -0,0 +1,29 @@
+use system_error::SystemError;
+
+use crate::init::version_info;
+
+use super::{ProcFSInode, ProcfsFilePrivateData};
+
+impl ProcFSInode {
+    #[inline(never)]
+    pub(super) fn open_version(
+        &self,
+        pdata: &mut ProcfsFilePrivateData,
+    ) -> Result<i64, SystemError> {
+        let info = version_info::get_kernel_build_info();
+
+        // Linux version 5.15.0-152-generic (buildd@lcy02-amd64-094) (gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #162-Ubuntu SMP Wed Jul 23 09:48:42 UTC 2025
+        let version_content = format!(
+            "Linux version {} ({}@{}) ({}, {}) {}\n",
+            info.release,
+            info.build_user,
+            info.build_host,
+            info.compiler_info,
+            info.linker_info,
+            info.version
+        );
+
+        pdata.data = version_content.into_bytes();
+        return Ok(pdata.data.len() as i64);
+    }
+}

+ 1 - 0
kernel/src/init/.gitignore

@@ -0,0 +1 @@
+version_info.rs

+ 28 - 0
kernel/src/init/init.rs

@@ -33,6 +33,7 @@ use log::warn;
 use super::{
     boot::{boot_callback_except_early, boot_callbacks},
     cmdline::kenrel_cmdline_param_manager,
+    version_info::get_kernel_build_info,
 };
 
 /// The entry point for the kernel
@@ -55,6 +56,9 @@ pub fn start_kernel() -> ! {
 fn do_start_kernel() {
     init_before_mem_init();
 
+    // Print kernel version information after early init
+    print_kernel_version();
+
     unsafe { mm_init() };
 
     // crate::debug::jump_label::static_keys_init();
@@ -121,3 +125,27 @@ fn init_before_mem_init() {
         .ok();
     kenrel_cmdline_param_manager().early_init();
 }
+
+/// Print kernel version information similar to Linux boot message
+#[inline(never)]
+fn print_kernel_version() {
+    let info = get_kernel_build_info();
+
+    // Log version information similar to Linux format
+    log::info!(
+        "DragonOS release {} version {} ({}) #{}",
+        info.release,
+        info.version,
+        info.compiler_info.split(' ').next().unwrap_or("unknown"),
+        info.git_commit,
+    );
+
+    log::info!(
+        "build time: {} | git branch: {} | git commit: {} | build: {}@{}",
+        info.build_time,
+        info.git_branch,
+        info.git_commit,
+        info.build_user,
+        info.build_host,
+    );
+}

+ 1 - 0
kernel/src/init/mod.rs

@@ -7,6 +7,7 @@ pub mod cmdline;
 pub mod init;
 pub mod initcall;
 pub mod initial_kthread;
+pub mod version_info;
 
 /// 启动参数
 static BOOT_PARAMS: RwLock<BootParams> = RwLock::new(BootParams::new());

+ 3 - 2
kernel/src/process/namespace/uts_namespace.rs

@@ -7,6 +7,7 @@ use alloc::sync::{Arc, Weak};
 use cfg_if::cfg_if;
 use system_error::SystemError;
 
+use crate::init::version_info::get_kernel_build_info;
 use crate::libs::spinlock::SpinLockGuard;
 use crate::process::fork::CloneFlags;
 use crate::process::namespace::user_namespace::INIT_USER_NAMESPACE;
@@ -110,8 +111,8 @@ pub struct UtsNamespace {
 impl UtsNamespace {
     const UTS_SYSNAME: &str = "Linux";
     const UTS_NODENAME: &str = "dragonos";
-    const UTS_RELEASE: &str = "6.6.21";
-    const UTS_VERSION: &str = "6.6.21";
+    const UTS_RELEASE: &str = get_kernel_build_info().release;
+    const UTS_VERSION: &str = get_kernel_build_info().version;
 
     cfg_if! {
         if #[cfg(target_arch = "x86_64")] {

+ 2 - 8
user/apps/about/Makefile

@@ -4,12 +4,10 @@ else ifeq ($(ARCH), riscv64)
 	CROSS_COMPILE=riscv64-linux-musl-
 endif
 
-# 获得当前git提交的sha1,并截取前8位
-GIT_COMMIT_SHA1=$(shell git log -n 1 | head -n 1 | cut -d ' ' -f 2 | cut -c1-8)
 CC=$(CROSS_COMPILE)gcc
 
 
-all: version_header about.c
+all: about.c
 	$(CC) -static -o about about.c
 
 .PHONY: install clean
@@ -17,10 +15,6 @@ install: all
 	mv about $(DADK_CURRENT_BUILD_DIR)/about.elf
 
 clean:
-	rm about *.o
-
-# 生成版本头文件sys_version.h
-version_header: about.c
-	@echo "#define DRAGONOS_GIT_COMMIT_SHA1 \"$(GIT_COMMIT_SHA1)\"" > sys_version.h
+	rm about *.o sys_version.h
 
 fmt:

+ 13 - 6
user/apps/about/about.c

@@ -1,6 +1,6 @@
-#include "sys_version.h" // 这是系统的版本头文件,在编译过程中自动生成
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/utsname.h>
 
 void print_ascii_logo()
 {
@@ -15,11 +15,18 @@ void print_ascii_logo()
 void print_copyright()
 {
     printf(" DragonOS - An opensource operating system.\n");
-    printf(" Copyright: DragonOS Community. 2022-2024, All rights reserved.\n");
-    printf(" Version: ");
-    printf("\033[1;32m%s\033[0m", "V0.1.10\n");
-    printf(" Git commit SHA1: %s\n", DRAGONOS_GIT_COMMIT_SHA1);
-    printf(" Build time: %s %s\n", __DATE__, __TIME__);
+    printf(" Copyright: DragonOS Community. 2022-2025, All rights reserved.\n");
+    
+    // 使用 uname 获取版本信息
+    struct utsname buf;
+    if (uname(&buf) == 0) {
+        printf(" Version: ");
+        printf("\033[1;32m%s\033[0m\n", buf.version);
+    } else {
+        printf(" Version: ");
+        printf("\033[1;32m%s\033[0m", "Unknown\n");
+    }
+    
     printf(" \nYou can visit the project via:\n");
     printf("\n");
     printf("\x1B[1;36m%s\x1B[0m", "    Official Website: https://DragonOS.org\n");