2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2021-01-07 21:08:51 -05:00
|
|
|
|
2024-09-04 11:39:30 -04:00
|
|
|
use crate::args::check_warn_tsconfig;
|
2022-06-27 16:54:09 -04:00
|
|
|
use crate::args::CompileFlags;
|
2022-12-09 09:40:48 -05:00
|
|
|
use crate::args::Flags;
|
2023-05-01 14:35:23 -04:00
|
|
|
use crate::factory::CliFactory;
|
2024-06-03 17:17:08 -04:00
|
|
|
use crate::http_util::HttpClientProvider;
|
2024-12-11 09:40:50 -05:00
|
|
|
use crate::standalone::binary::WriteBinOptions;
|
2023-04-19 17:50:56 -04:00
|
|
|
use crate::standalone::is_standalone_binary;
|
2024-11-19 16:19:35 -05:00
|
|
|
use deno_ast::MediaType;
|
2024-07-03 20:54:33 -04:00
|
|
|
use deno_ast::ModuleSpecifier;
|
2021-11-16 09:02:28 -05:00
|
|
|
use deno_core::anyhow::bail;
|
2022-02-24 08:28:00 -05:00
|
|
|
use deno_core::anyhow::Context;
|
2022-03-28 14:38:15 -04:00
|
|
|
use deno_core::error::generic_error;
|
2021-01-07 21:08:51 -05:00
|
|
|
use deno_core::error::AnyError;
|
2022-03-28 14:38:15 -04:00
|
|
|
use deno_core::resolve_url_or_path;
|
2023-06-06 17:07:46 -04:00
|
|
|
use deno_graph::GraphKind;
|
2024-12-11 09:40:50 -05:00
|
|
|
use deno_path_util::url_from_file_path;
|
2024-12-12 13:07:35 -05:00
|
|
|
use deno_path_util::url_to_file_path;
|
2024-02-07 11:25:14 -05:00
|
|
|
use deno_terminal::colors;
|
2024-07-01 18:54:17 -04:00
|
|
|
use rand::Rng;
|
2024-12-12 13:07:35 -05:00
|
|
|
use std::collections::HashSet;
|
|
|
|
use std::collections::VecDeque;
|
2021-01-18 21:40:22 -05:00
|
|
|
use std::path::Path;
|
2021-01-07 21:08:51 -05:00
|
|
|
use std::path::PathBuf;
|
2022-12-09 09:40:48 -05:00
|
|
|
use std::sync::Arc;
|
2021-01-07 21:08:51 -05:00
|
|
|
|
2022-03-28 14:38:15 -04:00
|
|
|
use super::installer::infer_name_from_url;
|
|
|
|
|
2022-12-09 09:40:48 -05:00
|
|
|
pub async fn compile(
|
2024-07-23 19:00:48 -04:00
|
|
|
flags: Arc<Flags>,
|
2022-12-09 09:40:48 -05:00
|
|
|
compile_flags: CompileFlags,
|
|
|
|
) -> Result<(), AnyError> {
|
2024-07-23 19:00:48 -04:00
|
|
|
let factory = CliFactory::from_flags(flags);
|
|
|
|
let cli_options = factory.cli_options()?;
|
2024-02-20 16:29:57 -05:00
|
|
|
let module_graph_creator = factory.module_graph_creator().await?;
|
2023-05-10 20:06:59 -04:00
|
|
|
let binary_writer = factory.create_compile_binary_writer().await?;
|
2024-06-03 17:17:08 -04:00
|
|
|
let http_client = factory.http_client_provider();
|
2024-11-19 16:19:35 -05:00
|
|
|
let entrypoint = cli_options.resolve_main_module()?;
|
|
|
|
let (module_roots, include_files) = get_module_roots_and_include_files(
|
|
|
|
entrypoint,
|
|
|
|
&compile_flags,
|
|
|
|
cli_options.initial_cwd(),
|
|
|
|
)?;
|
2022-12-09 09:40:48 -05:00
|
|
|
|
2023-12-07 22:35:53 -05:00
|
|
|
// this is not supported, so show a warning about it, but don't error in order
|
|
|
|
// to allow someone to still run `deno compile` when this is in a deno.json
|
|
|
|
if cli_options.unstable_sloppy_imports() {
|
|
|
|
log::warn!(
|
|
|
|
concat!(
|
|
|
|
"{} Sloppy imports are not supported in deno compile. ",
|
2024-08-02 07:26:54 -04:00
|
|
|
"The compiled executable may encounter runtime errors.",
|
2023-12-07 22:35:53 -05:00
|
|
|
),
|
|
|
|
crate::colors::yellow("Warning"),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-03-13 21:12:09 -04:00
|
|
|
let output_path = resolve_compile_executable_output_path(
|
2024-06-03 17:17:08 -04:00
|
|
|
http_client,
|
2023-03-13 21:12:09 -04:00
|
|
|
&compile_flags,
|
2023-05-01 14:35:23 -04:00
|
|
|
cli_options.initial_cwd(),
|
2023-03-13 21:12:09 -04:00
|
|
|
)
|
|
|
|
.await?;
|
2022-12-09 09:40:48 -05:00
|
|
|
|
2023-04-14 16:22:33 -04:00
|
|
|
let graph = Arc::try_unwrap(
|
2024-02-20 16:29:57 -05:00
|
|
|
module_graph_creator
|
2023-06-06 17:07:46 -04:00
|
|
|
.create_graph_and_maybe_check(module_roots.clone())
|
2023-04-14 16:22:33 -04:00
|
|
|
.await?,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2023-06-07 10:09:10 -04:00
|
|
|
let graph = if cli_options.type_check_mode().is_true() {
|
2023-06-06 17:07:46 -04:00
|
|
|
// In this case, the previous graph creation did type checking, which will
|
|
|
|
// create a module graph with types information in it. We don't want to
|
2024-10-24 15:48:48 -04:00
|
|
|
// store that in the binary so create a code only module graph from scratch.
|
2024-02-20 16:29:57 -05:00
|
|
|
module_graph_creator
|
2024-12-10 21:24:23 -05:00
|
|
|
.create_graph(
|
|
|
|
GraphKind::CodeOnly,
|
|
|
|
module_roots,
|
|
|
|
crate::graph_util::NpmCachingStrategy::Eager,
|
|
|
|
)
|
2023-06-06 17:07:46 -04:00
|
|
|
.await?
|
2023-06-07 10:09:10 -04:00
|
|
|
} else {
|
|
|
|
graph
|
2023-06-06 17:07:46 -04:00
|
|
|
};
|
2022-12-09 09:40:48 -05:00
|
|
|
|
2024-07-19 15:56:07 -04:00
|
|
|
let ts_config_for_emit = cli_options
|
|
|
|
.resolve_ts_config_for_emit(deno_config::deno_json::TsConfigType::Emit)?;
|
2024-09-04 11:39:30 -04:00
|
|
|
check_warn_tsconfig(&ts_config_for_emit);
|
2022-12-09 09:40:48 -05:00
|
|
|
log::info!(
|
2023-04-19 17:50:56 -04:00
|
|
|
"{} {} to {}",
|
2022-12-09 09:40:48 -05:00
|
|
|
colors::green("Compile"),
|
2024-11-19 16:19:35 -05:00
|
|
|
entrypoint,
|
2023-04-19 17:50:56 -04:00
|
|
|
output_path.display(),
|
2022-12-09 09:40:48 -05:00
|
|
|
);
|
2023-04-19 17:50:56 -04:00
|
|
|
validate_output_path(&output_path)?;
|
|
|
|
|
2024-07-01 18:54:17 -04:00
|
|
|
let mut temp_filename = output_path.file_name().unwrap().to_owned();
|
|
|
|
temp_filename.push(format!(
|
|
|
|
".tmp-{}",
|
|
|
|
faster_hex::hex_encode(
|
|
|
|
&rand::thread_rng().gen::<[u8; 8]>(),
|
|
|
|
&mut [0u8; 16]
|
|
|
|
)
|
|
|
|
.unwrap()
|
|
|
|
));
|
|
|
|
let temp_path = output_path.with_file_name(temp_filename);
|
|
|
|
|
2024-08-01 00:15:13 -04:00
|
|
|
let file = std::fs::File::create(&temp_path).with_context(|| {
|
2024-07-01 18:54:17 -04:00
|
|
|
format!("Opening temporary file '{}'", temp_path.display())
|
|
|
|
})?;
|
2024-08-01 00:15:13 -04:00
|
|
|
|
2023-12-06 16:25:24 -05:00
|
|
|
let write_result = binary_writer
|
2024-12-11 09:40:50 -05:00
|
|
|
.write_bin(WriteBinOptions {
|
|
|
|
writer: file,
|
|
|
|
display_output_filename: &output_path
|
|
|
|
.file_name()
|
|
|
|
.unwrap()
|
|
|
|
.to_string_lossy(),
|
|
|
|
graph: &graph,
|
2024-11-19 16:19:35 -05:00
|
|
|
entrypoint,
|
2024-12-11 09:40:50 -05:00
|
|
|
include_files: &include_files,
|
|
|
|
compile_flags: &compile_flags,
|
|
|
|
})
|
2023-04-19 17:50:56 -04:00
|
|
|
.await
|
2024-07-01 18:54:17 -04:00
|
|
|
.with_context(|| {
|
2024-10-24 15:48:48 -04:00
|
|
|
format!(
|
|
|
|
"Writing deno compile executable to temporary file '{}'",
|
|
|
|
temp_path.display()
|
|
|
|
)
|
2024-07-01 18:54:17 -04:00
|
|
|
});
|
2023-04-19 17:50:56 -04:00
|
|
|
|
|
|
|
// set it as executable
|
|
|
|
#[cfg(unix)]
|
2024-07-01 18:54:17 -04:00
|
|
|
let write_result = write_result.and_then(|_| {
|
2023-04-19 17:50:56 -04:00
|
|
|
use std::os::unix::fs::PermissionsExt;
|
2024-07-01 18:54:17 -04:00
|
|
|
let perms = std::fs::Permissions::from_mode(0o755);
|
|
|
|
std::fs::set_permissions(&temp_path, perms).with_context(|| {
|
|
|
|
format!(
|
|
|
|
"Setting permissions on temporary file '{}'",
|
|
|
|
temp_path.display()
|
|
|
|
)
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
let write_result = write_result.and_then(|_| {
|
|
|
|
std::fs::rename(&temp_path, &output_path).with_context(|| {
|
|
|
|
format!(
|
|
|
|
"Renaming temporary file '{}' to '{}'",
|
|
|
|
temp_path.display(),
|
|
|
|
output_path.display()
|
|
|
|
)
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
if let Err(err) = write_result {
|
|
|
|
// errored, so attempt to remove the temporary file
|
|
|
|
let _ = std::fs::remove_file(temp_path);
|
|
|
|
return Err(err);
|
2021-01-18 21:40:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This function writes out a final binary to specified path. If output path
|
|
|
|
/// is not already standalone binary it will return error instead.
|
2023-04-19 17:50:56 -04:00
|
|
|
fn validate_output_path(output_path: &Path) -> Result<(), AnyError> {
|
2022-03-28 14:38:15 -04:00
|
|
|
if output_path.exists() {
|
2021-01-07 21:08:51 -05:00
|
|
|
// If the output is a directory, throw error
|
2022-03-28 14:38:15 -04:00
|
|
|
if output_path.is_dir() {
|
2022-03-18 19:18:50 -04:00
|
|
|
bail!(
|
|
|
|
concat!(
|
|
|
|
"Could not compile to file '{}' because a directory exists with ",
|
|
|
|
"the same name. You can use the `--output <file-path>` flag to ",
|
|
|
|
"provide an alternative name."
|
|
|
|
),
|
2022-03-28 14:38:15 -04:00
|
|
|
output_path.display()
|
2022-03-18 19:18:50 -04:00
|
|
|
);
|
2021-01-07 21:08:51 -05:00
|
|
|
}
|
|
|
|
|
2023-04-19 17:50:56 -04:00
|
|
|
// Make sure we don't overwrite any file not created by Deno compiler because
|
|
|
|
// this filename is chosen automatically in some cases.
|
|
|
|
if !is_standalone_binary(output_path) {
|
2022-03-18 19:18:50 -04:00
|
|
|
bail!(
|
|
|
|
concat!(
|
|
|
|
"Could not compile to file '{}' because the file already exists ",
|
|
|
|
"and cannot be overwritten. Please delete the existing file or ",
|
2023-05-16 08:30:16 -04:00
|
|
|
"use the `--output <file-path>` flag to provide an alternative name."
|
2022-03-18 19:18:50 -04:00
|
|
|
),
|
2022-03-28 14:38:15 -04:00
|
|
|
output_path.display()
|
2022-03-18 19:18:50 -04:00
|
|
|
);
|
2021-01-07 21:08:51 -05:00
|
|
|
}
|
2021-04-23 06:33:45 -04:00
|
|
|
|
|
|
|
// Remove file if it was indeed a deno compiled binary, to avoid corruption
|
|
|
|
// (see https://github.com/denoland/deno/issues/10310)
|
2023-04-19 17:50:56 -04:00
|
|
|
std::fs::remove_file(output_path)?;
|
2022-01-10 23:24:39 -05:00
|
|
|
} else {
|
2022-03-28 14:38:15 -04:00
|
|
|
let output_base = &output_path.parent().unwrap();
|
2022-01-10 23:24:39 -05:00
|
|
|
if output_base.exists() && output_base.is_file() {
|
2022-03-18 19:18:50 -04:00
|
|
|
bail!(
|
2023-04-19 17:50:56 -04:00
|
|
|
concat!(
|
|
|
|
"Could not compile to file '{}' because its parent directory ",
|
|
|
|
"is an existing file. You can use the `--output <file-path>` flag to ",
|
|
|
|
"provide an alternative name.",
|
|
|
|
),
|
|
|
|
output_base.display(),
|
|
|
|
);
|
2022-01-10 23:24:39 -05:00
|
|
|
}
|
2023-04-19 17:50:56 -04:00
|
|
|
std::fs::create_dir_all(output_base)?;
|
2021-01-07 21:08:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-11-19 16:19:35 -05:00
|
|
|
fn get_module_roots_and_include_files(
|
|
|
|
entrypoint: &ModuleSpecifier,
|
|
|
|
compile_flags: &CompileFlags,
|
|
|
|
initial_cwd: &Path,
|
|
|
|
) -> Result<(Vec<ModuleSpecifier>, Vec<ModuleSpecifier>), AnyError> {
|
|
|
|
fn is_module_graph_module(url: &ModuleSpecifier) -> bool {
|
|
|
|
if url.scheme() != "file" {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
let media_type = MediaType::from_specifier(url);
|
|
|
|
match media_type {
|
|
|
|
MediaType::JavaScript
|
|
|
|
| MediaType::Jsx
|
|
|
|
| MediaType::Mjs
|
|
|
|
| MediaType::Cjs
|
|
|
|
| MediaType::TypeScript
|
|
|
|
| MediaType::Mts
|
|
|
|
| MediaType::Cts
|
|
|
|
| MediaType::Dts
|
|
|
|
| MediaType::Dmts
|
|
|
|
| MediaType::Dcts
|
|
|
|
| MediaType::Tsx
|
|
|
|
| MediaType::Json
|
|
|
|
| MediaType::Wasm => true,
|
|
|
|
MediaType::Css | MediaType::SourceMap | MediaType::Unknown => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-12 13:07:35 -05:00
|
|
|
fn analyze_path(
|
|
|
|
url: &ModuleSpecifier,
|
|
|
|
module_roots: &mut Vec<ModuleSpecifier>,
|
|
|
|
include_files: &mut Vec<ModuleSpecifier>,
|
|
|
|
searched_paths: &mut HashSet<PathBuf>,
|
|
|
|
) -> Result<(), AnyError> {
|
|
|
|
let Ok(path) = url_to_file_path(url) else {
|
|
|
|
return Ok(());
|
|
|
|
};
|
|
|
|
let mut pending = VecDeque::from([path]);
|
|
|
|
while let Some(path) = pending.pop_front() {
|
|
|
|
if !searched_paths.insert(path.clone()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if !path.is_dir() {
|
|
|
|
let url = url_from_file_path(&path)?;
|
|
|
|
include_files.push(url.clone());
|
|
|
|
if is_module_graph_module(&url) {
|
|
|
|
module_roots.push(url);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for entry in std::fs::read_dir(&path).with_context(|| {
|
|
|
|
format!("Failed reading directory '{}'", path.display())
|
|
|
|
})? {
|
|
|
|
let entry = entry.with_context(|| {
|
|
|
|
format!("Failed reading entry in directory '{}'", path.display())
|
|
|
|
})?;
|
|
|
|
pending.push_back(entry.path());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut searched_paths = HashSet::new();
|
|
|
|
let mut module_roots = Vec::new();
|
|
|
|
let mut include_files = Vec::new();
|
2024-11-19 16:19:35 -05:00
|
|
|
module_roots.push(entrypoint.clone());
|
|
|
|
for side_module in &compile_flags.include {
|
|
|
|
let url = resolve_url_or_path(side_module, initial_cwd)?;
|
|
|
|
if is_module_graph_module(&url) {
|
2024-12-12 13:07:35 -05:00
|
|
|
module_roots.push(url.clone());
|
|
|
|
if url.scheme() == "file" {
|
|
|
|
include_files.push(url);
|
|
|
|
}
|
2024-11-19 16:19:35 -05:00
|
|
|
} else {
|
2024-12-12 13:07:35 -05:00
|
|
|
analyze_path(
|
|
|
|
&url,
|
|
|
|
&mut module_roots,
|
|
|
|
&mut include_files,
|
|
|
|
&mut searched_paths,
|
|
|
|
)?;
|
2024-11-19 16:19:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok((module_roots, include_files))
|
|
|
|
}
|
|
|
|
|
2023-02-10 10:11:11 -05:00
|
|
|
async fn resolve_compile_executable_output_path(
|
2024-06-03 17:17:08 -04:00
|
|
|
http_client_provider: &HttpClientProvider,
|
2022-03-28 14:38:15 -04:00
|
|
|
compile_flags: &CompileFlags,
|
2023-03-13 21:12:09 -04:00
|
|
|
current_dir: &Path,
|
2022-03-28 14:38:15 -04:00
|
|
|
) -> Result<PathBuf, AnyError> {
|
2023-03-13 21:12:09 -04:00
|
|
|
let module_specifier =
|
|
|
|
resolve_url_or_path(&compile_flags.source_file, current_dir)?;
|
2023-02-10 10:11:11 -05:00
|
|
|
|
2024-03-14 19:53:46 -04:00
|
|
|
let output_flag = compile_flags.output.clone();
|
|
|
|
let mut output_path = if let Some(out) = output_flag.as_ref() {
|
|
|
|
let mut out_path = PathBuf::from(out);
|
|
|
|
if out.ends_with('/') || out.ends_with('\\') {
|
2024-06-03 17:17:08 -04:00
|
|
|
if let Some(infer_file_name) =
|
|
|
|
infer_name_from_url(http_client_provider, &module_specifier)
|
|
|
|
.await
|
|
|
|
.map(PathBuf::from)
|
2023-02-10 10:11:11 -05:00
|
|
|
{
|
2024-03-14 19:53:46 -04:00
|
|
|
out_path = out_path.join(infer_file_name);
|
2023-02-10 10:11:11 -05:00
|
|
|
}
|
2022-03-28 14:38:15 -04:00
|
|
|
} else {
|
2024-03-14 19:53:46 -04:00
|
|
|
out_path = out_path.to_path_buf();
|
2022-03-28 14:38:15 -04:00
|
|
|
}
|
2024-03-14 19:53:46 -04:00
|
|
|
Some(out_path)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2023-02-10 10:11:11 -05:00
|
|
|
|
2024-03-14 19:53:46 -04:00
|
|
|
if output_flag.is_none() {
|
2024-06-03 17:17:08 -04:00
|
|
|
output_path = infer_name_from_url(http_client_provider, &module_specifier)
|
2023-02-10 10:11:11 -05:00
|
|
|
.await
|
|
|
|
.map(PathBuf::from)
|
|
|
|
}
|
|
|
|
|
2024-03-14 19:53:46 -04:00
|
|
|
output_path.ok_or_else(|| generic_error(
|
2022-03-28 14:38:15 -04:00
|
|
|
"An executable name was not provided. One could not be inferred from the URL. Aborting.",
|
2024-03-14 19:53:46 -04:00
|
|
|
)).map(|output_path| {
|
|
|
|
get_os_specific_filepath(output_path, &compile_flags.target)
|
2022-03-28 14:38:15 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-09-22 11:49:27 -04:00
|
|
|
fn get_os_specific_filepath(
|
|
|
|
output: PathBuf,
|
|
|
|
target: &Option<String>,
|
|
|
|
) -> PathBuf {
|
|
|
|
let is_windows = match target {
|
|
|
|
Some(target) => target.contains("windows"),
|
|
|
|
None => cfg!(windows),
|
|
|
|
};
|
|
|
|
if is_windows && output.extension().unwrap_or_default() != "exe" {
|
|
|
|
if let Some(ext) = output.extension() {
|
|
|
|
// keep version in my-exe-0.1.0 -> my-exe-0.1.0.exe
|
|
|
|
output.with_extension(format!("{}.exe", ext.to_string_lossy()))
|
|
|
|
} else {
|
|
|
|
output.with_extension("exe")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
output
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-28 14:38:15 -04:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
pub use super::*;
|
|
|
|
|
2023-02-10 10:11:11 -05:00
|
|
|
#[tokio::test]
|
|
|
|
async fn resolve_compile_executable_output_path_target_linux() {
|
2024-06-03 17:17:08 -04:00
|
|
|
let http_client = HttpClientProvider::new(None, None);
|
2023-03-13 21:12:09 -04:00
|
|
|
let path = resolve_compile_executable_output_path(
|
2024-06-03 17:17:08 -04:00
|
|
|
&http_client,
|
2023-03-13 21:12:09 -04:00
|
|
|
&CompileFlags {
|
|
|
|
source_file: "mod.ts".to_string(),
|
2024-03-14 19:53:46 -04:00
|
|
|
output: Some(String::from("./file")),
|
2023-03-13 21:12:09 -04:00
|
|
|
args: Vec::new(),
|
|
|
|
target: Some("x86_64-unknown-linux-gnu".to_string()),
|
2023-07-28 11:46:26 -04:00
|
|
|
no_terminal: false,
|
2024-08-15 00:42:23 -04:00
|
|
|
icon: None,
|
2023-03-18 19:43:07 -04:00
|
|
|
include: vec![],
|
2023-03-13 21:12:09 -04:00
|
|
|
},
|
|
|
|
&std::env::current_dir().unwrap(),
|
|
|
|
)
|
2023-02-10 10:11:11 -05:00
|
|
|
.await
|
2022-03-28 14:38:15 -04:00
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// no extension, no matter what the operating system is
|
|
|
|
// because the target was specified as linux
|
|
|
|
// https://github.com/denoland/deno/issues/9667
|
|
|
|
assert_eq!(path.file_name().unwrap(), "file");
|
|
|
|
}
|
|
|
|
|
2023-02-10 10:11:11 -05:00
|
|
|
#[tokio::test]
|
|
|
|
async fn resolve_compile_executable_output_path_target_windows() {
|
2024-06-03 17:17:08 -04:00
|
|
|
let http_client = HttpClientProvider::new(None, None);
|
2023-03-13 21:12:09 -04:00
|
|
|
let path = resolve_compile_executable_output_path(
|
2024-06-03 17:17:08 -04:00
|
|
|
&http_client,
|
2023-03-13 21:12:09 -04:00
|
|
|
&CompileFlags {
|
|
|
|
source_file: "mod.ts".to_string(),
|
2024-03-14 19:53:46 -04:00
|
|
|
output: Some(String::from("./file")),
|
2023-03-13 21:12:09 -04:00
|
|
|
args: Vec::new(),
|
|
|
|
target: Some("x86_64-pc-windows-msvc".to_string()),
|
2023-03-18 19:43:07 -04:00
|
|
|
include: vec![],
|
2024-08-15 00:42:23 -04:00
|
|
|
icon: None,
|
2023-07-28 11:46:26 -04:00
|
|
|
no_terminal: false,
|
2023-03-13 21:12:09 -04:00
|
|
|
},
|
|
|
|
&std::env::current_dir().unwrap(),
|
|
|
|
)
|
2023-02-10 10:11:11 -05:00
|
|
|
.await
|
2022-03-28 14:38:15 -04:00
|
|
|
.unwrap();
|
|
|
|
assert_eq!(path.file_name().unwrap(), "file.exe");
|
|
|
|
}
|
2022-09-22 11:49:27 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_os_specific_file_path() {
|
|
|
|
fn run_test(path: &str, target: Option<&str>, expected: &str) {
|
|
|
|
assert_eq!(
|
|
|
|
get_os_specific_filepath(
|
|
|
|
PathBuf::from(path),
|
|
|
|
&target.map(|s| s.to_string())
|
|
|
|
),
|
|
|
|
PathBuf::from(expected)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg!(windows) {
|
|
|
|
run_test("C:\\my-exe", None, "C:\\my-exe.exe");
|
|
|
|
run_test("C:\\my-exe.exe", None, "C:\\my-exe.exe");
|
|
|
|
run_test("C:\\my-exe-0.1.2", None, "C:\\my-exe-0.1.2.exe");
|
|
|
|
} else {
|
|
|
|
run_test("my-exe", Some("linux"), "my-exe");
|
|
|
|
run_test("my-exe-0.1.2", Some("linux"), "my-exe-0.1.2");
|
|
|
|
}
|
|
|
|
|
|
|
|
run_test("C:\\my-exe", Some("windows"), "C:\\my-exe.exe");
|
|
|
|
run_test("C:\\my-exe.exe", Some("windows"), "C:\\my-exe.exe");
|
|
|
|
run_test("C:\\my-exe.0.1.2", Some("windows"), "C:\\my-exe.0.1.2.exe");
|
|
|
|
run_test("my-exe-0.1.2", Some("linux"), "my-exe-0.1.2");
|
|
|
|
}
|
2022-03-28 14:38:15 -04:00
|
|
|
}
|