As noted in PR 14316, collect2 doesn't build on Windows due to the use of vfork. There have been at least two patches to address this, one of them from me, one from Zack.
My patch is here: http://gcc.gnu.org/ml/gcc-patches/2004-03/msg01445.html Zack had some comments: http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00227.html http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00637.html http://gcc.gnu.org/ml/gcc-patches/2004-04/msg01044.html And at that point I kind of ran out of steam. Anyhow, I've returned to the issue, and I've tried to put together an interface based on Zack's suggestion which can handle everything we might want to handle. I'm not too crazy about it--there are several different requirements, and so the interface has again gotten kind of complicated. It implements what collect2 needs, and I think can also do most of what gcc.c needs to implement -time, -pipe, and --save-temps. At the moment I've implemented a Unix version. Versions for other operating systems should not be difficult. I'd like to hear comments on this interface. Thanks. Ian /* Flags for pex_init. These are bits to be or'ed together. */ /* Record subprocess times if possible. */ #define PEX_RECORD_TIMES (1) /* Use files for communication between processes. Each file will hold one process's standard output, and will be used for standard input for the next process (if any). If this flag is set, the TEMPBASE argument to pex_init must not be NULL. The SUFFIX argument to pex_run will be appended to TEMPBASE to form the file name. If the SUFFIX argument is NULL, no file will be saved (i.e., PEX_SAVE_TEMPS may be overridden on a program by program basis). If PEX_SAVE_TEMPS is not set, communication will use pipes when possible, and will otherwise use temporary files which will be removed when they are no longer needed. */ #define PEX_SAVE_TEMPS (2) /* Prepare to execute one or more programs, with standard output of each program fed to standard input of the next. FLAGS are above, PNAME is the name of the program for error messages, TEMPBASE is a base name to use for temporary/intermediate files if needed. PNAME and TEMPBASE must be valid at least until the call to pex_free. If PEX_SAVE_TEMPS is not set, TEMPBASE may be NULL to use a random file name if one is needed. Returns NULL on error. */ extern struct pex_obj *pex_init PARAMS ((int flags, const char *pname, const char *tempbase)); /* Flags for pex_run. These are bits to be or'ed together. */ /* Last program in pipeline. Standard output of program is standard output of caller. Do not use this if you want to call pex_read_output. */ #define PEX_LAST (1) /* Search for program in executable search path. */ #define PEX_SEARCH (2) /* Send program's standard error to standard output. */ #define PEX_STDERR_TO_STDOUT (4) /* Execute one program. Returns NULL on success. On error returns an error string (typically just the name of a system call) and sets *ERR to an errno value or to 0 if there is no relevant errno. OBJ is returned by pex_init, FLAGS are above, EXECUTABLE is the program to execute, ARGV is the arguments to pass, SUFFIX is a suffix to use for a temporary file if needed. SUFFIX may be NULL to use a random file name if one is needed, and to override the setting of PEX_SAVE_TEMPS. */ extern const char *pex_run PARAMS ((struct pex_obj *obj, int flags, const char *executable, char * const *argv, const char *suffix, int *err)); /* Read the standard output of the last program to be executed. pex_run can not be called after this. Returns NULL on error. Don't fclose the return value; it will be closed by pex_free. */ extern FILE *pex_read_output PARAMS ((struct pex_obj *)); /* Return exit status of all programs. The status codes in the vector are ordered by the calls to pex_run. Returns 0 on error, 1 on success. */ extern int pex_get_status PARAMS ((struct pex_obj *, int count, int *vector)); /* Return times of all programs. This is really just struct timeval, but that is not portable to all systems. Returns 0 on error, 1 on success. */ struct pex_time { unsigned long user_seconds; unsigned long user_microseconds; unsigned long system_seconds; unsigned long system_microseconds; }; extern int pex_get_times PARAMS ((struct pex_obj *, int count, struct pex_time *vector)); /* Clean up a pex_obj. */ extern void pex_free PARAMS ((struct pex_obj *)); /* Just execute one program. On success, returns NULL and puts the exit status in *STATUS. On failure, returns an error string and sets *ERR as for pex_run. */ extern const char *pex_one PARAMS ((const char *executable, char * const *argv, const char *pname, int *status, int *err));