Possible to link multiple static libs into one with same arch? [duplicate] - c++

I tried the approach in this question, but it seems the linux version of ar is not the same as the mac version since I failed to combine the object files again.
What I basically want to do is is merge another static library into my Xcode static library build product via a run-script build phase.
Unfortunately I can't compile the other library directly into my project because it has it's own build system (therefore I use the compiled libs).
I think it should be possible to merge the other library via ar into the Xcode generated library without decompiling the build product. How do I accomplish this?

you can use libtool to do it
libtool -static -o new.a old1.a old2.a

If you're dealing with multi-architecture static libraries, a bit of extra manipulation is required to thin each library, combine the thinned versions, and then fatten the result. Here's a handy script which you can edit to your satisfaction which does all that in one. The example takes three iOS libraries path/to/source/libs/libone.a, path/to/source/libs/libtwo.a, and path/to/source/libs/libthree.a and merges them into a single library libcombined.a.
#! /bin/bash
INPATH="path/to/source/libs"
LIBPREFIX="lib"
LIBS="one two three"
LIBEXT=".a"
OUT="combined"
ARCHS="armv7 armv7s arm64"
for arch in $ARCHS
do
for lib in $LIBS
do
lipo -extract $arch $INPATH/$LIBPREFIX$lib$LIBEXT -o $LIBPREFIX$lib-$arch$LIBEXT
done
INLIBS=`eval echo $LIBPREFIX\{${LIBS// /,}\}-$arch$LIBEXT`
libtool -static -o $LIBPREFIX$OUT-$arch$LIBEXT $INLIBS
rm $INLIBS
done
OUTLIBS=`eval echo $LIBPREFIX$OUT-\{${ARCHS// /,}\}$LIBEXT`
lipo -create $OUTLIBS -o $LIBPREFIX$OUT$LIBEXT
rm $OUTLIBS

You should just be able to link one to the other. So... just use ld to merge the images.

You should use ar -r to create an archive on MacOS:
ar -x libabc.a
ar -x libxyz.a
ar -r libaz.a *.o

Related

tensorflow C API static library

Can I build/get static library (.a files instead of .so files) of tensorflow C API? I need to include/link tensorflow c api in my C++ software xyz and then I build shared library xyz.so that will be sent to other party. The other party should be able to run xyz.so without installing/building tensorflow.
Download tensorflow c api and link .so files using CMakeLists.txt file.
I have gotten some things to work by compiling Tensorflow with the following bazel command:
bazel build --config=monolithic -j 1 //tensorflow:libtensorflow.so
And then linking together the object files with libtool for MacOS:
libtool -static -o libtensorflow_arm64_libtool_SO3.a $(cat bazel-bin/tensorflow/libtensorflow_cc.so.*.params | sed -e 's!-Wl,-force_load,!!' | grep -e '\.a$' -e '\.lo$' | sort -t: -u -k1,1)
Or ar for linux:
ar -cr libtensorflow.a $(cat bazel-bin/tensorflow/libtensorflow_cc.so.*.params | grep '\.o$')
I have not figured out all the details, but this does make at least version control and tensor allocation work.
EDIT:
In the end I opted for going with TFLite as it supports almost all TF operations and have Cmake support for building static libraries. For the full solution see this thread:
Has anyone experience in building a static library for the Tensorflow C++ API?

What do link flags mean for static library?

