How to fix linking error for linxal crate in Rust? - rust

I tried running the example I found in the linxal crate for calculating eigenvalues, as follows:
#[macro_use]
extern crate linxal;
extern crate ndarray;
use linxal::eigenvalues::{Eigen};
use linxal::solve_linear::{SolveLinear};
use linxal::types::{c32};
use ndarray::{arr1, arr2};
fn main() {
let m = arr2(&[[1.0f32, 2.0],
[-2.0, 1.0]]);
let r = Eigen::compute(&m, false, false);
assert!(r.is_ok());
let r = r.unwrap();
let true_evs = arr1(&[c32::new(1.0, 2.0), c32::new(1.0, -2.0)]);
assert_eq_within_tol!(true_evs, r.values, 0.01);
let b = arr1(&[-1.0, 1.0]);
let x = SolveLinear::compute(&m, &b).unwrap();
let true_x = arr1(&[-0.6, -0.2]);
assert_eq_within_tol!(x, true_x, 0.0001);
}
The code above panicked with the following error:
= note: /usr/bin/ld: cannot find -lgfortran
So I installed gfortran and lapack:
sudo apt-get install gfortran libblas-dev liblapack-dev
Now the error is different:
= note: /usr/bin/ld: /home/marcelo/dev/rust/tests/target/debug/deps/tests-8044bb79540c2a73.1gluatgbtgjkbw4v.rcgu.o: in function `lapack::c::sgeev':
/home/marcelo/.cargo/registry/src/github.com-1ecc6299db9ec823/lapack-0.11.4/src/c.rs:1078: undefined reference to `LAPACKE_sgeev'
/usr/bin/ld: /home/marcelo/dev/rust/tests/target/debug/deps/tests-8044bb79540c2a73.1gluatgbtgjkbw4v.rcgu.o: in function `lapack::c::sgesv':
/home/marcelo/.cargo/registry/src/github.com-1ecc6299db9ec823/lapack-0.11.4/src/c.rs:1882: undefined reference to `LAPACKE_sgesv'
collect2: error: ld returned 1 exit status
= help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
= note: use the `-l` flag to specify native libraries to link
= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
I then installed LAPACKE with the following commands, but the error message did not change.
= note: /usr/bin/ld: /home/marcelo/dev/rust/tests/target/debug/deps/tests-8044bb79540c2a73.1gluatgbtgjkbw4v.rcgu.o: in function `lapack::c::sgeev':
/home/marcelo/.cargo/registry/src/github.com-1ecc6299db9ec823/lapack-0.11.4/src/c.rs:1078: undefined reference to `LAPACKE_sgeev'
/usr/bin/ld: /home/marcelo/dev/rust/tests/target/debug/deps/tests-8044bb79540c2a73.1gluatgbtgjkbw4v.rcgu.o: in function `lapack::c::sgesv':
/home/marcelo/.cargo/registry/src/github.com-1ecc6299db9ec823/lapack-0.11.4/src/c.rs:1882: undefined reference to `LAPACKE_sgesv'
collect2: error: ld returned 1 exit status
= help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
= note: use the `-l` flag to specify native libraries to link
= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
The commands:
sudo apt update
sudo apt install liblapack3
sudo apt install liblapack-dev
sudo apt install libopenblas-base
sudo apt install libopenblas-dev
sudo apt install liblapacke-dev
sudo apt install liblapack-dev
What do I have to do to make the example work?
Thanks in advance!

Related

Cross compile shared library for armv5te-unknown-linux-gnueabi Rust [Mindstorm Ev3dev]

