Skip to content

Commit 865c089

Browse files
committed
Add setdyld_lib_path.c + a list of known OSX SDK bugs and caveats
1 parent d3c056c commit 865c089

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

README.md

+31
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,37 @@ ld: unknown option: -no_deduplicate
9898
```
9999
The reason is that the newer versions of the linker introduced the option `-no_deduplicate`, which Xcode adds by default. To disable this, add a User-Defined build setting in Xcode named `LD_DONT_RUN_DEDUPLICATION` and set its value to `NO`.
100100

101+
Known bugs (and fixes) in OS X SDKs
102+
-----------------------------------
103+
104+
### Recent GCC versions cannot build universal binaries
105+
106+
The GCC in Apple SDK is actually a small binary that lauches several compilers and merges the results (see [driverdriver.c](http://opensource.apple.com/source/gcc/gcc-5666.3/driverdriver.c)). The same executable can be compiled for recent GCC versions too, see [devernay/macportsGCCfixup](https://github.com/devernay/macportsGCCfixup) on github.
107+
108+
### bad_typeid dyld Error on Leopard (10.5)
109+
110+
This is a bug in the 10.6 (and later) SDKs, which can be easily fixed:
111+
112+
- http://lists.apple.com/archives/xcode-users/2010/May/msg00183.html
113+
- http://stackoverflow.com/questions/12980931/how-to-ignore-out-of-line-definition-error-in-xcode-with-llvm-4-1
114+
115+
### code compiled with g++ > 4.2.1 crashes with "pointer being freed not allocated"
116+
117+
The problem comes from the fact that some system frameworks load the system libstdc++, which results in incompatible data structures.
118+
119+
After exploring various options (install_name_tool, rpath, etc.), the only solution is to set the environment variable `DYLD_LIBRARY_PATH` to the path of a directory where you *only* put a symbolic link to the newest libstdc++ from GCC (libstdc++ is guaranteed to be backward-compatible, not other libraries).
120+
121+
If you are building an application bundle, you should replace your executable by a small executable that sets the environment variable `DYLD_LIBRARY_PATH`. It can be a script (see below), or a binary (better, because it handles spaces in arguments correctly).
122+
123+
The [`setdyld_lib_path.c`](setdyld_lib_path.c) source code can be compiled to act as a "launcher" for your binary that correctly sets the `DYLD_LIBRARY_PATH` variable. See the full instructions at the top of the source file.
124+
125+
An alternate solution, using a shell-script (doesn't handle spaces in arguments): http://devblog.rarebyte.com/?p=157
126+
127+
Other references:
128+
129+
- http://stackoverflow.com/questions/6365772/unable-to-run-an-application-compiled-on-os-x-snow-leopard-10-6-7-on-another-m
130+
- http://stackoverflow.com/questions/4697859/mac-os-x-and-static-boost-libs-stdstring-fail
131+
101132
License
102133
-------
103134
This script is distributed under the [Creative Commons BY-NC-SA 3.0 license](http://creativecommons.org/licenses/by-nc-sa/3.0/).

setdyld_lib_path.c

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
setdyld_lib_path.c
3+
4+
Author: Frederic Devernay <[email protected]>
5+
6+
Licence:
7+
Creative Commons BY-NC-SA 3.0 license
8+
http://creativecommons.org/licenses/by-nc-sa/3.0/
9+
10+
This small sample program sets the environment variable
11+
DYLD_LIBRARY_PATH and executes another binary with the same
12+
arguments.
13+
14+
This can be used when a given program was compiled using GCC
15+
libraries that are different from the system-provided ones,
16+
e.g. when compiling with a recent version of GCC. In this case, put
17+
the GCC libraries (and only these) in a directory, and modify
18+
DYLD_LIBRARY_PATH in the code below to point to the correct
19+
lcation. These libraries are mad to be backward-compatible. Never
20+
set DYLD_LIBRARY_PATH to a directory containing all your shared
21+
libraries, because the system frameworks sometimes load shared
22+
libraries which have very common names (eg the ImageIO framework
23+
loads a libJPEG.dylib), and may not work anymore.
24+
25+
In the following example, the binary name is the name of this
26+
executable with the suffix "-driver", and the DYLD_LIBRARY_PATH is
27+
%s/../Frameworks/libgcc where %s is the dirname of this
28+
executable. These should probably be adated to your needs.
29+
30+
This sample is part of the xcodelegacy source code.
31+
https://github.com/devernay/xcodelegacy
32+
*/
33+
#if __APPLE__
34+
#include <stdio.h>
35+
#include <stdlib.h>
36+
#include <string.h>
37+
#include <unistd.h>
38+
#include <libgen.h>
39+
#include <sys/errno.h>
40+
#include <mach-o/dyld.h> /* for _NSGetExecutablePath(char* buf, uint32_t* bufsize); */
41+
#include <limits.h> /* PATH_MAX */
42+
43+
int main(int argc, char *argv[])
44+
{
45+
char programPath[PATH_MAX];
46+
uint32_t buflen = PATH_MAX;
47+
_NSGetExecutablePath(programPath, &buflen);
48+
49+
/* append "-driver" to the program name to get the executable binary path */
50+
strncat(programPath, "-driver", PATH_MAX - strlen(programPath) - 1);
51+
52+
/*
53+
* set the DYLD_LIBRARY_PATH environment variable to the directory containing only a link to libstdc++.6.dylib
54+
* and re-exec the binart. The re-exec is necessary as the DYLD_LIBRARY_PATH is only read at exec.
55+
*/
56+
char *dyldLibraryPathDef;
57+
char *programDir = dirname(programPath);
58+
if (asprintf(&dyldLibraryPathDef, "DYLD_LIBRARY_PATH=%s/../Frameworks/libgcc", programDir) == -1) {
59+
fprintf(stderr, "Could not allocate space for defining DYLD_LIBRARY_PATH environment variable\n");
60+
exit(1);
61+
}
62+
putenv(dyldLibraryPathDef);
63+
execv(programPath, argv); // note that argv is always NULL-terminated
64+
65+
fprintf(stderr, "execv(%s(%d), %s(%d), ...) failed: %s\n", programPath, (int)strlen(programPath), argv[0], (int)strlen(argv[0]), strerror(errno));
66+
exit(1);
67+
}
68+
#endif

0 commit comments

Comments
 (0)