12

I have a trivial program to test for availability of python development files:

#include<Python.h>
int main(){Py_Initialize(); Py_Finalize(); }

I compile it (with python 2.7 installed) as gcc -I/usr/include/python2.7 -lpython2.7 p.c. It works fine on other machines, except that at mostly-clean chroot of Ubuntu 12.04 (precise) I keep getting

/tmp/ccj8Mgjb.o: In function `main':
p.c:(.text+0x5): undefined reference to `Py_Initialize'
p.c:(.text+0xa): undefined reference to `Py_Finalize'
collect2: ld returned 1 exit status

Headers are installed, /usr/lib/libpython2.7.so exists but the linker nevertheless fails. The symbol is listed in the .so file, and gcc is reading the right libpython2.7.so:

$ nm -D libpython2.7.so.1.0  | grep Py_Initialize
00000000000c9c20 T Py_Initialize
00000000000c9260 T Py_InitializeEx

$ strace -f gcc -I/usr/include/python2.7 -lpython2.7 /tmp/p.c 2>&1 |grep   libpython2.7 |grep open
[pid 10618] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/libpython2.7.so", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 10618] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/libpython2.7.a", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 10618] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libpython2.7.so", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 10618] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libpython2.7.a", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 10618] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../lib/libpython2.7.so", O_RDONLY) = 7

Any ideas?

JJJ
  • 32,902
  • 20
  • 89
  • 102
eudoxos
  • 18,545
  • 10
  • 61
  • 110

4 Answers4

26

Try:

gcc -I/usr/include/python2.7 p.c -lpython2.7 

the linker doesn't yet know that Py_Initialize is a required symbol when it loads libpython2.7.a, so it tosses it away. And then it gets to p.o and throws a fit about the missing symbol. Ordering it this way will let the linker look for the missing symbol in subsequent inputs.

See: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o' searches libraryz' after file foo.o but before bar.o. If bar.o refers to functions in `z', those functions may not be loaded.

yiding
  • 3,482
  • 18
  • 17
  • BTW any idea why it works for other machines? Is that version-dependent behavior? – eudoxos Dec 19 '12 at 12:11
  • It depends on the linker that's being used, I think. But if you put it afterwards it will always work. – yiding Dec 19 '12 at 12:15
  • OK, I just found out that the `gold` linker works, but the old `ldd` from binutils fails. – eudoxos Dec 19 '12 at 12:21
  • I had the same issue building a super simple test program with python. Phil P reminded me of this in the Exim mailing list a while back: "Didn't some recentish release of gcc restore some historical behaviour (of Unix cc) when it comes to symbol resolution and the order of files and libraries on the command-line?" Basically, put the object file before the libraries so the linker knows which functions to include references to. – Todd Lyons May 08 '13 at 16:37
11

I encountered the same linking problem as well. But in my case it was not enough to provide -lpython. Also -L was needed. I.e.

g++ -I/usr/include/python3.5 hw.cpp -L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu -lpython3.5

And yes. Order matters.

Jimilian
  • 3,859
  • 30
  • 33
0

I encountered the same linking problem and personally my problem was that my 32 bit mingw compiler can't load 64 bit python library. I upgrade my mingw to 64 bit and solved my problem. Left a note here in case someone newbie stuck into same problem.

BennyHunag
  • 26
  • 6
0

if with python 3.x installed, maybe this command can work:

g++ hw.cpp `/usr/bin/python3-config --cflags` `/usr/python3-config --ldflags`

By the way, you should check you gcc and python version.

As I know, if gcc version is 5.4 and python version is 3.7, it doesn't work.(python 3.5 is work)

When you run /usr/bin/python3-config --cflags, in fact, it is the compile option.

LittleSec
  • 11
  • 2