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));