OpenGL issue: 'incompatible' vs 'cannot find' - c

I'm trying a program about blender deformation. My laptop is amd64 and able to support i386.
faye#fish:/usr/bin$ dpkg --print-foreign-architectures
i386
faye#fish:/usr/bin$ dpkg --print-architecture
amd64
I have no much experience about makefile script. According to the google search info, I made two line code additions in the makefile.mk.
# -I option to help the compiler finding the headers
CFLAGS += $(addprefix -I, $(INCLUDE_PATH))
CC=gcc -m32
Here is the issue:
When I run any template OpenGL code with:
gcc test.c -lm -lpthread -lglut -lGL -lGLU -o test
It seems the code and the libs work correctly.
However, if I do the same to the makefile.mk(CC=gcc), it gives many errors in the following form:
/usr/bin/ld: i386 architecture of input file `../external/lib/libxxxxxxxx.a(xxxxxxxx.o)' is incompatible with i386:x86-64 output
if I use (CC = gcc -m32), the error will switch to:
/usr/bin/ld: cannot find -lglut
/usr/bin/ld: cannot find -lGL
/usr/bin/ld: cannot find -lGLU
I guess maybe there is something wrong in 64 bit os running 32 bit application and libs linking?

-m32, when used with a x86-64 compiler does not mean "compile this program for i386", but actually means "create a program for x86-64 CPUs using only instructions that operate on 32 bit registers".
What you have there is some binary that has been compiled for native i386 and now try to combine it with a program that's compile for x86-64 with just 32 bit registers. Those two don't fit together. The big question here of course is, why do you want to use those i386 binaries at all. There are some good reasons for using 32bit-x86-64 (half the size for pointers and which can massively reduce the memory bandwidth), but in general you want 64 bit binaries. So many problems of 32 bit memory management vanish by virtue of having vast amounts of address space.

Looks like extenal/lib is full of 32 bit precompiled archives. You could track each one down and recompile (or use shared libraries), but that'll be a massive PITA.
Just because your OS supports i386 doesn't mean you've got the libraries installed. In this case of that program, it's enough to install libc6-dev-i386 and freeglut3-dev:i386 packages.
PS: No need to edit anything. make CC='gcc -m32'

Related

RISC V linker cannot find -lgcc

I'm trying to compile C code for GCC, but the linker is unable to find libgcc.
I want to compile some simple tests for an RV32I core.
When I try to use the modulo operator, GCC generates a call to the soft implementation of
the mod instruction.
call __modsi3
But linking fails because I think im missing libgcc
test.c:(.text+0x34): undefined reference to `__modsi3'
This is my compilation command:
riscv64-unknown-elf-gcc -lm -lgcc -static -march=rv32i -mabi=ilp32 -nostartfiles -ffreestanding crt0.s -O0
These are my linker options:
-lgcc -b elf32-littleriscv -m elf32lriscv
If I try to use the -lgcc option on the linker, it will throw the following error:
riscv64-unknown-elf-ld: cannot find -lgcc
I also tried to provide directly the path of libgcc.a. But it didn't help.
I got the path of libgcc.a this way:
riscv64-unknown-elf-gcc -march=rv32i -print-libgcc-file-name
I added the path directly to my compilation command like so:
-L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a"
Also, the way I compiled the toolchain might be the issue, I'm using the RISCV toolchain with multi-lib support
I followed the instructions from https://github.com/riscv/riscv-gnu-toolchain
with some slight modification (-j12)
./configure --prefix=/opt/riscv --enable-multilib
make -j12
This also installed the toolchain so I didn't had to make install
Thanks.
The problem comes from -L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a" you must only give the path to the L option. Your option should be :-L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0"
the enable-multilib is working well, it only provide libraries for set of archs. However be careful to give the path of the libgcc corresponding to your arch. When you enable multilib the default one will be a 64 bit versions. Normally for rv32i, the option you need is :-L="/mnt/c/Users/camin/Documents/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/rv32i/ilp32".
If you don't give the good library you will probably get ABI is incompatible with that of the selected emulation error.
It would be easier to use the riscv64-unknown-elf-gcc driver to make the link because he knows all the options better. Normally it will find the necessary libraries (libgcc, libgloss ....) automatically for your arch.
This worked for me, had to manually add the path to the libgcc.a as an argument to elf-ld:
riscv32-unknown-elf-ld -o exampleProg2.elf -T bram.ld -m elf32lriscv -nostdlib --no-relax /(RVTOOLCHAIN_GCC_LIB_DIR)/libgcc.a
Just be careful of choosing the right libgcc.a, there may be multiple in your installation, depending of your multilib seutp.

Gcc on OS X: Undefined symbols for architecture x86_64

