0xcafed00d / tac08

tac08 is an an emulation of the runtime part of the Pico-8 fantasy console. It takes a .p8 (text format) pico-8 cart file and runs it as closely posible
MIT License
197 stars 21 forks source link

link error #2

Closed mogenson closed 5 years ago

mogenson commented 5 years ago

I'm having a hard time linking liblua.a during the build process.

$ make
...
g++ bin/main.o bin/hal_core.o bin/hal_palette.o bin/hal_audio.o bin/pico_core.o bin/pico_audio.o bin/pico_memory.o bin/pico_data.o bin/pico_script.o bin/pico_cart.o bin/utf8-util.o bin/utils.o bin/log.o bin/crypt.o -L/usr/lib -lSDL2 -Lsrc/z8lua -llua -o tac08
/usr/bin/ld: bin/pico_script.o: in function `dbg_hookfunc(lua_State*, lua_Debug*)':
pico_script.cpp:(.text+0xa7): undefined reference to `lua_getstack(lua_State*, int, lua_Debug*)'
...
# 100 or so additional undefined reference errors from pico_script.cpp

But I can see that those symbols exist in liblua.a

$ nm -g src/z8lua/liblua.a | c++filt | grep lua_getstack
0000000000000540 T lua_getstack(lua_State*, int, lua_Debug*)
                 U lua_getstack(lua_State*, int, lua_Debug*)
                 U lua_getstack(lua_State*, int, lua_Debug*)
                 U lua_getstack(lua_State*, int, lua_Debug*)

The linker flags are the makefile default

LUA_LIB =  -Lsrc/z8lua -llua
LDFLAGS = $(SDL_LIB) $(LUA_LIB)

I'm on x86-64 Linux, GCC 9.1.0, binutils 2.32.

0xcafed00d commented 5 years ago

Thats very odd. I'm building with GCC 7.4.0 on ubuntu 18.04, I'll upgrade to the lastest GCC tonight to see if I can replicate the problem.

mogenson commented 5 years ago

I can confirm that everything works on a Ubuntu 18.04 VM. My main machine is on Arch Linux so something with GCC/binutils or the Linux distro is causing the link error.

0xcafed00d commented 5 years ago

I've upgraded to gcc9.1 and bintools 2.32 (fun) and it still builds fine. do you happen to have another liblua.a somewhere in your include path? cant really think what else it could be

0xcafed00d commented 5 years ago

could you run the link step under strace and attach the output, (out.txt)

strace -f -o out.txt -e trace=%file g++ bin/*.o -L/usr/local/lib -lSDL2 -Lsrc/z8lua -llua  -o tac08

should help determine if its failing to open the .a file

mogenson commented 5 years ago

Found the issue:

Changing SDL_PATH_LIB = /usr/lib and SDL_PATH_INC = /usr/include (where the sdl2 shared library is installed on Arch Linux) breaks the linking. Perhaps ld doesn't like multiple -L flags? Maybe the name of the sdl2 shared library (libSDL2.so) is different?

It's curious that the errors are about liblua. Anyways, I can take a full strace later if you still need it.

0xcafed00d commented 5 years ago

its all very strange. from the man page for ld:

-L searchdir --library-path=searchdir Add path searchdir to the list of paths that ld will search for archive libraries and ld control scripts. You may use this option any number of times.

If you could get a chance to do the strace it may help a bit.

mogenson commented 5 years ago

I've attached two strace files. One for a successful build specifying the SDL_PATH as /usr/local/lib and one for a failed build with the SDL_PATH set to /usr/lib.

The successful build first looks for libSDL2.so in /usr/local/lib and eventually finds it in /usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../lib/, which is /usr/lib. It then looks for liblua.so first in /usr/local/lib then finds it in src/z8lua

openat(AT_FDCWD, "/usr/local/lib/libSDL2.so", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/lib/libSDL2.a", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "src/z8lua/libSDL2.so", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "src/z8lua/libSDL2.a", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0/libSDL2.so", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0/libSDL2.a", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../lib/libSDL2.so", O_RDONLY) = 21
openat(AT_FDCWD, "/usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../lib/libSDL2.so", O_RDONLY) = 22
openat(AT_FDCWD, "/usr/local/lib/liblua.so", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/lib/liblua.a", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "src/z8lua/liblua.so", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "src/z8lua/liblua.a", O_RDONLY) = 22

The failed build looks for libSDL2.so and liblua.so first in /usr/lib and finds both. So we're failing because were trying to link against /usr/lib/liblua.so not /src/z8lua/liblua.a. It doesn't seem likeld` is respecting the LUA_LIB path.

openat(AT_FDCWD, "/usr/lib/libSDL2.so", O_RDONLY) = 21
openat(AT_FDCWD, "/usr/lib/libSDL2.so", O_RDONLY) = 22
openat(AT_FDCWD, "/usr/lib/liblua.so", O_RDONLY) = 22
openat(AT_FDCWD, "/usr/lib/liblua.so", O_RDONLY) = 23

strace-good.txt strace-fail.txt

0xcafed00d commented 5 years ago

Thanks for taking the time to investigate this. I have renamed liblua.a to libluaz8.a so it shouldn't happen again.