From 387b6927d518de5d3419e26a83ed25dbe0010e96 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 8 Aug 2023 19:55:38 +0200 Subject: [PATCH 1/3] libgcc_s.so.1 fix #5732 --- crates/compiler/build/src/link.rs | 108 +++++++++--------- crates/compiler/test_gen/benches/list_map.rs | 2 +- crates/compiler/test_gen/benches/quicksort.rs | 2 +- flake.nix | 6 + 4 files changed, 64 insertions(+), 54 deletions(-) diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 7d8e800f302..9231aee0ae0 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -4,6 +4,7 @@ use roc_command_utils::{cargo, clang, rustup, zig}; use roc_error_macros::internal_error; use roc_mono::ir::OptLevel; use std::collections::HashMap; +use std::ffi::OsString; use std::fs::DirEntry; use std::io; use std::path::{Path, PathBuf}; @@ -785,11 +786,25 @@ fn get_target_str(target: &Triple) -> &str { } } -fn nix_path_opt() -> Option { - env::var_os("NIX_GLIBC_PATH").map(|path| path.into_string().unwrap()) +fn nix_paths() -> Vec { + let mut paths = vec![]; + + if let Some(nix_libgcc_s_path) = env::var_os("NIX_LIBGCC_S_PATH") { + paths.push(nix_libgcc_s_path.into_string().unwrap()) + } + + if let Some(nix_glibc_path) = nix_glibc_path_opt() { + paths.push(nix_glibc_path.into_string().unwrap()) + } + + paths +} + +fn nix_glibc_path_opt() -> Option { + env::var_os("NIX_GLIBC_PATH") } -fn library_path(segments: [&str; N]) -> Option { +fn build_path(segments: [&str; N]) -> Option { let mut guess_path = PathBuf::new(); for s in segments { guess_path.push(s); @@ -812,22 +827,21 @@ fn library_path(segments: [&str; N]) -> Option { /// match will be returned. /// /// If there are no matches, [`None`] will be returned. -fn look_for_library(lib_dirs: &[&[&str]], lib_filename: &str) -> Option { +fn look_for_library(lib_dirs: &[PathBuf], lib_filename: &str) -> Option { lib_dirs .iter() - .map(|lib_dir| { - lib_dir.iter().fold(PathBuf::new(), |mut path, segment| { - path.push(segment); - path - }) - }) - .map(|mut path| { - path.push(lib_filename); - path + .map(|path| { + let mut path_cl = path.clone(); + path_cl.push(lib_filename); + path_cl }) .find(|path| path.exists()) } +fn strs_to_path(strs: &[&str]) -> PathBuf { + strs.iter().collect() +} + fn link_linux( target: &Triple, output_path: PathBuf, @@ -863,49 +877,39 @@ fn link_linux( } // Some things we'll need to build a list of dirs to check for libraries - let maybe_nix_path = nix_path_opt(); - let usr_lib_arch = ["/usr", "lib", &architecture]; - let lib_arch = ["/lib", &architecture]; - let nix_path_segments; - let lib_dirs_if_nix: [&[&str]; 5]; - let lib_dirs_if_nonix: [&[&str]; 4]; - - // Build the aformentioned list - let lib_dirs: &[&[&str]] = - // give preference to nix_path if it's defined, this prevents bugs - if let Some(nix_path) = &maybe_nix_path { - nix_path_segments = [nix_path.as_str()]; - lib_dirs_if_nix = [ - &nix_path_segments, - &usr_lib_arch, - &lib_arch, - &["/usr", "lib"], - &["/usr", "lib64"], - ]; - &lib_dirs_if_nix - } else { - lib_dirs_if_nonix = [ - &usr_lib_arch, - &lib_arch, - &["/usr", "lib"], - &["/usr", "lib64"], - ]; - &lib_dirs_if_nonix - }; + //env::var_os("NIX_GLIBC_PATH").map(|path| path.into_string().unwrap()), + //env::var_os("NIX_LIBGCC_S_PATH").map(|path| path.into_string().unwrap()) + let nix_paths_vec_string = nix_paths(); + let nix_paths_vec: Vec = nix_paths_vec_string.iter().map(|path_string| PathBuf::from(path_string)).collect(); + let usr_lib_arch_path = strs_to_path(&["/usr", "lib", &architecture]); + let lib_arch_path = strs_to_path(&["/lib", &architecture]); + + let mut lib_dirs: Vec = vec![]; + + // start with nix paths, this prevents bugs + if !nix_paths_vec.is_empty() { + lib_dirs.extend(nix_paths_vec) + } - // Look for the libraries we'll need + lib_dirs.extend( [ + usr_lib_arch_path, + lib_arch_path, + strs_to_path(&["/usr", "lib"]), + strs_to_path(&["/usr", "lib64"]), + ]); + // Look for the libraries we'll need let libgcc_name = "libgcc_s.so.1"; - let libgcc_path = look_for_library(lib_dirs, libgcc_name); + let libgcc_path = look_for_library(&lib_dirs, libgcc_name); let crti_name = "crti.o"; - let crti_path = look_for_library(lib_dirs, crti_name); + let crti_path = look_for_library(&lib_dirs, crti_name); let crtn_name = "crtn.o"; - let crtn_path = look_for_library(lib_dirs, crtn_name); + let crtn_path = look_for_library(&lib_dirs, crtn_name); let scrt1_name = "Scrt1.o"; - let scrt1_path = look_for_library(lib_dirs, scrt1_name); + let scrt1_path = look_for_library(&lib_dirs, scrt1_name); // Unwrap all the paths at once so we can inform the user of all missing libs at once let (libgcc_path, crti_path, crtn_path, scrt1_path) = @@ -925,7 +929,7 @@ fn link_linux( let dirs = lib_dirs .iter() - .map(|segments| segments.join("/")) + .map(|path_buf| path_buf.as_path().to_str().unwrap_or("FAILED TO CONVERT PATH TO STR").to_string()) .collect::>() .join("\n"); eprintln!("We looked in the following directories:\n{dirs}"); @@ -936,13 +940,13 @@ fn link_linux( let ld_linux = match target.architecture { Architecture::X86_64 => { // give preference to nix_path if it's defined, this prevents bugs - if let Some(nix_path) = nix_path_opt() { - library_path([&nix_path, "ld-linux-x86-64.so.2"]) + if let Some(nix_glibc_path) = nix_glibc_path_opt() { + build_path([&nix_glibc_path.into_string().unwrap(), "ld-linux-x86-64.so.2"]) } else { - library_path(["/lib64", "ld-linux-x86-64.so.2"]) + build_path(["/lib64", "ld-linux-x86-64.so.2"]) } } - Architecture::Aarch64(_) => library_path(["/lib", "ld-linux-aarch64.so.1"]), + Architecture::Aarch64(_) => build_path(["/lib", "ld-linux-aarch64.so.1"]), _ => internal_error!( "TODO gracefully handle unsupported linux architecture: {:?}", target.architecture diff --git a/crates/compiler/test_gen/benches/list_map.rs b/crates/compiler/test_gen/benches/list_map.rs index 877957322b0..ff8951cb051 100644 --- a/crates/compiler/test_gen/benches/list_map.rs +++ b/crates/compiler/test_gen/benches/list_map.rs @@ -63,7 +63,7 @@ fn roc_function<'a, 'b>( let context = inkwell::context::Context::create(); let (main_fn_name, errors, lib) = - helpers::llvm::helper(arena, config, source, arena.alloc(context)); + helpers::llvm::helper(arena, config, source, arena.alloc(context), roc_load::FunctionKind::LambdaSet); assert!(errors.is_empty(), "Encountered errors:\n{errors}"); diff --git a/crates/compiler/test_gen/benches/quicksort.rs b/crates/compiler/test_gen/benches/quicksort.rs index 2c02646b492..ba8b2cf21bc 100644 --- a/crates/compiler/test_gen/benches/quicksort.rs +++ b/crates/compiler/test_gen/benches/quicksort.rs @@ -92,7 +92,7 @@ fn roc_function<'a>( let context = inkwell::context::Context::create(); let (main_fn_name, errors, lib) = - helpers::llvm::helper(arena, config, source, arena.alloc(context)); + helpers::llvm::helper(arena, config, source, arena.alloc(context), roc_load::FunctionKind::LambdaSet); assert!(errors.is_empty(), "Encountered errors:\n{errors}"); diff --git a/flake.nix b/flake.nix index a8be3b40e1e..40d9d6b77ee 100644 --- a/flake.nix +++ b/flake.nix @@ -125,9 +125,15 @@ [ ]); LLVM_SYS_130_PREFIX = "${llvmPkgs.llvm.dev}"; + # nix does not store libs in /usr/lib or /lib + # for libgcc_s.so.1 + NIX_LIBGCC_S_PATH = + if pkgs.stdenv.isLinux then "${pkgs.stdenv.cc.cc.lib}/lib" else ""; + # for crti.o, crtn.o, and Scrt1.o NIX_GLIBC_PATH = if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else ""; + LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath ([ pkg-config stdenv.cc.cc.lib libffi ncurses zlib ] From ec3bcb33f60721375483a319b1f8ed79425d14f9 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 8 Aug 2023 20:03:21 +0200 Subject: [PATCH 2/3] fmt, clippy, nix aliases fix --- crates/compiler/build/src/link.rs | 17 +++++++++++++---- crates/compiler/test_gen/benches/list_map.rs | 9 +++++++-- crates/compiler/test_gen/benches/quicksort.rs | 9 +++++++-- flake.nix | 2 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 9231aee0ae0..a9240a916ad 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -880,7 +880,7 @@ fn link_linux( //env::var_os("NIX_GLIBC_PATH").map(|path| path.into_string().unwrap()), //env::var_os("NIX_LIBGCC_S_PATH").map(|path| path.into_string().unwrap()) let nix_paths_vec_string = nix_paths(); - let nix_paths_vec: Vec = nix_paths_vec_string.iter().map(|path_string| PathBuf::from(path_string)).collect(); + let nix_paths_vec: Vec = nix_paths_vec_string.iter().map(PathBuf::from).collect(); let usr_lib_arch_path = strs_to_path(&["/usr", "lib", &architecture]); let lib_arch_path = strs_to_path(&["/lib", &architecture]); @@ -891,7 +891,7 @@ fn link_linux( lib_dirs.extend(nix_paths_vec) } - lib_dirs.extend( [ + lib_dirs.extend([ usr_lib_arch_path, lib_arch_path, strs_to_path(&["/usr", "lib"]), @@ -929,7 +929,13 @@ fn link_linux( let dirs = lib_dirs .iter() - .map(|path_buf| path_buf.as_path().to_str().unwrap_or("FAILED TO CONVERT PATH TO STR").to_string()) + .map(|path_buf| { + path_buf + .as_path() + .to_str() + .unwrap_or("FAILED TO CONVERT PATH TO STR") + .to_string() + }) .collect::>() .join("\n"); eprintln!("We looked in the following directories:\n{dirs}"); @@ -941,7 +947,10 @@ fn link_linux( 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() { - build_path([&nix_glibc_path.into_string().unwrap(), "ld-linux-x86-64.so.2"]) + build_path([ + &nix_glibc_path.into_string().unwrap(), + "ld-linux-x86-64.so.2", + ]) } else { build_path(["/lib64", "ld-linux-x86-64.so.2"]) } diff --git a/crates/compiler/test_gen/benches/list_map.rs b/crates/compiler/test_gen/benches/list_map.rs index ff8951cb051..2aa8243bfdf 100644 --- a/crates/compiler/test_gen/benches/list_map.rs +++ b/crates/compiler/test_gen/benches/list_map.rs @@ -62,8 +62,13 @@ fn roc_function<'a, 'b>( }; let context = inkwell::context::Context::create(); - let (main_fn_name, errors, lib) = - helpers::llvm::helper(arena, config, source, arena.alloc(context), roc_load::FunctionKind::LambdaSet); + let (main_fn_name, errors, lib) = helpers::llvm::helper( + arena, + config, + source, + arena.alloc(context), + roc_load::FunctionKind::LambdaSet, + ); assert!(errors.is_empty(), "Encountered errors:\n{errors}"); diff --git a/crates/compiler/test_gen/benches/quicksort.rs b/crates/compiler/test_gen/benches/quicksort.rs index ba8b2cf21bc..2b786ac8dd6 100644 --- a/crates/compiler/test_gen/benches/quicksort.rs +++ b/crates/compiler/test_gen/benches/quicksort.rs @@ -91,8 +91,13 @@ fn roc_function<'a>( }; let context = inkwell::context::Context::create(); - let (main_fn_name, errors, lib) = - helpers::llvm::helper(arena, config, source, arena.alloc(context), roc_load::FunctionKind::LambdaSet); + let (main_fn_name, errors, lib) = helpers::llvm::helper( + arena, + config, + source, + arena.alloc(context), + roc_load::FunctionKind::LambdaSet, + ); assert!(errors.is_empty(), "Encountered errors:\n{errors}"); diff --git a/flake.nix b/flake.nix index 40d9d6b77ee..4493103d8fe 100644 --- a/flake.nix +++ b/flake.nix @@ -142,7 +142,7 @@ 1; # to run the editor with NVIDIA's closed source drivers shellHook = '' - source <(echo "${aliases}") + ${aliases} ''; }; From cb9a348871956de6ed9c11aae22fae5ad8c47369 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Tue, 8 Aug 2023 20:09:15 +0200 Subject: [PATCH 3/3] cleanup --- crates/compiler/build/src/link.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index a9240a916ad..03c55f767f4 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -876,9 +876,6 @@ fn link_linux( )); } - // Some things we'll need to build a list of dirs to check for libraries - //env::var_os("NIX_GLIBC_PATH").map(|path| path.into_string().unwrap()), - //env::var_os("NIX_LIBGCC_S_PATH").map(|path| path.into_string().unwrap()) let nix_paths_vec_string = nix_paths(); let nix_paths_vec: Vec = nix_paths_vec_string.iter().map(PathBuf::from).collect(); let usr_lib_arch_path = strs_to_path(&["/usr", "lib", &architecture]); @@ -886,7 +883,7 @@ fn link_linux( let mut lib_dirs: Vec = vec![]; - // start with nix paths, this prevents bugs + // start with nix paths, this prevents version incompatibility if !nix_paths_vec.is_empty() { lib_dirs.extend(nix_paths_vec) }