diff options
author | Shawn Landden <slandden@gmail.com> | 2017-11-25 23:42:43 -0800 |
---|---|---|
committer | Shawn Landden <slandden@gmail.com> | 2018-02-25 18:58:54 -0800 |
commit | 2b160f3d20bc235c02c3b3da89d02a52509768e8 (patch) | |
tree | 2421b5f52ebbb1936696a0da0741f32521a7a258 | |
parent | 6dadc5f64b6f3ecbcb213974923cfcd4454bdc4c (diff) | |
download | distcc-git-2b160f3d20bc235c02c3b3da89d02a52509768e8.tar.gz |
cross-compilation support
-rw-r--r-- | man/distcc.1 | 5 | ||||
-rw-r--r-- | src/compile.c | 90 |
2 files changed, 95 insertions, 0 deletions
diff --git a/man/distcc.1 b/man/distcc.1 index 9ab9afb..296d8f4 100644 --- a/man/distcc.1 +++ b/man/distcc.1 @@ -762,6 +762,11 @@ variable is set to 0 then fallbacks are disabled and those compilations will simply fail. Note that this does not affect jobs which must always be local such as linking. .TP +.B "DISTCC_NO_CROSS_REWRITE" +By default distcc will rewrite calls gcc to use fully qualified names +(like x86_64-linux-gnu-gcc), and clang to use the -target option. Setting this +turns that off. +.TP .B "DISTCC_BACKOFF_PERIOD" Specifies how long (in seconds) distcc will avoid trying to use a particular compilation server after that server yields a compile diff --git a/src/compile.c b/src/compile.c index df73e9c..f78faa2 100644 --- a/src/compile.c +++ b/src/compile.c @@ -445,6 +445,92 @@ static int dcc_please_send_email_after_investigation( return dcc_note_discrepancy(discrepancy_filename); } +/* Clang is a native cross-compiler, but needs to be told to what target it is + * building. + * TODO: actually probe clang with clang --version, instead of trusting + * autoheader. + */ +static void dcc_add_clang_target(char **argv) +{ + /* defined by autoheader */ + const char *target = GNU_HOST; + + if (strcmp(argv[0], "clang") == 0 || strncmp(argv[0], "clang-", strlen("clang-")) == 0 || + strcmp(argv[0], "clang++") == 0 || strncmp(argv[0], "clang++-", strlen("clang++-")) == 0) + ; + else + return; + + if (dcc_argv_search(argv, "-target")) + return; + + rs_log_info("Adding '-target %s' to support clang cross-compilation.", + target); + dcc_argv_append(argv, strdup("-target")); + dcc_argv_append(argv, strdup(target)); +} + +/* + * Cross compilation for gcc +*/ +static int dcc_gcc_rewrite_fqn(char **argv) +{ + /* defined by autoheader */ + const char *target_with_vendor = GNU_HOST; + char *newcmd, *t, *path; + int pathlen = 0; + + if (strcmp(argv[0], "gcc") == 0 || strncmp(argv[0], "gcc-", strlen("gcc-")) == 0 || + strcmp(argv[0], "g++") == 0 || strncmp(argv[0], "g++-", strlen("g++-")) == 0) + ; + else + return -ENOENT; + + + newcmd = malloc(strlen(target_with_vendor) + 1 + strlen(argv[0] + 1)); + if (!newcmd) + return -ENOMEM; + + if ((t = strstr(target_with_vendor, "-pc-"))) { + strncpy(newcmd, target_with_vendor, t - target_with_vendor); + strcat(newcmd, t + strlen("-pc")); + } else + strcpy(newcmd, target_with_vendor); + + + strcat(newcmd, "-"); + strcat(newcmd, argv[0]); + + /* TODO, is this the right PATH? */ + path = getenv("PATH"); + do { + char binname[strlen(path) + 1 + strlen(newcmd) + 1]; + int r; + + /* emulate strchrnul() */ + t = strchr(path, ':'); + if (!t) + t = path + strlen(path); + pathlen = t - path; + if (*path == '\0') + return -ENOENT; + strncpy(binname, path, pathlen); + binname[pathlen] = '\0'; + strcat(binname, "/"); + strcat(binname, newcmd); + r = access(binname, X_OK); + if (r < 0) + continue; + /* good!, now rewrite */ + rs_log_info("Re-writing call to '%s' to '%s' to support cross-compilation.", + argv[0], newcmd); + free(argv[0]); + argv[0] = newcmd; + return 0; + } while ((path += pathlen + 1)); + return -ENOENT; +} + /** * Execute the commands in argv remotely or locally as appropriate. * @@ -521,6 +607,10 @@ dcc_build_somewhere(char *argv[], ret = dcc_scan_args(argv, &input_fname, &output_fname, &new_argv); dcc_free_argv(argv); argv = new_argv; + if (!getenv("DISTCC_NO_REWRITE_CROSS")) { + dcc_add_clang_target(new_argv); + dcc_gcc_rewrite_fqn(new_argv); + } if (ret != 0) { /* we need to scan the arguments even if we already know it's * local, so that we can pick up distcc client options. */ |