error linking to 32bit boost library with g++ - boost

I am making a project in Mac OSX and use the boost compiled libraries (serialisation amongst others). I installed all my dependencies as x86_64 libraries, but now want to make explicitly 32 bit ones (i386) and recompile my project for 32bit users.
I have recompiled by libraries with g++ -m32 where appropriate and then re made 32 bit boost libraries using
./bootstrap.sh link=static
./b2 cflags=-m32 cxxflags=-m32 address-model=32 threading=multi architecture=x86 instruction-set=i686
I then recompile my project by explicitly linking to the 32 bit libraries. So something like
g++ file.cpp /usr/local/lib/boost_i386/libboost_serialization.a -m32 -o executable
where the library is explicitly the 32 bit version verified by using otool as follows with (partial) output (all list cputype as i386)
otool -hv -arch all libboost_serialization.a
Archive : libboost_serialization.a
libboost_serialization.a(basic_archive.o):
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC I386 ALL 0x00 OBJECT 3 1180 SUBSECTIONS_VIA_SYMBOLS
However, when I compile my project (despite most dependencies working fine), it trips up and that symbols are missing for this architecture
Explicitly:
Undefined symbols for architecture i386:
"boost::archive::detail::shared_ptr_helper::shared_ptr_helper()", referenced from:
boost::archive::binary_iarchive::binary_iarchive(std::basic_istream<char, std::char_traits<char> >&, unsigned int)in ccCH1ama.o
"boost::archive::detail::shared_ptr_helper::~shared_ptr_helper()", referenced from:
boost::archive::binary_iarchive::~binary_iarchive()in ccCH1ama.o
boost::archive::binary_iarchive::~binary_iarchive()in ccCH1ama.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
I have explicitly built the 32bit libraries, checked they are in fact 32 bit, and explicitly linked to them, I don't know what else to do. Any ideas?

Turns out the header files were boost v1.55 but the i386 libraries used the most current version v1.57. This caused the error. Building the libraries with the older v1.55 to match the headers fixed the problem.

Related

When installing a library is it one of `ar`, `libtool`, `ranlib`, or other which decides if it's 32 or 64bit?

