Skip to content

Commit

Permalink
Refactor utils and remove packages from build module
Browse files Browse the repository at this point in the history
  • Loading branch information
BeichenY1 committed Mar 2, 2024
1 parent 9e21e99 commit b03e2f3
Show file tree
Hide file tree
Showing 15 changed files with 755 additions and 965 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ruxgo"
version = "0.8.9"
version = "0.9.0"
edition = "2021"
authors = ["Zewei Yang <[email protected]>"]
description = "A Cargo-like build tool for building C and C++ applications"
Expand Down
6 changes: 2 additions & 4 deletions doc/ruxgo_book/src/guide/builder_module.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# builder 模块

**[build]** 模块描述了编译器的类型和所需远程库包。它包含两个部分: `compiler``packages`
**[build]** 模块描述了编译器的类型。它包含 `compiler`

- `compiler`: 指定编译器类型,例如: "gcc"。

- `packages`: 可选。主要用于从 Github 中获取应用的源代码,然后通过解析其中的 `config_linux.toml`文件来获取所需的库。当使用包时,你需要指定远程仓库和分支。
- `compiler`: 指定编译器类型,例如: "gcc"。
58 changes: 12 additions & 46 deletions src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! This module contains the build related functions
use crate::features::cfg_feat;
use crate::utils::{BuildConfig, TargetConfig, Package, log, LogLevel, OSConfig};
use crate::utils::features::cfg_feat;
use crate::parser::{BuildConfig, TargetConfig, OSConfig};
use crate::utils::log::{log, LogLevel};
use std::path::{Path, PathBuf};
use std::io::{Read, Write};
use std::fs;
Expand Down Expand Up @@ -62,7 +63,6 @@ pub struct Target<'a> {
hash_file_path: String,
path_hash: HashMap<String, String>,
dependant_libs: Vec<Target<'a>>,
packages: &'a Vec<Package>,
}

