Skip to content

Commit

Permalink
resolving merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
tanneberger committed Oct 1, 2023
2 parents 2900d8d + 2ed7d50 commit e5ddf49
Show file tree
Hide file tree
Showing 12 changed files with 398 additions and 178 deletions.
337 changes: 184 additions & 153 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ crossbeam = "*"
termion = "1.5"
git2 = "*"
run_script = "0.10"
tempfile = "*"
5 changes: 5 additions & 0 deletions defaults/HelloTS.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target TypeScript

main reactor {
reaction(startup) {= console.log("Hello World"); =}
}
12 changes: 8 additions & 4 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use clap::{Args, Parser, Subcommand};
use serde_derive::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize)]
#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
pub enum TargetLanguage {
C,
Cpp,
Expand All @@ -16,13 +16,16 @@ pub enum TargetLanguage {
pub enum Platform {
Native,
Zephyr,
RP2040,
}

#[derive(clap::ValueEnum, Clone, Copy, Debug, Deserialize, Serialize, Eq, PartialEq, Hash)]
pub enum BuildSystem {
LFC,
CMake,
Cargo,
Npm,
Pnpm,
}

#[derive(Args, Debug)]
Expand Down Expand Up @@ -85,16 +88,17 @@ impl ToString for TargetLanguage {
pub struct InitArgs {
#[clap(value_enum, short, long)]
pub language: Option<TargetLanguage>,

#[clap(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({
// Target language for Zephyr is C, else Cpp.
// Target language for Zephyr and RP2040 is C
// Else use Cpp.
match self.platform {
Platform::Zephyr => TargetLanguage::C,
Platform::RP2040 => TargetLanguage::C,
_ => TargetLanguage::Cpp,
}
})
Expand All @@ -106,7 +110,7 @@ pub enum Command {
/// initializing a lingua-franca project
Init(InitArgs),

/// compiling one ore multiple binaries in a lingua-franca package
/// compiling one or multiple binaries in a lingua-franca package
Build(BuildArgs),

/// Updates the dependencies and potentially build tools
Expand Down
1 change: 1 addition & 0 deletions src/backends/cmake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ fn gen_cmake_files(app: &App, options: &BuildCommandOptions) -> BuildResult {
fs::create_dir_all(&build_dir)?;

let mut cmake = Command::new("cmake");
// cmake args
cmake.arg(format!(
"-DCMAKE_BUILD_TYPE={}",
if options.profile == BuildProfile::Release {
Expand Down
9 changes: 5 additions & 4 deletions src/backends/lfc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl BatchBackend for LFC {
CommandSpec::Update => todo!(),
CommandSpec::Clean => {
results.par_map(|app| {
fs::remove_dir_all(app.src_gen_dir())?;
crate::util::default_build_clean(&app.output_root)?;
Ok(())
});
}
Expand Down Expand Up @@ -89,10 +89,11 @@ impl<'a> LfcJsonArgs<'a> {
.unwrap()
.as_object_mut()
.unwrap();

if !self.no_compile {
properties.insert("no-compile".to_string(), serde_json::Value::Bool(true));
// lfc does not support no-compile:false
if self.no_compile {
properties.insert("no-compile".to_string(), self.no_compile.into());
}

Ok(value)
}
}
Expand Down
10 changes: 8 additions & 2 deletions src/backends/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ use std::sync::Arc;

use rayon::prelude::*;

use crate::args::Platform;
use crate::args::{BuildSystem, Platform};
use crate::package::App;
use crate::util::errors::{AnyError, BuildResult, LingoError};
use crate::{args::BuildSystem, package::App};

pub mod cmake;
pub mod lfc;
pub mod npm;
pub mod pnpm;

pub fn execute_command<'a>(command: &CommandSpec, apps: &[&'a App]) -> BatchBuildResults<'a> {
// Group apps by build system
Expand Down Expand Up @@ -39,6 +41,8 @@ pub fn execute_command<'a>(command: &CommandSpec, apps: &[&'a App]) -> BatchBuil
BuildSystem::LFC => lfc::LFC.execute_command(command, &mut sub_res),
BuildSystem::CMake => cmake::Cmake.execute_command(command, &mut sub_res),
BuildSystem::Cargo => todo!(),
BuildSystem::Npm => npm::Npm.execute_command(command, &mut sub_res),
BuildSystem::Pnpm => pnpm::Pnpm.execute_command(command, &mut sub_res),
};
result.append(sub_res);
}
Expand All @@ -64,6 +68,8 @@ pub struct BuildCommandOptions {
/// that the number will be automatically determined.
/// A value of one effectively disables parallel builds.
pub max_threads: usize,
/// if compilation should continue if one of the apps fails building
pub keep_going: bool,
}

/// Description of a lingo command
Expand Down
109 changes: 109 additions & 0 deletions src/backends/npm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::util::errors::LingoError;
use crate::util::execute_command_to_build_result;
use std::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

pub struct Npm;

pub struct TypeScriptToolCommands {
pub binary_name: &'static str,
pub install_command: &'static str,
pub release_build_argument: &'static str,
}

use crate::backends::{
BatchBackend, BatchBuildResults, BuildCommandOptions, BuildProfile, CommandSpec,
};

pub fn do_typescript_build(
results: &mut BatchBuildResults,
options: &BuildCommandOptions,
commands: TypeScriptToolCommands,
) {
super::lfc::LFC::do_parallel_lfc_codegen(options, results, false);
if !options.compile_target_code {
return;
}

let extract_name = |path: &PathBuf| -> Result<String, Box<dyn Error + Send + Sync>> {
match Path::new(&path).file_stem() {
Some(value) => value
.to_str()
.map(String::from)
.ok_or(Box::new(LingoError::InvalidMainReactor)),
None => Err(Box::new(LingoError::InvalidMainReactor)),
}
};

results
.map(|app| {
let file_name = extract_name(&app.main_reactor)?;
let path = app.output_root.join("src-gen").join(file_name);

let mut npm_install = Command::new(commands.binary_name);
npm_install.current_dir(path);
npm_install.arg(commands.install_command);
if options.profile == BuildProfile::Release {
npm_install.arg(commands.release_build_argument);
}
execute_command_to_build_result(npm_install)?;
Ok(())
})
.map(|app| {
let file_name = extract_name(&app.main_reactor)?;
let path = app.output_root.join("src-gen").join(file_name);

let mut npm_build = Command::new(commands.binary_name);
npm_build.current_dir(path);
npm_build.arg("run");
npm_build.arg("build");

if options.profile == BuildProfile::Release {
npm_build.arg(commands.release_build_argument);
}
execute_command_to_build_result(npm_build)?;

Ok(())
})
.map(|app| {
fs::create_dir_all(app.output_root.join("bin"))?;

let file_name = extract_name(&app.main_reactor)?;
let path = app
.output_root
.join("src-gen")
.join(&file_name)
.join("dist")
.join(file_name + ".js");

// cleanup: rename executable to match the app name
fs::rename(path, app.executable_path())?;
Ok(())
});
}

impl BatchBackend for Npm {
fn execute_command(&mut self, command: &CommandSpec, results: &mut BatchBuildResults) {
match command {
CommandSpec::Build(options) => do_typescript_build(
results,
options,
TypeScriptToolCommands {
binary_name: "npm",
install_command: "install",
release_build_argument: "--production",
},
),
CommandSpec::Clean => {
results.par_map(|app| {
crate::util::default_build_clean(&app.output_root)?;
crate::util::delete_subdirs(&app.output_root, &["node_modules", "dist"])?;
Ok(())
});
}
_ => todo!(),
}
}
}
29 changes: 29 additions & 0 deletions src/backends/pnpm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::backends::npm::{do_typescript_build, TypeScriptToolCommands};

pub struct Pnpm;

use crate::backends::{BatchBackend, BatchBuildResults, CommandSpec};

impl BatchBackend for Pnpm {
fn execute_command(&mut self, command: &CommandSpec, results: &mut BatchBuildResults) {
match command {
CommandSpec::Build(options) => do_typescript_build(
results,
options,
TypeScriptToolCommands {
binary_name: "pnpm",
install_command: "install",
release_build_argument: "--prod",
},
),
CommandSpec::Clean => {
results.par_map(|app| {
crate::util::default_build_clean(&app.output_root)?;
crate::util::delete_subdirs(&app.output_root, &["node_modules", "dist"])?;
Ok(())
});
}
_ => todo!(),
}
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ fn build<'a>(args: &BuildArgs, config: &'a Config) -> BatchBuildResults<'a> {
compile_target_code: !args.no_compile,
lfc_exec_path: util::find_lfc_exec(args).expect("TODO replace me"),
max_threads: args.threads,
keep_going: args.keep_going,
}),
config,
args.keep_going,
Expand Down
55 changes: 40 additions & 15 deletions src/package/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use std::{env, io};
use crate::args::BuildSystem::{CMake, Cargo, LFC};
use crate::util::errors::{BuildResult, LingoError};
use git2::Repository;
use tempfile::tempdir;
use which::which;

fn is_valid_location_for_project(path: &std::path::Path) -> bool {
!path.join("src").exists() && !path.join(".git").exists() && !path.join("application").exists()
Expand Down Expand Up @@ -91,8 +93,16 @@ pub struct App {
impl App {
pub fn build_system(&self) -> BuildSystem {
match self.target {
TargetLanguage::C => LFC,
TargetLanguage::Cpp => CMake,
TargetLanguage::Rust => Cargo,
TargetLanguage::TypeScript => {
if which("pnpm").is_ok() {
BuildSystem::Pnpm
} else {
BuildSystem::Npm
}
}
_ => LFC,
}
}
Expand All @@ -101,21 +111,25 @@ impl App {
}
pub fn executable_path(&self) -> PathBuf {
let mut p = self.output_root.join("bin");
p.push(&self.name);
if self.target == TargetLanguage::TypeScript {
p.push(self.name.clone() + ".js")
} else {
p.push(&self.name);
}
p
}
}

/// Simple or DetailedDependcy
/// Simple or DetailedDependency
#[derive(Clone, Deserialize, Serialize)]
pub enum FileDependcy {
pub enum FileDependency {
// the version string
Simple(String),
/// version string and source
Advanced(DetailedDependency),
}

/// Dependcy with source and version
/// Dependency with source and version
#[derive(Clone, Deserialize, Serialize)]
pub struct DetailedDependency {
version: String,
Expand Down Expand Up @@ -202,30 +216,40 @@ impl ConfigFile {
let hello_world_code: &'static str = match self.apps[0].target {
TargetLanguage::Cpp => include_str!("../../defaults/HelloCpp.lf"),
TargetLanguage::C => include_str!("../../defaults/HelloC.lf"),
TargetLanguage::TypeScript => include_str!("../../defaults/HelloTS.lf"),
_ => panic!("Target langauge not supported yet"), // FIXME: Add examples for other programs
};

write(Path::new("./src/Main.lf"), hello_world_code)?;
Ok(())
}

// Sets up a LF project with Zephyr as the target platform.
pub fn setup_zephyr(&self) -> BuildResult {
// Clone lf-west-template into a temporary directory
let tmp_path = Path::new("zephyr_tmp");
if tmp_path.exists() {
remove_dir_all(tmp_path)?;
}
let url = "https://github.com/lf-lang/lf-west-template";
fn setup_template_repo(&self, url: &str) -> BuildResult {
let dir = tempdir()?;
let tmp_path = dir.path();
Repository::clone(url, tmp_path)?;

// Copy the cloned template repo into the project directory
copy_recursively(tmp_path, Path::new("."))?;
// Remove temporary folder
dir.close()?;
Ok(())
}

// Remove .git, .gitignore ad temporary folder
// Sets up a LF project with Zephyr as the target platform.
fn setup_zephyr(&self) -> BuildResult {
let url = "https://github.com/lf-lang/lf-west-template";
self.setup_template_repo(url)?;
remove_file(".gitignore")?;
remove_dir_all(Path::new(".git"))?;
remove_dir_all(tmp_path)?;
Ok(())
}

// Sets up a LF project with RP2040 MCU as the target platform.
// Initializes a repo using the lf-pico-template
fn setup_rp2040(&self) -> BuildResult {
let url = "https://github.com/lf-lang/lf-pico-template";
// leave git artifacts
self.setup_template_repo(url)?;
Ok(())
}

Expand All @@ -234,6 +258,7 @@ impl ConfigFile {
match self.apps[0].platform {
Some(Platform::Native) => self.setup_native(),
Some(Platform::Zephyr) => self.setup_zephyr(),
Some(Platform::RP2040) => self.setup_rp2040(),
_ => Ok(()),
}
} else {
Expand Down
Loading

0 comments on commit e5ddf49

Please sign in to comment.