Snippet from Recompiling libiconv, gettext undefined symbols occurring after an already successful install ; thought to make it its own question.
Trying to use libiconv in a simple .c file:
#include <iconv.h>
// works: gcc -m32 -I/usr/local/include -liconv -o test-iconv.exe test-iconv.c
// does NOT work: gcc -I/usr/local/include -liconv -o test-iconv.exe test-iconv.c
int main(int argc, char **argv) {
iconv_t conv = iconv_open("ISO8859-1", "UTF-8");
if (conv != (iconv_t) -1) {
return 0;
}
return 1;
}
If I do not specify -m32 for gcc then I received the following error:
$ gcc -I/usr/local/include -liconv -o test-iconv.exe test-iconv.c
Undefined symbols for architecture x86_64:
"_libiconv_open", referenced from:
_main in ccr9tTic.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
When you 'install' a library, the library has already been built and the installation cannot change whether it is a 32-bit or 64-bit library.
What controls whether a library is for 32-bit or 64-bit (or both, if you're on macOS Sierra or Mac OS X) is the way the object files are compiled. If you compile with gcc -m32, the object files will be 32-bit and the library will be 32-bit; if you compile with -m64, they'll be 64-bit. If you compile with neither option, you'll get a default behaviour, and the default depends on the platform and how the compiler was built. If you're using one of the Mac operating systems, it is possible to compile both the 32-bit and 64-bit versions into a single object file, and then create a library that contains both 32-bit and 64-bit.
By the looks of it, you need to ensure that you compile libiconv with the 64-bit options. You might need to use ./configure CC='gcc -m64' CXX=g++ -m64… or something similar to force 64-bit compilations — it is a trick I sometimes use.

Static -libgfortran in library build

I am trying to build a library that only has static references to libgfortran (and preferably libgcc also).
However, if I use the linker flags
-static -lgfortran -static-libgfortran -static-libgcc
on OS X I get
ld: library not found for -lcrt0.o
collect2: error: ld returned 1 exit status
and if I try to use
-shared -lgfortran -static-libgfortran
I get
Undefined symbols for architecture x86_64:
"_quadmath_snprintf", referenced from:
_write_float in libgfortran.a(write.o)
"_strtoflt128", referenced from:
__gfortrani_convert_real in libgfortran.a(read.o)
__gfortrani_convert_infnan in libgfortran.a(read.o)
and everything compiles fine (but has a dynamic link to libgfortran and libgcc) if I use -dynamiclib -lgfortran.
It would appear that gcc is not build statically on OS X.
How do I build my library so that end-users don't need to have gfortran or gcc installed?
I'm using the macports version of gcc but I'm prepared to use another distributor of gfortran/gcc if it allows me to do this.
-dynamiclib -lgfortran -static-libgfortran \
/opt/local/lib/gcc47/libquadmath.a -static-libgcc
seems to do the trick!
The bizarre thing was figuring out that I needed to add a full path to the libquadmath.a, which feels like a bug with gcc/gfortran to be honest.

Make Xcode to run g++ on linking an object file

I am trying to build an small sample CUDA code matrixMul.cu in XCode 4.5.2. I did:
a custom script which runs nvcc to compile the .cu file to an object file.
then let xcode to link it with cuda lib to produce the final executable matrixMul
However, in the linking stage, xcode always runs gcc on the .o file instead of g++, and becos of this it results in error:
/Applications/Xcode.app/Contents/Developer/usr/bin/gcc -arch x86_64 -isysroot ...
Undefined symbols for architecture x86_64:
"std::ios_base::Init::Init()", referenced from:
__static_initialization_and_destruction_0(int, int)in matrixMul.o
"std::ios_base::Init::~Init()", referenced from:
___tcf_0 in matrixMul.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
I don't know how to make XCode to run g++ instead of gcc to link the object file. I have only the .cu file in the project so no .cpp to indicate it's c++. However, I DO choose C++ when I created the xcode project in the very beginning. It runs gcc for me regardless I choose Apple LLVM compiler or LLVM GCC in the build settings.
Thank you!
Gary
It turns out that I can't force XCode to use g++ for linkage, but has a workaround where I add -lstdc++ to the "Other linker flags" section, making gcc link the c++ lib for me.
It works for now, but I am not too sure if this the only/best solution. Please let me know if anyone has other solution.
Gary

Error when making dynamic lib from .o

I'm trying to make dynamic lib from set of .o files, but when i do
gcc -dynamiclib -current_version 1.0 mymod.o -o mylib.dylib
or
ld *.o -o mylib.dylib
i get a lot of errors like:
"_objc_msgSend", referenced from:
-[NSObject(NSObject_SBJSON) JSONFragment] in NSObject+SBJSON.o
"operator new(unsigned long)", referenced from:
MStatistic::instance() in MStatistic.o
StatisticProfileLoggingObserver::instance() in StatisticObserver.o
ld: symbol(s) not found for architecture x86_64
Can you please help me, how to solve it and get my .dylib?
You can pass -undefined dynamic_lookup as an option to ld, or:
-Wl,-undefined -Wl,dynamic_lookup to gcc or clang (which passes it to the linker).
From this line:
ld: symbol(s) not found for architecture x86_64
it sounds like you are building some libraries that have make files that only build for 32-bit architectures.
You need to modify the makefiles for all the libraries / frameworks you're building to build both 32-bit and 64-bit; and in a practical sense, all shipping MacOS machines are 64-bit capable so it may just be safe to build only for 64-bit.
In your compile / linking lines, add something like this: "-arch x86_64" and that should compile things for the 64-bit side. To do both 32 & 64-bit, you'll basically need to duplicate the compile & link lines with their own "-arch i386" and "-arch x86_64" lines.

How do I suppress '-arch', 'x86_64' flags when compiling an OpenGL/SDL application with Waf on OSX?

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.

Resources