mirror of
https://github.com/dexoron/dcr.git
synced 2026-10-21 23:19:36 +00:00
feat: add AGENTS.md for quick start and CI guidelines; update documentation for dcr add and dcr build commands
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use crate::core::config::Config;
|
||||
use crate::core::deps::register;
|
||||
use crate::utils::fs::find_project_root;
|
||||
use crate::utils::log::error;
|
||||
use crate::utils::text::{BOLD_GREEN, colored};
|
||||
@@ -12,6 +13,7 @@ pub struct AddArgs {
|
||||
pub branch: Option<String>,
|
||||
pub tag: Option<String>,
|
||||
pub rev: Option<String>,
|
||||
pub version_from_registry: Option<String>,
|
||||
}
|
||||
|
||||
pub fn add(args: &[String]) -> i32 {
|
||||
@@ -71,6 +73,8 @@ pub fn add(args: &[String]) -> i32 {
|
||||
let mut table = Map::new();
|
||||
table.insert("path".to_string(), Value::String(path));
|
||||
Value::Table(table)
|
||||
} else if let Some(version) = add_args.version_from_registry {
|
||||
Value::String(version)
|
||||
} else {
|
||||
error("Dependency source (path or git) must be provided");
|
||||
return 1;
|
||||
@@ -124,8 +128,38 @@ fn parse_add_args(args: &[String]) -> Result<AddArgs, i32> {
|
||||
}
|
||||
source_spec = s.clone();
|
||||
} else {
|
||||
error("Dependency source is required");
|
||||
return Err(1);
|
||||
// No source provided — try registry auto-lookup
|
||||
match register::resolve_package_from_registry(&name) {
|
||||
Ok(info) => {
|
||||
let version = info
|
||||
.get("latest_version")
|
||||
.or_else(|| info.get("version"))
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| {
|
||||
(
|
||||
"Registry entry for `".to_string() + &name + "` has no version field",
|
||||
1,
|
||||
)
|
||||
})
|
||||
.map_err(|(msg, code)| {
|
||||
error(&msg);
|
||||
code
|
||||
})?;
|
||||
return Ok(AddArgs {
|
||||
name,
|
||||
path: None,
|
||||
git: None,
|
||||
branch: None,
|
||||
tag: None,
|
||||
rev: None,
|
||||
version_from_registry: Some(version.to_string()),
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
error(&format!("Cannot add `{}` without source: {}", name, e));
|
||||
return Err(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(arg) = iter.next() {
|
||||
@@ -197,5 +231,6 @@ fn parse_add_args(args: &[String]) -> Result<AddArgs, i32> {
|
||||
branch,
|
||||
tag,
|
||||
rev,
|
||||
version_from_registry: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -77,7 +77,13 @@ pub fn build(args: &[String]) -> i32 {
|
||||
let _ = clean(&clean_args);
|
||||
}
|
||||
match with_dir(&root, || {
|
||||
build_from_root(&root, &flags.profile, flags.target.as_deref(), flags.force)
|
||||
build_from_root(
|
||||
&root,
|
||||
&flags.profile,
|
||||
flags.target.as_deref(),
|
||||
flags.force,
|
||||
flags.verbose,
|
||||
)
|
||||
}) {
|
||||
Ok(()) => 0,
|
||||
Err(msg) => {
|
||||
@@ -377,6 +383,7 @@ fn build_from_root(
|
||||
profile: &str,
|
||||
target: Option<&str>,
|
||||
force: bool,
|
||||
verbose: bool,
|
||||
) -> Result<(), String> {
|
||||
let config = Config::open("./dcr.toml").map_err(|err| err.to_string())?;
|
||||
let project_name = get_config_str(&config, "package.name");
|
||||
@@ -418,12 +425,19 @@ fn build_from_root(
|
||||
);
|
||||
}
|
||||
if let Some(workspace) = parse_workspace(&config, profile, build_target.as_deref(), root)? {
|
||||
build_workspace(&workspace, profile, build_target.as_deref(), force)?;
|
||||
build_workspace(&workspace, profile, build_target.as_deref(), force, verbose)?;
|
||||
let excludes: Vec<std::path::PathBuf> =
|
||||
workspace.members.iter().map(|m| m.path.clone()).collect();
|
||||
build_project_at(root, profile, build_target.as_deref(), &excludes, force)?;
|
||||
build_project_at(
|
||||
root,
|
||||
profile,
|
||||
build_target.as_deref(),
|
||||
&excludes,
|
||||
force,
|
||||
verbose,
|
||||
)?;
|
||||
} else {
|
||||
build_project_at(root, profile, build_target.as_deref(), &[], force)?;
|
||||
build_project_at(root, profile, build_target.as_deref(), &[], force, verbose)?;
|
||||
}
|
||||
}
|
||||
let elapsed = ((start_time.elapsed().as_secs_f64() * 100.0).trunc()) / 100.0;
|
||||
@@ -440,9 +454,10 @@ fn build_workspace(
|
||||
profile: &str,
|
||||
target: Option<&str>,
|
||||
force: bool,
|
||||
verbose: bool,
|
||||
) -> Result<(), String> {
|
||||
for member in &workspace.members {
|
||||
build_project_at(&member.path, profile, target, &[], force)?;
|
||||
build_project_at(&member.path, profile, target, &[], force, verbose)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -453,6 +468,7 @@ fn build_project_at(
|
||||
target: Option<&str>,
|
||||
exclude_dirs: &[std::path::PathBuf],
|
||||
force: bool,
|
||||
verbose: bool,
|
||||
) -> Result<(), String> {
|
||||
with_dir(project_root, || {
|
||||
check_interrupted()?;
|
||||
@@ -500,21 +516,30 @@ fn build_project_at(
|
||||
.or_else(|| get_config_opt(&config, "toolchain.rcc"));
|
||||
let mut build_cflags =
|
||||
get_list_with_profile_and_target(&config, "cflags", profile, build_target)?;
|
||||
// Автоматически добавляем --target=..., если задан build.target и флаг ещё не указан
|
||||
if let Some(t) = build_target {
|
||||
if !t.trim().is_empty() {
|
||||
let target_flag = format!("--target={}", t.trim());
|
||||
if !build_cflags.iter().any(|f| f == &target_flag || f.starts_with("--target=")) {
|
||||
build_cflags.insert(0, target_flag);
|
||||
}
|
||||
if let Some(t) = build_target
|
||||
&& !t.trim().is_empty()
|
||||
{
|
||||
let target_flag = format!("--target={}", t.trim());
|
||||
if !build_cflags
|
||||
.iter()
|
||||
.any(|f| f == &target_flag || f.starts_with("--target="))
|
||||
{
|
||||
build_cflags.insert(0, target_flag);
|
||||
}
|
||||
}
|
||||
let build_ldflags =
|
||||
let mut build_ldflags =
|
||||
get_list_with_profile_and_target(&config, "ldflags", profile, build_target)?;
|
||||
let build_ldscript =
|
||||
get_string_with_profile_and_target(&config, "ldscript", profile, build_target);
|
||||
if !build_ldscript.is_empty() {
|
||||
build_ldflags.push(format!("-T{}", build_ldscript));
|
||||
}
|
||||
|
||||
// Новые поля: filename и extension
|
||||
let output_filename = get_string_with_profile_and_target(&config, "filename", profile, build_target);
|
||||
let output_extension = get_string_with_profile_and_target(&config, "extension", profile, build_target);
|
||||
let output_filename =
|
||||
get_string_with_profile_and_target(&config, "filename", profile, build_target);
|
||||
let output_extension =
|
||||
get_string_with_profile_and_target(&config, "extension", profile, build_target);
|
||||
let build_excludes =
|
||||
get_list_with_profile_and_target(&config, "exclude", profile, build_target)?;
|
||||
let build_includes =
|
||||
@@ -578,7 +603,7 @@ fn build_project_at(
|
||||
dep_root.display()
|
||||
));
|
||||
}
|
||||
build_project_at(&dep_root, profile, build_target, &[], force)?;
|
||||
build_project_at(&dep_root, profile, build_target, &[], force, verbose)?;
|
||||
print!(
|
||||
"\r{:100}\r {} {} v{}",
|
||||
"",
|
||||
@@ -693,8 +718,17 @@ fn build_project_at(
|
||||
libs: &resolved.libs,
|
||||
cflags: &resolved_cflags,
|
||||
ldflags: &resolved_ldflags,
|
||||
output_filename: if output_filename.is_empty() { None } else { Some(output_filename.as_str()) },
|
||||
output_extension: if output_extension.is_empty() { None } else { Some(output_extension.as_str()) },
|
||||
output_filename: if output_filename.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(output_filename.as_str())
|
||||
},
|
||||
output_extension: if output_extension.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(output_extension.as_str())
|
||||
},
|
||||
verbose,
|
||||
};
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] debug: compiler={}", ctx.compiler);
|
||||
|
||||
@@ -6,6 +6,7 @@ pub struct BuildRunFlags {
|
||||
pub target: Option<String>,
|
||||
pub force: bool,
|
||||
pub clean: bool,
|
||||
pub verbose: bool,
|
||||
}
|
||||
|
||||
pub fn parse_build_run_flags(args: &[String]) -> Result<BuildRunFlags, i32> {
|
||||
@@ -13,6 +14,7 @@ pub fn parse_build_run_flags(args: &[String]) -> Result<BuildRunFlags, i32> {
|
||||
let mut target = None;
|
||||
let mut force = false;
|
||||
let mut clean = false;
|
||||
let mut verbose = false;
|
||||
let mut iter = args.iter();
|
||||
|
||||
while let Some(arg) = iter.next() {
|
||||
@@ -29,6 +31,10 @@ pub fn parse_build_run_flags(args: &[String]) -> Result<BuildRunFlags, i32> {
|
||||
clean = true;
|
||||
continue;
|
||||
}
|
||||
if candidate == "verbose" {
|
||||
verbose = true;
|
||||
continue;
|
||||
}
|
||||
if candidate == "target" {
|
||||
if let Some(t) = iter.next() {
|
||||
target = Some(t.clone());
|
||||
@@ -55,5 +61,6 @@ pub fn parse_build_run_flags(args: &[String]) -> Result<BuildRunFlags, i32> {
|
||||
target,
|
||||
force,
|
||||
clean,
|
||||
verbose,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -339,6 +339,7 @@ fn collect_project_info_inner(root: &Path, profile: &str) -> Result<ProjectInfo,
|
||||
ldflags: &resolved_ldflags,
|
||||
output_filename: None,
|
||||
output_extension: None,
|
||||
verbose: false,
|
||||
};
|
||||
|
||||
let sources = collect_sources(&ctx).map_err(|e| format!("Failed to collect sources: {e}"))?;
|
||||
|
||||
@@ -37,7 +37,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
for obj in &objects {
|
||||
cmd.arg(obj);
|
||||
}
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
@@ -72,7 +72,11 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
}
|
||||
let name = ctx.output_filename.unwrap_or(ctx.project_name);
|
||||
let ext = ctx.output_extension.unwrap_or("");
|
||||
let final_name = if ext.is_empty() { name.to_string() } else { format!("{}.{}", name, ext) };
|
||||
let final_name = if ext.is_empty() {
|
||||
name.to_string()
|
||||
} else {
|
||||
format!("{}.{}", name, ext)
|
||||
};
|
||||
|
||||
let out_path = if ctx.kind == "sharedlib" {
|
||||
platform::shared_lib_path(ctx.profile, &final_name, ctx.target_dir)
|
||||
@@ -81,7 +85,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
};
|
||||
cmd.arg("-o").arg(out_path);
|
||||
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
|
||||
@@ -28,6 +28,7 @@ pub struct BuildContext<'a> {
|
||||
pub ldflags: &'a [String],
|
||||
pub output_filename: Option<&'a str>,
|
||||
pub output_extension: Option<&'a str>,
|
||||
pub verbose: bool,
|
||||
}
|
||||
|
||||
pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
for obj in &objects {
|
||||
cmd.arg(obj);
|
||||
}
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
@@ -97,7 +97,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
};
|
||||
cmd.arg(format!("/Fe:{out_path}"));
|
||||
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
|
||||
@@ -37,7 +37,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
for obj in &objects {
|
||||
cmd.arg(obj);
|
||||
}
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
@@ -72,7 +72,11 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
}
|
||||
let name = ctx.output_filename.unwrap_or(ctx.project_name);
|
||||
let ext = ctx.output_extension.unwrap_or("");
|
||||
let final_name = if ext.is_empty() { name.to_string() } else { format!("{}.{}", name, ext) };
|
||||
let final_name = if ext.is_empty() {
|
||||
name.to_string()
|
||||
} else {
|
||||
format!("{}.{}", name, ext)
|
||||
};
|
||||
|
||||
let out_path = if ctx.kind == "sharedlib" {
|
||||
platform::shared_lib_path(ctx.profile, &final_name, ctx.target_dir)
|
||||
@@ -81,7 +85,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
};
|
||||
cmd.arg("-o").arg(out_path);
|
||||
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
@@ -151,7 +155,7 @@ fn build_object(
|
||||
cmd.arg(flag);
|
||||
}
|
||||
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
for obj in &objects {
|
||||
cmd.arg(obj);
|
||||
}
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
@@ -65,7 +65,11 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
}
|
||||
let name = ctx.output_filename.unwrap_or(ctx.project_name);
|
||||
let ext = ctx.output_extension.unwrap_or("");
|
||||
let final_name = if ext.is_empty() { name.to_string() } else { format!("{}.{}", name, ext) };
|
||||
let final_name = if ext.is_empty() {
|
||||
name.to_string()
|
||||
} else {
|
||||
format!("{}.{}", name, ext)
|
||||
};
|
||||
|
||||
let out_path = if ctx.kind == "sharedlib" {
|
||||
platform::shared_lib_path(ctx.profile, &final_name, ctx.target_dir)
|
||||
@@ -74,7 +78,7 @@ pub fn build(ctx: &BuildContext) -> Result<f64, String> {
|
||||
};
|
||||
cmd.arg("-o").arg(out_path);
|
||||
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
match cmd.status() {
|
||||
@@ -214,7 +218,7 @@ fn build_object(
|
||||
let d_path = Path::new(obj_path).with_extension("d");
|
||||
cmd.arg("-MMD").arg("-MF").arg(&d_path);
|
||||
|
||||
if std::env::var("DCR_DEBUG").is_ok() {
|
||||
if ctx.verbose || std::env::var("DCR_DEBUG").is_ok() {
|
||||
eprintln!("[dcr] {:?}", cmd);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,23 @@ pub struct DcrConfig {
|
||||
pub registry: std::collections::HashMap<String, Registry>,
|
||||
}
|
||||
|
||||
fn home_dir() -> Option<PathBuf> {
|
||||
if let Ok(home) = std::env::var("HOME") {
|
||||
return Some(PathBuf::from(home));
|
||||
}
|
||||
if let Ok(profile) = std::env::var("USERPROFILE") {
|
||||
return Some(PathBuf::from(profile));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn dcr_config_dir() -> Option<PathBuf> {
|
||||
home_dir().map(|h| h.join(".dcr"))
|
||||
}
|
||||
|
||||
pub fn get_registry_config() -> Option<DcrConfig> {
|
||||
let home = std::env::var("HOME").ok()?;
|
||||
let config_path = Path::new(&home).join(".dcr/config.toml");
|
||||
let home = home_dir()?;
|
||||
let config_path = home.join(".dcr/config.toml");
|
||||
if !config_path.exists() {
|
||||
return None;
|
||||
}
|
||||
@@ -30,8 +44,9 @@ pub fn get_index_path() -> PathBuf {
|
||||
std::env::var("DCR_INDEX_PATH")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| {
|
||||
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
||||
Path::new(&home).join(".dcr").join("index.json")
|
||||
dcr_config_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
.join("index.json")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,21 @@ pub struct RegistryManager {
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
fn home_dir() -> Option<PathBuf> {
|
||||
if let Ok(home) = std::env::var("HOME") {
|
||||
return Some(PathBuf::from(home));
|
||||
}
|
||||
if let Ok(profile) = std::env::var("USERPROFILE") {
|
||||
return Some(PathBuf::from(profile));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
impl RegistryManager {
|
||||
pub fn load() -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let home = std::env::var("HOME")?;
|
||||
let dcr_dir = PathBuf::from(home).join(".dcr");
|
||||
let dcr_dir = home_dir()
|
||||
.ok_or("Cannot determine home directory")?
|
||||
.join(".dcr");
|
||||
let config_path = dcr_dir.join("config.toml");
|
||||
|
||||
if !config_path.exists() {
|
||||
|
||||
Reference in New Issue
Block a user