|
| 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