/// Represents a source file (A single C or Cpp file)
Expand All @@ -81,13 +81,11 @@ impl<'a> Target<'a> {
/// * `build_config` - Build config
/// * `target_config` - Target config
/// * `targets` - All targets
/// * `packages` - All packages
pub fn new (
build_config: &'a BuildConfig,
os_config: &'a OSConfig,
target_config: &'a TargetConfig,
targets: &'a Vec<TargetConfig>,
packages: &'a Vec<Package>
targets: &'a Vec<TargetConfig>
) -> Self {
let srcs = Vec::new();
let dependant_includes: HashMap<String, Vec<String>> = HashMap::new();
Expand Down Expand Up @@ -122,29 +120,20 @@ impl<'a> Target<'a> {
for dependant_lib in &target_config.deps {
for target in targets {
if target.name == *dependant_lib {
dependant_libs.push(Target::new(build_config, os_config, target, targets, packages));
}
}
for pkg in packages {
for target in &pkg.target_configs {
if target.name == *dependant_lib {
dependant_libs.push(Target::new(&pkg.build_config, os_config, target, &pkg.target_configs, &pkg.sub_packages));
}
dependant_libs.push(Target::new(build_config, os_config, target, targets));
}
}
}

// check types of the dependant libs
for dep_lib in &dependant_libs {
if dep_lib.target_config.typ != "dll" && dep_lib.target_config.typ != "static" && dep_lib.target_config.typ != "object" {
log(LogLevel::Error, "Can add only dlls, static or object libraries as dependant libs");
log(LogLevel::Error, "Can add only dll, static or object libs as dependant libs");
log(LogLevel::Error, &format!("Target: {} is not a dll, static or object library", dep_lib.target_config.name));
log(LogLevel::Error, &format!("Target: {} is a {}", dep_lib.target_config.name, dep_lib.target_config.typ));
std::process::exit(1);
}
else {
log(LogLevel::Info, &format!("Adding dependant lib: {}", dep_lib.target_config.name));
}
log(LogLevel::Info, &format!("Adding dependant lib: {}", dep_lib.target_config.name));
if !dep_lib.target_config.name.starts_with("lib") {
log(LogLevel::Error, "Dependant lib name must start with lib");
log(LogLevel::Error, &format!("Target: {} does not start with lib", dep_lib.target_config.name));
Expand All @@ -154,12 +143,7 @@ impl<'a> Target<'a> {
if target_config.deps.len() > dependant_libs.len() {
log(LogLevel::Error, "Dependant libs not found!");
log(LogLevel::Error, &format!("Dependant libs: {:?}", target_config.deps));
let mut targets_pkg = Vec::new();
for pkg in packages {
targets_pkg.extend(pkg.target_configs.clone());
}
let targets_all = targets.iter().chain(targets_pkg.iter());
log(LogLevel::Error, &format!("Found libs: {:?}", targets_all.map(|x| {
log(LogLevel::Error, &format!("Found libs: {:?}", targets.iter().map(|x| {
if x.typ == "dll" || x.typ == "static" || x.typ == "object" {
x.name.clone()
} else {
Expand All @@ -179,7 +163,6 @@ impl<'a> Target<'a> {
path_hash,
hash_file_path,
dependant_libs,
packages,
};
target.get_srcs(&target_config.src);
target
Expand All @@ -188,21 +171,12 @@ impl<'a> Target<'a> {
/// Builds the target
/// # Arguments
/// * `gen_cc` - Generate compile_commands.json
/// * `relink` - Determine whether to re-link
pub fn build(&mut self, gen_cc: bool, relink: bool) {
// build other lib targets of packages firstly
for pkg in self.packages {
for target in &pkg.target_configs {
if target.typ == "dll" || target.typ == "static" || target.typ == "object" {
// If the root target(exe target) adds os_config, the pkg_tgt also adds os_config
let mut pkg_tgt = Target::new(&pkg.build_config, &self.os_config, target, &pkg.target_configs, &pkg.sub_packages);
pkg_tgt.build(gen_cc, relink);
}
}
}
let mut to_link: bool = false;

// if the source file needs to be build, then to link
let mut link_causer: Vec<&str> = Vec::new(); // trace the linked source files
let mut link_causer: Vec<&str> = Vec::new();
let mut srcs_needed = 0;
let total_srcs = self.srcs.len();
let mut src_ccs = Vec::new();
Expand Down Expand Up @@ -266,7 +240,7 @@ impl<'a> Target<'a> {
return;
}

// Parallel built
// parallel built
let progress_bar = Arc::new(Mutex::new(ProgressBar::new(srcs_needed as u64)));
let num_complete = Arc::new(Mutex::new(0));
let src_hash_to_update = Arc::new(Mutex::new(Vec::new()));
Expand Down Expand Up @@ -306,7 +280,7 @@ impl<'a> Target<'a> {
Hasher::save_hash(&src.path, &mut self.path_hash);
}

// Link target
// links the target
if to_link {
for src in link_causer {
log(LogLevel::Info, &format!("\tLinking file: {}", &src));
Expand Down Expand Up @@ -592,14 +566,6 @@ impl<'a> Target<'a> {
cc.push_str(include);
});
}
for pack in self.packages {
for tgtg in &pack.target_configs {
tgtg.include_dir.iter().for_each(|include| {
cc.push_str(" -I");
cc.push_str(include);
});
}
}

cc.push_str(" ");
let cflags = &self.target_config.cflags;
Expand Down
86 changes: 19 additions & 67 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
use crate::builder::Target;
use crate::global_cfg::GlobalConfig;
use crate::utils::{self, BuildConfig, TargetConfig, OSConfig, QemuConfig, Package, log, LogLevel};
use crate::features;
use crate::parser::{self, BuildConfig, TargetConfig, OSConfig, QemuConfig};
use crate::utils::log::{log, LogLevel};
use crate::utils::env;
use crate::utils::features;
use std::path::Path;
use std::io::Write;
use std::fs;
Expand All @@ -17,7 +19,6 @@ static OBJ_DIR: &str = "ruxgo_bld/obj_win32";
#[cfg(target_os = "linux")]
static OBJ_DIR: &str = "ruxgo_bld/obj_linux";
static TARGET_DIR: &str = "ruxgo_bld/target";
static PACKAGES_DIR: &str = "ruxgo_bld/packages";

// OSConfig hash file
static OSCONFIG_HASH_FILE: &str = "ruxgo_bld/os_config.hash";
Expand Down Expand Up @@ -56,9 +57,8 @@ lazy_static! {
/// # Arguments
/// * `targets` - A vector of targets to clean
/// * `os_config` - The local os configuration
/// * `packages` - A vector of packages to clean
/// * `choices` - A vector of choices to select which components to delete
pub fn clean(targets: &Vec<TargetConfig>, os_config: &OSConfig, packages: &Vec<Package>, choices: Vec<String>) {
pub fn clean(targets: &Vec<TargetConfig>, os_config: &OSConfig, choices: Vec<String>) {
// Helper function to remove a directory or a file and log the result
let remove_dir = |dir_path: &str| {
if Path::new(dir_path).exists() {
Expand Down Expand Up @@ -133,44 +133,13 @@ pub fn clean(targets: &Vec<TargetConfig>, os_config: &OSConfig, packages: &Vec<P
remove_file(&elf_name);
}
}
// removes bins of packages if have
for pack in packages {
for target in &pack.target_configs {
#[cfg(target_os = "windows")]
let hash_path = format!("ruxgo_bld/{}.win32.hash", &target.name);
#[cfg(target_os = "linux")]
let hash_path = format!("ruxgo_bld/{}.linux.hash", &target.name);
remove_file(&hash_path);
if Path::new(BIN_DIR).exists() {
let mut bin_name = format!("{}/{}", BIN_DIR, target.name);
#[cfg(target_os = "windows")]
match target.typ.as_str() {
"dll" => bin_name.push_str(".dll"),
_ => (),
}
#[cfg(target_os = "linux")]
match target.typ.as_str() {
"dll" => bin_name.push_str(".so"),
"static" => bin_name.push_str(".a"),
"object" => bin_name.push_str(".o"),
_ => (),
}
remove_file(&bin_name);
}
}
}
}

// Removes obj if choices includes "Obj" or choices includes "All"
if choices.contains(&String::from("Obj")) || choices.contains(&String::from("All")) {
remove_dir(OBJ_DIR);
}

// Removes downloaded packages if choices includes "Packages" or choices includes "All"
if choices.contains(&String::from("Packages")) || choices.contains(&String::from("All")) {
remove_dir(PACKAGES_DIR);
}

// Removes all if choices includes "All"
if choices.contains(&String::from("All")) {
remove_dir(BUILD_DIR);
Expand All @@ -184,14 +153,12 @@ pub fn clean(targets: &Vec<TargetConfig>, os_config: &OSConfig, packages: &Vec<P
/// * `os_config` - The local os configuration
/// * `gen_cc` - Whether to generate a compile_commands.json file
/// * `gen_vsc` - Whether to generate a .vscode/c_cpp_properties.json file
/// * `packages` - A vector of packages to get libs
pub fn build(
build_config: &BuildConfig,
targets: &Vec<TargetConfig>,
os_config: &OSConfig,
gen_cc: bool,
gen_vsc: bool,
packages: &Vec<Package>
) {
if !Path::new(BUILD_DIR).exists() {
fs::create_dir(BUILD_DIR).unwrap_or_else(|why| {
Expand Down Expand Up @@ -224,12 +191,7 @@ pub fn build(
std::process::exit(1);
});

let mut inc_dirs: Vec<String> = targets.iter().flat_map(|t| t.include_dir.clone()).collect();
for package in packages {
for target in &package.target_configs {
inc_dirs.extend(target.include_dir.clone());
}
}
let inc_dirs: Vec<String> = targets.iter().flat_map(|t| t.include_dir.clone()).collect();
let compiler_path: String = build_config.compiler.read().unwrap().clone();
let mut intellimode: String = String::new();
if compiler_path == "gcc" || compiler_path == "g++" {
Expand Down Expand Up @@ -354,7 +316,7 @@ pub fn build(

// Constructs each target separately based on the os_config changes.
for target in targets {
let mut tgt = Target::new(build_config, os_config, target, targets, packages);
let mut tgt = Target::new(build_config, os_config, target, targets);

let needs_relink = config_changed && target.typ == "exe";
tgt.build(gen_cc, needs_relink);
Expand Down Expand Up @@ -454,8 +416,7 @@ fn build_ruxlibc(build_config: &BuildConfig, os_config: &OSConfig, gen_cc: bool)
deps: Vec::new(),
};
let ulib_targets = Vec::new();
let ulib_packages = Vec::new();
let mut tgt = Target::new(build_config, os_config, &ulib_tgt, &ulib_targets, &ulib_packages);
let mut tgt = Target::new(build_config, os_config, &ulib_tgt, &ulib_targets);
tgt.build(gen_cc, false);
}

Expand Down Expand Up @@ -538,16 +499,14 @@ fn build_ruxmusl(build_config: &BuildConfig, os_config: &OSConfig) {
/// * `build_config` - The local build configuration
/// * `exe_target` - The exe target to run
/// * `targets` - A vector of targets
/// * `packages` - A vector of packages
pub fn run (
bin_args: Option<Vec<&str>>,
build_config: &BuildConfig,
os_config: &OSConfig,
exe_target: &TargetConfig,
targets: &Vec<TargetConfig>,
packages: &Vec<Package>
targets: &Vec<TargetConfig>
) {
let trgt = Target::new(build_config, os_config, exe_target, targets, packages);
let trgt = Target::new(build_config, os_config, exe_target, targets);
if !Path::new(&trgt.bin_path).exists() {
log(LogLevel::Error, &format!("Could not find binary: {}", &trgt.bin_path));
std::process::exit(1);
Expand Down Expand Up @@ -894,9 +853,9 @@ pub fn init_project(project_name: &str, is_c: Option<bool>, config: &GlobalConfi
}

/// Parses the config file of local project
pub fn parse_config() -> (BuildConfig, OSConfig, Vec<TargetConfig>, Vec<Package>) {
pub fn parse_config() -> (BuildConfig, OSConfig, Vec<TargetConfig>) {
#[cfg(target_os = "linux")]
let (build_config, os_config, targets) = utils::parse_config("./config_linux.toml", true);
let (build_config, os_config, targets) = parser::parse_config("./config_linux.toml", true);
#[cfg(target_os = "windows")]
let (build_config, os_config, targets) = utils::parse_config("./config_win32.toml", true);

Expand All @@ -905,29 +864,22 @@ pub fn parse_config() -> (BuildConfig, OSConfig, Vec<TargetConfig>, Vec<Package>
if targets.is_empty() {
log(LogLevel::Error, "No targets in config");
std::process::exit(1);
} else {
// Allow only one exe and set it as the exe_target
for target in &targets {
if target.typ == "exe" {
num_exe += 1;
exe_target = Some(target);
}
}
for target in &targets {
if target.typ == "exe" {
num_exe += 1;
exe_target = Some(target);
}
}
if num_exe != 1 || exe_target.is_none() {
log(LogLevel::Error, "Exactly one executable target must be specified");
std::process::exit(1);
}

#[cfg(target_os = "linux")]
let packages = Package::parse_packages("./config_linux.toml");
#[cfg(target_os = "windows")]
let packages = Package::parse_packages("./config_win32.toml");

// Add environment config
utils::config_env(&os_config);
env::config_env(&os_config);

(build_config, os_config, targets, packages)
(build_config, os_config, targets)
}

pub fn pre_gen_cc() {
Expand Down
Loading

0 comments on commit b03e2f3

Please sign in to comment.