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

Librarify #50

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
779 changes: 479 additions & 300 deletions Cargo.lock

Large diffs are not rendered by default.

26 changes: 20 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "lingua-franca"
name = "lingo"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave it as lingua-franca because we still want to squat that name on crates.io ;D

version = "0.2.0"
edition = "2021"

Expand All @@ -8,25 +8,39 @@ homepage = "https://lf-lang.org"
repository = "https://github.com/lf-lang/lingo"
license = "BSD-2-Clause"

[lib]
name = "liblingo"
path = "src/lib.rs"

[[bin]]
name = "lingo"
publish = true
path = "./src/main.rs"
required-features = ["binary"]

[features]
default = ["binary"]
binary = ["which", "git2"]

[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"
regex = "1.8"
lazy_static = "1.4"
rayon = "1.7"
toml = {version = "0.8"}
toml = { version = "0.8" }
crossbeam = "0.8"
termion = "2.0"
git2 = "0.18"
run_script = "0.10"
which = { version = "5.0", optional = true }
git2 = { version = "0.18", optional = true }
print_logger = "0.2.0"
tempfile = "3.0"
url = { version = "2.5", features = ["serde"] }
anyhow = "1.0"
versions = { version = "6.3.2", 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.

42 changes: 21 additions & 21 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ 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,
CCpp,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Cpp,
Rust,
TypeScript,
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,40 +33,39 @@ pub enum BuildSystem {
#[derive(Args, Debug)]
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 = "[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 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::package::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!(),
}
}
}
Loading
Loading