Parameters:
source = x86_x64 windows 10 or x86_x64 linux (ubuntu wsl)
target = armv5te linux
target_type = cdylib
target_glibc = 2.24
language = rust
build_tool = cargo
compiler = rustc
(The target is a Lego Mindstorm running a linux image from Ev3dev)
Cargo Configuration:
[package]
name = "ev3"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
jni = "0.19"
ev3dev-lang-rust = { version = "0.12.1", features=["screen"]}
jni_proc_macro= {path= "./jni_proc_macro"}
[lib]
crate-type= ["cdylib"]
[workspace]
members= ["jni_proc_macro"]
Build Configuration:
[build]
target = "armv5te-unknown-linux-gnueabi"
[target.armv5te-unknown-linux-gnueabi]
linker = "rust-lld"
Build Error:
error: linking with `rust-lld` failed: exit code: 1
|
= note: {...}
= note: rust-lld: error: unable to find library -lgcc_s
rust-lld: error: unable to find library -lutil
rust-lld: error: unable to find library -lrt
rust-lld: error: unable to find library -lpthread
rust-lld: error: unable to find library -lm
rust-lld: error: unable to find library -ldl
rust-lld: error: unable to find library -lc
error: could not compile `ev3` due to previous error
As the error suggests the linker is missing libraries. I found no clear solution where I can download and or provide these dependencies.
My question is, A is there a diffrent way to build this successfully or B how do I solve these dependencies.
The result needs to be a shared library (.so) for linux and armv5te
Requirements
wsl or linux installed
cargo and rustc installed
(everthing is done in wsl/linux)
Prep/Build
Install cross on cargo
cargo install cross --git https://github.com/cross-rs/cross
Install docker
Clone the cross repository
Navigate into the docker folder
Create a new file with the name "Dockerfile.armv5te-unknown-linux-gnueabi-cross"
Paste this in the new file:
FROM ubuntu:16.04
ARG DEBIAN_FRONTEND=noninteractive
COPY common.sh lib.sh /
RUN /common.sh
COPY cmake.sh /
RUN /cmake.sh
COPY xargo.sh /
RUN /xargo.sh
RUN apt-get update && apt-get install --assume-yes --no-install-recommends \
g++-arm-linux-gnueabi \
crossbuild-essential-armel \
libc6-dev-armel-cross
COPY deny-debian-packages.sh /
RUN TARGET_ARCH=armel /deny-debian-packages.sh \
binutils \
binutils-arm-linux-gnueabi
# Qemu is disabled since we've changed the scripts to require newer Python versions.
#COPY qemu.sh /
#RUN /qemu.sh arm
COPY qemu-runner base-runner.sh /
ENV CROSS_TOOLCHAIN_PREFIX=arm-linux-gnueabi-
ENV CROSS_SYSROOT=/usr/arm-linux-gnueabi
ENV CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_GNUEABI_LINKER="$CROSS_TOOLCHAIN_PREFIX"gcc \
CARGO_TARGET_ARMV5TE_UNKNOWN_LINUX_GNUEABI_RUNNER="/qemu-runner arm" \
AR_armv5te_unknown_linux_gnueabi="$CROSS_TOOLCHAIN_PREFIX"ar \
CC_armv5te_unknown_linux_gnueabi="$CROSS_TOOLCHAIN_PREFIX"gcc \
CXX_armv5te_unknown_linux_gnueabi="$CROSS_TOOLCHAIN_PREFIX"g++ \
BINDGEN_EXTRA_CLANG_ARGS_armv5te_unknown_linux_gnueabi="--sysroot=$CROSS_SYSROOT" \
QEMU_LD_PREFIX="$CROSS_SYSROOT" \
RUST_TEST_THREADS=1 \
PKG_CONFIG_PATH="/usr/lib/arm-linux-gnueabi/pkgconfig/:${PKG_CONFIG_PATH}"
Make sure the project uses "LF" newlines. if not this fixes it.
Compile the custom cross/docker build using the following command in the root of the cloned repository:
cargo build-docker-image armv5te-unknown-linux-gnueabi-cross
This will create a new docker image that will be used to compile the rust code.
Then navigate to your target project folder and run:
export CROSS_TARGET_ARMV5TE_UNKNOWN_LINUX_GNUEABI_IMAGE=ghcr.io/cross-rs/armv5te-unknown-linux-gnueabi-cross:local
(Do not close this terminal)
Now add the following to the Cargo.toml file:
[package.metadata.cross.build]
default-target = "armv5te-unknown-linux-gnueabi"
now you can run:
cross build
Many cargo options like "--release" can be used (for more info have a look at cross in the credits)
Credits
MeetTitan(Stackoverflow) who recomended me to use cross
Cross project(GitHub) which powers the whole solution
Custom cross version discussion(Cross Github)
Alexhuszagh(Cross Github) who showed me how to build a custom cross version
Emilgardis(Cross Github) who explained the newline bug