"ar" -- is just tool to create archives.
And all static libraries of form "lib*.a" are in fact just archived compiled objects + additional file with symbol table, added there by "ranlib".
No linking is performing during creation of such library.
So why do most of projects use ***_LDFLAGS ***_LIBADD in their Makefile.am during creation of such ("lib*.a" static library) archives?
Does automake ignore those flags (in case when they relate to any "lib*.a" static library), or does it in fact link something there?
So why do most of projects use ***_LDFLAGS ***_LIBADD in their Makefile.am during creation of such ("lib*.a" static library) archives?
The GNU Build System is capable of creating dynamic and static libs (or both) determined at configure time using the --enable-shared and --enable-static flags. As you guessed, _LDFLAGS and _LIBADD are more oriented to dynamic shared objects or program linkage than to the static linker. The static linker of libtool is essentially another link pass that invokes ar to create the archive (omitting all the flags). For example:
lib_LTLIBRARIES=libfoo.la
libfoo_la_SOURCES=$(SRCS)
libfoo_la_LDFLAGS=-Wl,-t
when both shared and static libs are generated outputs something like:
libtool: link: gcc -shared -fPIC -DPIC .libs/foo.o -g -O2 -Wl,-t -Wl,-soname -Wl,libfoo.so.0 -o .libs/libfoo.so.0.0.0
...
libtool: link: (cd ".libs" && rm -f "libfoo.so.0" && ln -s "libfoo.so.0.0.0" "libfoo.so.0")
libtool: link: (cd ".libs" && rm -f "libfoo.so" && ln -s "libfoo.so.0.0.0" "libfoo.so")
libtool: link: ar cru .libs/libfoo.a foo.o
libtool: link: ranlib .libs/libfoo.a
libtool: link: ( cd ".libs" && rm -f "libfoo.la" && ln -s "../libfoo.la" "libfoo.la" )
automake does ignore _LDFLAGS; however the script that performs the linking (libtool) does not. It looks for flags that affect linking there also. For example:
lib_LTLIBRARIES=libfoo.la
libfoo_la_SOURCES=$(SRCS)
libfoo_la_LDFLAGS=-Wl,-t -static
will only generate a static lib, even if configure --disable-static was run to generate the Makefile.
libtool is just a wrapper script over the native compiler/linker tools for portability.
Answer to your question Does automake ignore them is: NO
That is completely true: ""ar" -- is just tool to create archives."
But, Automake does not ignore ***_LDFLAGS ***_LIBADD in their Makefile.am at all, otherwise what is point of having such flag if they are not making any sense for the build system!
From documentation (link give below):
The ‘library_LIBADD’ variable should be used to list extra libtool objects (.lo files) or libtool libraries (.la) to add to library.
The ‘library_LDFLAGS’ variable is the place to list additional libtool linking flags, such as -version-info, -static, and a lot more.
For more details, you should go through this Libtool Documentation for more clarity in these flags.
8.3.7 _LIBADD, _LDFLAGS, and _LIBTOOLFLAGS
Libtool Documentation
EDIT:
As your question is still generic, let me put it in two different scenario...
Static Lib is stand-alone:
In this scenario ***_LIBADD could be not much useful, as mentioned in documentation: "the library_LIBADD variable should be used to list extra libtool objects (.lo files) or libtool libraries (.la) to add to library"
Which means, if your static lib does not have dependency then this flag is no of use in it's Makefile.am.
Static Lib is Dependent (not stand-alone)
From above quote from documentation, it is now clear that, ***_LIBADD flag is used to mentioned libs names which are required to build your current library.
So this flag would be necessary in such requirement.
And about ***_LDFLAGS, as mentioned in documentation, The library_LDFLAGS variable is the place to list additional libtool linking flags for that library.
If your lib does not require such flags, then this can be ignored too. It is all about how you want your final result.
Few more additional links for your reference:
LDFLAGS usage in autotools with libtool
What is the difference between LDADD and LIBADD?
I hope this EDIT suffices what you're looking for.
PS: If you would read my answer carefully and went through documentation, you could have get the same data. Njoy. :)

How to build coreutils with LLVM 3.4

