1 Commits
v1.1.1 ... main

Author SHA1 Message Date
Yakumo Hokori
3575497448 feat: Generate platform-specific shared library boilerplate in source files and improve code formatting.
All checks were successful
Rust Cross-Compile and Release / build_and_release (push) Successful in 3m8s
2026-01-18 01:20:44 +08:00

View File

@@ -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,23 +144,67 @@ 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 {
fn generate_source_file(lang: &Lang, project_type: &ProjectType) -> String {
match project_type {
ProjectType::SharedLib => {
match lang {
Lang::C => {
r#"#ifdef _WIN32
#include <windows.h>
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 <windows.h>
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()
}
}
}
_ => {
match lang {
Lang::C => {
"#include <stdio.h>\n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}"
@@ -165,6 +216,8 @@ fn generate_source_file(lang: &Lang) -> String {
}
}
}
}
}
fn sanitize_folder_name(name: &str) -> String {
let re = Regex::new(r"[^a-zA-Z0-9_-]").unwrap();
@@ -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(())
}