In running an example from the guile handbook I stumbled upon an error while running foreign-library-function. It fails and prints a backtrace stating dlopen failed, because of an invalid elf format of the library. But the library is both present and working in other contexts.
The details to reproduce the issue:
test.scm (taken straight from the manual at https://www.gnu.org/software/guile/manual/guile.html#Foreign-Functions)
(define-module (math bessel)
#:use-module (system foreign)
#:use-module (system foreign-library)
#:export (j0))
(define j0)
(foreign-library-function "libm" "j0"
#:return-type double
#:arg-types (list double))
If I execute guile -s test.scm I get the following output:
;;; note: source file /home/max/projects/guile-tests/test.scm
;;; newer than compiled /home/max/.cache/guile/ccache/3.0-LE-8-4.5/home/max/projects/guile-tests/test.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;; compiling /home/max/projects/guile-tests/test.scm
;;; compiled /home/max/.cache/guile/ccache/3.0-LE-8-4.5/home/max/projects/guile-tests/test.scm.go
Backtrace:
In ice-9/boot-9.scm:
1752:10 8 (with-exception-handler _ _ #:unwind? _ # _)
In unknown file:
7 (apply-smob/0 #<thunk 7f57b930ef60>)
In ice-9/boot-9.scm:
724:2 6 (call-with-prompt _ _ #<procedure default-prompt-handle…>)
In ice-9/eval.scm:
619:8 5 (_ #(#(#<directory (guile-user) 7f57b9307c80>)))
In ice-9/boot-9.scm:
2835:4 4 (save-module-excursion _)
4380:12 3 (_)
In system/foreign-library.scm:
240:6 2 (foreign-library-function "libm" "j0" #:return-type _ # …)
190:25 1 (load-foreign-library _ #:extensions _ # _ #:search-path …)
In unknown file:
0 (dlopen "/usr/lib64/libm.so" 1)
ERROR: In procedure dlopen:
In procedure dlopen: file "/usr/lib64/libm.so", message "/usr/lib64/libm.so: Ungültiger ELF-Header"
To ensure the file in question is actually there here's the output of ls -la /usr/lib64/libm.so:
-rw-r--r-- 1 root root 110 20. Jun 19:52 /usr/lib64/libm.so
The problem also occured for all other libraries I tried to adapt the snippet to.
My current system is running on
openSUSE Tumbleweed 20210723
with Linux kernel 5.22.3
I installed the guile-package using zypper in guile from the official repositories. (currently version 3.0.7)
I heavily suspect that openSUSEs compilation/linking settings could be at fault here, but can neither confirm nor invalidate that theory. - It would be ideal to both know why the issue occurs as well as knowing a workaround.
dlopen: file "/usr/lib64/libm.so"
I don't know anything about Guile, but the problem appears to be that it is trying to dlopen libm.so.
On Linux with GLIBC, libm.so is a linker script, not an ELF file. The real ELF library (and the library guile should be dlopening) is libm.so.6.
You can see that your libm.so (at 110 bytes) is way too small to be an ELF file. If you run file -L /usr/lib64/libm.so*, you should see something like this:
/usr/lib64/libm.so: ASCII text
/usr/lib64/libm.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=07ae52cfc7f4eda1d13383c04564e3236e059993, for GNU/Linux 3.2.0, stripped
Possibly you need to fix system/foreign-library.scm so it dlopens correct library.
The solution to the problem was that libm.so is a linker script, just like the other answer says.
The problem is resolved, if instead of "libm" one passes "libm.so.6" to the function.
The following is the corrected, working snippet.
(define-module (math bessel)
#:use-module (system foreign)
#:use-module (system foreign-library)
#:export (j0))
(define j0)
(foreign-library-function "libm.so.6" "j0"
#:return-type double
#:arg-types (list double))
Related
Context:
I am currently coding the generate-ninja-build.scm script in git commit cb7530e3ff10 of my GPLv3+ project bismon (funded by H2020 research projects). This is contractually some Linux free software project supposed to run on Debian.
That script should become an improvement over the existing shell script bismon/generate-ninja-builder.sh which generates some build.ninja file for the ninja tool (some build automation one).
Question:
The current generate-ninja-build.scm has just (outside of copyright notice comment) :
(use-modules
;; see https://www.gnu.org/software/guile/manual/html_node/Modules.html
(ice-9 posix) ;;;; problematic line, but why ?
(ice-9 readline)
(ice-9 format)
(ice-9 pretty-print)
)
;;;;;;;;;;;;;;;; constants
(define bm-packages '("glib-2.0" "jansson" "gtk+-3.0"))
(define bm-gcc "gcc")
but when I run it as ./generate-ninja-build.scm on my Debian/Sid, whose guile --version gives
guile (GNU Guile) 2.2.4
Packaged by Debian (2.2.4-deb+1-3)
I am getting:
rimski.x86_64 ~/bismon 8:17 .0 % ./generate-ninja-build.scm
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;; or pass the --no-auto-compile argument to disable.
;;; compiling /home/basile/bismon/./generate-ninja-build.scm
;;; WARNING: compilation of /home/basile/bismon/generate-ninja-build.scm failed:
;;; no code for module (ice-9 posix)
Backtrace:
9 (primitive-load "/home/basile/bismon/./generate-ninja-b…")
In ice-9/eval.scm:
721:20 8 (primitive-eval (use-modules (ice-9 posix) (ice-9 #) # …))
In ice-9/psyntax.scm:
1235:36 7 (expand-top-sequence ((use-modules (ice-9 posix) (…) …)) …)
1182:24 6 (parse _ (("placeholder" placeholder)) ((top) #(# # …)) …)
285:10 5 (parse _ (("placeholder" placeholder)) (()) _ c&e (eval) …)
In ice-9/boot-9.scm:
3377:20 4 (process-use-modules _)
222:17 3 (map1 (((ice-9 posix)) ((ice-9 readline)) ((ice-9 #)) #))
3378:31 2 (_ ((ice-9 posix)))
2803:6 1 (resolve-interface _ #:select _ #:hide _ #:prefix _ # _ …)
In unknown file:
0 (scm-error misc-error #f "~A ~S" ("no code for modu…" …) …)
ERROR: In procedure scm-error:
no code for module (ice-9 posix)
however the output of locate ice-9/posix includes:
/usr/lib/x86_64-linux-gnu/guile/2.0/ccache/ice-9/posix.go
/usr/lib/x86_64-linux-gnu/guile/2.2/ccache/ice-9/posix.go
/usr/share/guile/2.0/ice-9/posix.scm
/usr/share/guile/2.2/ice-9/posix.scm
So I was expecting the (ice-9 posix) line to work. If I comment that line, everything works as I want.
My ~/.guile just has:
;; file ~/.guile
(use-modules
(ice-9 readline)
(ice-9 format)
(ice-9 pretty-print))
(activate-readline)
and my interactive guile works like a charm with the expected fancy GNU readline and autocompletion interface.
What am I doing wrong?
sudo apt install guile-2.2-dev guile-2.0-dev guile-1.8-dev
Consider use Guix instead Debian. All develop dependencies is install by default in replace of Python. http://guix.gnu.org/
I couldn't find any mention of a (ice-9 posix) module in the guile 2.2 documentation, and while the appropriate file exists in the source tree, the modules/ice-9 directory README says
The non-module files are:
boot-9.scm -- loaded on guile startup
...
posix.scm -- loaded by boot-9.scm
You can't load it because it's not a module file intended to be loaded by user code. Same thing applies at least as far back as guile 1.8, so if you found some documentation or tutorial somewhere including an attempt to load a module by that name, it's simply wrong.
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).
I run ./myprogram and it gives me a warning:
Warning: Your program was compiled with SimGrid version 3.13.90, and then linked against SimGrid 3.13.0. Proceeding anyway.
Tryldd myprogram and it gives following:
libsimgrid.so.3.13.90 => /usr/lib/libsimgrid.so.3.13.90 (0x00007f338ef47000)
Then I go to usr/lib and type ll *sim* in terminal:
lrwxrwxrwx 1 ken ken 21 июл 28 19:29 libsimgrid.so -> libsimgrid.so.3.13.90*
-rwxrwxr-x 1 ken ken 12307480 июл 28 19:29 libsimgrid.so.3.13.90*
In CMakeLists.txt I link library simgrid in such way:
target_link_libraries(CSim2Sim simgrid)
Why myprogram still links against SimGrid 3.13.0 (it doesn't exist in /usr/lib while SimGrid 3.13.90 does)?
UPDATE:
Command locate libsimgrid.so in ternimal gives:
/home/ken/Downloads/simgrid-master/lib/libsimgrid.so
/home/ken/Downloads/simgrid-master/lib/libsimgrid.so.3.13.90
/home/ken/SimGrid/lib/libsimgrid.so
/home/ken/SimGrid/lib/libsimgrid.so.3.13.90
/usr/lib/libsimgrid.so
/usr/lib/libsimgrid.so.3.13.90
The message seems buggy, it looks like your application was actually compiled with 3.13.0, and linked to libsimgrid 3.13.90. The order was inverted in the message, I will fix that.
It could be a problem with your includes when you compile your code, I think. Please check that you don't use old versions of msg.h/simgrid_config.h files when you compile your app (maybe there are still one in /usr/include ?).
To check, you can look for SIMGRID_VERSION_PATCH in simgrid_config.h. it should be 90 in a recent one, not 0.
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
I have a problem with a shared library (Linux) and a program that links against this library but does not find the symbols - although they are there. That's what I have:
A shared library "libetest.so" that is located in /usr/lib. When I do an
readelf -Ws /usr/lib/libetest.so.0
it gives (beside some others) this output:
54: 000052c0 905 FUNC LOCAL DEFAULT 11 ETEST_open_connection
Now I have an application that makes use of ETEST_open_connection(). When I build it with
gcc lib_test.cpp -DENV_LINUX -letest
it fails with a linker error
lib_test.cpp:(.text+0x32): undefined reference to `ETEST_open_connection'
As shown before the symbol is there! Any idea why this fails?
Please try:
gcc -DENV_LINUX -letest lib_test.cpp
This should be the correct argument order.