From 35754974489bdca7ae7eea1e922d8a029cd82678 Mon Sep 17 00:00:00 2001 From: Yakumo Hokori Date: Sun, 18 Jan 2026 01:20:44 +0800 Subject: [PATCH] feat: Generate platform-specific shared library boilerplate in source files and improve code formatting. --- src/main.rs | 131 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 102 insertions(+), 29 deletions(-) diff --git a/src/main.rs b/src/main.rs index e6af5d0..15f891a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Context, Result}; +use anyhow::{Context, Result, anyhow}; use clap::{Parser, ValueEnum}; use inquire::{Confirm, Select, Text}; use regex::Regex; @@ -85,7 +85,11 @@ fn generate_cmakelists( ) -> String { let mut lines = vec![ "cmake_minimum_required(VERSION 3.20)".to_string(), - format!("project({} LANGUAGES {})", project_name, get_lang_cmake(lang)), + format!( + "project({} LANGUAGES {})", + project_name, + get_lang_cmake(lang) + ), "".to_string(), ]; @@ -110,24 +114,27 @@ fn generate_cmakelists( let ext = get_lang_ext(lang); match project_type { ProjectType::Exe => { - lines.push(format!( - "add_executable({} src/main.{})", - project_name, ext, - )); + lines.push(format!("add_executable({} src/main.{})", project_name, ext,)); } ProjectType::StaticLib => { lines.push(format!( "add_library({} STATIC src/main.{})", project_name, ext, )); - lines.push(format!("target_include_directories({} PUBLIC include)", project_name)); + lines.push(format!( + "target_include_directories({} PUBLIC include)", + project_name + )); } ProjectType::SharedLib => { lines.push(format!( "add_library({} SHARED src/main.{})", project_name, ext, )); - lines.push(format!("target_include_directories({} PUBLIC include)", project_name)); + lines.push(format!( + "target_include_directories({} PUBLIC include)", + project_name + )); lines.push(format!( "target_compile_definitions({} PUBLIC {}_EXPORTS)", project_name, @@ -137,31 +144,77 @@ fn generate_cmakelists( } // 添加导出设置(仅库类型) - if matches!(project_type, ProjectType::StaticLib | ProjectType::SharedLib) { + if matches!( + project_type, + ProjectType::StaticLib | ProjectType::SharedLib + ) { lines.push("".to_string()); lines.push("# Export targets".to_string()); lines.push("include(GNUInstallDirs)".to_string()); - lines.push(format!( - "install(TARGETS {} DESTINATION lib)", - project_name - )); - lines.push( - "install(DIRECTORY include/ DESTINATION include)".to_string(), - ); + lines.push(format!("install(TARGETS {} DESTINATION lib)", project_name)); + lines.push("install(DIRECTORY include/ DESTINATION include)".to_string()); } lines.join("\n") } -fn generate_source_file(lang: &Lang) -> String { - match lang { - Lang::C => { - "#include \n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}" - .to_string() +fn generate_source_file(lang: &Lang, project_type: &ProjectType) -> String { + match project_type { + ProjectType::SharedLib => { + match lang { + Lang::C => { + r#"#ifdef _WIN32 +#include + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +#else +// Non-Windows platforms +void __attribute__((constructor)) lib_init(void) {} +void __attribute__((destructor)) lib_fini(void) {} +#endif"# + .to_string() + } + Lang::Cpp => { + r#"#include + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +}"# + .to_string() + } + } } - Lang::Cpp => { - "#include \n\nint main() {\n std::cout << \"Hello, World!\" << std::endl;\n return 0;\n}" - .to_string() + _ => { + match lang { + Lang::C => { + "#include \n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}" + .to_string() + } + Lang::Cpp => { + "#include \n\nint main() {\n std::cout << \"Hello, World!\" << std::endl;\n return 0;\n}" + .to_string() + } + } } } } @@ -257,7 +310,10 @@ fn create_project( // 创建目录结构 fs::create_dir_all(output_dir.join("src"))?; - if matches!(project_type, ProjectType::StaticLib | ProjectType::SharedLib) { + if matches!( + project_type, + ProjectType::StaticLib | ProjectType::SharedLib + ) { fs::create_dir_all(output_dir.join("include"))?; } @@ -272,12 +328,15 @@ fn create_project( let ext = get_lang_ext(lang); fs::write( output_dir.join("src").join(format!("main.{}", ext)), - generate_source_file(lang), + generate_source_file(lang, project_type), ) .with_context(|| "写入源文件失败")?; // 为库类型创建 README.md - if matches!(project_type, ProjectType::StaticLib | ProjectType::SharedLib) { + if matches!( + project_type, + ProjectType::StaticLib | ProjectType::SharedLib + ) { let readme_content = format!( "# {}\n\nA CMake library project.\n\n## Build\n\n```bash\nmkdir build && cd build\ncmake ..\nmake\n```\n\n## Install\n\n```bash\ncmake --install .\n```\n", project_name @@ -306,7 +365,14 @@ fn main() -> Result<()> { let (name, lang, project_type, cxx_standard) = interactive_mode()?; let folder_name = sanitize_folder_name(&name); let output_path = Path::new(".").join(&folder_name); - create_project(&name, &lang, &project_type, &cxx_standard, &output_path, args.force)?; + create_project( + &name, + &lang, + &project_type, + &cxx_standard, + &output_path, + args.force, + )?; return Ok(()); } @@ -323,7 +389,14 @@ fn main() -> Result<()> { Path::new(".").join(&folder_name) }; - create_project(&name, &lang, &project_type, &cxx_standard, &output_path, args.force)?; + create_project( + &name, + &lang, + &project_type, + &cxx_standard, + &output_path, + args.force, + )?; Ok(()) }