Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency Management #46

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

40 changes: 20 additions & 20 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +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)]
#[clap(rename_all = "lowercase")]
#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
#[value(rename_all = "lowercase")]
pub enum TargetLanguage {
C,
Cpp,
Expand All @@ -13,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 @@ -33,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 @@ -81,9 +81,9 @@ impl BuildArgs {

#[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,
}

Expand Down Expand Up @@ -120,20 +120,20 @@ pub enum Command {
}

#[derive(Parser)]
#[clap(name = "Lingua Franca package manager and build tool")]
#[clap(author = "tassilo.tanneberger@tu-dresden.de")]
#[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 = "tassilo.tanneberger@tu-dresden.de")]
#[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 will give more detailed feedback
#[clap(short, long, action)]
#[arg(short, long)]
pub verbose: bool,
}
118 changes: 118 additions & 0 deletions src/backends/cmake_c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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);
let _ = std::fs::create_dir_all(&app_build_folder);
let cmake_file = app_build_folder.clone().join("CMakeLists.txt");

// 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
let mut content = fs::read_to_string(&cmake_file)?;
let include_statement = "\ninclude(./aggregated_cmake_include.cmake)";
content += include_statement;

// 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");

// 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!(),
}
}
}
40 changes: 35 additions & 5 deletions src/backends/cmake.rs → src/backends/cmake_cpp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fs;
use std::io::Write;

use std::process::Command;

Expand All @@ -9,14 +10,37 @@ use crate::backends::{
BatchBackend, BatchBuildResults, BuildCommandOptions, BuildProfile, BuildResult, CommandSpec,
};

pub struct Cmake;
pub struct CmakeCpp;

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

let mut cmake = Command::new("cmake");
// location of the cmake file
let app_build_folder = app.src_gen_dir().join(&app.main_reactor_name);
let cmake_file = app_build_folder.clone().join("CMakeLists.txt");

// create potential files that come from the target properties
app.properties.write_artifacts(&app_build_folder)?;

// we need to modify the cmake file here to include our generated cmake files
let src_gen_dir = app.src_gen_dir();

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

// overwrite cmake file
let mut f = fs::OpenOptions::new().write(true).open(&cmake_file)?;
f.write_all(content.as_ref())?;
f.flush()?;

// cmake args
let mut cmake = Command::new("cmake");
cmake.arg(format!(
"-DCMAKE_BUILD_TYPE={}",
if options.profile == BuildProfile::Release {
Expand All @@ -39,19 +63,25 @@ fn gen_cmake_files(app: &App, options: &BuildCommandOptions) -> BuildResult {
.expect("not a valid main reactor path")
.display()
));
cmake.arg(app.src_gen_dir());
cmake.arg(src_gen_dir);
cmake.arg(format!("-B {}", build_dir.display()));
cmake.current_dir(&build_dir);

execute_command_to_build_result(cmake)
}

fn do_cmake_build(results: &mut BatchBuildResults, options: &BuildCommandOptions) {
// configure keep going parameter
results.keep_going(options.keep_going);
super::lfc::LFC::do_parallel_lfc_codegen(options, results, true);

// start code-generation
super::lfc::LFC::do_parallel_lfc_codegen(options, results, false);

// stop process if the user request code-generation only
if !options.compile_target_code {
return;
}

results
// generate all CMake files ahead of time
.map(|app| gen_cmake_files(app, options))
Expand Down Expand Up @@ -89,7 +119,7 @@ fn do_cmake_build(results: &mut BatchBuildResults, options: &BuildCommandOptions
});
}

impl BatchBackend for Cmake {
impl BatchBackend for CmakeCpp {
fn execute_command(&mut self, command: &CommandSpec, results: &mut BatchBuildResults) {
match command {
CommandSpec::Build(options) => do_cmake_build(results, options),
Expand Down
Loading
Loading