Autotools - libtool: link: -rpath with #executable_path on MacOS - macos

I'm trying to build a framework with Autotools on MacOS. This frameworks contains a library, let's call it libmytools.dylib, and an executable that uses the library.
What I want is to link this library dynamically at runtime.
The executable is usually installed to /Library/Frameworks/mytools.Framework/Versions/Current/Commands/mytools
The library is usually installed to
/Library/Frameworks/mytools.Framework/Versions/Current/Libraries/libmytools.dylib
In case the framework is installed in that location, everything works fine, but when the framework is not installed on the machine but instead it's only embedded in another project, the library can't be found.
What I need is a so called "Runpath Dependent Library" as described here:
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/RunpathDependentLibraries.html
So what I did was adding mytools_LDFLAGS = -rpath #executable_path/../Libraries to the makefile.
But unfortunately libtool refuses to link my executable with the dynamic -rpath
and shows the following error: libtool: link: only absolute run-paths are allowed.
I also tried mytools_LDFLAGS = -dynamic -rpath #executable_path/../Libraries but the result is the same...
What am I doing wrong??

This is the current libtool design. This thread from the libtool patches list may have a suggestion which will work for you. The suggestion is:
build as normal and then postprocess using install_name_tool
If you don't like this suggestion, it may be possible to adapt the hacky patch that started off that thread to work for you, and apply the patch to the generated libtool as part of bootstrap.sh configuration.

Related

Modify default library search dirs that gcc passes to ld

I want to force new GCC 12 on my old debian (that only has GCC 6 by default) to use fresh libstdc++ headers with new header-only features, but link with old stdlibc++,gcc_s (and other system/compiler libs used by GCC6) to keep binary compatibility with native runtime of old debian (so that users of old GCC6 can link with my binaries without having GCC12).
Of course I know that some functionality in the old runtime will be missing, and ABI is also different, but I guess I can fight with that. Afterall RedHat seems to be using similar scheme for their devtoolset packages (they try to link missing functionality of new runtime statically to your binary if these symbols are not found in native old runtime)
So far I am stuck with -L arguments that GCC is passing to ld.
Here is complete output of /usr/local/gcc12/bin/x86_64-linux-gnu-gcc-12 main.cpp -Wl,-v -v command for simple hello-world main.cpp:
https://pastebin.com/JhYSfg4x
The question: Where does GCC take all these -L paths from, and how do I remove/modify them? I don't want to accidentally link with new version of libraries that were built with GCC12:
-L/usr/lib/gcc/x86_64-linux-gnu -L/usr/local/gcc12/lib/gcc/x86_64-linux-gnu/12 -L/usr/local/gcc12/lib/gcc/x86_64-linux-gnu/12/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc -L/usr/local/gcc12/lib/gcc/x86_64-linux-gnu/12/../../.. /tmp/ccXfhCs4.o
System ld.conf does not mention any paths to /usr/local/gcc12 folder.
-nostdlib and -nodefaultlibs are removing some standard -l flags, but they are not doing anything to -L flags.
Update: I ended up just removing all *.a, .so, *.la files from include, lib and lib64 folders of gcc12, and I also added -L path to native libraries. This way I am sure gcc12 can't pickup one of its libraries for li nking. Not sure if this is good solution, but it works.

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.

automake program libtool wrapper linking

