[distcc] Using cc1/cc1plus directly from distccd?

Stuart D. Gathman stuart at bmsi.com
Tue Feb 18 17:30:14 GMT 2003


Hello, I am new to distcc.  I have been using my own version of distributed 
gcc for 15 years.  It works by replacing cc1 and cc1plus with a stub that runs 
those programs on a remote system.  The remote system is typically running a 
cross compiler.  This allowed me to port GCC to SysV88 despite the fact that 
the included GreenHills compiler was too buggy to compile GCC.  It allowed me 
to port GCC to AIX without buying IBM's very good but very expensive compiler. 
  It now allows me to compile much faster on our old slow (100Mhz PPC604) AIX 
system than with the local compiler.

I wanted to upgrade my distributed cc1 system to:
1) Degrade gracefully to the local compiler when the remote system is not 
available
2) Use a TCP protocol to copy preprocessed C input and assembler output, 
instead of the clumsy remsh.

Lo and behold, I found distcc which already does everything I want - almost. 
The problem is that I compile only the cc1 and cc1plus cross compiler 
programs.  It is way too much trouble to get includes, libraries, etc 
installed in an alien system for a complete cross compiler.  These are in 
fact, the only programs needed for distcc (and my own stub).  However, distccd 
seems to call the gcc front end rather than cc1 or cc1plus.  Is there any way 
to avoid calling the front end on the volunteer system, and run only the 
compiler proper with distcc?

I have attached my 15 year old clumsy solution for the curious.  (Note, we 
didn't install RCS until 1994.)
-------------- next part --------------
/* run GNU compiler pass on remote machine
 * $Log: cc1.c,v $
 * Revision 1.8  2002/06/25  21:19:36  stuart
 * retrieve result code from remote execution
 *
 * Revision 1.7  2002/06/25  20:22:34  stuart
 * Support pipe
 *
 * Revision 1.6  2002/05/21  21:17:50  stuart
 * track input vs output files
 *
 * Revision 1.3  1994/03/08  15:51:56  stuart
 * getcwd needed trailing slash
 *
 * Revision 1.2  1994/03/08  15:41:18  stuart
 * print version and remsh command when -version
 *
 */
static const char what[] = "$Id: cc1.c,v 1.8 2002/06/25 21:19:36 stuart Exp stuart $";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>

extern char *getcwd(char *,int);

static void *xmalloc(size_t n) {
  void *p = malloc(n);
  if (!p) {
    perror("malloc");
    exit(1);
  }
  return p;
}

static char *cat(const char *a,const char *b) {
  int len = strlen(a);
  char *p = xmalloc(len + strlen(b) + 1);
  strcpy(p,a);
  strcpy(p+len,b);
  return p;
}

const char *basename(const char *s) {
  const char *p = strrchr(s,'/');
  return p ? ++p : s;
}

enum { MAXCLEAN = 10 };
static char *cleanup[MAXCLEAN];
static int cleancnt = 0;

static void preClean(char *c) {
  int i;
  if (cleancnt < MAXCLEAN) {
    for (i = cleancnt++; i > 0; --i)
      cleanup[i] = cleanup[i - 1];
    cleanup[0] = c;
  }
}

static void addClean(char *c) {
  if (cleancnt < MAXCLEAN) {
    cleanup[cleancnt++] = c;
  }
}

/* convert a local pathname to an input pathname for the remote compiler */
static char *makeInput(char *s,const char *sys) {
  if (strcmp(s,"-")) {
    char *ns = cat("/usr/tmp/",basename(s));
    char *buf = xmalloc(strlen(sys) + strlen(ns) + strlen(s) + 8);
    sprintf(buf,"rcp %s %s:%s",s,sys,ns);
    system(buf);
    buf = xmalloc(strlen(sys) + strlen(ns) + 12);
    sprintf(buf,"remsh %s rm %s",sys,ns);
    addClean(buf);
    return ns;
  }
  return s;
}

static char *outfile = 0;

/* convert a local pathname to an output pathname for the remote compiler */
static char *makeOutput(char *s,const char *sys) {
  if (s[0] == '/') {
    if (!outfile) {
      char *ns = cat("/usr/tmp/",basename(s));
      char *buf = xmalloc(strlen(sys) + strlen(ns) + strlen(s) + 8);
      sprintf(buf,"rcp %s:%s %s",sys,ns,s);
      addClean(buf);
      buf = xmalloc(strlen(sys) + strlen(ns) + 12);
      sprintf(buf,"remsh %s rm %s",sys,ns);
      addClean(buf);
      return ns;
    }
  }
  return s;
}

int main(int argc,char **argv) {
  int i, j, rc;
  char quiet = 1, input = 1;
  char **nargv;
  const char *sys = "bmsred";
  const char *resname = tempnam("/var/tmp","remcc");
  char *buf = xmalloc(strlen(sys) + strlen(resname) + 16);
  FILE *p;
  sprintf(buf,"remsh %s -n rm %s",sys,resname);
  addClean(buf);

  for (i = 1; i < argc; ++i) {
    if (strcmp(argv[i],"-o") == 0) {
      if (++i >= argc) break;
      argv[i] = makeOutput(argv[i],sys);
    }
    else if (strcmp(argv[i],"-version") == 0)
      quiet = 0;
    else {
      const char *p = strrchr(argv[i],'.');
      if (p && p[1] == 'i') {
	argv[i]  = makeInput(argv[i],sys);
	input = 0;
      }
    }
  }

  nargv = calloc(argc + 7,sizeof *nargv);
  if (!nargv) {
    perror("calloc");
    return 1;
  }
  j = 0;
  nargv[j++] = "remsh";
  nargv[j++] = sys;
  if (!input)
    nargv[j++] = "-n";
  nargv[j++] = "nice";
  nargv[j] = cat("/usr/local/lib/gcc-lib/powerpc-aix/2.95.3/",basename(argv[0]));
  for (i = 1; i < argc; ++i)
    nargv[i + j] = argv[i];
  nargv[j++ + argc] = "; echo $? >";
  nargv[j + argc] = resname;

  if (!quiet) {
    fprintf(stderr,"%s\n",what);
    fputs(nargv[0],stderr);
    for (i = 1; nargv[i]; ++i) {
      putc(' ',stderr);
      fputs(nargv[i],stderr);
    }
    putc('\n',stderr);
  }

  if (spawnv(P_WAIT,"/usr/bin/remsh",nargv)) {
    perror("remsh");
    return 1;
  }
  buf = xmalloc(strlen(sys) + strlen(resname) + 16);
  sprintf(buf,"remsh %s -n cat %s",sys,resname);
  p = popen(buf,"r");
  fgets(buf,strlen(buf) + 1,p);
  pclose(p);
  rc = atoi(buf);

  for (i = 0; i < cleancnt; ++i) {
    system(cleanup[i]);
    /* free(cleanup[i]); */
  }
  return rc;
}


More information about the distcc mailing list