How to compile lapack with rust

I am trying to use lapack with rust. Therefore I started with the example from the rust crates https://crates.io/crates/lapack
My Cargo.toml file looks like
enter [package]
name = "matmul"
version = "0.1.0"
edition = "2021"
[dependencies]
lapack = "0.19.0"
[profile.dev]
opt-level = 0
[profile.release]
opt-level = 3
When trying to compile I get the following error
error: linking with `cc` failed: exit status: 1
|
= note: "cc" "-m64"
then there is a file list
"-Wl,--gc-sections" "-pie" "-Wl,-zrelro,-znow" "-nodefaultlibs"
= note: /usr/bin/ld: ~/programs/Rust/matmul/target/debug/deps/matmul-9ca04f70dc77cf78.3ybb6pvq2ip54xxg.rcgu.o: in function `lapack::dsyev':
~/.cargo/registry/src/github.com-1ecc6299db9ec823/lapack-0.19.0/src/lapack-sys.rs:29108: undefined reference to `dsyev_'
collect2: error: ld returned 1 exit status
= help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
= note: use the `-l` flag to specify native libraries to link
= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
error: could not compile `matmul` due to previous error
Am I missing some dependencies or why does this code not compile?
Looks like your gnu linker is stuck - not uncommon. I see cc, so I’m guessing this is a Cray. You need to make sure you have the correct modules loaded and possibly figure out where lapack lives. Typically, this is cray-libsci (if I remember correctly). Then, you may need to tell cargo explicitly as suggested in the error message: cargo:rustc-link-lib.
Does that help?

Compiling curl-sys on x86_64-pc-windows-gnu fails with undefined reference to '__imp___acrt_iob_func'

I'm trying to install wasm-pack on Windows using the x86_64-pc-windows-gnu target (can't use msvc) and the build fails because of a linker error (undefined reference to '__imp___acrt_iob_func').
After a little research I found this issue, so I changed my .cargo/config.
[target.x86_64-pc-windows-gnu]
linker = "c:/msys64/mingw64/bin/gcc.exe"
ar = "c:/msys64/mingw64/bin/ar.exe"
[target.i686-pc-windows-gnu]
linker = "c:/msys64/mingw32/bin/gcc.exe"
ar = "c:/msys64/mingw32/bin/ar.exe"
But the problem persists. Is there anything else to be done here?

Statically linking ffmpeg-sys on Amazon Linux fails with undefined references

