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

Get compiler args #88

Merged
merged 5 commits into from
Apr 10, 2024
Merged
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
71 changes: 69 additions & 2 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ pub mod packages;
pub mod parse;
pub mod read_compile_state;

use crate::helpers;
use crate::helpers::emojis::*;
use crate::helpers::{self, get_workspace_root};
use build_types::*;
use console::style;
use indicatif::{ProgressBar, ProgressStyle};
use serde::Serialize;
use std::io::{stdout, Write};
use std::path::PathBuf;
use std::process::Command;
use std::time::Instant;

use self::compile::compiler_args;
use self::parse::parser_args;

pub fn get_version(bsc_path: &str) -> String {
let version_cmd = Command::new(bsc_path)
.args(["-v"])
Expand Down Expand Up @@ -44,6 +49,68 @@ fn is_dirty(module: &Module) -> bool {
}
}

#[derive(Serialize, Debug, Clone)]
pub struct CompilerArgs {
pub compiler_args: Vec<String>,
pub parser_args: Vec<String>,
}

pub fn get_compiler_args(path: &str) -> String {
let filename = &helpers::get_abs_path(path);
let package_root = helpers::get_abs_path(
&helpers::get_nearest_bsconfig(&std::path::PathBuf::from(path)).expect("Couldn't find package root"),
);
let workspace_root = get_workspace_root(&package_root).map(|p| helpers::get_abs_path(&p));
let root_config_name =
packages::get_package_name(&workspace_root.to_owned().unwrap_or(package_root.to_owned()));
let package_name = packages::get_package_name(&package_root);
let bsc_path = helpers::get_bsc(&package_root, workspace_root.to_owned());
let rescript_version = get_version(&bsc_path);
let packages = packages::make(
&None,
&workspace_root.to_owned().unwrap_or(package_root.to_owned()),
workspace_root.to_owned(),
);
// make PathBuf from package root and get the relative path for filename
let relative_filename = PathBuf::from(&filename)
.strip_prefix(PathBuf::from(&package_root).parent().unwrap())
.unwrap()
.to_string_lossy()
.to_string();
let root_package = packages.get(&root_config_name).unwrap();
let package = packages.get(&package_name).unwrap();
let (ast_path, parser_args) = parser_args(
package,
root_package,
&relative_filename,
&rescript_version,
&workspace_root,
);
let is_interface = filename.ends_with("i");
let has_interface = if is_interface {
true
} else {
let mut interface_filename = filename.to_string();
interface_filename.push('i');
PathBuf::from(&interface_filename).exists()
};
let compiler_args = compiler_args(
package,
root_package,
&ast_path,
&rescript_version,
&relative_filename,
is_interface,
has_interface,
&packages,
);
serde_json::to_string_pretty(&CompilerArgs {
compiler_args,
parser_args,
})
.unwrap()
}

pub fn build(filter: &Option<regex::Regex>, path: &str, no_timing: bool) -> Result<BuildState, ()> {
let timing_total = Instant::now();
let project_root = helpers::get_abs_path(path);
Expand Down Expand Up @@ -141,7 +208,7 @@ pub fn build(filter: &Option<regex::Regex>, path: &str, no_timing: bool) -> Resu
&mut build_state,
|| pb.inc(1),
&bsc_path,
workspace_root.to_owned(),
&workspace_root,
);
let timing_ast_elapsed = timing_ast.elapsed();

Expand Down
64 changes: 42 additions & 22 deletions src/build/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,26 +337,24 @@ pub fn compile(
(compile_errors, compile_warnings, num_compiled_modules)
}

