blob: ccd19e3d2e514768d6d3243b5992c456c081bf33 [file] [log] [blame]
/* ltmain.c - C implementation of GNU Libtool
*
* Copyright (C) 1998-2000 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*
* As a special exception to the GNU General Public License, if you
* distribute this file as part of a program that contains a
* configuration script generated by Autoconf, you may include it under
* the same distribution terms that you use for the rest of that program.
*/
#include <sys/types.h>
#include <stdio.h> /* printf */
#include <stdlib.h> /* exit */
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include "ltopts.h"
#include "ltstr.h"
static char* pzTarget = NULL;
static char* pzSource = NULL;
static int oldLibs = 0;
static char* pzPicMode = "default";
static int xCompile = 0;
/* BEGIN-STATIC-FORWARD */
LOCAL void
parseCompileOpts LT_PARAMS((
int* pArgc,
char*** pArgv ));
/* END-STATIC-FORWARD */
EXPORT void
emitCompile( argc, argv )
int argc;
char** argv; /*end-decl*/
{
tSCC zDbgFmt[] = "set -x\n";
tSCC zQuiet[] = "run=\nshow=%s\n";
tSCC zDynFmt[] = "build_libtool_libs=%s\n";
tSCC zStatic[] = "build_old_libs=%s\n";
tSCC zModeName[] = "suppress_output=\nmodename='%s: %s'\nmode='%s'\n";
/*
* When we emit our script, we want the interpreter to invoke *US*
* if echo does not work right.
*/
tSCC zChkEcho[] =
"\n\nif test \"X`($echo '\\t') 2>/dev/null`\" = 'X\\t'\n\
then :\n\
else echo='%s --echo --' ; fi\n";
FILE* fp = HAVE_OPT( DRY_RUN ) ? stdout : popen( pz_shell, "w" );
if (fp == (FILE*)NULL) {
tSCC zErr[] = "%s error: fs error %d (%s) on popen( \"%s\",\"w\")\n";
fprintf( stderr, zErr, libtoolOptions.pzProgPath, errno,
strerror( errno ), pz_shell );
exit( EXIT_FAILURE );
}
# define CKSERV if (signalReceived != 0) { \
closeScript( fp ); if (scriptStatus == 0) scriptStatus = EXIT_FAILURE; \
return; }
# define CLOSEOK if (signalReceived != 0) { closeScript( fp ); return; }
parseCompileOpts( &argc, &argv );
/*
* Emit the default configuration set up at program configuration time
*/
fputs( pz_ltconfig, fp );
CKSERV;
fputs( apz_mode_cmd[ 0 ], fp );
CKSERV;
fprintf( fp, zChkEcho, libtoolOptions.pzProgPath );
CKSERV;
fprintf( fp, zQuiet, HAVE_OPT( QUIET ) ? ":" : "\"$echo\"" );
CKSERV;
/*
* IF we have DYNAMIC or STATIC, then we override the configured
* values. We emitted the configured values with `z_ltconfig'.
*/
if (HAVE_OPT( DYNAMIC ) && (oldLibs == 0))
fprintf( fp, zDynFmt, ENABLED_OPT( DYNAMIC ) ? "yes" : "no" );
if (HAVE_OPT( STATIC ) || oldLibs)
fprintf( fp, zStatic, ENABLED_OPT( STATIC )
? "yes" : (oldLibs ? "yes" : "no") );
if (HAVE_OPT( DEBUG )) {
fprintf( stderr, "%s: enabling shell trace mode\n",
libtoolOptions.pzProgName );
fputs( zDbgFmt, fp );
}
CKSERV;
if (HAVE_OPT( DLOPEN )) {
emitDlopenOption( fp );
CKSERV;
}
/*
* Insert our modal stuff and one shell option processing dinkleberry
* that one of the command scripts depends upon.
*/
fprintf( fp, zModeName, libtoolOptions.pzProgName,
apzModeName[ OPT_VALUE_MODE ], libtoolOptions.pzProgName );
CKSERV;
if (pzTarget == NULL) {
pzTarget = strrchr( pzSource, '/' );
if (pzTarget == NULL)
pzTarget = pzSource;
else
pzTarget++;
}
fputs( "libobj='", fp );
emitRawQuoted( pzTarget, fp );
fprintf( fp, "'\nbuild_old_libs=%s\n", oldLibs ? "yes" : "no" );
CKSERV;
fprintf( fp, "pic_mode=%s\n", pzPicMode );
CKSERV;
fputs( "base_compile='", fp );
for (;;) {
emitShellArg( *(argv++), fp, '"' );
CKSERV;
if (--argc <= 0)
break;
fputc( ' ', fp );
}
fputs( "'\n", fp );
{
struct stat stbf;
if (stat( pzSource, &stbf ) != 0) do {
char* pz = getenv( "source" );
if ( (pz != NULL)
&& (stat( pz, &stbf ) == 0)) {
pzSource = pz;
break;
}
pz = getenv( "srcdir" );
if (pz == NULL)
pz = getenv( "VPATH" );
if (pz != NULL) {
char* p = xmalloc( strlen( pz ) + strlen( pzSource ) + 2 );
sprintf( p, "%s/%s", pz, pzSource );
if (stat( p, &stbf ) == 0)
pzSource = p;
else
free( p );
}
} while (0);
fprintf( fp, "srcfile='%s'\n", pzSource );
}
emitCommands( fp, apz_mode_cmd[ OPT_VALUE_MODE ]);
}
EXPORT void*
xmalloc( size )
size_t size; /*end-decl*/
{
void* p = malloc( size );
if (p == NULL) {
fprintf( stderr, "%s error: cannot allocate %d bytes\n",
libtoolOptions.pzProgPath );
exit( EXIT_FAILURE );
}
return p;
}
LOCAL void
parseCompileOpts( pArgc, pArgv )
int* pArgc;
char*** pArgv; /*end-decl*/
{
tSCC zTooManyTargets[] =
"%s compile: you cannot specify `-o' more than once\n";
tSCC zNoTarget[] =
"%s compile: `-o' must specify an output file name\n";
tSCC zNoXcompile[] =
"%s compile: `-Xcompiler' must specify a cross compiler\n";
tSCC zEarlyOpts[] =
"%s compile: error: you cannot supply options before the command\n";
int argc = *pArgc;
char** argv = *pArgv;
tCC** newArgv = xmalloc( sizeof( char* ) * argc );
int newCt = 0;
int alocCt = argc;
tCC* pzCmd = NULL;
int i;
for (i=0; i<argc; i++) {
if (strncmp( argv[i], "-o", 2 ) == 0) {
if (pzTarget != NULL) {
fprintf( stderr, zTooManyTargets, libtoolOptions.pzProgPath );
exit( EXIT_FAILURE );
}
if (argv[i][2] != '\0')
pzTarget = (argv[i]) + 2;
else {
pzTarget = argv[ ++i ];
if (pzTarget == NULL) {
fprintf( stderr, zNoTarget, libtoolOptions.pzProgPath );
exit( EXIT_FAILURE );
}
}
} else if (strcmp( argv[i], "-static" ) == 0) {
oldLibs = 1;
} else if (strcmp( argv[i], "-prefer-pic" ) == 0) {
pzPicMode = "yes";
} else if (strcmp( argv[i], "-prefer-non-pic" ) == 0) {
pzPicMode = "no";
} else if (strcmp( argv[i], "-Xcompiler" ) == 0) {
if (argv[++i] == NULL) {
fprintf( stderr, zNoXcompile, libtoolOptions.pzProgPath );
exit( EXIT_FAILURE );
}
if (++newCt >= alocCt) {
alocCt = (alocCt + 8) & ~0x07;
newArgv = realloc( newArgv, alocCt * sizeof( char* ));
}
pzCmd = newArgv[ newCt-1 ] = argv[i];
} else if (strncmp( argv[i], "-Wc,", 4 ) == 0) {
char* pz = argv[i] + 4;
for (;;) {
while (isspace( *pz )) pz++;
if (*pz == NUL)
break;
if (++newCt >= alocCt) {
alocCt = (alocCt + 8) & ~0x07;
newArgv = realloc( newArgv, alocCt * sizeof( char* ));
}
newArgv[ newCt-1 ] = pz;
pz = strchr( pz, ',' );
if (pz == NULL)
break;
*(pz++) = NUL;
}
} else if (pzCmd == NULL) {
pzCmd = newArgv[ newCt++ ] = argv[i];
} else if (pzSource == NULL) {
pzSource = argv[i];
} else {
if (++newCt >= alocCt) {
alocCt = (alocCt + 8) & ~0x07;
newArgv = realloc( newArgv, alocCt * sizeof( char* ));
}
pzCmd = newArgv[ newCt-1 ] = pzSource;
pzSource = argv[i];
}
}
if (pzSource == NULL) {
fprintf( stderr, "%s compile: error: no source file to compile\n",
libtoolOptions.pzProgName );
exit( EXIT_FAILURE );
}
if (++newCt >= alocCt)
newArgv = realloc( newArgv, ++alocCt * sizeof( char* ));
newArgv[ newCt-1 ] = NULL;
*pArgc = newCt;
*pArgv = (char**)newArgv;
}
/*
* Local Variables:
* c-file-style: "stroustrup"
* indent-tabs-mode: nil
* tab-width: 4
* End:
* end of ltcompile.c */