My aim is just to test FFTW on a one dimensional example. I've already installed everything, following the instructions. When I try to compile:
gfortran fftg.f90 -L/usr/local/lib -lfftw3
The terminal is giving the error:
/usr/bin/ld : can't find -lfftw3
I don't understand why because it is installed on my compute and when I'm searching for it, the library of FFTW is here
/usr/local/lib$ ls
cmake libfftw3.a libfftw3.la pkgconfig python2.7 python3.4 R site_ruby
I did not find any answer. Where the error is coming from? For more details, this is my code (taken from http://homepage.ntu.edu.tw/~wttsai/fortran)
program example
implicit none
include 'fftw3.f90'
integer, parameter :: N=16
integer*8 :: PLAN_FOR,PLAN_BAC
real*8,dimension(N) :: IN,OUT,IN2
real*8 :: xj
integer :: j,k,mode
real*8, parameter ::twopi=2.*acos(-1.)
!Discrete data of function f(x)=cos(x)+0.2*sin(2x)
do j=0,N-1
xj=twopi*real(j)/real(N)
IN(j)=cos(xj) +0.2*sin(2.*xj)
end do
write(*,*) "Original data"
do j=1,N
write(*,100) j,IN(j)
end do
100 format(i4,f12.5)
! Forward transform
call dfftw_plan_r2r_1d(PLAN_FOR,N,IN,OUT,FFTW_R2HC,FFTW_ESTIMATE)
call dfftw_execute_r2r(PLAN_FOR,IN,OUT)
OUT=OUT/real(N,KIND=8)
! Normalize
write(*,*) "Fourier coefficient after forward FFT"
do k=1,N
mode=k-1
if(k > N/2+1) mode=N-k+1
write(*,100) mode,OUT(k)
end do
call dfftw_destroy_plan(PLAN_FOR)
end program example
You normally have to setup the paths too, but I see you are using -L/usr/local/lib instead. That should suffice for the linking (not necessarily for running).
But your compiled FFTW is static (.a) and you are compiling dynamically. You can try compiling with -static. If you need to link dynamically you need to install also the dynamic version (.so) of the library (i.e. NOT use -enable-static in configure).
Related
I'm trying to speed up an optimization routine using MKL's blas implementation in fortran. I need to have the result in a shared library so that it is accessible from a larger script. I can compile and link my code without any warnings, but the resulting .so file has an undefined reference to the blas routine I'm trying to call, namely dgemm.
relevant section of the fortran code:
subroutine sumsquares(params, Mx, flen, glen, numr, numcols, g, lambda, res)
implicit none
integer, intent(in):: flen, glen, numr, numcols
real(8), dimension(flen, numcols) :: params
real(8), dimension(flen, numcols) :: g
real(8), dimension(flen, numcols) :: gc
real(8), dimension(flen, glen) :: Mx
gc = -g
call dgemm('N', 'N', flen, glen, numcols, 1, Mx, flen, params, numcols, 1, gc,flen)
return
end subroutine sumsquares
and the corresponding makefile
FC=ifort
LD_LIBRARY_PATH=/opt/intel/composerxe-2011.1.107/compiler/lib/intel64:/opt/intel/composerxe-2011.1.107/mkl/lib/intel64
LIBRARY_PATH=/opt/intel/composerxe-2011.1.107/compiler/lib/intel64:/opt/intel/composerxe-2011.1.107/mkl/lib/intel64
INCLUDE=/opt/intel/composerxe-2011.1.107/mkl/include
FPATH=/opt/intel/composerxe-2011.1.107/mkl/include
CPATH=/opt/intel/composerxe-2011.1.107/mkl/include
FFLAGS=-i8 -I$(MKLROOT)/include/intel64/ilp64 -I$(MKLROOT)/include
LDFLAGS= -shared -nofor-main -fPIC
LINKLIBS=-fPIC -shared -L$(MKLROOT)/lib/intel64 $(MKLROOT)/lib/intel64/libmkl_blas95_ilp64.a -lmkl_rt -lpthread -lm
sumsquares: sumsquares.f90
$(FC) $(FFLAGS) -c -fPIC /opt/intel/composerxe-2011.1.107/mkl/include/blas.f90 -o blas95.o
$(FC) $(FFLAGS) -nofor-main -c -fPIC sumsquares.f90
$(FC) $(LDFLAGS) sumsquares.o $(LINKLIBS) sumsquares.o
As I said, I can run make without any warnings, but when I run nm sumsquares.so | grep dgemm I see U dgemm_, and when I try to load the .so file, I crash with a segfault (while calling an unrelated subroutine, so I don't think it's related to this code). How do I get the linker to put in the relevant function into the so file?
Update
I am loading the so file in an R script by calling dyn.load in R as follows:
Variation 1:
dyn.load("/home/me/path/sumsquares.so")
Variation 2:
dyn.load("/opt/intel/composerxe-2011.1.107/mkl/lib/intel64/libmkl_rt.so")
dyn.load("/home/me/path/sumsquares.so")
Both variations lead to the same result, with a segfault.
Update # 2
I should point out that intel MKL static libaries are compiled with the -fPIC flag, at least according to the documentation. I clearly don't know what I'm doing, but from what I can tell, something like this should be possible.
As blas is used extensively in scientific computing, I am concerned about collisions with different versions. If I'm linking statically within my so file, and load that so file into a program that uses a different blas implementation, would that lead to a collision, or would my library play nice?
If the library is really static, you cannot put in a shared library. Shared object code is compiled in a different way, so that it can work independent of the position. Flags like -fPIC must be used that are not used for static libraries.
Either compile your BLAS with dgemm as a dynamic library and load it before you load your custom library (perhaps the R dyn.load will load the dependencies automatically, I do not know, you can try) or just include the code of DGEMM into your own library and compile everything together into one .so.
Do not forget you have to use the MKL Linking Advisor https://software.intel.com/content/www/us/en/develop/articles/intel-mkl-link-line-advisor.html Do NOT link with the ILP64 library, unless you know what you are doing and have a good reason to do so.
Also, although most of the MKL is shipped with static libraries built using -fPIC, the Fortran 95 interfaces to LAPACK and BLAS are not. The source files for the interfaces are included, so you need to compile them yourself with -fPIC if you want to use them. They are found at $MKLROOT/interfaces/blas95 and $MKLROOT/interfaces/lapack95.
How do I get the linker to put in the relevant function into the so file?
That's not how shared libraries work; you need to ship the so with your other files (and set the appropriate RPATH), or link to a static version of the library.
When you say:
when I try to load the .so file, I crash with a segfault
This sounds like you're trying to directly dlopen() or something similar; just let the dynamic (runtime) linker do its job.
I want to call a C single header library with FFI.
Here's the Nuk.hs
{-# LANGUAGE CPP, ForeignFunctionInterface #-}
module Main where
import Foreign
import Foreign.C.Types
foreign import ccall unsafe "nuklear.h nk_sin"
c_nk_sin:: IO CFloat
main = print $ c_nk_sin (5)
In the same directory, I have the nuklear.h
When I do stack ghc Nuk.hs, I get
[1 of 1] Compiling Main ( Nuk.hs, Nuk.o )
Linking Nuk ...
Nuk.o:r1Rq_info: error: undefined reference to 'nk_sin'
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)
How should I solve this?
If it’s a header-only library, you need a C compiler to produce an object file for it so that your Haskell program can link to the definitions. According to the documentation for Nuklear, you can create a stub C file:
// nuklear.c
#define NK_IMPLEMENTATION
#include "nuklear.h"
As part of your build, compile this (e.g. with gcc -c nuklear.c -o nuklear.o) to produce an object file nuklear.o, use ar (e.g. ar -csr libnuklear.a nuklear.o) to create a static library libnuklear.a, then supposing this archive is in libs, you would add:
extra-lib-dirs: libs
extra-libraries: nuklear
To the executable section in your Cabal file. (Or the corresponding section in package.yml for hpack.)
To coordinate this, you might have a Makefile that builds this library and also invokes stack/cabal/ghc to produce the final build result. This tutorial covers the process in a little more explicit detail. But for this simple use case, you may be able to just use the c-sources section to do this from within Cabal:
c-sources: nuklear.c
You may also need to specify includes and include-dirs, e.g.:
includes: nuklear.h
We are working on the Project which contains thousands of the cmake files. Code is develop on the Linux platform. Now we are porting this project for Windows CE platform.
We are facing lots of linking error when change some of the functionality to project in Linux platform.
We are resolving this linking error by adding respective library in target_link_library of cmake file.
I am surprised how it worked for Linux? And it is failing for Windows CE.
Difference between the platform additional library :
Linux Platform
[A.Common]
[B]
[C]
[C]
[C]
[TLV]
[D]
[Boost.Filesystem]
[Boost.System]
[Boost.Thread]
[Boost.Atomic]
[Boost.DateTime]
[Boost.Chrono]
[Platform.Socket]
[D]
[C]
[C]
[Debug]
[SQLite]
[C]
[C]
[C]
[Meta]
[E]
WinCE
[A.Common]
[B]
[E]
[E]
[E]
[TLV]
[D]
[Boost.Filesystem]
[Boost.System]
[Boost.Thread]
[Boost.Atomic]
[Boost.DateTime]
[Boost.Chrono]
[Platform.Socket]
[D]
[C]
[C]
[Debug]
[SQLite]
[ZLib]
[C]
[C]
[C]
[Meta]
[E]
Any help will be appreciated.
From my experience I can confirm that moving with a CMake project to a new platform is also a check if you have setup your library dependencies correctly.
If we are talking about SHARED libraries, please first confirm that you have correctly exported your function declarations:
Creating and using shared libraries with different compilers on different operating systems
cmake link shared library on Windows
If you are using STATIC libraries, I see two possible approaches (not taking linker errors about missing symbols from system libraries into account):
You may have some if statements checking for this or that platform in your CMake code. So first check that your library dependencies are truly the same by activating GLOBAL_DEPENDS_DEBUG_MODE:
set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_DEBUG_MODE 1)
Put it in your main CMakeList.txt file and compare the output on both platforms.
The linking order is also important, not only that the library is named somewhere on the linker command line. I like to quote from the Beginner's Guide to Linkers:
Another important detail to note is the order of events; the libraries are consulted only when then the normal linking is done, and they are processed in order, left to right. This means that if an object pulled in from a library late in the link line needs a symbol from a library earlier in the link line, the linker won't automatically find it.
Use the following CMake test program to see if your linker does a multi-path scan for open symbols. I've tested it with GCC 4.8.1 (doesn't work) and Visual Studio 2013 (does work). So I don't have your environments, so please do the test yourself.
The program is deliberately setup to have a wrong library linkage order by not using normal library dependencies like target_link_libraries(lib1 lib2) (a rule of thumb is to add as dependecies all libraries you directly include a header file from), but by giving the order in a global list to main:
cmake_minimum_required(VERSION 2.8)
project(WrongLinkOrderTest CXX)
set(_idx 1)
while (_idx LESS 10)
math(EXPR _next_idx "${_idx} + 1")
file(WRITE lib${_idx}.h "int lib${_idx}_func();")
file(WRITE lib${_idx}.cc "#include \"lib${_next_idx}.h\"\nint lib${_idx}_func() { return lib${_next_idx}_func(); }")
add_library(lib${_idx} lib${_idx}.cc)
# NOTE: This would fix it
#target_link_libraries(lib${_idx} lib${_next_idx})
set(_idx "${_next_idx}")
endwhile()
file(WRITE lib${_idx}.h "int lib${_idx}_func();")
file(WRITE lib${_idx}.cc "int lib${_idx}_func() { return 0; }")
add_library(lib${_idx} lib${_idx}.cc)
file(WRITE main.cc "#include \"lib1.h\"\nint main() { return lib1_func(); }")
add_executable(main main.cc)
if (CMAKE_COMPILER_IS_GNUCXX)
#target_link_libraries(main "-Wl,--start-group")
endif()
while (_idx GREATER 0)
math(EXPR _next_idx "${_idx} - 1")
# NOTE: Here it's done wrong
target_link_libraries(main lib${_idx})
set(_idx "${_next_idx}")
endwhile()
if (CMAKE_COMPILER_IS_GNUCXX)
#target_link_libraries(main "-Wl,--end-group")
endif()
By default, it will show the following error with GCC:
liblib1.a(lib1.cc.obj):lib1.cc:(.text+0x7): undefined reference to `lib2_func()'
Uncomment the target_link_libraries(lib${_idx} lib${_next_idx}) or --start-group/--end-group lines to fix it.
Additional References
How do I list the defined make targets from the command line?
Why does the order in which libraries are linked sometimes cause errors in GCC?
GCC: what are the --start-group and --end-group command line options?
Porting code to Windows and getting "error LNK2019: unresolved external symbol ...."
Use -Wl,--start-group and -Wl,--end-group for Android linking
As an alternative to accelerate, I'm trying to call CUDA code over Haskell's FFI.
Here's a simple program that fails to compile:
cuda_code.cu:
void cuda_init() {
cudaFree (0);
cudaThreadSynchronize ();
}
Test.hs:
foreign import ccall unsafe "cuda_init" cuda_init :: IO ()
main = cuda_init
I compiled with
$> nvcc -c -o cuda_code.o cuda_code.cu
$> ghc Test cuda_code.o
and got several linking errors (undefined reference to cudaFree, etc). This isn't terribly surprising, and the obvious solution (to me) is to link with NVCC using -pgml nvcc. (This worked when I was using Intel CILK+ in my C code: I simply changed the linker to ICC, and everything worked just fine.)
Howver, using NVCC to link results in the linking error:
ghc Test -pgml nvcc cuda_code.o
[1 of 1] Compiling Main ( Test.hs, Test.o )
Linking Test ...
nvcc fatal : Unknown option 'u'
Running
strace -v -f -e execve ghc Test -pgml nvcc cuda_code.o
(is there an easier way?) I discovered ghc is calling nvcc with
nvcc ... -L~/ghc... -L... -l... -l... -u ghczmprim_GHC... -u ghc...
I assume the -u options are intended for linking gcc (and apparently icc) with undefined symbols, something nvcc clearly doesn't like.
I have no knowledge about how GHC links files. Thoughts on how I can get GHC to link to my CUDA code?
--------EDIT-----------------
Someone suggested that I try linking with GCC (as usual), but pass in the necessary linker options to gcc so that it can link to the CUDA libraries. If anyone knows what these might be, this would probably work!
GHC uses /usr/lib/ghc/settings to determine compiler and linker options, and per-package files like /var/lib/ghc/package.conf.d/builtin_rts.conf to determine package-specific linker options. (Custom directory installation will have them in ${GHC}/lib/ghc-${VERSION}/settings and ${GHC}/lib/ghc-${VERSION}/package.conf.d respectively.)
Here is what I found for the RTS:
ld-options: -u ghczmprim_GHCziTypes_Izh_static_info -u
ghczmprim_GHCziTypes_Czh_static_info -u
ghczmprim_GHCziTypes_Fzh_static_info -u
ghczmprim_GHCziTypes_Dzh_static_info
...
According to the ld man page, the -u option defines a symbol as an undefined extern that must be defined somewhere else.
As far as I know this is the ONLY package that has these custom -u options in the ld-options: section of package.conf.d.
These must be unfortunately translated for a compiler/linker that uses a different option interface.
Be so kind and keep people posted about it on haskell-cafe#haskell.org. I'm sure there are others trying something like this too!
I figured out how to make this work.
cudaTest.cu:
// the `extern "C"` is important! It tells nvcc to not
// mangle the name, since nvcc assumes C++ code by default
extern "C"
void cudafunc() {
cudaFree(0);
cudaThreadSynchronize();
}
Test.hs
foreign import ccall unsafe "cudafunc" cudaFunc :: IO ()
main = cudaFunc
Compile with:
>nvcc -c -o cudaTest.o cudaTest.cu
>ghc --make Test.hs -o Test cudaTest.o -optl-lcudart
I also tried giving GHC the option -pgmc g++ and removing the extern "C" (which I expected to work), but got compile errors in some CUDA header files. There's probably some easy way to fix this so that you don't need to explicitly tag every function with extern "C".
I'm trying to dynamically load a camera library .so file into a Linux executable to gain access to simple camera functions.
I'm attempting to do this by:
if ( (newHandle = dlopen("./libCamera.so",RTLD_LAZY | RTLD_GLOBAL)) == NULL )
{
printf( "Could not open file : %s\n", dlerror() );
return 1;
}
However this fails and I receive the following output:
"Could not open file : libCamera.so: undefined symbol: ZTVN10_cxxabiv117__class_type_infoE"
How do I find out what symbols it is relying on?
Most likely, libCamera.so uses a symbol defined in a shared library without depending on that library.
Find a culprit. Take a real executable which links against libCamera.so (and it works). List its dependencies with ldd /path/to/executable. Among them should be a library which has a definition for ZTVN10_cxxabiv117__class_type_infoE (use grep to select likely candidates, nm -D on a library to be sure). That library won't be in the list shown by ldd ./libCamera.so.
Solve a problem. Load the library found in step 1 by dlopen first (use RTLD_GLOBAL there as well).
If there is a problem with another symbol, goto step 1.
If newly-added libraries have the same problem too, goto step 1.
Tell library authors to please fix their linking.
It could also happen that one of the prerequisites in ldd ./libCamera.so got upgraded and lost a symbol definition (maybe it was recompiled with a compiler which does name mangling differently). Then you won't find the culprit in step 1, and there is no solution but downgrading something again.
The ldd command can be used to display shared library dependencies.
ldd libCamera.so
Once you know the dependencies, you can use nm to show the symbols in each library.
nm -DC libCamera.so
I had a similar problem. It was to do with a .a library, which should have been linked to my .so and statically linked into the archive being left out.
I determined this with (OP object name used here):
nm mylibrary.so | grep ZTVN10_cxxabiv117__class_type_infoE
0000ABC0 U ZTVN10_cxxabiv117__class_type_infoE
The U here means that the symbol is "undefined". You can find the demangled name of the missing object with --demangle:
$ nm --demangle mylibrary.so | grep 0000ABC0
0000ABC0 U abi::class_type_info(params...)
(or something like that) this should help you figure out which library is missing.
In my case, even after including the library on the compiler line I still had the issue. Eventually, after some tinkering I discovered that the library-file (.a) has to come after its dependent object (.o) file like:
g++ -Wl,-E -g -m32 ... -fPIC myobjects1.o myobjects2.o missing_library.a -shared -o mylibrary.so
Now I get (no more U):
$ nm --demangle mylibrary.so | grep 0000ABC0
0000ABC0 T abi::class_type_info(params...)
and most importantly I don't get the error any more!
In your source code for libCamera.so, you have unresolved external symbol. It means that type_infoE have no definition in your source code and should be resolved.