I am trying to build GNU Coreutils 8.23 using the LLVM 3.4 tool-chain. One very important aspect is that I also need the LLVM bytecode for all the coreutils. Therefore, I need to include -emit-llvm in the CFLAGS. Therefore, I removed the $(CFLAGS) from the LINK variable of the coreutils Makefile. Afterwards, I run the following command:
make CC=/home/user/llvm-3.4.2/build/Release+Asserts/bin/clang
CCLD=/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-link
IGNORE_UNUSED_LIBRARIES_CFLAGS= CFLAGS="-emit-llvm -S"
VERBOSE=1 AM_CFLAGS= AM_LDFLAGS=
AR=/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-ar
RANLIB=/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-ranlib
and I get the following error:
/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-link: src/libver.a:1:2: error: expected integer
!<arch>
^
/home/user/llvm-3.4.2/build/Release+Asserts/bin/llvm-link: error loading file 'src/libver.a'
Any ideas of how to get this to work?
Try this.
export CC="/home/user/llvm-3.4.2/build/Release+Asserts/bin/clang"
export CXX="/home/user/llvm-3.4.2/build/Release+Asserts/bin/clang++"
Make sure this is where your compiler toolchain is present.
Then in the the coreutils directory, run ./configure (before this run ./bootstrap if you havent already run it). Running ./configure checks if your clang can compile properly and creates a Makefile with the correct configuration.
Then do a make and make install as instructed.
Lib file '.a' here is not readable by llvm-link.
A possible informal hack to this probably is to find out the Makefile generating this lib, and let
AR = llvm-link, ar option = -o(i.e. change ar rv to llvm-link -o),
and disable ranlib command while compling(you don't need ranlib if using llvm-link).
Then the '.a' file generated is a stitched bc file, and this '.a' file should be accpetable by llvm-link command you are calling

Statically linking libtcod

I'm trying to statically link libtcod to my C++ project without success. I get many linking errors, including:
./tuto: error while loading shared libraries: libtcodxx.so.1: cannot open shared object file: No such file or directory
Has anyone had similar problems with that library?
There are dynamic libs provided in current libtcod (1.6.0) distribution.
You can link libtcod dynamically, but you need to create symbolic links:
cd /var/lib/libtcod
ln -s libtcod.so libtcod.so.1
ln -s libtcodxx.so libtcodxx.so.1
Compile with following command:
g++ src/*.cpp -o tuto -I/var/lib/libtcod/include -L/var/lib/libtcod -ltcod -ltcodxx -Wl,-rpath=/var/lib/libtcod -Wall
Which flags do you use while linking to the library? Did you used -static flag, do you specified -ltcod? If not, add -static -ltcod to the end of command line.
Or you can force tell gcc to link with static builded library:
gcc %YOUR_OTHER_FLAGS_ANDFILES% -l:libtcod.a -L%PATH_TO_TCOD_STATIC_BUILDED_FILE%

Simple libtool alternative?

Being perfectly satisfied with old-style Makefiles, I am looking for a simple alternative to libtool. I do not want to switch to automake, and I keep running into problems with libtool when I try to use it directly. The latest one is 'unsupported hardcode properties', and I am getting fed up with the lack of complete documentation that just tells me what is wrong this time...
I only want to compile a bunch of .o files with the right flags and then link them into a shared library, such that it works on as many platforms as possible. Is there anything out there that does just that and not force me to switch all of my other tools at the same time?
I not sure if it would fit info your workflow but I'd recommend looking at CMake. It works on Windows, Linux and Mac and should not force you to change any of your other tools. You'll have to judge its suitability yourself though.
There's jlibtool (which has nothing to do with java).
It's written in C, and can just be bundled with your source.
It was originally an apache project, but whoever was working it there seems to of abandoned it around 2004.
It was taken over by FreeRADIUS project maintainer Alan Dekok, who modernised the code and fixed a few niggling issues. We use it for the FreeRADIUS project (>= 3.0.0) to do all the build time linking.
Given your description in the comment to Milliams' answer,
I just want one tool that I tell: "give me the compiler flags so that I can compile these n files for use in a shared library, and then give me the commands to link them together",
then libtool may well be the simplest tool for the job. I know of no other alternative.
You are right that the documentation for using libtool with plain makefiles is practically nonexistent, but libtool certainly does not require you to switch to automake. Cross-platform libraries are difficult, and the price you have to pay for them is libtool. (Or maybe the discount price is libtool+automake+autoconf or CMake or Jam.)
slibtool (dl.midipix.org/slibtool, git://midipix.org/slibtool) is a libtool drop-in replacement, written in C. A single slibtool binary aims to seamlessly support both native and cross-builds, and the utility also provides some additional features (installation of .la files is optional, optional color-coded annotation, etc). The following minimal plain makefile demonstrates how to (cross-) build a library using slibtool.
CC = cc
LIBTOOL = slibtool
DESTDIR = destdir
all: libfoo.la
a.lo:
$(LIBTOOL) --mode=compile --tag=CC $(CC) -c a.c
libfoo.la: a.lo
$(LIBTOOL) --mode=link --tag=CC $(CC) -o libfoo.la -rpath /lib
install: all
mkdir -p destdir
$(LIBTOOL) --mode=install cp libfoo.la $(DESTDIR)
# the -rpath argument is required for semantic compatibility with libtool.
native build, default (both shared library and static library)
$ make
$ make install
native build, shared library only
$ make LIBTOOL=slibtool-shared
$ make install
native build, static library only
$ make LIBTOOL=slibtool-static
$ make install
cross-build, default
$ make CC=some-target-tuple-gcc
$ make install
cross-build, default, with lots of colors
$ make LIBTOOL=dlibtool CC=some-target-tuple-gcc
$ make install