diff options
Diffstat (limited to 'lang/ifc8/files/ld.c')
-rw-r--r-- | lang/ifc8/files/ld.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/lang/ifc8/files/ld.c b/lang/ifc8/files/ld.c new file mode 100644 index 000000000000..d06d451b2945 --- /dev/null +++ b/lang/ifc8/files/ld.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2002-2003 Marius Strobl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Wrapper for Intel(R) C/C++ Compiler for Linux to allow linking of native + * FreeBSD binaries. + * Based on a shell-script written by Dan Nelson <dnelson@allantgroup.com> + * with some modifications by Alexander Leidinger <netchild@FreeBSD.org>. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: /tmp/pcvs/ports/lang/ifc8/files/Attic/ld.c,v 1.1 2004-01-19 14:52:12 maho Exp $"); + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <osreldate.h> + +#define PATH_LD "/usr/bin/ld" + +#define LDW_CPP (1<<0) +#define LDW_DYN (1<<1) +#define LDW_GPROF (1<<2) +#define LDW_PIC (1<<3) +#define LDW_THR (1<<4) +#define LDW_LGCC (1<<5) + +struct arglist { + size_t argc; + const char **argv; +}; + +static void addarg(struct arglist *al, const char *arg); +int main(int argc, char *argv[], char *envp[]); + +static void +addarg(struct arglist *al, const char *arg) +{ + const char **argv2; + + argv2 = realloc(al->argv, (al->argc + 1) * sizeof(al->argv[0])); + + if (argv2 == NULL) + err(1, NULL); + + al->argv = argv2; + + al->argv[al->argc++] = arg; +} + +int +main(int argc, char *argv[], char *envp[]) +{ + size_t i; + u_int flags; + const char *libc, *libthr, *icc_localbase; + struct arglist al = { 0, NULL }; + + flags = 0; + + if (argc == 1) + errx(1, "no input files"); + + if ((icc_localbase = getenv("ICC_LOCALBASE")) == NULL) + errx(1, "can't get ICC_LOCALBASE"); + +#ifdef DEBUG + printf("input: "); +#endif + +#define ARGCMP(i, x) !strcmp(argv[i], (x)) + + /* + * XXX This doesn't deal with whitespace but a) the output of the + * compiler should be fixed and b) the real linker is also picky + * about whitespace. + */ + for (i = 0; i < argc; i++) { +#ifdef DEBUG + printf("%s ", argv[i]); +#endif + + if (ARGCMP(i, "-CPLUSPLUS")) { + flags |= LDW_CPP; + continue; + } + + if (ARGCMP(i, "-MT") +/* ifc8 */ + || ARGCMP(i, "-lpthread")) { +/* ifc8 */ + flags |= LDW_THR; + continue; + } + + if (ARGCMP(i, "-PIC")) { + flags |= LDW_PIC; + continue; + } + + /* + * Check if the compiler wants us to do dynamic linking, i.e. + * the compiler was called with -shared or without -static. + * If the compiler was called with -static we shouldn't see + * "--dynamic-linker" here. + * Note: According to ld(1) this is "--dynamic-linker" but + * ICC passes "-dynamic-linker" to it. + */ + if (ARGCMP(i, "--dynamic-linker") || + ARGCMP(i, "-dynamic-linker") || ARGCMP(i, "-shared")) { + flags |= LDW_DYN; + continue; + } + + /* + * Link against libc_p when "-qp" or "-p" were given, + * "/usr/lib/gcrt1.o" indicates this. + */ + if (ARGCMP(i, "/usr/lib/gcrt1.o")) { + flags |= LDW_GPROF; + continue; + } + + if (ARGCMP(i, "-lgcc")) { + flags |= LDW_LGCC; + continue; + } + } + + /* + * Allow the user to specify an alternative threads library + * implementation, such as -lthr, or whatever. + */ +#if __FreeBSD_version >= 500016 + if ((libthr = getenv("PTHREAD_LIBS")) == NULL) +#endif + libthr = "-lc_r"; + /* + * Use the appropriate libs for libc and libthr when linking static + * and "-KPIC" or "-pg" where given. + */ + if (!(flags & LDW_DYN) && flags & (LDW_PIC | LDW_GPROF)) { + /* + * Let libc_p win above libc_pic when both, "-KPIC" and "-pg", + * where given, GCC does the same. + */ + if (!(flags & LDW_GPROF)) + libc = "-lc_pic"; + else { + char *p; + libc = "-lc_p"; + asprintf(&p, "%s_p", libthr); + if (p == NULL) + err(1, NULL); + libthr = p; + } + } else + libc = "-lc"; + +#ifdef DEBUG + printf("\n"); +#endif + + for (i = 0; i < argc; i++) { + if (ARGCMP(i, "-CPLUSPLUS") || ARGCMP(i, "-MT") || +/* ifc8 */ + ARGCMP(i, "-lpthread") || +/* ifc8 */ + ARGCMP(i, "-PIC")) + continue; + + /* prepend "-melf_i386" to the commandline */ + if (i == 0) { + addarg(&al, argv[0]); +#if __FreeBSD_version < 500042 + addarg(&al, "-melf_i386"); +#else + addarg(&al, "-melf_i386_fbsd"); +#endif + continue; + } + + /* Don't add obsolete flag "-Qy", don't add libgcc_s. */ + if (ARGCMP(i, "-Qy") || ARGCMP(i, "-lgcc_s")) + continue; + + /* + * Replace libcprts with libstlport_icc. The Dinkumware STL + * shipping with ICC has unresolvable glibc dependencies + * in both, the static and the dynamic, versions. + */ + if (ARGCMP(i, "-lcprts")) { + if (flags & LDW_CPP && !(flags & LDW_LGCC)) { + addarg(&al, + flags & LDW_DYN ? "-Bdynamic" : "-Bstatic"); + addarg(&al, "-lstlport_icc"); + } + continue; + } + + /* + * Link against libthr when compiling multi-threaded or C++ + * code (libcxa and libunwind depend on a threads library + * when compiling C++ source). + */ + if (ARGCMP(i, "-lc")) { + if (al.argc > 0 && + strncmp(al.argv[al.argc - 1], "-B", 2)) + addarg(&al, + flags & LDW_DYN ? "-Bdynamic" : "-Bstatic"); + if (flags & (LDW_CPP | LDW_THR)) { + addarg(&al, libthr); +#if __FreeBSD_version >= 500016 + addarg(&al, + flags & LDW_DYN ? "-Bdynamic" : "-Bstatic"); + addarg(&al, libc); +#endif + } else + addarg(&al, libc); + continue; + } + + /* Switch Linux stuff to FreeBSD counterparts. */ + if (ARGCMP(i, "/lib/ld-linux.so.2")) { +#if __FreeBSD_version >= 501105 + addarg(&al, "/libexec/ld-elf.so.1"); +#else + addarg(&al, "/usr/libexec/ld-elf.so.1"); +#endif + continue; + } + if (ARGCMP(i, "-L/usr/lib")) { + addarg(&al, "-L/usr/libexec/elf"); + addarg(&al, "-L/usr/libexec"); + addarg(&al, "-L/usr/lib"); + if (flags & LDW_CPP && !(flags & LDW_LGCC)) { + char *p; + asprintf(&p, "-L%s/lib", icc_localbase); + if (p == NULL) + err(1, NULL); + addarg(&al, p); + } + continue; + } + + /* + * Force libcxa, libcxaguard and libunwind to static linkage, + * since the dynamic versions have glibc dependencies. + * Don't add superfluous -Bdynamic. + */ + if (ARGCMP(i, "-Bdynamic") && i < argc - 1) { + if (ARGCMP(i + 1, "-lcxa") || + ARGCMP(i + 1, "-lcxaguard") || + ARGCMP(i + 1, "-lunwind")) { + addarg(&al, "-Bstatic"); + continue; + } + + if (ARGCMP(i + 1, "-lcprts") || + ARGCMP(i + 1, "-lgcc_s")) + continue; + } + + /* Don't add superfluous -Bstatic. */ + if (ARGCMP(i, "-Bstatic") && i < argc - 1 && + (ARGCMP(i + 1, "-lcprts") || ARGCMP(i + 1, "-lgcc_s") || + ARGCMP(i + 1, "-lunwind"))) + continue; + + /* + * Sanity check if every lib is prepended by a linkage option, + * add if missing. + */ + if (!strncmp(argv[i], "-l", 2) && al.argc > 0 && + strncmp(al.argv[al.argc - 1], "-B", 2)) { + if (ARGCMP(i, "-lcxa") || ARGCMP(i, "-lcxaguard") || + ARGCMP(i, "-limf") || ARGCMP(i, "-lirc") || + ARGCMP(i, "-lircmt") || ARGCMP(i, "-lunwind")) + addarg(&al, "-Bstatic"); + else + addarg(&al, + flags & LDW_DYN ? "-Bdynamic" : "-Bstatic"); + + addarg(&al, argv[i]); + continue; + } + + /* default */ + addarg(&al, argv[i]); + } + + /* Still something to do? */ + if (al.argc == 1) + errx(1, "no input files"); + +#ifdef DEBUG + printf("output: "); + + for (i = 0; i < al.argc; i++) + printf("%s ", al.argv[i]); + + printf("\n"); +#endif + + addarg(&al, NULL); + + /* Launch the real linker. */ + if (execve(PATH_LD, (char **)al.argv, envp) == -1) + err(1, "execing " PATH_LD); + + exit (1); +} |