mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Use roc_target over target_lexicon
Tailors a target class for our needs. Replaces tons of uses across the entire compiler. This is a base for later adding new targets like thumb.
This commit is contained in:
parent
185262510c
commit
6dc5bfb1b7
72 changed files with 1008 additions and 1371 deletions
|
@ -1,9 +1,10 @@
|
|||
use crate::target::{arch_str, target_zig_str};
|
||||
use crate::target::arch_str;
|
||||
use libloading::{Error, Library};
|
||||
use roc_command_utils::{cargo, clang, rustup, zig};
|
||||
use roc_debug_flags;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_mono::ir::OptLevel;
|
||||
use roc_target::{Architecture, OperatingSystem, Target};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::DirEntry;
|
||||
|
@ -11,7 +12,6 @@ use std::io;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::process::{self, Child, Command};
|
||||
use std::{env, fs};
|
||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||
use wasi_libc_sys::{WASI_COMPILER_RT_PATH, WASI_LIBC_PATH};
|
||||
|
||||
pub use roc_linker::LinkType;
|
||||
|
@ -28,46 +28,33 @@ pub enum LinkingStrategy {
|
|||
|
||||
/// input_paths can include the host as well as the app. e.g. &["host.o", "roc_app.o"]
|
||||
pub fn link(
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
output_path: PathBuf,
|
||||
input_paths: &[&str],
|
||||
link_type: LinkType,
|
||||
) -> io::Result<(Child, PathBuf)> {
|
||||
match target {
|
||||
Triple {
|
||||
architecture: Architecture::Wasm32,
|
||||
..
|
||||
} => link_wasm32(target, output_path, input_paths, link_type),
|
||||
Triple {
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => link_linux(target, output_path, input_paths, link_type),
|
||||
Triple {
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => link_macos(target, output_path, input_paths, link_type),
|
||||
Triple {
|
||||
operating_system: OperatingSystem::Windows,
|
||||
..
|
||||
} => link_windows(target, output_path, input_paths, link_type),
|
||||
match target.arch_os() {
|
||||
(Architecture::Wasm32, _) => link_wasm32(target, output_path, input_paths, link_type),
|
||||
(_, OperatingSystem::Linux) => link_linux(target, output_path, input_paths, link_type),
|
||||
(_, OperatingSystem::Mac) => link_macos(target, output_path, input_paths, link_type),
|
||||
(_, OperatingSystem::Windows) => link_windows(output_path, input_paths, link_type),
|
||||
_ => internal_error!("TODO gracefully handle unsupported target: {:?}", target),
|
||||
}
|
||||
}
|
||||
|
||||
/// Same format as the precompiled host filename, except with a file extension like ".o" or ".obj"
|
||||
pub fn legacy_host_file(target: &Triple, platform_main_roc: &Path) -> Option<PathBuf> {
|
||||
let os = roc_target::OperatingSystem::from(target.operating_system);
|
||||
let lib_ext = os.static_library_file_ext();
|
||||
pub fn legacy_host_file(target: Target, platform_main_roc: &Path) -> PathBuf {
|
||||
let lib_ext = target.static_library_file_ext();
|
||||
|
||||
let file_name = roc_linker::preprocessed_host_filename(target)?
|
||||
let file_name = roc_linker::preprocessed_host_filename(target)
|
||||
.replace(roc_linker::PRECOMPILED_HOST_EXT, lib_ext);
|
||||
|
||||
let lib_path = platform_main_roc.with_file_name(file_name);
|
||||
if lib_path.exists() {
|
||||
Some(lib_path)
|
||||
lib_path
|
||||
} else {
|
||||
let obj_ext = os.object_file_ext();
|
||||
Some(lib_path.with_extension(obj_ext))
|
||||
let obj_ext = target.object_file_ext();
|
||||
lib_path.with_extension(obj_ext)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +303,7 @@ pub fn build_zig_host_wasm32(
|
|||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn build_c_host_native(
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
env_path: &str,
|
||||
env_home: &str,
|
||||
env_cpath: &str,
|
||||
|
@ -335,7 +322,7 @@ pub fn build_c_host_native(
|
|||
.args(sources)
|
||||
.args(["-o", dest]);
|
||||
if let Some(shared_lib_path) = shared_lib_path {
|
||||
match target.operating_system {
|
||||
match target.operating_system() {
|
||||
OperatingSystem::Windows => {
|
||||
// just use zig as a C compiler
|
||||
|
||||
|
@ -347,7 +334,7 @@ pub fn build_c_host_native(
|
|||
env_home,
|
||||
dest,
|
||||
sources[0],
|
||||
get_target_str(target),
|
||||
"native",
|
||||
opt_level,
|
||||
Some(shared_lib_path),
|
||||
builtins_host_path,
|
||||
|
@ -406,7 +393,7 @@ pub fn build_swift_host_native(
|
|||
.env("HOME", env_home);
|
||||
|
||||
match arch {
|
||||
Architecture::Aarch64(_) => command.arg("-arm64"),
|
||||
Architecture::Aarch64 => command.arg("-arm64"),
|
||||
_ => command.arg(format!("-{arch}")),
|
||||
};
|
||||
|
||||
|
@ -437,7 +424,7 @@ pub fn build_swift_host_native(
|
|||
|
||||
pub fn rebuild_host(
|
||||
opt_level: OptLevel,
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
platform_main_roc: &Path,
|
||||
shared_lib_path: Option<&Path>,
|
||||
) -> PathBuf {
|
||||
|
@ -450,14 +437,12 @@ pub fn rebuild_host(
|
|||
let swift_host_src = platform_main_roc.with_file_name("host.swift");
|
||||
let swift_host_header_src = platform_main_roc.with_file_name("host.h");
|
||||
|
||||
let os = roc_target::OperatingSystem::from(target.operating_system);
|
||||
let executable_extension = match os {
|
||||
roc_target::OperatingSystem::Windows => "exe",
|
||||
roc_target::OperatingSystem::Unix => "",
|
||||
roc_target::OperatingSystem::Wasi => "",
|
||||
let executable_extension = match target.operating_system() {
|
||||
OperatingSystem::Windows => "exe",
|
||||
_ => "",
|
||||
};
|
||||
|
||||
let host_dest = if matches!(target.architecture, Architecture::Wasm32) {
|
||||
let host_dest = if matches!(target.architecture(), Architecture::Wasm32) {
|
||||
if matches!(opt_level, OptLevel::Development) {
|
||||
platform_main_roc.with_extension("o")
|
||||
} else {
|
||||
|
@ -468,7 +453,7 @@ pub fn rebuild_host(
|
|||
.with_file_name("dynhost")
|
||||
.with_extension(executable_extension)
|
||||
} else {
|
||||
legacy_host_file(target, platform_main_roc).unwrap()
|
||||
legacy_host_file(target, platform_main_roc)
|
||||
};
|
||||
|
||||
let env_path = env::var("PATH").unwrap_or_else(|_| "".to_string());
|
||||
|
@ -480,7 +465,7 @@ pub fn rebuild_host(
|
|||
|
||||
if zig_host_src.exists() {
|
||||
// Compile host.zig
|
||||
let zig_cmd = match target.architecture {
|
||||
let zig_cmd = match target.architecture() {
|
||||
Architecture::Wasm32 => {
|
||||
let emit_bin = if matches!(opt_level, OptLevel::Development) {
|
||||
format!("-femit-bin={}", host_dest.to_str().unwrap())
|
||||
|
@ -501,12 +486,12 @@ pub fn rebuild_host(
|
|||
&env_home,
|
||||
host_dest.to_str().unwrap(),
|
||||
zig_host_src.to_str().unwrap(),
|
||||
get_target_str(target),
|
||||
"native",
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
builtins_host_tempfile.path(),
|
||||
),
|
||||
Architecture::X86_32(_) => build_zig_host_native(
|
||||
Architecture::X86_32 => build_zig_host_native(
|
||||
&env_path,
|
||||
&env_home,
|
||||
host_dest.to_str().unwrap(),
|
||||
|
@ -516,17 +501,17 @@ pub fn rebuild_host(
|
|||
shared_lib_path,
|
||||
builtins_host_tempfile.path(),
|
||||
),
|
||||
Architecture::Aarch64(_) => build_zig_host_native(
|
||||
Architecture::Aarch64 => build_zig_host_native(
|
||||
&env_path,
|
||||
&env_home,
|
||||
host_dest.to_str().unwrap(),
|
||||
zig_host_src.to_str().unwrap(),
|
||||
target_zig_str(target),
|
||||
"native",
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
builtins_host_tempfile.path(),
|
||||
),
|
||||
_ => internal_error!("Unsupported architecture {:?}", target.architecture),
|
||||
_ => internal_error!("Unsupported architecture {:?}", target.architecture()),
|
||||
};
|
||||
|
||||
run_build_command(zig_cmd, "host.zig", 0);
|
||||
|
@ -714,7 +699,7 @@ pub fn rebuild_host(
|
|||
swift_host_header_src
|
||||
.exists()
|
||||
.then(|| swift_host_header_src.to_str().unwrap()),
|
||||
target.architecture,
|
||||
target.architecture(),
|
||||
);
|
||||
|
||||
run_build_command(swiftc_cmd, "host.swift", 0);
|
||||
|
@ -784,16 +769,6 @@ fn find_in_folder_or_subfolders(path: &PathBuf, folder_to_find: &str) -> Vec<Dir
|
|||
matching_dirs
|
||||
}
|
||||
|
||||
fn get_target_str(target: &Triple) -> &str {
|
||||
if target.operating_system == OperatingSystem::Windows
|
||||
&& target.environment == target_lexicon::Environment::Gnu
|
||||
{
|
||||
"x86_64-windows-gnu"
|
||||
} else {
|
||||
"native"
|
||||
}
|
||||
}
|
||||
|
||||
fn nix_paths() -> Vec<String> {
|
||||
let mut paths = vec![];
|
||||
|
||||
|
@ -862,12 +837,12 @@ fn extra_link_flags() -> Vec<String> {
|
|||
}
|
||||
|
||||
fn link_linux(
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
output_path: PathBuf,
|
||||
input_paths: &[&str],
|
||||
link_type: LinkType,
|
||||
) -> io::Result<(Child, PathBuf)> {
|
||||
let architecture = format!("{}-linux-gnu", target.architecture);
|
||||
let architecture = format!("{}-linux-gnu", target.architecture());
|
||||
|
||||
// Command::new("cp")
|
||||
// .args(&[input_paths[0], "/home/folkertdev/roc/wasm/host.o"])
|
||||
|
@ -879,7 +854,7 @@ fn link_linux(
|
|||
// .output()
|
||||
// .unwrap();
|
||||
|
||||
if let Architecture::X86_32(_) = target.architecture {
|
||||
if let Architecture::X86_32 = target.architecture() {
|
||||
return Ok((
|
||||
zig()
|
||||
.args(["build-exe"])
|
||||
|
@ -971,7 +946,7 @@ fn link_linux(
|
|||
scrt1_path.to_string_lossy(),
|
||||
);
|
||||
|
||||
let ld_linux_path = match target.architecture {
|
||||
let ld_linux_path = match target.architecture() {
|
||||
Architecture::X86_64 => {
|
||||
// give preference to nix_path if it's defined, this prevents bugs
|
||||
if let Some(nix_glibc_path) = nix_glibc_path_opt() {
|
||||
|
@ -983,10 +958,10 @@ fn link_linux(
|
|||
build_path_or_panic(["/lib64", "ld-linux-x86-64.so.2"])
|
||||
}
|
||||
}
|
||||
Architecture::Aarch64(_) => build_path_or_panic(["/lib", "ld-linux-aarch64.so.1"]),
|
||||
Architecture::Aarch64 => build_path_or_panic(["/lib", "ld-linux-aarch64.so.1"]),
|
||||
_ => internal_error!(
|
||||
"TODO gracefully handle unsupported linux architecture: {:?}",
|
||||
target.architecture
|
||||
target.architecture()
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -1083,7 +1058,7 @@ fn link_linux(
|
|||
}
|
||||
|
||||
fn link_macos(
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
output_path: PathBuf,
|
||||
input_paths: &[&str],
|
||||
link_type: LinkType,
|
||||
|
@ -1100,9 +1075,9 @@ fn link_macos(
|
|||
LinkType::None => internal_error!("link_macos should not be called with link type of none"),
|
||||
};
|
||||
|
||||
let arch = match target.architecture {
|
||||
Architecture::Aarch64(_) => "arm64".to_string(),
|
||||
_ => target.architecture.to_string(),
|
||||
let arch = match target.architecture() {
|
||||
Architecture::Aarch64 => "arm64".to_string(),
|
||||
_ => target.architecture().to_string(),
|
||||
};
|
||||
|
||||
let mut ld_command = Command::new("ld");
|
||||
|
@ -1177,8 +1152,8 @@ fn link_macos(
|
|||
|
||||
let mut ld_child = ld_command.spawn()?;
|
||||
|
||||
match target.architecture {
|
||||
Architecture::Aarch64(_) => {
|
||||
match target.architecture() {
|
||||
Architecture::Aarch64 => {
|
||||
ld_child.wait()?;
|
||||
|
||||
let mut codesign_cmd = Command::new("codesign");
|
||||
|
@ -1214,7 +1189,7 @@ fn get_macos_version() -> String {
|
|||
}
|
||||
|
||||
fn link_wasm32(
|
||||
_target: &Triple,
|
||||
_target: Target,
|
||||
output_path: PathBuf,
|
||||
input_paths: &[&str],
|
||||
_link_type: LinkType,
|
||||
|
@ -1249,7 +1224,6 @@ fn link_wasm32(
|
|||
}
|
||||
|
||||
fn link_windows(
|
||||
target: &Triple,
|
||||
output_path: PathBuf,
|
||||
input_paths: &[&str],
|
||||
link_type: LinkType,
|
||||
|
@ -1282,7 +1256,7 @@ fn link_windows(
|
|||
.args(input_paths)
|
||||
.args([
|
||||
"-target",
|
||||
get_target_str(target),
|
||||
"native",
|
||||
"--subsystem",
|
||||
"console",
|
||||
"-lc",
|
||||
|
@ -1298,7 +1272,7 @@ fn link_windows(
|
|||
|
||||
pub fn llvm_module_to_dylib(
|
||||
module: &inkwell::module::Module,
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
opt_level: OptLevel,
|
||||
) -> Result<Library, Error> {
|
||||
use crate::target::{self, convert_opt_level};
|
||||
|
@ -1322,7 +1296,7 @@ pub fn llvm_module_to_dylib(
|
|||
|
||||
// Link app.o into a dylib - e.g. app.so or app.dylib
|
||||
let (mut child, dylib_path) = link(
|
||||
&Triple::host(),
|
||||
target,
|
||||
app_o_file.clone(),
|
||||
&[app_o_file.to_str().unwrap()],
|
||||
LinkType::Dylib,
|
||||
|
@ -1339,7 +1313,7 @@ pub fn llvm_module_to_dylib(
|
|||
// Load the dylib
|
||||
let path = dylib_path.as_path().to_str().unwrap();
|
||||
|
||||
if matches!(target.architecture, Architecture::Aarch64(_)) {
|
||||
if matches!(target.architecture(), Architecture::Aarch64) {
|
||||
// On AArch64 darwin machines, calling `ldopen` on Roc-generated libs from multiple threads
|
||||
// sometimes fails with
|
||||
// cannot dlopen until fork() handlers have completed
|
||||
|
|
|
@ -17,7 +17,7 @@ use roc_reporting::{
|
|||
cli::{report_problems, Problems},
|
||||
report::{RenderTarget, DEFAULT_PALETTE},
|
||||
};
|
||||
use roc_target::{OperatingSystem, TargetInfo};
|
||||
use roc_target::{Architecture, Target};
|
||||
use std::ffi::OsStr;
|
||||
use std::ops::Deref;
|
||||
use std::{
|
||||
|
@ -25,7 +25,6 @@ use std::{
|
|||
thread::JoinHandle,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use target_lexicon::Triple;
|
||||
|
||||
#[cfg(feature = "target-wasm32")]
|
||||
use roc_collections::all::MutSet;
|
||||
|
@ -96,7 +95,7 @@ pub fn gen_from_mono_module<'a>(
|
|||
arena: &'a bumpalo::Bump,
|
||||
loaded: MonomorphizedModule<'a>,
|
||||
roc_file_path: &Path,
|
||||
target: &target_lexicon::Triple,
|
||||
target: Target,
|
||||
code_gen_options: CodeGenOptions,
|
||||
preprocessed_host_path: &Path,
|
||||
wasm_dev_stack_bytes: Option<u32>,
|
||||
|
@ -146,7 +145,7 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
arena: &'a bumpalo::Bump,
|
||||
loaded: MonomorphizedModule<'a>,
|
||||
roc_file_path: &Path,
|
||||
target: &target_lexicon::Triple,
|
||||
target: Target,
|
||||
opt_level: OptLevel,
|
||||
backend_mode: LlvmBackendMode,
|
||||
emit_debug_info: bool,
|
||||
|
@ -162,7 +161,6 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
let all_code_gen_start = Instant::now();
|
||||
|
||||
// Generate the binary
|
||||
let target_info = roc_target::TargetInfo::from(target);
|
||||
let context = Context::create();
|
||||
let module = arena.alloc(module_from_builtins(target, &context, "app"));
|
||||
|
||||
|
@ -210,7 +208,7 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
context: &context,
|
||||
interns: loaded.interns,
|
||||
module,
|
||||
target_info,
|
||||
target,
|
||||
mode: backend_mode,
|
||||
|
||||
exposed_to_host: loaded
|
||||
|
@ -387,9 +385,8 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
}
|
||||
|
||||
// Emit the .o file
|
||||
use target_lexicon::Architecture;
|
||||
match target.architecture {
|
||||
Architecture::X86_64 | Architecture::X86_32(_) | Architecture::Aarch64(_) => {
|
||||
match target.architecture() {
|
||||
Architecture::X86_64 | Architecture::X86_32 | Architecture::Aarch64 => {
|
||||
let reloc = RelocMode::PIC;
|
||||
let target_machine =
|
||||
target::target_machine(target, convert_opt_level(opt_level), reloc).unwrap();
|
||||
|
@ -405,7 +402,7 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
}
|
||||
_ => internal_error!(
|
||||
"TODO gracefully handle unsupported architecture: {:?}",
|
||||
target.architecture
|
||||
target.architecture()
|
||||
),
|
||||
}
|
||||
};
|
||||
|
@ -432,21 +429,19 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
fn gen_from_mono_module_dev<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
loaded: MonomorphizedModule<'a>,
|
||||
target: &target_lexicon::Triple,
|
||||
target: Target,
|
||||
preprocessed_host_path: &Path,
|
||||
wasm_dev_stack_bytes: Option<u32>,
|
||||
backend_mode: AssemblyBackendMode,
|
||||
) -> GenFromMono<'a> {
|
||||
use target_lexicon::Architecture;
|
||||
|
||||
match target.architecture {
|
||||
match target.architecture() {
|
||||
Architecture::Wasm32 => gen_from_mono_module_dev_wasm32(
|
||||
arena,
|
||||
loaded,
|
||||
preprocessed_host_path,
|
||||
wasm_dev_stack_bytes,
|
||||
),
|
||||
Architecture::X86_64 | Architecture::Aarch64(_) => {
|
||||
Architecture::X86_64 | Architecture::Aarch64 => {
|
||||
gen_from_mono_module_dev_assembly(arena, loaded, target, backend_mode)
|
||||
}
|
||||
_ => todo!(),
|
||||
|
@ -457,15 +452,13 @@ fn gen_from_mono_module_dev<'a>(
|
|||
pub fn gen_from_mono_module_dev<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
loaded: MonomorphizedModule<'a>,
|
||||
target: &target_lexicon::Triple,
|
||||
target: Target,
|
||||
_host_input_path: &Path,
|
||||
_wasm_dev_stack_bytes: Option<u32>,
|
||||
backend_mode: AssemblyBackendMode,
|
||||
) -> GenFromMono<'a> {
|
||||
use target_lexicon::Architecture;
|
||||
|
||||
match target.architecture {
|
||||
Architecture::X86_64 | Architecture::Aarch64(_) => {
|
||||
match target.architecture() {
|
||||
Architecture::X86_64 | Architecture::Aarch64 => {
|
||||
gen_from_mono_module_dev_assembly(arena, loaded, target, backend_mode)
|
||||
}
|
||||
_ => todo!(),
|
||||
|
@ -549,7 +542,7 @@ fn gen_from_mono_module_dev_wasm32<'a>(
|
|||
fn gen_from_mono_module_dev_assembly<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
loaded: MonomorphizedModule<'a>,
|
||||
target: &target_lexicon::Triple,
|
||||
target: Target,
|
||||
backend_mode: AssemblyBackendMode,
|
||||
) -> GenFromMono<'a> {
|
||||
let all_code_gen_start = Instant::now();
|
||||
|
@ -694,12 +687,10 @@ pub fn handle_loading_problem(problem: LoadingProblem) -> std::io::Result<i32> {
|
|||
}
|
||||
|
||||
pub fn standard_load_config(
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
order: BuildOrdering,
|
||||
threading: Threading,
|
||||
) -> LoadConfig {
|
||||
let target_info = TargetInfo::from(target);
|
||||
|
||||
let exec_mode = match order {
|
||||
BuildOrdering::BuildIfChecks => ExecutionMode::ExecutableIfCheck,
|
||||
BuildOrdering::AlwaysBuild => ExecutionMode::Executable,
|
||||
|
@ -717,7 +708,7 @@ pub fn standard_load_config(
|
|||
};
|
||||
|
||||
LoadConfig {
|
||||
target_info,
|
||||
target,
|
||||
function_kind,
|
||||
render: RenderTarget::ColorTerminal,
|
||||
palette: DEFAULT_PALETTE,
|
||||
|
@ -729,7 +720,7 @@ pub fn standard_load_config(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn build_file<'a>(
|
||||
arena: &'a Bump,
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
app_module_path: PathBuf,
|
||||
code_gen_options: CodeGenOptions,
|
||||
emit_timings: bool,
|
||||
|
@ -767,7 +758,7 @@ pub fn build_file<'a>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_loaded_file<'a>(
|
||||
arena: &'a Bump,
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
app_module_path: PathBuf,
|
||||
code_gen_options: CodeGenOptions,
|
||||
emit_timings: bool,
|
||||
|
@ -779,8 +770,6 @@ fn build_loaded_file<'a>(
|
|||
compilation_start: Instant,
|
||||
out_path: Option<&Path>,
|
||||
) -> Result<BuiltFile<'a>, BuildFileError<'a>> {
|
||||
let operating_system = roc_target::OperatingSystem::from(target.operating_system);
|
||||
|
||||
let platform_main_roc = match &loaded.entry_point {
|
||||
EntryPoint::Executable { platform_path, .. } => platform_path.to_path_buf(),
|
||||
_ => unreachable!(),
|
||||
|
@ -792,9 +781,9 @@ fn build_loaded_file<'a>(
|
|||
|
||||
if is_platform_prebuilt && linking_strategy == LinkingStrategy::Surgical {
|
||||
// Fallback to legacy linking if the preprocessed host file does not exist, but a legacy host does exist.
|
||||
let preprocessed_host_path = platform_main_roc
|
||||
.with_file_name(roc_linker::preprocessed_host_filename(target).unwrap());
|
||||
let legacy_host_path = legacy_host_file(target, &platform_main_roc).unwrap();
|
||||
let preprocessed_host_path =
|
||||
platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target));
|
||||
let legacy_host_path = legacy_host_file(target, &platform_main_roc);
|
||||
if !preprocessed_host_path.exists() && legacy_host_path.exists() {
|
||||
linking_strategy = LinkingStrategy::Legacy;
|
||||
}
|
||||
|
@ -802,15 +791,15 @@ fn build_loaded_file<'a>(
|
|||
|
||||
// the preprocessed host is stored beside the platform's main.roc
|
||||
let preprocessed_host_path = if linking_strategy == LinkingStrategy::Legacy {
|
||||
if let roc_target::OperatingSystem::Wasi = operating_system {
|
||||
if target == Target::Wasm32 {
|
||||
// when compiling a wasm application, we implicitly assume here that the host is in zig
|
||||
// and has a file called "host.zig"
|
||||
platform_main_roc.with_file_name("host.zig")
|
||||
} else {
|
||||
legacy_host_file(target, &platform_main_roc).unwrap()
|
||||
legacy_host_file(target, &platform_main_roc)
|
||||
}
|
||||
} else {
|
||||
platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target).unwrap())
|
||||
platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target))
|
||||
};
|
||||
|
||||
let output_exe_path = match out_path {
|
||||
|
@ -841,22 +830,12 @@ fn build_loaded_file<'a>(
|
|||
if ends_with_sep {
|
||||
let filename = app_module_path.file_name().unwrap_or_default();
|
||||
|
||||
with_output_extension(
|
||||
&path.join(filename),
|
||||
operating_system,
|
||||
linking_strategy,
|
||||
link_type,
|
||||
)
|
||||
with_output_extension(&path.join(filename), target, linking_strategy, link_type)
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
}
|
||||
None => with_output_extension(
|
||||
&app_module_path,
|
||||
operating_system,
|
||||
linking_strategy,
|
||||
link_type,
|
||||
),
|
||||
None => with_output_extension(&app_module_path, target, linking_strategy, link_type),
|
||||
};
|
||||
|
||||
// We don't need to spawn a rebuild thread when using a prebuilt host.
|
||||
|
@ -1018,13 +997,13 @@ fn build_loaded_file<'a>(
|
|||
std::fs::write(&output_exe_path, &*roc_app_bytes).unwrap();
|
||||
}
|
||||
(LinkingStrategy::Legacy, _) => {
|
||||
let extension = if matches!(operating_system, roc_target::OperatingSystem::Wasi) {
|
||||
let extension = if target == Target::Wasm32 {
|
||||
// Legacy linker is only by used llvm wasm backend, not dev.
|
||||
// llvm wasm backend directly emits a bitcode file when targeting wasi, not a `.o` or `.wasm` file.
|
||||
// If we set the extension wrong, zig will print a ton of warnings when linking.
|
||||
"bc"
|
||||
} else {
|
||||
operating_system.object_file_ext()
|
||||
target.object_file_ext()
|
||||
};
|
||||
let app_o_file = tempfile::Builder::new()
|
||||
.prefix("roc_app")
|
||||
|
@ -1124,10 +1103,9 @@ fn spawn_rebuild_thread(
|
|||
platform_main_roc: PathBuf,
|
||||
preprocessed_host_path: PathBuf,
|
||||
output_exe_path: PathBuf,
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
dll_stub_symbols: Vec<String>,
|
||||
) -> std::thread::JoinHandle<u128> {
|
||||
let thread_local_target = target.clone();
|
||||
std::thread::spawn(move || {
|
||||
// Printing to stderr because we want stdout to contain only the output of the roc program.
|
||||
// We are aware of the trade-offs.
|
||||
|
@ -1138,19 +1116,14 @@ fn spawn_rebuild_thread(
|
|||
|
||||
match linking_strategy {
|
||||
LinkingStrategy::Additive => {
|
||||
let host_dest = rebuild_host(
|
||||
opt_level,
|
||||
&thread_local_target,
|
||||
platform_main_roc.as_path(),
|
||||
None,
|
||||
);
|
||||
let host_dest = rebuild_host(opt_level, target, platform_main_roc.as_path(), None);
|
||||
|
||||
preprocess_host_wasm32(host_dest.as_path(), &preprocessed_host_path);
|
||||
}
|
||||
LinkingStrategy::Surgical => {
|
||||
build_and_preprocess_host_lowlevel(
|
||||
opt_level,
|
||||
&thread_local_target,
|
||||
target,
|
||||
platform_main_roc.as_path(),
|
||||
preprocessed_host_path.as_path(),
|
||||
&dll_stub_symbols,
|
||||
|
@ -1161,12 +1134,7 @@ fn spawn_rebuild_thread(
|
|||
std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap();
|
||||
}
|
||||
LinkingStrategy::Legacy => {
|
||||
rebuild_host(
|
||||
opt_level,
|
||||
&thread_local_target,
|
||||
platform_main_roc.as_path(),
|
||||
None,
|
||||
);
|
||||
rebuild_host(opt_level, target, platform_main_roc.as_path(), None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1176,7 +1144,7 @@ fn spawn_rebuild_thread(
|
|||
|
||||
pub fn build_and_preprocess_host(
|
||||
opt_level: OptLevel,
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
platform_main_roc: &Path,
|
||||
preprocessed_host_path: &Path,
|
||||
exposed_symbols: roc_linker::ExposedSymbols,
|
||||
|
@ -1194,7 +1162,7 @@ pub fn build_and_preprocess_host(
|
|||
|
||||
fn build_and_preprocess_host_lowlevel(
|
||||
opt_level: OptLevel,
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
platform_main_roc: &Path,
|
||||
preprocessed_host_path: &Path,
|
||||
stub_dll_symbols: &[String],
|
||||
|
@ -1227,12 +1195,12 @@ pub fn check_file<'a>(
|
|||
|
||||
// only used for generating errors. We don't do code generation, so hardcoding should be fine
|
||||
// we need monomorphization for when exhaustiveness checking
|
||||
let target_info = TargetInfo::default_x86_64();
|
||||
let target = Target::LinuxX64;
|
||||
|
||||
// Step 1: compile the app and generate the .o file
|
||||
|
||||
let load_config = LoadConfig {
|
||||
target_info,
|
||||
target,
|
||||
// TODO: we may not want this for just checking.
|
||||
function_kind: FunctionKind::LambdaSet,
|
||||
// TODO: expose this from CLI?
|
||||
|
@ -1295,7 +1263,7 @@ pub fn build_str_test<'a>(
|
|||
app_module_source: &'a str,
|
||||
assume_prebuild: bool,
|
||||
) -> Result<BuiltFile<'a>, BuildFileError<'a>> {
|
||||
let triple = target_lexicon::Triple::host();
|
||||
let target = target_lexicon::Triple::host().into();
|
||||
|
||||
let code_gen_options = CodeGenOptions {
|
||||
backend: CodeGenBackend::Llvm(LlvmBackendMode::Binary),
|
||||
|
@ -1314,7 +1282,7 @@ pub fn build_str_test<'a>(
|
|||
let build_ordering = BuildOrdering::AlwaysBuild;
|
||||
let threading = Threading::AtMost(2);
|
||||
|
||||
let load_config = standard_load_config(&triple, build_ordering, threading);
|
||||
let load_config = standard_load_config(target, build_ordering, threading);
|
||||
|
||||
let compilation_start = std::time::Instant::now();
|
||||
|
||||
|
@ -1331,7 +1299,7 @@ pub fn build_str_test<'a>(
|
|||
|
||||
build_loaded_file(
|
||||
arena,
|
||||
&triple,
|
||||
target,
|
||||
app_module_path.to_path_buf(),
|
||||
code_gen_options,
|
||||
emit_timings,
|
||||
|
@ -1347,15 +1315,15 @@ pub fn build_str_test<'a>(
|
|||
|
||||
fn with_output_extension(
|
||||
path: &Path,
|
||||
os: OperatingSystem,
|
||||
target: Target,
|
||||
linking_strategy: LinkingStrategy,
|
||||
link_type: LinkType,
|
||||
) -> PathBuf {
|
||||
match (linking_strategy, link_type) {
|
||||
(LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => {
|
||||
// Additive linking and no linking both output the object file type.
|
||||
path.with_extension(os.object_file_ext())
|
||||
path.with_extension(target.object_file_ext())
|
||||
}
|
||||
_ => path.with_extension(os.executable_file_ext().unwrap_or_default()),
|
||||
_ => path.with_extension(target.executable_file_ext().unwrap_or_default()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,121 +1,65 @@
|
|||
use inkwell::{
|
||||
targets::{CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple},
|
||||
targets::{
|
||||
CodeModel, InitializationConfig, RelocMode, Target as LlvmTarget, TargetMachine,
|
||||
TargetTriple,
|
||||
},
|
||||
OptimizationLevel,
|
||||
};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_mono::ir::OptLevel;
|
||||
use target_lexicon::{Architecture, Environment, OperatingSystem, Triple};
|
||||
use roc_target::{Architecture, Target};
|
||||
|
||||
pub fn target_triple_str(target: &Triple) -> &'static str {
|
||||
pub fn target_triple_str(target: Target) -> &'static str {
|
||||
// Best guide I've found on how to determine these magic strings:
|
||||
//
|
||||
// https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
|
||||
match target {
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => "x86_64-unknown-linux-gnu",
|
||||
Triple {
|
||||
architecture: Architecture::X86_32(target_lexicon::X86_32Architecture::I386),
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => "i386-unknown-linux-gnu",
|
||||
Triple {
|
||||
architecture: Architecture::Wasm32,
|
||||
..
|
||||
} => "wasm32-unknown-unknown",
|
||||
Triple {
|
||||
architecture: Architecture::Aarch64(_),
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => "aarch64-unknown-linux-gnu",
|
||||
Triple {
|
||||
architecture: Architecture::Aarch64(_),
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => "aarch64-apple-darwin",
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => "x86_64-unknown-darwin10",
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Windows,
|
||||
..
|
||||
} => "x86_64-pc-windows-gnu",
|
||||
Target::LinuxArm64 => "aarch64-unknown-linux-gnu",
|
||||
Target::LinuxX32 => "i386-unknown-linux-gnu",
|
||||
Target::LinuxX64 => "x86_64-unknown-linux-gnu",
|
||||
Target::MacArm64 => "aarch64-apple-darwin",
|
||||
Target::MacX64 => "x86_64-unknown-darwin10",
|
||||
Target::Wasm32 => "wasm32-unknown-unknown",
|
||||
Target::WinX64 => "x86_64-pc-windows-gnu",
|
||||
_ => internal_error!("TODO gracefully handle unsupported target: {:?}", target),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn target_zig_str(target: &Triple) -> &'static str {
|
||||
pub fn target_zig_str(target: Target) -> &'static str {
|
||||
// Zig has its own architecture mappings, defined here:
|
||||
// https://github.com/ziglang/zig/blob/master/tools/process_headers.zig
|
||||
//
|
||||
// and an open proposal to unify them with the more typical "target triples":
|
||||
// https://github.com/ziglang/zig/issues/4911
|
||||
match target {
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Linux,
|
||||
environment: Environment::Musl,
|
||||
..
|
||||
} => "x86_64-linux-musl",
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => "x86_64-linux-gnu",
|
||||
Triple {
|
||||
architecture: Architecture::X86_32(target_lexicon::X86_32Architecture::I386),
|
||||
operating_system: OperatingSystem::Linux,
|
||||
environment: Environment::Musl,
|
||||
..
|
||||
} => "i386-linux-musl",
|
||||
Triple {
|
||||
architecture: Architecture::X86_32(target_lexicon::X86_32Architecture::I386),
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => "i386-linux-gnu",
|
||||
Triple {
|
||||
architecture: Architecture::Aarch64(_),
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => "aarch64-linux-gnu",
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => "x86_64-macos-none",
|
||||
Triple {
|
||||
architecture: Architecture::Aarch64(_),
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => "aarch64-macos-none",
|
||||
Target::LinuxArm64 => "aarch64-linux-gnu",
|
||||
Target::LinuxX32 => "i386-linux-gnu",
|
||||
Target::LinuxX64 => "x86_64-linux-gnu",
|
||||
Target::MacArm64 => "aarch64-macos-none",
|
||||
Target::MacX64 => "x86_64-macos-none",
|
||||
_ => internal_error!("TODO gracefully handle unsupported target: {:?}", target),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_arch(target: &Triple) {
|
||||
match target.architecture {
|
||||
Architecture::X86_64 | Architecture::X86_32(_)
|
||||
pub fn init_arch(target: Target) {
|
||||
match target.architecture() {
|
||||
Architecture::X86_64 | Architecture::X86_32
|
||||
if cfg!(any(feature = "target-x86", feature = "target-x86_64")) =>
|
||||
{
|
||||
Target::initialize_x86(&InitializationConfig::default());
|
||||
LlvmTarget::initialize_x86(&InitializationConfig::default());
|
||||
}
|
||||
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => {
|
||||
Target::initialize_aarch64(&InitializationConfig::default());
|
||||
Architecture::Aarch64 if cfg!(feature = "target-aarch64") => {
|
||||
LlvmTarget::initialize_aarch64(&InitializationConfig::default());
|
||||
}
|
||||
Architecture::Arm(_) if cfg!(feature = "target-arm") => {
|
||||
Target::initialize_arm(&InitializationConfig::default());
|
||||
Architecture::Aarch32 if cfg!(feature = "target-arm") => {
|
||||
LlvmTarget::initialize_arm(&InitializationConfig::default());
|
||||
}
|
||||
Architecture::Wasm32 if cfg!(feature = "target-wasm32") => {
|
||||
Target::initialize_webassembly(&InitializationConfig::default());
|
||||
LlvmTarget::initialize_webassembly(&InitializationConfig::default());
|
||||
}
|
||||
_ => internal_error!(
|
||||
"TODO gracefully handle unsupported target architecture: {:?}",
|
||||
target.architecture
|
||||
target.architecture()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -123,25 +67,25 @@ pub fn init_arch(target: &Triple) {
|
|||
/// NOTE: arch_str is *not* the same as the beginning of the magic target triple
|
||||
/// string! For example, if it's "x86-64" here, the magic target triple string
|
||||
/// will begin with "x86_64" (with an underscore) instead.
|
||||
pub fn arch_str(target: &Triple) -> &'static str {
|
||||
pub fn arch_str(target: Target) -> &'static str {
|
||||
// Best guide I've found on how to determine these magic strings:
|
||||
//
|
||||
// https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
|
||||
match target.architecture {
|
||||
Architecture::X86_64 if cfg!(feature = "target-x86_64") => "x86-64",
|
||||
Architecture::X86_32(_) if cfg!(feature = "target-x86") => "x86",
|
||||
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => "aarch64",
|
||||
Architecture::Arm(_) if cfg!(feature = "target-arm") => "arm",
|
||||
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32",
|
||||
match target.architecture() {
|
||||
roc_target::Architecture::X86_64 if cfg!(feature = "target-x86_64") => "x86-64",
|
||||
roc_target::Architecture::X86_32 if cfg!(feature = "target-x86") => "x86",
|
||||
roc_target::Architecture::Aarch64 if cfg!(feature = "target-aarch64") => "aarch64",
|
||||
roc_target::Architecture::Aarch32 if cfg!(feature = "target-arm") => "arm",
|
||||
roc_target::Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32",
|
||||
_ => internal_error!(
|
||||
"TODO gracefully handle unsupported target architecture: {:?}",
|
||||
target.architecture
|
||||
target.architecture()
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn target_machine(
|
||||
target: &Triple,
|
||||
target: Target,
|
||||
opt: OptimizationLevel,
|
||||
reloc: RelocMode,
|
||||
) -> Option<TargetMachine> {
|
||||
|
@ -150,11 +94,7 @@ pub fn target_machine(
|
|||
init_arch(target);
|
||||
|
||||
let code_model = match target {
|
||||
Triple {
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
architecture: Architecture::Aarch64(_),
|
||||
..
|
||||
} => {
|
||||
Target::MacArm64 => {
|
||||
// We used to have a problem that LLVM 12 would not compile our programs without a large code model.
|
||||
// The reason was not totally clear to us, but one guess is a few special-cases in
|
||||
// llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (instructions)
|
||||
|
@ -168,7 +108,7 @@ pub fn target_machine(
|
|||
_ => CodeModel::Default,
|
||||
};
|
||||
|
||||
Target::from_name(arch).unwrap().create_target_machine(
|
||||
LlvmTarget::from_name(arch).unwrap().create_target_machine(
|
||||
&TargetTriple::create(target_triple_str(target)),
|
||||
"generic",
|
||||
"",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue