As the commenters said, you need to link to libgfortran
.
Specifically, in the Rust world, you should use (or create) a *-sys
package that details the appropriate linking steps and exposes the base API. Then build higher-level abstractions on top of that.
However, I didn't seem to need to do any of that:
timer.f90
subroutine timer(ttime)
double precision ttime
temp = sngl(ttime)
call cpu_time(temp)
ttime = dble(temp)
return
end
Cargo.toml
[package]
name = "woah"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
build = "build.rs"
[dependencies]
libc = "*"
build.rs
fn main() {
println!("cargo:rustc-link-lib=dylib=timer");
println!("cargo:rustc-link-search=native=/tmp/woah");
}
src/main.rs
extern crate libc;
use libc::{c_double};
extern "C" {
pub fn timer_(d: *mut c_double);
}
fn main() {
let mut value = 0.0;
unsafe { timer_(&mut value); }
println!("The value was: {}", value);
}
And it's put together via
$ gfortran-4.2 -shared -o libtimer.dylib timer.f90
$ cargo run
The value was: 0.0037589999847114086
Which seems to indicate that this shared library either doesn't need libgfortran
or it's being automatically included.
If you create a static library instead (and link to it appropriately via cargo:rustc-link-lib=dylib=timer
):
$ gfortran-4.2 -c -o timer.o timer.f90
$ ar cr libtimer.a *.o
$ cargo run
note: Undefined symbols for architecture x86_64:
"__gfortran_cpu_time_4", referenced from:
_timer_ in libtimer.a(timer.o)
In this case, adding gfortran
allows the code to compile:
println!("cargo:rustc-link-lib=dylib=gfortran");
Disclaimer: I've never compiled Fortran before, so it's very likely I've done something silly.