Cython not finding shared library - linker

My issue started identical to this one: Python executable not finding libpython shared library
I updated .bashrc with export LD_LIBRARY_PATH=$HOME/local/lib/python/2.7.6/lib and things were fine. Python works, and I installed pip. But now, I'm running into something similar when installing cython with pip. I get this error message when I execute pip install cython:
gcc -pthread -shared build/temp.linux-x86_64-2.7/tmp/pip_build/cython/Cython/Plex/Scanners.o -L. -lpython2.7 -o build/lib.linux-x86_64-2.7/Cython/Plex/Scanners.so
/usr/bin/ld: cannot find -lpython2.7
collect2: ld returned 1 exit status
error: command 'gcc' failed with exit status 1
I cannot add $HOME/local/lib/python/2.7.6/lib to /etc/ld.so.conf and run ldconfig as I do not have root. I was under the impression that setting the LD_LIBRARY_PATH was the way around this, but this appears to not be true for compilation. Is there a way to get the compiler to see this local library without running root commands?

Update:
The LD_LIBRARY_PATH is only used by the dynamic loader at runtime, not at build time, so that is not the issue. The issue is that you forgot to put the -L/path/to/pylib before the -l. I've never had to use LIBRARY_PATH because a build requires path extension that is specific to a given build, so you never set LIBRARY_PATH you just use -L. You would only set if if you are going to regularly do builds that use a specific library, and even then I find it better to use -L because sooner or later this will cause linker to find the wrong lib and by then you will have forgotten that it's because LIBRARY_PATH is set permanently.
There are many ways to set -L values in a build: if you run the compiler from command line you don't need that env var, you just specify as many -L as required as part of the command; if you use a makefile, you edit whatever make variable you are using, such as CFLAGS or other, different platforms have different conventions. So whereas setting -L directly will always work, setting CFLAGS will only work if that is the variable used by the makefile.
Now this is a python installation so where to set this may not be obvious, but I am sure there is another way than setting LIBRARY_PATH. In principle any python package you install, if it involves compilation of C++ modules, could require edit of the setup.py to set library paths. For example
Extension(...,
library_dirs=['/usr/X11R6/lib'],
...)
Since you mention nympy, another place to set this might be in site.cfg (see Supplying NumPy site.cfg arguments to pip).
Old (wrong) answer:
Set your LD_LIBRARY_PATH in your bash console. If this doesn't work then it's because you have the wrong path: check by echoing the environment var.
Once you get that to work, edit your .bashrc or .profile then exit your shell and restart it. Echo the env var to verify that contains the part you added.
Also, ensure that you are appending to the path rather overwriting it:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/...
export LD_LIBRARY_PATH
Because python lib might depend on .so in other folders, if the linker can't find them it may appear as though it is the python lib that was not found. This is not explained on the page you linked to in your question.

OK after some more digging I found this: LD_LIBRARY_PATH vs LIBRARY_PATH
Setting LIBRARY_PATH to the same path as LD_LIBRARY_PATH made the compiler aware of the python lib. cython/numpy/scipy all built and installed no problem afterwords.

Related

Why can my C program run in "git bash", but not in "cmd"?

I wrote a demo using libpq to connect to a PostgreSQL database.
I tried to connect the C file to PostgreSQL by including
#include <libpq-fe.h>
after I added the paths into system variables I:\Program Files\PostgreSQL\12\lib as well as to I:\Program Files\PostgreSQL\12\include and compiled with this command:
gcc -Wall -Wextra -m64 -I "I:\Program Files\PostgreSQL\12\include" -L "I:\Program Files\PostgreSQL\12\lib" testpsql.c -lpq -o testpsql
It first raised three errors, like
libssl-1_1-x64.dll is missing
libintl-8.dll was missing
libcrypto-1_1-x64.dll was missing
After I downloaded these three files and put them into I:\Program Files\PostgreSQL\12\lib, and compiled it again, it shows the error
The application was unable to start correctly (0xc0150002)
when I type testpsql. But if I type ./testpsql on git bash, it works. Anyone can please tell me why?
The code that I used was the first example from here.
Environment: PostgreSQL 12, Windows 10, MinGW64
“Download the DLL files” sounds dangerous. From where?
I would get rid of these files again. Since you probably don't reference these libraries from your code, it must be the dependencies of libpq.dll and are probably found in I:\Program Files\PostgreSQL\12\bin (if you used the EDB installer).
The problem is probably that you the PATH environment variable is different in git bash and in cmd.exe, and in the latter case not all required shared libraries can be found on the PATH. The solution is to change the PATH so that it includes all DLL files the executable requires, not to start copying around files.
It is probably enough to include I:\Program Files\PostgreSQL\12\bin in the PATH. To resolve missing dependencies, use a tool like dependency walker or this replacement.

Where do the pkg-config targets get defined?

When I perform the command
pkg-config --variable pc_path pkg-config
The output is
/usr/lib64/pkgconfig:/usr/share/pkgconfig
However, there are two other pkgconfig directories on my system: /usr/lib/pkgconfig and /usr/local/lib/pkgconfig
If I try
echo $PKG_CONFIG_PATH
the result is
Undefined variable
I also tried to
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
but the response was
export: Command not found.
Now, I have built Gstreamer on multiple occasions and it will put the
metadata files (gstreamer-1.0.pc) into the other pkgconfig folder (usr/local/lib/pkgconfig). (I have been able to overcome this issue by modifying the configure file, changing lib to lib64 at the libdir definition.) But I would rather understand my system rather than try work-arounds.
So two questions: where does the pkg-config program get its target directories?
And why and how do the metadata files get put into a directory that is not apparently indicated by the pkg-config program?
Since the command is not working because that variable was not present
first check that variable is there or not for to do this
execute command
env
root#localhost:/etc/apt# env
if the path is not declare in env
then do something like
root#localhost:/etc/apt# PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
root#localhost:/etc/apt# export PKG_CONFIG_PATH
root#localhost:/etc/apt# echo $PKG_CONFIG_PATH
/usr/local/lib/pkgconfig
root#localhost:/etc/apt# env
Hope this will work for you
for any further help please post the queries with error
When you install a foo package, foo package has an appropriate foo.pc that gets installed in the default pkgconfig directories. If a package puts its *.pc file in a custom location, as you already know, you should set your PKG_CONFIG_PATH accordingly. So, the pkg-config will not only look in the default directories, but also in the custom path you specified in PKG_CONFIG_PATH. This guide explains it well:
pkg-config guide