I am writing an application that has multiple subdirectories. I have created a Makefile structure such that the subdirectories compile the file and do "ar rvs" and "ranlib libxxx.a" to create archives into the parent directory for linking.
However the "ld" command is running into the following problem.
ld: warning: ignoring file ./libxxx.a, file was built for archive which is not
the architecture being linked (x86_64):
./libxxx.a Undefined symbols for architecture x86_64:
I am using gcc on Mac OS X 10.10.1
I read many posts on this. I tried "gcc -arch i386", then I encounter the same error for i386
Undefined symbols for architecture i386:
I installed gcc-4.9.2 and tried using it instead of the default gcc, with no luck. I tried using x86_64-apple-darwin14.0.0-g++-4.9.2 and that did not help either.
The errors you are seeing mean that you have a mixture of i386 and x86_64 code in the build, and you need to be consistent. Unless there's a compelling reason to do otherwise (I'd be curious to know what it is), you should be compiling everything for 64-bit only. Using gcc on Mac, that is normally the default, but you can force it by adding a -m64 flag to the compilations. One way of doing that is to set CC="gcc -m64" on the make command line; there are other better ways too, but the details depend on your makefile contents.
To resolve: first, remove all the libraries and object code you've built in your project area (maybe make clean will do it — if you wrote a clean target). Then, fettle the value of CC or its flags (CFLAGS ultimately, but how CFLAGS is built depends on the makefile) so that 64-bit compilation is enforced. Then make sure you're using that in all compilations. If you don't see the -m64, you've got a problem.
If you must use 32-bit, substitute -m32 for -m64.
The discussion above assumes you are using gcc to run the ld command. If you are not, then you're on your own until you use gcc to run the ld command. In my view, you've got better things to do with your life than work out how to run the ld command correctly; I certainly have.

Linking C function lib to x86 assembly program in modern 64bit Linux

