Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3575497448 | ||
|
|
8b2c3ffe53 |
139
src/main.rs
139
src/main.rs
@@ -1,4 +1,4 @@
|
|||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{Context, Result, anyhow};
|
||||||
use clap::{Parser, ValueEnum};
|
use clap::{Parser, ValueEnum};
|
||||||
use inquire::{Confirm, Select, Text};
|
use inquire::{Confirm, Select, Text};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
@@ -30,6 +30,8 @@ enum CxxStandard {
|
|||||||
Cxx20,
|
Cxx20,
|
||||||
#[value(name = "23")]
|
#[value(name = "23")]
|
||||||
Cxx23,
|
Cxx23,
|
||||||
|
#[value(name = "26")]
|
||||||
|
Cxx26,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -83,7 +85,11 @@ fn generate_cmakelists(
|
|||||||
) -> String {
|
) -> String {
|
||||||
let mut lines = vec![
|
let mut lines = vec![
|
||||||
"cmake_minimum_required(VERSION 3.20)".to_string(),
|
"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(),
|
"".to_string(),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -95,6 +101,7 @@ fn generate_cmakelists(
|
|||||||
Some(CxxStandard::Cxx17) => "17",
|
Some(CxxStandard::Cxx17) => "17",
|
||||||
Some(CxxStandard::Cxx20) => "20",
|
Some(CxxStandard::Cxx20) => "20",
|
||||||
Some(CxxStandard::Cxx23) => "23",
|
Some(CxxStandard::Cxx23) => "23",
|
||||||
|
Some(CxxStandard::Cxx26) => "26",
|
||||||
None => "17",
|
None => "17",
|
||||||
};
|
};
|
||||||
lines.push(format!("set(CMAKE_CXX_STANDARD {})", standard));
|
lines.push(format!("set(CMAKE_CXX_STANDARD {})", standard));
|
||||||
@@ -107,24 +114,27 @@ fn generate_cmakelists(
|
|||||||
let ext = get_lang_ext(lang);
|
let ext = get_lang_ext(lang);
|
||||||
match project_type {
|
match project_type {
|
||||||
ProjectType::Exe => {
|
ProjectType::Exe => {
|
||||||
lines.push(format!(
|
lines.push(format!("add_executable({} src/main.{})", project_name, ext,));
|
||||||
"add_executable({} src/main.{})",
|
|
||||||
project_name, ext,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
ProjectType::StaticLib => {
|
ProjectType::StaticLib => {
|
||||||
lines.push(format!(
|
lines.push(format!(
|
||||||
"add_library({} STATIC src/main.{})",
|
"add_library({} STATIC src/main.{})",
|
||||||
project_name, ext,
|
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 => {
|
ProjectType::SharedLib => {
|
||||||
lines.push(format!(
|
lines.push(format!(
|
||||||
"add_library({} SHARED src/main.{})",
|
"add_library({} SHARED src/main.{})",
|
||||||
project_name, ext,
|
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!(
|
lines.push(format!(
|
||||||
"target_compile_definitions({} PUBLIC {}_EXPORTS)",
|
"target_compile_definitions({} PUBLIC {}_EXPORTS)",
|
||||||
project_name,
|
project_name,
|
||||||
@@ -134,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("".to_string());
|
||||||
lines.push("# Export targets".to_string());
|
lines.push("# Export targets".to_string());
|
||||||
lines.push("include(GNUInstallDirs)".to_string());
|
lines.push("include(GNUInstallDirs)".to_string());
|
||||||
lines.push(format!(
|
lines.push(format!("install(TARGETS {} DESTINATION lib)", project_name));
|
||||||
"install(TARGETS {} DESTINATION lib)",
|
lines.push("install(DIRECTORY include/ DESTINATION include)".to_string());
|
||||||
project_name
|
|
||||||
));
|
|
||||||
lines.push(
|
|
||||||
"install(DIRECTORY include/ DESTINATION include)".to_string(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.join("\n")
|
lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_source_file(lang: &Lang) -> String {
|
fn generate_source_file(lang: &Lang, project_type: &ProjectType) -> String {
|
||||||
match lang {
|
match project_type {
|
||||||
Lang::C => {
|
ProjectType::SharedLib => {
|
||||||
"#include <stdio.h>\n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}"
|
match lang {
|
||||||
.to_string()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Lang::Cpp => {
|
_ => {
|
||||||
"#include <iostream>\n\nint main() {\n std::cout << \"Hello, World!\" << std::endl;\n return 0;\n}"
|
match lang {
|
||||||
.to_string()
|
Lang::C => {
|
||||||
|
"#include <stdio.h>\n\nint main() {\n printf(\"Hello, World!\\n\");\n return 0;\n}"
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
Lang::Cpp => {
|
||||||
|
"#include <iostream>\n\nint main() {\n std::cout << \"Hello, World!\" << std::endl;\n return 0;\n}"
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,14 +267,15 @@ fn interactive_mode() -> Result<(String, Lang, ProjectType, Option<CxxStandard>)
|
|||||||
};
|
};
|
||||||
|
|
||||||
let cxx_standard = if matches!(lang, Lang::Cpp) {
|
let cxx_standard = if matches!(lang, Lang::Cpp) {
|
||||||
let standard_choices = vec!["11", "14", "17", "20", "23"];
|
let standard_choices = vec!["11", "14", "17", "20", "23", "26"];
|
||||||
let standard_raw = Select::new("请选择C++标准版本:", standard_choices).prompt()?;
|
let standard_raw = Select::new("请选择C++标准版本:", standard_choices).prompt()?;
|
||||||
Some(match standard_raw {
|
Some(match standard_raw {
|
||||||
"11" => CxxStandard::Cxx11,
|
"11" => CxxStandard::Cxx11,
|
||||||
"14" => CxxStandard::Cxx14,
|
"14" => CxxStandard::Cxx14,
|
||||||
"17" => CxxStandard::Cxx17,
|
"17" => CxxStandard::Cxx17,
|
||||||
"20" => CxxStandard::Cxx20,
|
"20" => CxxStandard::Cxx20,
|
||||||
_ => CxxStandard::Cxx23,
|
"23" => CxxStandard::Cxx23,
|
||||||
|
_ => CxxStandard::Cxx26,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -253,7 +310,10 @@ fn create_project(
|
|||||||
|
|
||||||
// 创建目录结构
|
// 创建目录结构
|
||||||
fs::create_dir_all(output_dir.join("src"))?;
|
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"))?;
|
fs::create_dir_all(output_dir.join("include"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,12 +328,15 @@ fn create_project(
|
|||||||
let ext = get_lang_ext(lang);
|
let ext = get_lang_ext(lang);
|
||||||
fs::write(
|
fs::write(
|
||||||
output_dir.join("src").join(format!("main.{}", ext)),
|
output_dir.join("src").join(format!("main.{}", ext)),
|
||||||
generate_source_file(lang),
|
generate_source_file(lang, project_type),
|
||||||
)
|
)
|
||||||
.with_context(|| "写入源文件失败")?;
|
.with_context(|| "写入源文件失败")?;
|
||||||
|
|
||||||
// 为库类型创建 README.md
|
// 为库类型创建 README.md
|
||||||
if matches!(project_type, ProjectType::StaticLib | ProjectType::SharedLib) {
|
if matches!(
|
||||||
|
project_type,
|
||||||
|
ProjectType::StaticLib | ProjectType::SharedLib
|
||||||
|
) {
|
||||||
let readme_content = format!(
|
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",
|
"# {}\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
|
project_name
|
||||||
@@ -302,7 +365,14 @@ fn main() -> Result<()> {
|
|||||||
let (name, lang, project_type, cxx_standard) = interactive_mode()?;
|
let (name, lang, project_type, cxx_standard) = interactive_mode()?;
|
||||||
let folder_name = sanitize_folder_name(&name);
|
let folder_name = sanitize_folder_name(&name);
|
||||||
let output_path = Path::new(".").join(&folder_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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +389,14 @@ fn main() -> Result<()> {
|
|||||||
Path::new(".").join(&folder_name)
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user