My project depends on the ffmpeg-sys crate which is configured to build statically, as follows:
[dependencies.ffmpeg-sys]
version = "3.4.1"
default-features = false
features = ["avcodec", "avformat", "swresample", "build", "static"]
My project consists of a single simple file:
extern crate ffmpeg_sys;
use ffmpeg_sys::av_register_all;
fn main() {
unsafe { av_register_all() };
println!("Hello, world!");
}
When compiling with cargo build I get the following error:
Compiling sample v0.1.0 (file:///home/ec2-user/sample)
error: linking with 'cc' failed: exit code: 1 | = note: "cc"
"-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L"
[... elided for clarity ...]
In function 'sample::main::hbbb19855251826d6':
/home/ec2-user/sample/src/main.rs:6: undefined reference to 'av_register_all'
collect2: error: ld returned 1 exit status
The required static libraries, libavformat.a and friends, are found in the target/build/debug folder, showing that ffmpeg-sys successfully compiled the libraries.
Here's the rustc command that is failing:
Caused by: process didn't exit successfully: 'rustc --crate-name
sample src/main.rs --crate-type bin --emit=dep-info,link -C
debuginfo=2 -C metadata=250bf40eb277d05a -C
extra-filename=-250bf40eb277d05a --out-dir
/home/ec2-user/sample/target/debug/deps -C
incremental=/home/ec2-user/sample/target/debug/incremental -L
dependency=/home/ec2-user/sample/target/debug/deps --extern
ffmpeg_sys=/home/ec2-user/sample/target/debug/deps/libffmpeg_sys-fa3ff87f80f2d27e.rlib
-L native=/home/ec2-user/sample/target/debug/build/ffmpeg-sys-0b3c813f29a9a20e/out/dist/lib'
(exit code: 1)
libffmpeg_sys-fa3ff87f80f2d27e.rlib is 207M and I assume therefore contains all the statically compiled ffmpeg code.
This only happens when I build on an Amazon Linux instance. Compiling on my regular Fedora 28 desktop results in a working binary.
How would I go about figuring out the root cause of this error?
I solved this problem by building llvm 6.0.1 and then rebuilding with LIBCLANG_PATH set to point to the newer version.
It would appear that rustc has a minimum version requirement on libclang.so, but I could not find an official source documenting that. The version installed on amazon-linux is 3.6.2 which is evidently too old.

linking SDL2 libraries with pkg-config

I am using Ubuntu 14.04LTS. I have installed the SDL2 libraries both by compiling from source (method1 https://askubuntu.com/questions/344512/what-is-the-general-procedure-to-install-development-libraries-in-ubuntu) and using sudo apt-get install libsdl2-dev.
As I understand, the former installed the libraries and headers in /usr/local/(lib and include), while the latter installs them system wide in /usr/(lib and include).
When I tried to compile a simple code to test the functionality:
#include <SDL.h>
#include <stdio.h>
int main(int argc, char* argv[]) {SDL_Window *window;
// Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"An SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
// The window is open: could enter program loop here (see SDL_PollEvent())
SDL_Delay(3000); // Pause execution for 3000 milliseconds, for example
// Close and destroy the window
SDL_DestroyWindow(window);
// Clean up
SDL_Quit();
return 0;
using: g++ sdl_test.cpp -o sdlout
the compiler outputs:
sdltest.cpp:2:17: fatal error: SDL.h: No such file or directory
#include <SDL.h>
^
compilation terminated.
if I change to #include <SDL2/SDL.h> I get the following error:
/tmp/cc05JSKn.o: In function `main':
sdltest.cpp:(.text+0x15): undefined reference to `SDL_Init'
sdltest.cpp:(.text+0x3a): undefined reference to `SDL_CreateWindow'
sdltest.cpp:(.text+0x4a): undefined reference to `SDL_GetError'
sdltest.cpp:(.text+0x6d): undefined reference to `SDL_Delay'
sdltest.cpp:(.text+0x79): undefined reference to `SDL_DestroyWindow'
sdltest.cpp:(.text+0x7e): undefined reference to `SDL_Quit'
collect2: error: ld returned 1 exit status
Which are the basic functions, so I assume that the shared object libraries are not linked correctly.
I also tried: g++ -Wall sdltest.cpp -o outsdl -I /usr/local/include -L /usr/local/lib
to specify the paths, but again I get:
sdltest.cpp:2:17: fatal error: SDL.h: No such file or directory
#include <SDL.h>
^
compilation terminated.
The only command that worked and successfully compiled, is when using pkg-config g++ sdltest.cpp -o outsdl $(pkg-config --cflags --libs sdl2)
Therefore, I have the following questions:
1) Why is pkg-config necessary and how do compilation and linking flags work?
2) Is it possible to do something else in order to make the compilation command simpler?
3) (if not explained previously) What is the difference between pkg-config and using -I and -L which do not work?
4) what does $(...) actually do in the command line and is it completely the same as `...` ?
Thank you.
The pkg-config command is a more-or-less cross-platform or cross-distro way to provide the correct flags to your compiler to allow it to find header and library files. That way, your system can store files in different locations and everyone can use the same commands to compile your code. It also helps resolve any special requirements of the library you're trying to use.
Using $() is the same as using backticks, so you can execute what is inside the parentheses in order to see what extra arguments are being passed to your compiler to make it work. Here is what I get on my machine when I run pkg-config --cflags --libs sdl2:
-D_REENTRANT -I/usr/include/SDL2 -lSDL2
The reason you're getting SDL.h: No such file or directory is because pkg-config adds -I/usr/include/SDL2 to the include search paths so you can include SDL.h in your code (without the SDL2 subdirectory).
The reason you get undefined reference errors is because you don't have -lSDL2 (which tells the compiler to link libSDL2).

Resources