libtool vs ar for creating a static library (xcode linker) - xcode

Creating a static library on Mac 10.5 with xcode via libtool and with ar via the command line both generate a libMainProject.a file however, when trying to use the one generate by libtool to link into a xcode application I end up with multiple message like
"vtable for project1 referenced from:
_ZTV27project1$non _lazy _ ptr in libMainProject.a(project1.o)"
Using the ar one is totally fine and links correctly. I have tried the addition of the -c option to the libtool while linking but that does not seem to have an impact. So I guess my 2 options are
1) Figure out what is causing the differences in symbols between the ar and libtool version and make the libtool generate the same information.
2) Make xcode use ar instead of libtool to generate the static libs.
Any ideas or suggestions would be appreciated.
Thanks in advance.

I suggest to unarchive the static library with ar. You will end up with the *.o files. Then use gobjdump (you might have to install that yourself from MacPorts/fink/homebrew) to see what's inside the *.o files and compare the two versions.

Related

ld: building for macOS-x86_64 but attempting to link with file built for macOS-x86_64

I have this strange issue where creating / using a static library works in my Ubuntu VM but not on macOS:
ld: warning: ignoring file ./dist/libXXXX.a, building for macOS-x86_64 but attempting to link with file built for macOS-x86_64
Command to create the static library is:
ar rcs libtest.a obj1.o obj2.o ...
Compiler invocation:
gcc -g -Wall -Wextra main.c -L./dist -lXXXX -o main
Searching on google didn't yield any usable results except for this (maybe) related question on SO:
Possible related question
I realize this is an old post and you found your fix, but let me post this here for anyone else who runs into this problem for whom these answers don't provide a solution.
You might be using two different toolchains unknowingly, one from Apple (installed via Xcode) and one from GNU (installed via Home-brew or MacPorts). If you type ranlib --version and see version info showing that ranlib is GNU, this is likely the case.
Make sure that /usr/bin comes in your $PATH before /usr/local/bin and /opt/local/bin. When you run which -a ranlib, the first result in the list should be /usr/bin/ranlib. Same for which -a ar-- the first result should be /usr/bin/ar. If it is not so, you need to fix your $PATH.
Once you fix your path and clean your project, try building again and things should work.
The issue was solved when I directly put those object files rather than gathering them into a static library, i.e.,
gcc -g -Wall -Wextra main.c obj1.o obj2.o -o main
After that, I got many warnings like ld: warning: object file (obj1.o) was built for newer macOS version (11.0) than being linked (10.14), but it is a warning, and the object is linked, so the problem is solved.
The root cause is that some library passes -mmacosx-version-min=10.14 to gcc, so the object file is built for 10.14, but my macos is now 11.0.
If you want to make things work, try directly using object files rather than creating a static library.
If you want to resolve all the warnings, find ``-mmacosx-version-min` and comment it.
After looking at my script that automatically creates the static library I've found the culprit:
For some reason my tool created object files for header files (resulting in files like header.h.o).
Removing those fixed the issue.

Linking against static Lua libraries on macOS

I'm trying to compile and link a program (using CMake) that uses Lua 5.3's C interface on Mac OS X 10.15.7. However I have these problems:
brew install lua#5.3 only installs dynamic libraries
I cannot copy static libraries built from source to /usr/local due to System Integrity Protection (?)
I don't know how to make CMake find the libraries if I put them anywhere else (using find_package(Lua 5.3 REQUIRED)
What's the easiest way to solve this?
If I correctly understand your question, you are trying to use Lua's C API, which means that you need access to the principal header files lua.h, lualib.h, and lauxlib.h, as well the static library liblua.a that is created when the interpreter is built.
I would recommend downloading lua-5.3.5.tar.gz from lua.org and then building from source.
This can be done easily from the Terminal:
$ wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
$ tar xzf lua-5.3.5.tar.gz
$ cd lua-5.3.5
$ make macosx
After that you should be able to do make install as well, which copies the Lua interpreter to /usr/local/bin, I believe.
If you do not want the key Lua header files put into your include path, build your program with -I and -L flags. Also, don't forget the -llua -ldl -lm flags when linking your program.

libtool and Windows DLLs

I have an difficult relationship with the GNU autotools, especially libtool. But because they kick ass when it comes to portability and cross compilation I started using them again.
Unfortunately I can't get libtool to build proper windows DLLs. Yet with vanilla make gcc
will happily build the DLL for me.
For example:
LIBEXT = .dll
pkzo$(LIBEXT): $(patsubst %.cpp, %.o, $(pkzo_SOURCES)) resources.o
$(CXX) -shared -fPIC $(CXXFLAGS) $^ $(LDFLAGS) -Wl,--out-implib=libpkzo.lib -o $#
Will haily build a DLL and import library. (Even without any annoying decelspec).
Yet if I use libtool like so:
lib_LTLIBRARIES = libpkzo.la
libpkzo_la_CXXFALGS = ...
libpkzo_la_LDADD = ...
libpkzo_la_SOURCES = ...
Libtool comes complaining:
*** Warning: linker path does not have real file for library -lSDL2main.
*** I have the capability to make that library automatically link in when
*** you link to this library. But I can only do this if you have a
*** shared version of the library, which you do not appear to have
*** because I did check the linker path looking for a file starting
*** with libSDL2main and none of the candidates passed a file format test
*** using a file magic. Last file checked: /usr/local/lib/libSDL2main.a
*** Since this library must not contain undefined symbols,
*** because either the platform does not support them or
*** it was explicitly requested with -no-undefined,
*** libtool will only create a static version of it.
Well guess what libSDL2main.a is a static library and has no DLL.
It there a way to build a DLL with automake not using libtool or telling libtool to stop making a fuss about nothing?
PS: Before anyone mentions it, I am configuring libtool with LT_INIT([shared static win32-dll])
For the first problem, make sure you have a shared version of the SDL library installed.
If you absolutely must link your DLL to static libs, you can trick libtool into doing it by editing the libtool script. E.g., if you want all of the dependent libs statically linked to your DLL, you can do that by putting this at the end of your configure.ac:
sed -i '/^whole_archive_flag_spec=/s/"$/ \\${wl}-static"/' libtool
Now, this is a gross hack and relies on the particular way that libtool builds command lines right now, so there's no guarantee that it will continue to work---but it does work with libtool 2.4.2. Since you have just one library which you want statically linked, you could achieve that by applying sed a bit differently. Probably you'll want
sed -i '/^whole_archive_flag_spec=/s/"$/ \\${wl}-static \\${wl}-lSDL2main \\${wl}-shared"/' libtool
in order to keep shared linking with whatever other shared libs you have, and then you'll need to take -lSDL2main out of wherever else you have it. This is gimpy, but the thing you're trying to do is also gimpy and libtool isn't made for this.
For the second problem, add -no-undefined to libpkzo_la_LDFLAGS.

Building a Shared Library but linking against a Static One

I have an Autogen Makefile.am that I'm trying to use to build a test program for a shared library. To build my test binary, I want to continue building the shared library as target but I want the test program to be linked statically. I've spent the last few hours trying to craft my Makefile.am to get it to do this.
I've tried explicitly changing the LDADD line to use the .a version of the library and get a file not found error even though I can see this library is getting built.
I try to add the .libs directory to my link path via LDFLAGS and still it can't find it.
I tried moving my library sources to my test SOURCES list and this won't work because executable object files are built differently than those for static libraries.
I even tried replicating a lib_LIBRARIES entry for the .a version (so there's both a lib_LTLIBRARIES and a lib_LIBRARIES) and replicate all the LDFLAGS, SOURCES, dir and HEADERS for the shared version as part of the static version (replacing la with a of the form _a_SOURCES = _la_SOURCES. Still that doesn't work because now it can't figure out what to build.
My configure.ac file is using the default LT_INIT which should give me both static and dynamic libraries and as I said it is apprently building both even if the libtool can't see the .a file.
Please, anyone know how to do this?
As #Brett Hale mentions in his comment, you should tell Makefile.am that you want the program to be statically linked.
To achieve this you must append -static to your LDFLAGS.
Changing the LDFLAGS for a specific binary is achieved by changing binary_LDFLAGS (where binary is the name of the binary you want to build).
so something like this should do the trick:
binary_LDFLAGS = $(AM_LDFLAGS) -static

could not read symbols: Archive has no index; run ranlib to add one

i tried making library with
ar -r -c -s libtestlib.a *.o
as given in this tutorial http://matrixprogramming.com/Tools/CompileLink.html
But on linking with library following error comes
g++ -o uni2asc uni2asc.o -L../Modules -ltestlib
../Modules/libtestlib.a: could not read symbols: Archive has no index; run ranlib to add one
collect2: ld returned 1 exit status
i tried with ranlib also but still the error comes..
im working with ubuntu9.10
Please suggest me some solution for this
Your archive command looks fine, can you try the following.
1) Get the object files in the archive/static library
ar -t libtestlib.a
2) For each object file (say foo.o) from step 1
file foo.o
This will tell you the format of the object file. If the object file was compiled for a different platform, this would cause a failure to build the index for the archive.
To correct this you would need to recompile these files.
3) For each object file from step 1, do
nm foo.o
This will list the symbols exported from the file.
I was using MinGW to compile a windows app when I got the error, so I found the built-in MinGW commands:
i686-w64-mingw32-ar
And
x86_64-w64-mingw32-ar
Try using those instead of ar if you encounter the problem in MinGW. They both fixed the question's problem for me.
libtool also has an useful option:
-export-symbols-regexp.
I ran into the exact same problem when trying to compile the NBIS libraries. There is an option for
make install LIBNBIS=yes
which creates a single archive containing the other archive files. The gcc linker does not handle this gracefully and just emits the Archive has no index message. The fix is to leave the archives as separate files
make install LIBNBIS=no
Then just link the application to the required archive(s). The archive feed order is important to be sure that the linker identifies the required dependencies, then resolves them as it processes the .a files.

Resources