I've created some wrapper functions that encapsulate working with CoreAudio, and the goal is to create a C library that I can use with some command line C++ tools. So far things are working well. I took a sample project, modified it, and it builds and runs in XCode. I'd like to skip XCode altogether and build the library with gcc and a Makefile.
How can I link against an Apple Framework? Are Frameworks just shared libraries that I could include in the -l and -L options on gcc?
Here's an example:
gcc -framework CoreServices -o test test.c
From the man page of Apple's gcc (i686-apple-darwin10-gcc-4.2.1):
In addition to the options listed below, Apple's GCC also accepts and
passes nearly all of the options defined by the linker ld and by the
library tool libtool. Common options include -framework, -dynamic,
-bundle, -flat_namespace, and so forth. See the ld and libtool man
pages for further details.
And from ld's man page:
-framework name[,suffix]
This option tells the linker to search for `name.frame-
work/name' the framework search path. If the optional suffix
is specified the framework is first searched for the name
with the suffix and then without (e.g. look for `name.frame-
work/name_suffix' first, if not there try `name.frame-
work/name').
Related
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.
This file: MoltenVK Runtime User Guide offers a nice description of how to link MoltenVK to a project that uses it, within XCode.
I prefer using makefiles, as it removes the need to boot up XCode to build (+ is a consistent workflow with the same project on Linux).
The problem is there's quite a bit of OSX/XCode specific terminology in the instructions, and I'm not quite sure how it translates to running clang via command line.
If you assume I'm looking to link only with the minimum specified to use MoltenVK, what would such a command line argument look like?
Here is my minimal attempt:
MOLTENVKDIR = /blah/vulkansdk-macos-1.1.108.0
a.out: my_headers.h my_src_files.cpp
clang -I$(MOLTENVKDIR)/MoltenVK/include -L$(MOLTENVKDIR)/MoltenVK/macOS/dynamic -lMoltenVK my_src_files.cpp
More specific questions:
How should I be setting LD_RUNPATH_SEARCH_PATHS? I assume this is a PATH-style variable that gets embedded in the executable with a list of places to look for the MoltenVK.dylib file?
In step 4 of the user guide, it says "drag (MoltenVK/macOS/dynamic/libMoltenVK.dylib) to the Link Binary With Libraries list"- is that essentially the -lMoltenVK line?
Where does step 5 come in? Should I append -framework Metal -framework Foundation -framework ...? What should I do with the .tbd file?
Is step 6 just ensuring that I copy the libMoltenVK.dylib file relative to a.out consistent with LD_RUNPATH_SEARCH_PATHS?
Is step 7 safe to ignore, as I'm not using XCode?
TLDR; I use g++, use the flags -lMoltenVK and -L$(MOLTENVK_DIR), and at the top define VK_ICD_FILENAMES using export VK_ICD_FILENAMES=$(ICD_DIR)
Header Search Paths is -I$(PATH)
Library Search Paths is -L$(PATH)
Runpath Search Paths is -rpath $(PATH) (with the space)
What I did was copy the .dylibs into a folder called lib in my project folder, set Library Search Path with -Llib, and link them with -lvulkan and -lMoltenVK. Since these dynamic libraries are hardwired to use #rpath when linking, I set -rpath lib.
You can see the vulkan tutorial for linux which uses a Makefile which shows a very basic version of making a Makefile for Vulkan on linux (no MoltenVK)
Most importantly, to not get a VkResult -9 when calling vkCreateInstance (MoltenVK not installed properly) make sure to define the VK_ICD_FILENAMES environment variable! I did this by writing export VK_ICD_FILENAMES=lib/MoltenVK_icd.json near the top of my Makefile, and copied the MoltenVK_icd.json file to my project! This is a file which points to where the dylib is, and is necesarry for MoltenVK to work. When installing MoltenVK, it was inside the same folder as libMoltenVK.dylib
Similarily, you must define VK_LAYER_PATH for validation layers to work.
Minimally, all you need for MoltenVK is:
export VK_ICD_FILENAMES=lib/MoltenVK_icd.json
main:
g++ test.cpp -o App -Llib -rpath lib -lMoltenVK
I'm not an expert in best practices and conventions, I do what works. Hope this helped
I am a regular C programmer, and there's something I have wondered for some time about GNU GCC/LD internals.
I have noticed that, when passing a sequence of object files to GCC (e.g gcc main.o otherfile.o), GCC automatically links libc.a library file without my explicitly specifying -lc in the options. Similarly, when I compile a program using ncurses, I just need to specify -lncurses and libtinfo.a gets linked automatically (no need to specify -ltinfo). In other words, even though ncurses functions use functions from libtinfo (for instance, unctrl()), I don't need to explicitly link libtinfo.
How can it be possible?
Does GCC/LD have a list of "default libraries" where it looks for missing symbols when linking? If such a table exists, where is it and how can it be configured?
A direct answer is that you can see what libraries are linked by command line options by adding -v to the linking command line. This will show you the commands as they are executed.
The C library and the GCC support library or libraries are linked automatically; other libraries have to be specified manually.
The case of -lncurses and libtinfo.a (libtinfo.so?) is rather different. There, the link command used to build libncurses.so tells the linker that this library also needs -ltinfo, so it automatically picks up the extra library.
Suppose I have a third party library called somelib.a on a Mac running Mountain Lion with Xcode 4.4 installed. I want to get a dynamic library out of it called somelib.dylib. An appropriate Linux command would be:
g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.so
where -whole-archive and -no-whole-archive are passed to the linker.
When I do the equivalent for Mac:
g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.dylib
ld fails with an error:
ld: unknown option: -whole-archive
It seems that the ld on OSX is different from GNU ld. How do I have to modify above command so I will get the desired result?
Thank you in advance!
I found out the solution to my problem:
g++ -fpic -shared -Wl,-force_load somelib.a -o somelib.dylib
The required argument is -force_load:
Which needs to be followed by a single library you wanna ensure gets loaded.
I mean, it needs to be repeated for each library (unlike -noall_load approach, which wrapped them).
For example, -Wl,-force_load libYetAnotherFile.a (where -Wl, part is only required because we don't pass parameter directly to linker).
Note that Old answer (before edit) was using -noall_load instead, but nowadays that causes a linker error (as -noall_load has been removed, was obsolete previously).
Note: A link for the documentation of the OSX ld linker.
http://www.unix.com/man-page/osx/1/ld/
I know it is late to give an answer for this, but I do not have enough reputation to make a comment on #hanslovsky answer.
However, it helps me a lot to have the docs of the options too.
It helps what the options do exactly, and that other options the ld linker also has.
So I just wanted to share with others who finds linking an issue.
UPDATE:
After the comment from #GhostCat I have decided to expand my answer.
The docs for -all_load is:
-all_load
Loads all members of static archive libraries.
So it loads for all static libraries that you note.
If you want something similar to --whole-archive and --no-whole-archive, then you need to use -force_load and -noall_load.
-force_load "path_to_archive"
Loads all members of the specified static archive library. Note: -
all_load forces all members of all archives to be loaded.
This option allows you to target a specific archive.
-noall_load
This is the default. This option is obsolete.
Then you can define which libraries to fully load with -force_load and then later turn it off again with -noall_load.
According to the ld manual, -noall_load is the default and is ignored. (If you use it, you get an error message: ld: warning: option -noall_load is obsolete and being ignored)
Apparently the way to get -all_load to apply to only one library is as follows:
-Wl,-force_load,somelib.a
I'm building few command-line utilities in Xcode (plain C, no Cocoa). I want all of them to use my customized version of libpng, and I want to save space by sharing one copy of the library among all executables (I don't mind re-distributing .dylib with them).
Do I need to do some magic to get libpng export symbols?
Does "Link Binary With Libraries" build phase link statically?
Apple's docs mention loading of libraries at run time with dlopen, but how I can make Xcode create executable without complaining about missing symbols?
I think I've figured it out:
libpng wasn't linking properly, because I've built 32/64-bit executables and 32-bit library. Build settings of the library and executables must match.
libpng's config.h needs to have tons of defines like #define FEATURE_XXX_SUPPORTED
"Link Binary With Libraries" build phase handles dynamic libraries just fine, and DYLD_FALLBACK_LIBRARY_PATH environmental variable is neccessary for loading .dylibs from application bundle.
Dynamic linking on Mac OS X, a tiny example
Steps:
create a library libmylib.dylib containing mymod.o
compile and link a "callmymod" which calls it
call mymod from callmymod, using DYLD_LIBRARY_PATH and DYLD_PRINT_LIBRARIES
Problem: you "just" want to create a library for other modules to use.
However there's a daunting pile of programs -- gcc, ld, macosx libtool, dyld --
with zillions of options, some well-rotted compost, and differences between MacOSX and Linux.
There are tons of man pages (I count 7679 + 1358 + 228 + 226 lines in 10.4.11 ppc)
but not much in the way of examples, or programs with a "tell me what you're doing" mode.
(The most important thing in understanding is to make a simplified
OVERVIEW for yourself: draw some pictures, run some small examples,
explain it to someone else).
Background: apple OverviewOfDynamicLibraries,
Wikipedia Dynamic_library
Step 1, create libmylib.dylib --
mymod.c:
#include <stdio.h>
void mymod( int x )
{
printf( "mymod: %d\n", x );
}
gcc -c mymod.c # -> mymod.o
gcc -dynamiclib -current_version 1.0 mymod.o -o libmylib.dylib
# calls libtool with many options -- see man libtool
# -compatibility_version is used by dyld, see also cmpdylib
file libmylib.dylib # Mach-O dynamically linked shared library ppc
otool -L libmylib.dylib # versions, refs /usr/lib/libgcc_s.1.dylib
Step 2, compile and link callmymod --
callmymod.c:
extern void mymod( int x );
int main( int argc, char** argv )
{
mymod( 42 );
}
gcc -c callmymod.c
gcc -v callmymod.o ./libmylib.dylib -o callmymod
# == gcc callmymod.o -dynamic -L. -lmylib
otool -L callmymod # refs libmylib.dylib
nm -gpv callmymod # U undef _mymod: just a reference, not mymod itself
Step 3, run callmymod linking to libmylib.dylib --
export DYLD_PRINT_LIBRARIES=1 # see what dyld does, for ALL programs
./callmymod
dyld: loaded: libmylib.dylib ...
mymod: 42
mv libmylib.dylib /tmp
export DYLD_LIBRARY_PATH=/tmp # dir:dir:...
./callmymod
dyld: loaded: /tmp/libmylib.dylib ...
mymod: 42
unset DYLD_PRINT_LIBRARIES
unset DYLD_LIBRARY_PATH
That ends one tiny example; hope it helps understand the steps.
(If you do this a lot, see GNU Libtool
which is glibtool on macs,
and SCons.)
You probably need to ensure that the dynamic library you build has an exported symbols file that lists what should be exported from the library. It's just a flat list of the symbols, one per line, to export.
Also, when your dynamic library is built, it gets an install name embedded within it which is, by default, the path at which it is built. Subsequently anything that links against it will look for it at the specified path first and only afterwards search a (small) set of default paths described under DYLD_FALLBACK_LIBRARY_PATH in the dyld(1) man page.
If you're going to put this library next to your executables, you should adjust its install name to reference that. Just doing a Google search for "install name" should turn up a ton of information on doing that.
Unfortunately, in my experience Apple's documentation is antiquated, redundant and missing a LOT of common information that you would normally need.
I wrote a bunch of stuff on this on my website where I had to get FMOD (Sound API) to work with my cross platform game that we developed at uni. Its a weird process and I'm surprised that Apple do not add more info on their developer docs.
Unfortunately, as "evil" as Microsoft are, they actually do a much better job of looking after their devs with documentation ( this is coming from an Apple evangelist ).
I think basically, what you are not doing is AFTER you have compiled your .app Bundle. You then need to run a command on the executable binary /MyApp.app/contents/MacOS/MyApp in order to change where the executable looks for its library file. You must create a new build phase that can run a script. I won't explain this process again, I have already done it in depth here:
http://brockwoolf.com/blog/how-to-use-dynamic-libraries-in-xcode-31-using-fmod
Hope this helps.
Are you aware of the Apple reference page Dynamic Library Programming Topics? It should cover most of what you need. Be aware that there a shared libraries that get loaded unconditionally at program startup and dynamically loaded libraries (bundles, IIRC) that are loaded on demand, and the two are somewhat different on MacOS X from the equivalents on Linux or Solaris.