Am stumped on an automake link. Even after pouring over the manuals for hours and searching online it is probably a misunderstanding of autotools.
I have one .la library made by libtool, one .dylib shared library and am creating a program. The .la is linked to the .dylib and the program uses the .la.
Makefile.am for the .la library
lib_LTLIBRARIES = libA.la
libA_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined
libA_la_LIBADD = $(LIBM) -Ldir/to/ -lB
libA_la_CPPFLAGS = ${AM_CPPFLAGS}
Makefile.am for program with libtool wrapper
noinst_PROGRAMS = test
test_SOURCES = test_source.c
test_LDADD = libA.la -Ldir/to/ -lB
libA.la is created and links to B.dylib but the test program "wrapper" created by automake is exporting DYLD_LIBRARY_PATH to find libA.la while not linking to B.dylib. Giving the error
dyld: Library not loaded: ./B.dylib
Referenced from: /dir/to/test/.libs/test
Reason: image not found
Trace/BPT trap: 5
Some things that I have tried are adding -Ldir/to/ -lB to test_LDFLAGS in addition to already being added in test_LDADD. And have tried setting test_LDFLAGS = -rpath -Ldir/to in the hopes that setting the runtime search path to the directory where B.dylib is would help.
If I manually export DYLD_LIBRARY_PATH to include /dir/to/B.dylib then the test program is able to run but I'm looking to have autotools take care of this rather than requiring someone to export a path before being able to run it.
libB.dylib includes an rpath that gets copied into your binary and that is used to resolve -lB at runtime.
And it seems that this rpath is not /path/to, so libB.dylib cannot be resolved by the runtime linker.
The reasons why it works for libA.la is that libtools knows that the rpath in libA.dylib is wrong anyhow (as you haven't done a make install) and so it needs to be set manually.
The only way around this that i have found is to use install_name_tool to fix the stored rpath in the resulting binary.
(that is: I don't think that libtool will do this for you, as it contradicts the intended use of libB.dylib - as declared in its rpath)
The problem is that Libtool wasn't involved in building libB.dylib, so it does not know how to fix up your environment to find it. That means it is up to you. You can add path/to/ libB in your environment, or add a hardcoded search path to libA.la so that libA will find it.
libA_la_LIBADD = $(LIBM) -Ldir/to/ -rpath dir/to/ -lB
This will not only add the path to B in libA's binary, but will add it to dependency-libs in Libtool's libA.la file so that on platforms that won't automatically inherit the rpath specification it can be added by Libtool when linking.

Cannot get FreeType library to work in Mac OS X Mountain Lion

I have an OpenGL project which works/compiles fine in Windows.
I wanted to port the application to Mac OS.
I got the application up and running on Mac, but the text inside the project is not visible. So I decided to use a 3rd party library for text rendering in Mac, I came across FreeType, which has many advantages such as anti-aliasing and UNICODE support.
So, I downloaded the library on my Mac, './configure'd it, did 'make' and 'make install' as I would normally do.
Then in Xcode I set search paths for both include and library directories,
/usr/local/include and /usr/local/lib respectively. Then I added 'other linker flags' in Xcode, freetype-configure --libs gave me following flags- -L/usr/local/lib -lfreetype -lz -lbz2, I added them in Xcode.
Now, whenever I include a freetype header there is no problem, but when I call any method from the freetype library, it gives me following linker error.
After looking up on google I found out that I have to set the build targets accordingly, I did that, now my application builds for i386 x86 the issue still persist.
I also tried following flags while configuring freetype ./configure CC="gcc -arch i386" CXX="g++ -arch i386"
which did not help either.
I am relatively new to Mac OS X/Unix environment, I have previously got freetype working on windows with VS 2008. Any help would be greatly appreciated.
What:
It seems you have more than one libfreetype.dylib file in your library search paths.
/master_repository/......../lib contains one and /usr/local/lib contains another
-lfreetype is a convenient way of telling the linker to look for file named libfreetype.dylib in all the directories specified with -L flags. Because -L/master_repository... comes before -L/usr/local/lib in the linker argument list, the linker uses the first instance it finds and attempts linking to that one.
Fix:
Reorganising your -L flags so that -L/usr/local/lib comes before the other. Avoid this option if you can.
Removing the extra search path, leaving only the relevant one.
Specifying the library explicitly instead of relying on the convenient -l by replacing -lfreetype with a full path to a library: /usr/local/lib/libfreetype.dylib

custom built gcc 4.6.0 on ubuntu 11.04 links wrong libstdc++

my custom built gcc 4.6.0, installed in my home directory, on ubuntu 10.04, links the system libstdc++ instead of the custom built one, most of the time (as evidenced by ldd). to be more puzzling, using this newly built gcc, custom compiled openmpi libraries are linked correctly, and this is the only software i have compiled that behaves ok. does anybody have any explanation for this, or a workaround?
thanks
Isn't there an option to statically link the libstdc into the gcc when you configure it? --disable-shared if I understand how it works correctly. Worst case make another compile of gcc with that switch and see if you run into the issue.
I don't know why this isn't detailed more clearly on the GCC website for end-users. The GCC FAQ clearly states this is a common problem wrt libstdc++. Environment variables are troublesome. Wrapping the linker, nobody knows how to do that. Editing /etc/ld.so.conf isn't an option. Adding -Wl,-rpath everywhere, come on. The easiest solution is the specs file. For a typical 64-bit x86 Linux system, go into your custom gcc installation, in dirname `g++ -print-libgcc-file-name`and then run g++ -dumpspecs > specs. Edit that file, find the *link_command: section. After %(link_libgcc) add -rpath /home/user/bin/gcc-9/lib64 (of course use your own path). Or add the same rpath to end of *link: section. Alternatively, configure gcc with --with-specs='%{!static:%x{-rpath=/home/user/bin/gcc9/lib64} %x{-enable-new-dtags}}' . Enjoy your own C++ compiler that generates binaries that just work.
See also:
GCC specs file: how to get the installation path
Linking g++ 4.8 to libstdc++
How to configure libstdc++ with GCC 4.8?

Resources