fn compile_file(
pub fn compiler_args(
package: &packages::Package,
root_package: &packages::Package,
ast_path: &str,
module: &Module,
version: &str,
file_path: &str,
is_interface: bool,
bsc_path: &str,
has_interface: bool,
packages: &AHashMap<String, packages::Package>,
) -> Result<Option<String>, String> {
let build_path_abs = package.get_build_path();
let bsc_flags = bsconfig::flatten_flags(&package.bsconfig.bsc_flags);

) -> Vec<String> {
let normal_deps = package
.bsconfig
.bs_dependencies
.as_ref()
.unwrap_or(&vec![])
.to_owned();

let bsc_flags = bsconfig::flatten_flags(&package.bsconfig.bsc_flags);
// don't compile dev-deps yet
// let dev_deps = source
// .package
Expand All @@ -378,12 +376,7 @@ fn compile_file(
})
.collect::<Vec<Vec<String>>>();

let implementation_file_path = match module.source_type {
SourceType::SourceFile(ref source_file) => &source_file.implementation.path,
_ => panic!("Not a source file"),
};

let module_name = helpers::file_path_to_module_name(implementation_file_path, &package.namespace);
let module_name = helpers::file_path_to_module_name(file_path, &package.namespace);

let namespace_args = match &package.namespace {
packages::Namespace::NamespaceWithEntry { namespace: _, entry } if &module_name == entry => {
Expand Down Expand Up @@ -435,15 +428,15 @@ fn compile_file(
}
};

let read_cmi_args = match module.get_interface() {
Some(_) => {
let read_cmi_args = match has_interface {
true => {
if is_interface {
vec![]
} else {
vec!["-bs-read-cmi".to_string()]
}
}
_ => vec![],
false => vec![],
};

let implementation_args = if is_interface {
Expand All @@ -464,11 +457,7 @@ fn compile_file(
"-bs-package-output".to_string(),
format!(
"es6:{}:{}",
Path::new(implementation_file_path)
.parent()
.unwrap()
.to_str()
.unwrap(),
Path::new(file_path).parent().unwrap().to_str().unwrap(),
suffix
),
]
Expand All @@ -483,7 +472,7 @@ fn compile_file(
jsx_module_args,
jsx_mode_args,
uncurried_args,
bsc_flags,
bsc_flags.to_owned(),
warning_args,
// vec!["-warn-error".to_string(), "A".to_string()],
// ^^ this one fails for bisect-ppx
Expand All @@ -499,6 +488,37 @@ fn compile_file(
]
.concat();

to_mjs_args
}

fn compile_file(
package: &packages::Package,
root_package: &packages::Package,
ast_path: &str,
module: &Module,
version: &str,
is_interface: bool,
bsc_path: &str,
packages: &AHashMap<String, packages::Package>,
) -> Result<Option<String>, String> {
let build_path_abs = package.get_build_path();
let implementation_file_path = match module.source_type {
SourceType::SourceFile(ref source_file) => &source_file.implementation.path,
_ => panic!("Not a source file"),
};
let module_name = helpers::file_path_to_module_name(implementation_file_path, &package.namespace);
let has_interface = module.get_interface().is_some();
let to_mjs_args = compiler_args(
package,
root_package,
ast_path,
version,
&implementation_file_path,
is_interface,
has_interface,
packages,
);

let to_mjs = Command::new(bsc_path)
.current_dir(helpers::canonicalize_string_path(&build_path_abs.to_owned()).unwrap())
.args(to_mjs_args)
Expand Down
67 changes: 36 additions & 31 deletions src/build/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn generate_asts(
build_state: &mut BuildState,
inc: impl Fn() -> () + std::marker::Sync,
bsc_path: &str,
workspace_root: Option<String>,
workspace_root: &Option<String>,
) -> Result<String, String> {
let mut has_failure = false;
let mut stderr = "".to_string();
Expand Down Expand Up @@ -59,21 +59,19 @@ pub fn generate_asts(
package.to_owned(),
root_package.to_owned(),
&source_file.implementation.path.to_owned(),
&build_state.project_root,
&version,
bsc_path,
workspace_root.to_owned(),
workspace_root,
);

let iast_result = match source_file.interface.as_ref().map(|i| i.path.to_owned()) {
Some(interface_file_path) => generate_ast(
package.to_owned(),
root_package.to_owned(),
&interface_file_path.to_owned(),
&build_state.project_root,
&version,
bsc_path,
workspace_root.to_owned(),
workspace_root,
)
.map(|result| Some(result)),
_ => Ok(None),
Expand Down Expand Up @@ -189,40 +187,35 @@ pub fn generate_asts(
}
}

fn generate_ast(
package: packages::Package,
root_package: packages::Package,
pub fn parser_args(
package: &packages::Package,
root_package: &packages::Package,
filename: &str,
root_path: &str,
version: &str,
bsc_path: &str,
workspace_root: Option<String>,
) -> Result<(String, Option<String>), String> {
workspace_root: &Option<String>,
) -> (String, Vec<String>) {
let file = &filename.to_string();
let build_path_abs = package.get_build_path();
let path = PathBuf::from(filename);
let ast_extension = path_to_ast_extension(&path);

let ast_path = (helpers::get_basename(&file.to_string()).to_owned()) + ast_extension;

let ppx_flags = bsconfig::flatten_ppx_flags(
&if let Some(workspace_root) = workspace_root {
format!("{}/node_modules", &workspace_root)
} else {
format!("{}/node_modules", &root_path)
format!("{}/node_modules", &root_package.path)
},
&filter_ppx_flags(&package.bsconfig.ppx_flags),
&package.name,
);

let jsx_args = root_package.get_jsx_args();
let jsx_module_args = root_package.get_jsx_module_args();
let jsx_mode_args = root_package.get_jsx_mode_args();
let uncurried_args = root_package.get_uncurried_args(version, &root_package);
let bsc_flags = bsconfig::flatten_flags(&package.bsconfig.bsc_flags);

let res_to_ast_args = |file: &str| -> Vec<String> {
let file = "../../".to_string() + file;
let file = "../../".to_string() + file;
(
ast_path.to_string(),
vec![
vec!["-bs-v".to_string(), format!("{}", version)],
ppx_flags,
Expand All @@ -239,17 +232,29 @@ fn generate_ast(
file,
],
]
.concat()
};
.concat(),
)
}

fn generate_ast(
package: packages::Package,
root_package: packages::Package,
filename: &str,
version: &str,
bsc_path: &str,
workspace_root: &Option<String>,
) -> Result<(String, Option<String>), String> {
let build_path_abs = package.get_build_path();
let (ast_path, parser_args) = parser_args(&package, &root_package, filename, version, workspace_root);

/* Create .ast */
if let Some(res_to_ast) = Some(file).map(|file| {
if let Some(res_to_ast) = Some(
Command::new(bsc_path)
.current_dir(helpers::canonicalize_string_path(&build_path_abs).unwrap())
.args(res_to_ast_args(file))
.args(parser_args)
.output()
.expect("Error converting .res to .ast")
}) {
.expect("Error converting .res to .ast"),
) {
let stderr = std::str::from_utf8(&res_to_ast.stderr).expect("Expect StdErr to be non-null");
if helpers::contains_ascii_characters(stderr) {
if res_to_ast.status.success() {
Expand All @@ -262,21 +267,21 @@ fn generate_ast(
Ok((ast_path, None))
}
} else {
println!("Parsing file {}...", file);
return Err(format!(
println!("Parsing file {}...", filename);
Err(format!(
"Could not find canonicalize_string_path for file {} in package {}",
file, package.name
));
filename, package.name
))
}
}

fn path_to_ast_extension(path: &Path) -> &str {
let extension = path.extension().unwrap().to_str().unwrap();
return if helpers::is_interface_ast_file(extension) {
if helpers::is_interface_ast_file(extension) {
".iast"
} else {
".ast"
};
}
}

fn filter_ppx_flags(ppx_flags: &Option<Vec<OneOrMore<String>>>) -> Option<Vec<OneOrMore<String>>> {
Expand Down
Loading
Loading