Skip to content

Commit

Permalink
init: lingo dependency management
Browse files Browse the repository at this point in the history
- fetching packages
- libraries specification
- add backend for the C target
- lock files
  • Loading branch information
tanneberger committed Sep 20, 2024
1 parent d4ad592 commit 008f402
Show file tree
Hide file tree
Showing 18 changed files with 1,860 additions and 552 deletions.
783 changes: 409 additions & 374 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ path = "./src/main.rs"
[dependencies]

clap = { version = "4.1", features = ["derive"] }
os-version = "0.2"
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
which = "5.0"
which = "6.0"
regex = "1.8"
lazy_static = "1.4"
rayon = "1.7"
toml = {version = "0.8"}
crossbeam = "0.8"
termion = "2.0"
git2 = "0.18"
run_script = "0.10"
tempfile = "3.0"
url = { version = "2.5", features = ["serde"] }
anyhow = "1.0"
versions = { git = "https://github.com/tanneberger/rs-versions.git", features = ["serde"]}
log = "0.4"
sha1dir = { version = "1.0", git = "https://github.com/tanneberger/sha1dir" }
colored = "2.1.0"
3 changes: 3 additions & 0 deletions derivation.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ naersk.buildPackage {
src = ./.;

cargoSha256 = lib.fakeSha256;
preBuild = ''
export CARGO_BIN_NAME=cargo
'';

nativeBuildInputs = [ pkg-config cmake zlib openssl glibc];
buildInputs = [ ];
Expand Down
26 changes: 11 additions & 15 deletions flake.lock

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

48 changes: 22 additions & 26 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use clap::{Args, Parser, Subcommand};
use serde_derive::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[value(rename_all = "lowercase")]
pub enum TargetLanguage {
C,
Cpp,
Expand All @@ -12,7 +13,7 @@ pub enum TargetLanguage {
Python,
}

#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
pub enum Platform {
Native,
Zephyr,
Expand All @@ -32,39 +33,39 @@ pub enum BuildSystem {
pub struct BuildArgs {
/// Which build system to use
/// TODO: discuss this
#[clap(short, long)]
#[arg(short, long)]
pub build_system: Option<BuildSystem>,

/// Which target to build
#[clap(short, long)]
#[arg(short, long)]
pub language: Option<TargetLanguage>,

/// Overwrites any possible board definition in Lingo.toml
#[clap(long)]
#[arg(long)]
pub platform: Option<Platform>,

/// Tell lingo where the lfc toolchain can be found
#[clap(long)]
#[arg(long)]
pub lfc: Option<PathBuf>,

/// Skips building aka invoking the build system so it only generates code
#[clap(short, long, action)]
#[arg(short, long)]
pub no_compile: bool,

/// If one of the apps fails to build dont interrupt the build process
#[clap(short, long, action)]
#[arg(short, long)]
pub keep_going: bool,

/// Compiles the binaries with optimizations turned on and strips debug symbols
#[clap(short, long, action)]
#[arg(short, long)]
pub release: bool,

/// List of apps to build if left empty all apps are built
#[clap(short, long, value_delimiter = ',')]
#[arg(short, long, value_delimiter = ',')]
pub apps: Vec<String>,

/// Number of threads to use for parallel builds. Zero means it will be determined automatically.
#[clap(short, long, default_value_t = 0)]
#[arg(short, long, default_value_t = 0)]
pub threads: usize,
}

Expand All @@ -78,19 +79,14 @@ impl BuildArgs {
}
}

impl ToString for TargetLanguage {
fn to_string(&self) -> String {
format!("{:?}", self)
}
}

#[derive(Args, Debug)]
pub struct InitArgs {
#[clap(value_enum, short, long)]
#[arg(value_enum, short, long)]
pub language: Option<TargetLanguage>,
#[clap(value_enum, short, long, default_value_t = Platform::Native)]
#[arg(value_enum, short, long, default_value_t = Platform::Native)]
pub platform: Platform,
}

impl InitArgs {
pub fn get_target_language(&self) -> TargetLanguage {
self.language.unwrap_or({
Expand Down Expand Up @@ -124,20 +120,20 @@ pub enum Command {
}

#[derive(Parser)]
#[clap(name = "Lingua Franca package manager and build tool")]
#[clap(author = "[email protected]")]
#[clap(version = env!("CARGO_PKG_VERSION"))]
#[clap(about = "Build system for the Lingua Franca coordination language", long_about = None)]
#[command(name = "Lingua Franca package manager and build tool")]
#[command(author = "[email protected]")]
#[command(version = env!("CARGO_PKG_VERSION"))]
#[command(about = "Build system for the Lingua Franca coordination language", long_about = None)]
pub struct CommandLineArgs {
/// which command of lingo to use
#[clap(subcommand)]
pub command: Command,

/// lingo wouldn't produce any output
#[clap(short, long, action)]
#[arg(short, long)]
pub quiet: bool,

/// lingo wouldn't produce any output
#[clap(short, long, action)]
/// lingo will give more detailed feedback
#[arg(short, long)]
pub verbose: bool,
}
124 changes: 124 additions & 0 deletions src/backends/cmake_c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use std::fs;
use std::io::Write;
use std::process::Command;

use crate::backends::{
BatchBackend, BatchBuildResults, BuildCommandOptions, BuildProfile, BuildResult, CommandSpec,
};
use crate::util::errors::LingoError;
use crate::util::execute_command_to_build_result;
use crate::App;

pub struct CmakeC;

fn gen_cmake_files(app: &App, options: &BuildCommandOptions) -> BuildResult {
let build_dir = app.output_root.join("build");
fs::create_dir_all(&build_dir)?;

// location of the cmake file
let app_build_folder = app.src_gen_dir().join(&app.main_reactor_name);
println!("creating {}", &app_build_folder.display());
let _ = std::fs::create_dir_all(&app_build_folder);
let cmake_file = app_build_folder.clone().join("CMakeLists.txt");

println!("writing artifacts ...");
// create potential files that come from the target properties
app.properties
.write_artifacts(&app_build_folder)
.expect("cannot write artifacts");

// read file and append cmake include to generated cmake file
println!("reading cmake file ... {:?}", &cmake_file);
let mut content = fs::read_to_string(&cmake_file)?;
let include_statement = "\ninclude(./aggregated_cmake_include.cmake)";
content += &*include_statement;

println!("writing cmake file ...");
// overwrite cmake file
let mut f = fs::OpenOptions::new()
.write(true)
.open(&cmake_file)
.expect("cannot open file");
f.write_all(content.as_ref()).expect("cannot write file");
f.flush().expect("cannot flush");

println!("running file ...");

// cmake args
let mut cmake = Command::new("cmake");
cmake.arg(format!(
"-DCMAKE_BUILD_TYPE={}",
if options.profile == BuildProfile::Release {
"RELEASE"
} else {
"DEBUG"
}
));
cmake.arg(format!(
"-DCMAKE_INSTALL_PREFIX={}",
app.output_root.display()
));
cmake.arg("-DCMAKE_INSTALL_BINDIR=bin");
cmake.arg(&app_build_folder);
cmake.arg(format!("-B {}", app_build_folder.display()));
cmake.current_dir(&build_dir);

execute_command_to_build_result(cmake)
}

fn do_cmake_build(results: &mut BatchBuildResults, options: &BuildCommandOptions) {
// open lingo.toml of the dependency
// read the version
// cry loud when it doesn't match out specified version

results.keep_going(options.keep_going);
super::lfc::LFC::do_parallel_lfc_codegen(options, results, false);
if !options.compile_target_code {
return;
}
results
// generate all CMake files ahead of time
.map(|app| gen_cmake_files(app, options))
// Run cmake to build everything.
.map(|app| {
let app_build_folder = app.src_gen_dir().join(&app.main_reactor_name);

// compile everything
let mut cmake = Command::new("cmake");
cmake.current_dir(&app_build_folder);
cmake.args(["--build", "."]);

// add one target arg for each app
let name = app
.main_reactor
.file_stem()
.ok_or(LingoError::InvalidMainReactor)?;
cmake.arg("--target");
cmake.arg(name);

execute_command_to_build_result(cmake)
})
.map(|app| {
let bin_source = app
.src_gen_dir()
.join(&app.main_reactor_name)
.join(&app.main_reactor_name);
fs::rename(bin_source, app.executable_path())?;
Ok(())
});
}

impl BatchBackend for CmakeC {
fn execute_command(&mut self, command: &CommandSpec, results: &mut BatchBuildResults) {
match command {
CommandSpec::Build(options) => do_cmake_build(results, options),
CommandSpec::Clean => {
results.par_map(|app| {
crate::util::default_build_clean(&app.output_root)?;
Ok(())
});
}
_ => todo!(),
}
}
}
Loading

0 comments on commit 008f402

Please sign in to comment.