I'm going through a book focusing on x86 programming (Professional Assembly Language, WROX 2005). I had some problems last night and I was hoping to sort this out before returning home today so I can get a running-start and continue the text. My machine runs x64 Ubuntu (11.04 if I'm not mistaken) so the text focusing on 32bit x86 is slightly 'outdated' (I have to add --32 when assembling etc).
I am trying to dynamically link C-library functions with my assembly program but I am unsuccesfull (below commands are from memory).
ld -dynamic-linking /lib/ld-linux.so.2 -o complex -lc complex.o -m elf_i386
Running the above command in Linux gives me the message that it can't understand -lc. Okay, so I removed it.
ld -dynamic-linking /lib/ld-linux.so.2 -o complex complex.o -m elf_i386
I then get the notification that 'printf' is not recognised. The hopes was for the dynamic linker to link to the library but it does not seem to do so. Going to \lib\ I could not locate ld-linux.so.2 (strangely it didn't give me an error on this) but I did locate ld-linux-86-64.so.2. My code is 32bit but I thought what the heck, let's try this:
ld -dynamic-linking /lib/ld-linux-86-64.so.2 -o complex complex.o -m elf_i386
Still it gave the same error that 'call printf' was not recognized.
Need help dynamically linking C library functions with my 32bit Assembly program using 64bit Linux and standard GNU tools.
Sounds like you need to install the 32-bit C-runtime. Under Fedora this is:
yum install glibc-devel.i686
But I don't know the name of the equivalent Ubunutu package; perhaps:
apt-get install libc6-dev-i386
It is almost always a bad idea to try to construct a ld command line yourself. Let GCC do it for you; it automatically handles all sorts of subtleties that you don't want to have to worry about. For a 32-bit program, you do need one special command line switch, -m32:
gcc -m32 -o complex complex.o
If you have more .o files, just stack them up at the end. If you need to link against any system libraries other than libc, put appropriate -lwhatever options after all the object files.
trojanfoe is also correct; the 32-bit toolchain is an optional component. But you need more than just the 32-bit C library. Try this first:
apt-get install gcc-multilib
it should pull in most of what you need.
Try the following order please(suppose your code fil is try.s):
as --32 -g -o try.o try.s
ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -lc -o try try.o
For x86-64 format executable file:
as -g -o try.o try.s
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -o try try.o

How do I force Waf to build only for "-arch i386" target on OSX and not "-arch x86_64 -arch i386"? [duplicate]

I need to suppress "-arch x86_64 -arch i386" flags Waf is passing to GCC.
I am building an SDL/Opengl application. If I link against 32 bit SDL runtime I get error
Undefined symbols for architecture i386:
"_SDL_Quit", referenced from:
__del_video in SDL_functions.c.2.o
__init_video in SDL_functions.c.2.o
If I link against 64 bit SDL runtime, I get error "Undefined symbols for architecture x86_64"
The compiler is apparently using flags
-arch x86_64 -arch i386
I understand that this causes GCC on OSX to try to compile for both architectures. I want to either compile for 64 bit, or compile for 32 bit. How do I suppress the flags for one architecture?
I found out in my case that the double arch flags were originating here, specifically from distutils.sysconfig.get_config_var('LDFLAGS'). This returns the LDFLAGS that Python thinks you should link Python modules with. In my case, file $(which python) is a "Mach-O universal binary with 2 architectures", so Python thinks you should link with -arch x86_64 -arch i386 -Wl,F.
My problem was that I was building a Python native module that needed to link against Python and another library which was not built with both arches. When building my module with both arches, linking failed with "symbols not found", because both arches were not available in the third-party library.
Since waf unfortunately doesn't allow you to override its computed flags with your own flags, as Automake does, I could only fix this by messing directly with my ctx() object in my wscript:
for var in ['CFLAGS_PYEMBED', 'CFLAGS_PYEXT', 'CXXFLAGS_PYEMBED',
'CXXFLAGS_PYEXT', 'LINKFLAGS_PYEMBED', 'LINKFLAGS_PYEXT']:
newvar = []
for ix, arg in enumerate(ctx.env[var]):
if '-arch' not in (arg, ctx.env[var][ix - 1]):
newvar.append(arg)
ctx.env[var] = newvar
(This removes all -arch flags and their arguments from the relevant variables. Since I was also passing my own -arch flag in my CFLAGS, it now does not get overridden.)
I don't know of a way to issue a command/flag to suppress other flags. However, to compile for only 64 or 32 bits, you can use -m64 or -m32, respectively. Since you're compiling for both architectures, -m32 might be your only option because -m64 won't work for i386.

Undefined Symbols when linking against a mixed C and Fortran in OS X 10.6.4

I'm trying to compile a code (not mine) that consists of mixed Fortran and C source files, which are compiled into a library. This library can either be linked against directly, or (more usefully) driven from a python class. I have previously successfully built the code as 32-bit with g77 and gcc, but I've encountered a situation in which the code uses big chunks of memory, and needs to be 64-bit.
I've attempted to build as both 64-bit only, or as a universal binary, with gfortran 4.2.3 (binary dist from the AT&T R project) and the system gcc (4.2). The source files build correctly, but when I attempt to link against the library, I get many "Undefined Symbols" errors for a number of the Fortran functions. An nm on the library shows that the symbols appear to exist, but obviously the linker isn't finding them.
Here are two (of many) of the compile commands (which produce no errors):
/usr/local/bin/gfortran -arch ppc -arch i386 -arch x86_64 -fPIC -fno-strength-reduce -fno-common -ff2c -Wall -c lsame.f
gcc -c -I/Users/keriksen/Research/atomic_data/fac -I/Users/keriksen/Research/atomic_data/fac/faclib -O2 -fPIC -fno-strength-reduce -fno-common pmalloc.c
And the link step, which bombs:
gcc -o sfac sfac.c stoken.c -I/Users/keriksen/Research/atomic_data/fac -I/Users/keriksen/Research/atomic_data/fac/faclib -O2 -fPIC -fno-strength-reduce -fno-common -L/Users/keriksen/Research/atomic_data/fac -lfac -lm -lgfortran -lgcc
A sample Undefined Symbol:
"_acofz1", referenced from:
_HydrogenicDipole in libfac.a(coulomb.o)
_HydrogenicDipole in libfac.a(coulomb.o)
and the corresponding nm that shows that symbol exists:
niobe:atomic_data/fac[14] nm libfac.a | grep acof
0000000000000000 T _acofz1_
0000000000002548 S _acofz1_.eh
U _acofz1
Am I doing something stupid, like not including a necessary switch to the linker, or is something more subtle going on here?
Per Yuji's suggestion:
The cfortran.h header file (available on the Web, and apparently fairly widely used) that handles the C/Fortran compatibility issues does not handle gfortran out of the box. I hacked it (incorrectly) to ignore this fact, and paid for my insolence.
The specific issue is that gfortran emits object code containing symbols with a trailing underscore, gcc does not.
The correct thing to do was to set the environment variable CPPFLAGS to -Df2cFortran. Once this macro is set, cfortran.h adds the necessary underscore to the symbols in the calling C functions' object code, and the linker is happy.
The other surprising thing in this particular instance was the configure script looks at the F77 environment variable for the name of the fortran compiler. Once I set F77 to "/usr/local/bin/gfortran -arch x86_64" the generated Makefile was correct, and it produced 64-bit only object code. I'm not sure if this is standard configure behavior, or if it a peculiarity of this particular script.
The upshot is that I now have a 64-bit shared library which plays nicely with a 64-bit python I downloaded. I'm half-considering going back and trying to produce a universal library that will work with the system python, but I'm not sure I want to tempt fate.

Resources