domeengine/dome

Linking fails on ElementaryOS / Raspberry PI

Closed this issue · 4 comments

Hi, I know this is not the most popular platform :)

The output of uname -a is

Linux pi400 5.4.0-1045-raspi #49-Ubuntu SMP PREEMPT Wed Sep 29 17:49:16 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux

ElementaryOS is Ubuntu-based, 64 bit.

The last message when running either make or CC=clang CXX=clang++ make -e is

==== Linking DOME (64bit linux release   shared) ====
clang -DDOME_HASH=\"a502a22\" -DDOME_VERSION=\"v1.6.1\" -std=c99 -pedantic -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-value -Wno-clobbered -Wno-maybe-uninitialized -Wno-attributes -fvisibility=hidden -O3  -o dome obj/64bit/*.o  -Llib  -lSDL2  -Wl,--wrap=log,--wrap=log2,--wrap=exp,--wrap=pow,--wrap=expf,--wrap=powf,--wrap=logf -lm -lwren 
/usr/bin/ld: obj/64bit/glibc_compat.o: in function `__wrap_pow':
glibc_compat.c:(.text+0x0): undefined reference to `pow@GLIBC_2.2.5'
/usr/bin/ld: obj/64bit/glibc_compat.o: in function `__wrap_exp':
glibc_compat.c:(.text+0x4): undefined reference to `exp@GLIBC_2.2.5'
/usr/bin/ld: obj/64bit/glibc_compat.o: in function `__wrap_log':
glibc_compat.c:(.text+0x8): undefined reference to `log@GLIBC_2.2.5'
/usr/bin/ld: obj/64bit/glibc_compat.o: in function `__wrap_log2':
glibc_compat.c:(.text+0xc): undefined reference to `log2@GLIBC_2.2.5'
/usr/bin/ld: obj/64bit/glibc_compat.o: in function `__wrap_logf':
glibc_compat.c:(.text+0x1c): undefined reference to `logf@GLIBC_2.2.5'
/usr/bin/ld: obj/64bit/glibc_compat.o: in function `__wrap_powf':
glibc_compat.c:(.text+0x3c): undefined reference to `powf@GLIBC_2.2.5'
/usr/bin/ld: obj/64bit/glibc_compat.o: in function `__wrap_expf':
glibc_compat.c:(.text+0x58): undefined reference to `expf@GLIBC_2.2.5'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:196: dome] Fehler 1

This looks like a missing -lm. But invoking the linker command with an added -lm gives the same error.

I've unfortunately not tried to compile DOME myself on raspberry pi and ARM architecture hosts, but a couple members of the community have managed it. It requires a few modifications to the build process for DOME as well as Wren, from what I understand.

Hi @avivbeeri, thank you for your answer. I will look around for hints on how to proceed.

Trying another from my collection of aging machines, this time a laptop with i386-based Raspberry Pi Desktop. Same error in the link step when invoking with ARCH=32bit make -e:

==== Linking DOME (32bit linux release   shared) ====
cc -DDOME_HASH=\"a502a22\" -DDOME_VERSION=\"v1.6.1\" -std=c99 -pedantic -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-value -Wno-clobbered -Wno-maybe-uninitialized -Wno-attributes -fvisibility=hidden -O3  -o dome obj/32bit/*.o  -Llib  -lSDL2  -Wl,--wrap=log,--wrap=log2,--wrap=exp,--wrap=pow,--wrap=expf,--wrap=powf,--wrap=logf -lm -lwren 
/usr/bin/ld: obj/32bit/glibc_compat.o: in function `__wrap_pow':
glibc_compat.c:(.text+0x20): undefined reference to `pow@GLIBC_2.2.5'
/usr/bin/ld: obj/32bit/glibc_compat.o: in function `__wrap_exp':
glibc_compat.c:(.text+0x48): undefined reference to `exp@GLIBC_2.2.5'
/usr/bin/ld: obj/32bit/glibc_compat.o: in function `__wrap_log':
glibc_compat.c:(.text+0x78): undefined reference to `log@GLIBC_2.2.5'
/usr/bin/ld: obj/32bit/glibc_compat.o: in function `__wrap_log2':
glibc_compat.c:(.text+0xa8): undefined reference to `log2@GLIBC_2.2.5'
/usr/bin/ld: obj/32bit/glibc_compat.o: in function `__wrap_logf':
glibc_compat.c:(.text+0xdf): undefined reference to `logf@GLIBC_2.2.5'
/usr/bin/ld: obj/32bit/glibc_compat.o: in function `__wrap_powf':
glibc_compat.c:(.text+0x11f): undefined reference to `powf@GLIBC_2.2.5'
/usr/bin/ld: obj/32bit/glibc_compat.o: in function `__wrap_expf':
glibc_compat.c:(.text+0x14f): undefined reference to `expf@GLIBC_2.2.5'
collect2: error: ld returned 1 exit status

Check out the Makefile in my fork on the develop branch. The glibc wrapper functions do not work on any arm device that I have tried. I modified the makefile to not depend on the glibc_compat.o if the architecture is aarch64. I have a theory as to why this happens but I'm not knowledgeable enough to know for sure. What I do know is you don't need the wrapper functions on an arm distro and it is working fine.

Line 22:

UNAME_M = $(shell uname -m)

checks what architecture the machine is running and then here is where it assigns it to the ARCH variable:

else ifeq ($(UNAME_S), Linux)
SYSTEM ?= linux
	ifeq ($(UNAME_M), aarch64)
		ARCH ?= arm
	else
		ARCH ?= 64bit
	endif

All I did after that is check what the ARCH is when the compiler adds the dependencies for a linux build and omit the glibc COMPAT_DEP. That chunk is right here

ifneq ($(filter linux,$(TAGS)),)
	ifneq ($(filter arm,$(TAGS)),)
	else
		COMPAT_DEP = $(OBJS)/glibc_compat.o
		LDFLAGS += -Wl,--wrap=log,--wrap=log2,--wrap=exp,--wrap=pow,--wrap=expf,--wrap=powf,--wrap=logf
	endif
endif
LDFLAGS += $(DEPS)

I've found a solution:

In file include/glibc_compat.c, there is this block with assembly statements:

// x86_64 glibc -
#define asm __asm__
asm (".symver pow, pow@GLIBC_2.2.5");
asm (".symver exp, exp@GLIBC_2.2.5");
asm (".symver log, log@GLIBC_2.2.5");
asm (".symver log2, log2@GLIBC_2.2.5");
asm (".symver logf, logf@GLIBC_2.2.5");
asm (".symver powf, powf@GLIBC_2.2.5");
asm (".symver expf, expf@GLIBC_2.2.5");
#undef asm

If I wrap this in #if 0 ... #endif, dome links fine. I do not totally understand these statements, but I assume they bind the math function to a certain version of GLIBC which is not installed on my system.