Linking a library built from source code to a program managed by autotools

I have a c program which needs a library named libnuma to be installed. But I dont have root access in the parallel machine in which I need to run this program. So I downloaded the source code of libnuma and compiled it. I have a libnuma.a file which i assume is the library. I need to link this library with the c program that I have. This program uses autotools for generating the configuration files and the makefile. I am new to autotools. Please tell me what I have to do to link this library without being root.
Ajay.
It should be sufficient to set CPPFLAGS and LDFLAGS. First, try:
$ ./configure LDFLAGS=-L/path/to/lib CPPFLAGS=-I/path/to/include
(where libnuma.a is /path/to/lib/libnuma.a and numa.h is /path/to/include/numa.h.
That is, specify the directories.) If that does not work, check config.log to see what went wrong. If the configure script for the program you are using was built with an old version of autoconf, you may need to do:
$ LDFLAGS=-L/path/to/lib CPPFLAGS=-I/path/to/include ./configure
instead. (The second invocation will only work in Bourne shells. With csh/tcsh, you will need to set the environment variables some other way, for example with env.) You also have the option of making those settings in the environment of your shell (eg, in a .bashrc) or in a config.site file.

Substitute for LD_PRELOAD or LD_LIBRARY_PATH

I'm doing some C programming on a machine for which I don't have root access. I've compiled some shared libraries that I'm linking to, but because I cannot install the libraries in the typical location (/usr/local/lib) I have to explicitly specify the location of the libraries each time I compile and run. When compiling, this simply means adding the -L flag to the gcc command, but for program execution it's a lot more annoying. Either I must add the non-standard directory to LD_LIBRARY_PATH in each session, or I must add LD_PRELOAD=/path/to/libs to the beginning of the execute command.
Is there a better way to do this on a machine for which I don't have root access?
BTW, the machine is running Red Hat 4.1.
There are several solutions, from better to worse:
Use $ORIGIN, e.g. gcc main.o -L../lib -lfoo -Wl,-rpath='$ORIGIN'/../lib
Use target RPATH, e.g. gcc main.o -L../LIB -lfoo -Wl,-rpath=/home/user/lib
Set LD_LIBRARY_PATH from your .bashrc or .profile
Solution 1 allows you to install the binary anywhere, so long as you move the binary and the libraries together, e.g. my-app/bin/a.out and my-app/lib/{needed-shared-libs}.so. It also allows for multiple versions of the application and their set of shared libs.
Solution 2 works fine if you only need one set of shared libs, and never wish to move them around.
Solution 3 affects every application you run, and may cause some of them to bind to your shared libraries instead of the system ones. That may cause them to crash, fail with unresolved symbols, or cause you other pain. To exacerbate, the problem will only happen to you and nobody else, so you'll have hard time getting help for it.
You can add the environment variables to your .bashrc (or whatever file your shell sources when you log-in).
If you set the environment variable LD_RUN_PATH when you compile and link your program, then that search path will be baked in to the executable, and the dynamic linker will search it at runtime.
Using LD_LIBRARY_PATH or LD_PRELOAD is pretty much how to do this. To fix this, rename your program from myprog to myprog-exe, and create a shell script that looks like this called myprog:
#!/bin/sh
export LD_LIBRARY_PATH=/path/to/libs:$LD_LIBRARY_PATH
`dirname $0`/myprog-exe
This way, when someone runs myprog, it will really run the shell script which then runs myprog.

linking libraries -rpath LD_LIBRARY_PATH

I have some 3rd party libraries and includes (I have copied them to the this location /usr/ssd/include and /usr/ssd/lib) that I need to link with my application. I have just created a test application to see if I can link ok. However, when I try to run my app I get the following message.
./app: error while loading shared libraries: libssdn.so: cannot open shared object file: No such file or directory
On the command line I am compiling like this:
gcc -g -Wall -I/usr/ssd/include -L/usr/ssd/lib -lssdn test_app.c -o app
Everything compiles ok, as I don't get any warnings or errors. However, I get the error when I try and run the app.
In the usr/ssd/lib the library is called libssdn.so
I am been looking for solution and I have read something about -rpath, -Wl and LD_LIBRARY_PATH, but not sure what they are and how to include them when I compile.
I am using Ubuntu 9.04 Linux,
Thanks for any advice,
Test if adding /usr/ssd/lib to your $LD_LIBRARY_PATH helps:
In a shell:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/ssd/lib
If that solves the problem, make it permanent by adding /usr/ssd/lib to /etc/ld.so.conf or by running
ldconfig -n /usr/ssd/lib
My personal preference is not to bake the location of a shared object into an executable (which is what -rpath would do).
Instead, you should add /usr/ssd/lib to your LD_LIBRARY_PATH at run time. Assuming you are running bash or a bash like shell, do:
export LD_LIBRARY_PATH=/usr/ssd/lib:${LD_LIBRARY_PATH}
and once you do that, you can run your executable.

Resources