|
|
2bd749 |
/*******************************************************************/
|
|
|
2bd749 |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
2bd749 |
/* Copyright (C) 2016 Z. Gilboa */
|
|
|
2bd749 |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
2bd749 |
/*******************************************************************/
|
|
|
2bd749 |
|
|
|
2bd749 |
#include <string.h>
|
|
|
2bd749 |
#include <stdbool.h>
|
|
|
2bd749 |
#include <fcntl.h>
|
|
|
2bd749 |
#include <errno.h>
|
|
|
2bd749 |
#include <sys/stat.h>
|
|
|
2bd749 |
|
|
|
2bd749 |
#include <slibtool/slibtool.h>
|
|
|
2bd749 |
#include "slibtool_spawn_impl.h"
|
|
|
2bd749 |
|
|
|
5cc3b3 |
/*******************************************************************/
|
|
|
5cc3b3 |
/* */
|
|
|
5cc3b3 |
/* -o <ltlib> switches input result */
|
|
|
5cc3b3 |
/* ---------- --------------------- ----- ------ */
|
|
|
b07789 |
/* libfoo.a [-shared|-static] bar.lo libfoo.a */
|
|
|
5cc3b3 |
/* */
|
|
|
6d048d |
/* ar cru libfoo.a bar.o */
|
|
|
5cc3b3 |
/* ranlib libfoo.a */
|
|
|
5cc3b3 |
/* */
|
|
|
5cc3b3 |
/*******************************************************************/
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
static bool slbt_adjust_input_argument(char * arg, bool fpic)
|
|
|
5cc3b3 |
{
|
|
|
53aa85 |
char * slash;
|
|
|
5cc3b3 |
char * dot;
|
|
|
53aa85 |
char base[PATH_MAX];
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
if (*arg == '-')
|
|
|
5cc3b3 |
return false;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
if (!(dot = strrchr(arg,'.')))
|
|
|
5cc3b3 |
return false;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
if (strcmp(dot,".lo"))
|
|
|
5cc3b3 |
return false;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
if (fpic) {
|
|
|
53aa85 |
if ((slash = strrchr(arg,'/')))
|
|
|
53aa85 |
slash++;
|
|
|
53aa85 |
else
|
|
|
53aa85 |
slash = arg;
|
|
|
53aa85 |
|
|
|
53aa85 |
if ((size_t)snprintf(base,sizeof(base),"%s",
|
|
|
53aa85 |
slash) >= sizeof(base))
|
|
|
53aa85 |
return false;
|
|
|
53aa85 |
|
|
|
53aa85 |
sprintf(slash,".libs/%s",base);
|
|
|
53aa85 |
dot = strrchr(arg,'.');
|
|
|
5cc3b3 |
}
|
|
|
53aa85 |
|
|
|
53aa85 |
dot[1] = 'o';
|
|
|
53aa85 |
dot[2] = '\0';
|
|
|
53aa85 |
return true;
|
|
|
5cc3b3 |
}
|
|
|
5cc3b3 |
|
|
|
3b5e3d |
static int slbt_exec_link_create_archive(
|
|
|
5cc3b3 |
const struct slbt_driver_ctx * dctx,
|
|
|
a51ace |
struct slbt_exec_ctx * ectx,
|
|
|
3b5e3d |
const char * arfilename,
|
|
|
3b5e3d |
bool fpic)
|
|
|
5cc3b3 |
{
|
|
|
5cc3b3 |
char ** aarg;
|
|
|
5cc3b3 |
char ** parg;
|
|
|
5cc3b3 |
char * ranlib[3];
|
|
|
3c594d |
char program[PATH_MAX];
|
|
|
3c594d |
char output [PATH_MAX];
|
|
|
5cc3b3 |
|
|
|
e7ddb2 |
/* initial state */
|
|
|
e7ddb2 |
slbt_reset_arguments(ectx);
|
|
|
e7ddb2 |
|
|
|
5cc3b3 |
/* placeholders */
|
|
|
5cc3b3 |
slbt_reset_placeholders(ectx);
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
/* alternate program (ar, ranlib) */
|
|
|
5cc3b3 |
ectx->program = program;
|
|
|
5cc3b3 |
|
|
|
a51ace |
/* output */
|
|
|
a51ace |
if ((size_t)snprintf(output,sizeof(output),"%s",
|
|
|
a51ace |
arfilename) >= sizeof(output))
|
|
|
a51ace |
return -1;
|
|
|
a51ace |
|
|
|
5cc3b3 |
/* ar alternate argument vector */
|
|
|
5cc3b3 |
if ((size_t)snprintf(program,sizeof(program),"%s",
|
|
|
5cc3b3 |
dctx->cctx->host.ar) >= sizeof(program))
|
|
|
5cc3b3 |
return -1;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
aarg = ectx->altv;
|
|
|
5cc3b3 |
*aarg++ = program;
|
|
|
5cc3b3 |
*aarg++ = "cru";
|
|
|
a51ace |
*aarg++ = output;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
/* input argument adjustment */
|
|
|
5cc3b3 |
for (parg=ectx->cargv; *parg; parg++)
|
|
|
3b5e3d |
if (slbt_adjust_input_argument(*parg,fpic))
|
|
|
5cc3b3 |
*aarg++ = *parg;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
*aarg = 0;
|
|
|
5cc3b3 |
ectx->argv = ectx->altv;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
/* step output */
|
|
|
5cc3b3 |
if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT))
|
|
|
5cc3b3 |
if (slbt_output_link(dctx,ectx))
|
|
|
5cc3b3 |
return -1;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
/* ar spawn */
|
|
|
5cc3b3 |
if ((slbt_spawn(ectx,true) < 0) || ectx->exitcode)
|
|
|
5cc3b3 |
return -1;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
/* ranlib argv */
|
|
|
5cc3b3 |
if ((size_t)snprintf(program,sizeof(program),"%s",
|
|
|
5cc3b3 |
dctx->cctx->host.ranlib) >= sizeof(program))
|
|
|
5cc3b3 |
return -1;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
ranlib[0] = program;
|
|
|
a51ace |
ranlib[1] = output;
|
|
|
5cc3b3 |
ranlib[2] = 0;
|
|
|
5cc3b3 |
ectx->argv = ranlib;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
/* step output */
|
|
|
5cc3b3 |
if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT))
|
|
|
5cc3b3 |
if (slbt_output_link(dctx,ectx))
|
|
|
5cc3b3 |
return -1;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
/* ranlib spawn */
|
|
|
5cc3b3 |
if ((slbt_spawn(ectx,true) < 0) || ectx->exitcode)
|
|
|
5cc3b3 |
return -1;
|
|
|
5cc3b3 |
|
|
|
5cc3b3 |
return 0;
|
|
|
5cc3b3 |
}
|
|
|
5cc3b3 |
|
|
|
4c76f7 |
static int slbt_exec_link_create_symlink(
|
|
|
4c76f7 |
const struct slbt_driver_ctx * dctx,
|
|
|
4c76f7 |
struct slbt_exec_ctx * ectx,
|
|
|
4c76f7 |
const char * target,
|
|
|
4c76f7 |
char * lnkname)
|
|
|
4c76f7 |
{
|
|
|
4c76f7 |
const char * slash;
|
|
|
4c76f7 |
char * ln[6];
|
|
|
4c76f7 |
char atarget[PATH_MAX];
|
|
|
4c76f7 |
|
|
|
4c76f7 |
/* atarget */
|
|
|
4c76f7 |
if ((slash = strrchr(target,'/')))
|
|
|
4c76f7 |
slash++;
|
|
|
4c76f7 |
else
|
|
|
4c76f7 |
slash = target;
|
|
|
4c76f7 |
|
|
|
4c76f7 |
if ((size_t)snprintf(atarget,sizeof(atarget),"../%s",
|
|
|
4c76f7 |
slash) >= sizeof(atarget))
|
|
|
4c76f7 |
return -1;
|
|
|
4c76f7 |
|
|
|
4c76f7 |
/* ln argv (fake) */
|
|
|
4c76f7 |
ln[0] = "ln";
|
|
|
4c76f7 |
ln[1] = "-f";
|
|
|
4c76f7 |
ln[2] = "-s";
|
|
|
4c76f7 |
ln[3] = atarget;
|
|
|
4c76f7 |
ln[4] = lnkname;
|
|
|
4c76f7 |
ectx->argv = ln;
|
|
|
4c76f7 |
|
|
|
4c76f7 |
/* step output */
|
|
|
4c76f7 |
if (!(dctx->cctx->drvflags & SLBT_DRIVER_SILENT))
|
|
|
4c76f7 |
if (slbt_output_link(dctx,ectx))
|
|
|
4c76f7 |
return -1;
|
|
|
4c76f7 |
|
|
|
4c76f7 |
/* remove old symlink (if any) */
|
|
|
4c76f7 |
unlink(lnkname);
|
|
|
4c76f7 |
|
|
|
4c76f7 |
/* create symlink */
|
|
|
4c76f7 |
return symlink(atarget,lnkname);
|
|
|
4c76f7 |
}
|
|
|
5cc3b3 |
|
|
|
2bd749 |
int slbt_exec_link(
|
|
|
2bd749 |
const struct slbt_driver_ctx * dctx,
|
|
|
2bd749 |
struct slbt_exec_ctx * ectx)
|
|
|
2bd749 |
{
|
|
|
2bd749 |
int ret;
|
|
|
2bd749 |
int fdlibs;
|
|
|
a51ace |
const char * output;
|
|
|
2bd749 |
char * dot;
|
|
|
2bd749 |
FILE * fout;
|
|
|
2bd749 |
struct slbt_exec_ctx * actx;
|
|
|
2bd749 |
|
|
|
2bd749 |
/* context */
|
|
|
2bd749 |
if (ectx)
|
|
|
2bd749 |
actx = 0;
|
|
|
2bd749 |
else if ((ret = slbt_get_exec_ctx(dctx,&ectx)))
|
|
|
2bd749 |
return ret;
|
|
|
2bd749 |
else
|
|
|
2bd749 |
actx = ectx;
|
|
|
2bd749 |
|
|
|
5cc3b3 |
/* output suffix */
|
|
|
a51ace |
output = dctx->cctx->output;
|
|
|
a51ace |
dot = strrchr(output,'.');
|
|
|
5cc3b3 |
|
|
|
2bd749 |
/* .libs directory */
|
|
|
2bd749 |
if (dctx->cctx->drvflags & SLBT_DRIVER_SHARED) {
|
|
|
2bd749 |
if ((fdlibs = open(ectx->ldirname,O_DIRECTORY)) >= 0)
|
|
|
2bd749 |
close(fdlibs);
|
|
|
2bd749 |
else if ((errno != ENOENT) || mkdir(ectx->ldirname,0777)) {
|
|
|
2bd749 |
slbt_free_exec_ctx(actx);
|
|
|
2bd749 |
return -1;
|
|
|
2bd749 |
}
|
|
|
2bd749 |
}
|
|
|
2bd749 |
|
|
|
5cc3b3 |
/* non-pic libfoo.a */
|
|
|
5cc3b3 |
if (dot && !strcmp(dot,".a"))
|
|
|
3b5e3d |
if (slbt_exec_link_create_archive(dctx,ectx,output,false)) {
|
|
|
5cc3b3 |
slbt_free_exec_ctx(actx);
|
|
|
5cc3b3 |
return -1;
|
|
|
5cc3b3 |
}
|
|
|
5cc3b3 |
|
|
|
2bd749 |
/* no wrapper? */
|
|
|
5cc3b3 |
if (!dot || strcmp(dot,".la")) {
|
|
|
2bd749 |
slbt_free_exec_ctx(actx);
|
|
|
2bd749 |
return 0;
|
|
|
2bd749 |
}
|
|
|
2bd749 |
|
|
|
2bd749 |
/* hey, yo, let's rap it up */
|
|
|
687567 |
if (!(fout = fopen(output,"w"))) {
|
|
|
2bd749 |
slbt_free_exec_ctx(actx);
|
|
|
2bd749 |
return -1;
|
|
|
2bd749 |
}
|
|
|
2bd749 |
|
|
|
2bd749 |
ret = fprintf(fout,
|
|
|
2bd749 |
"# slibtool (pre-alphe) generated file\n\n");
|
|
|
2bd749 |
|
|
|
4c76f7 |
/* wrapper symlink */
|
|
|
4c76f7 |
if (slbt_exec_link_create_symlink(
|
|
|
4c76f7 |
dctx,ectx,
|
|
|
4c76f7 |
output,
|
|
|
4c76f7 |
ectx->lafilename)) {
|
|
|
4c76f7 |
slbt_free_exec_ctx(actx);
|
|
|
4c76f7 |
return -1;
|
|
|
4c76f7 |
}
|
|
|
4c76f7 |
|
|
|
2bd749 |
/* all done */
|
|
|
2bd749 |
fclose(fout);
|
|
|
2bd749 |
slbt_free_exec_ctx(actx);
|
|
|
2bd749 |
|
|
|
2bd749 |
return (ret > 0) ? 0 : -1;
|
|
|
2bd749 |
}
|