summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Landden <slandden@gmail.com>2017-11-25 23:42:43 -0800
committerShawn Landden <slandden@gmail.com>2018-02-25 18:58:54 -0800
commit2b160f3d20bc235c02c3b3da89d02a52509768e8 (patch)
tree2421b5f52ebbb1936696a0da0741f32521a7a258
parent6dadc5f64b6f3ecbcb213974923cfcd4454bdc4c (diff)
downloaddistcc-git-2b160f3d20bc235c02c3b3da89d02a52509768e8.tar.gz
cross-compilation support
-rw-r--r--man/distcc.15
-rw-r--r--src/compile.c90
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. */