summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--NEWS30
-rw-r--r--THANKS7
-rwxr-xr-xaux/ar-lib27
-rw-r--r--include/slibtool/slibtool.h3
-rw-r--r--m4/slibtool.m414
-rw-r--r--project/extras.mk1
-rw-r--r--project/tagver.mk4
-rw-r--r--src/driver/slbt_amain.c22
-rw-r--r--src/driver/slbt_driver_ctx.c12
-rw-r--r--src/driver/slbt_split_argv.c15
-rw-r--r--src/internal/argv/argv.h283
-rw-r--r--src/internal/slibtool_driver_impl.h7
-rw-r--r--src/internal/slibtool_lconf_impl.c18
-rw-r--r--src/logic/slbt_exec_stoolie.c26
-rw-r--r--src/skin/slbt_skin_default.c10
15 files changed, 441 insertions, 38 deletions
diff --git a/NEWS b/NEWS
index 1f802d3..22a4366 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,33 @@
+0.6.0:
+
+This minor release introduces the slibtoolize execution mode,
+as well as completion of the core slibtool.m4 functionality.
+In addition, this release entails several enhancements and
+fixes in other areas.
+
+- slibtoolize: new execution mode, driver integration, and symlink.
+- slibtoolize: added a no-op, yet backward compatible ltmain.sh.
+- slibtoolize: auxiliary files: added slibtool.sh (optional wrapper).
+- driver: --mkvars: implementation and integration.
+- driver: --mkvars: special case the SLIBTOOL make variable.
+- driver: --heuristics: added slibtool.cfg prioritized support.
+- driver: detect slibtool.cfg in non-heuristics mode where applicable.
+- driver: slbt_output_raw_vector(): refactor and prettify.
+- host: derive as from ranlib as needed.
+- host: derive windres and dlltool from ranlib as needed.
+- host: detect a native build environment based on ar(1).
+- host: set native mode based on the detected ar(1) as needed.
+- host: cfgmeta: mark tools derived from ranlib as such.
+- util: PE/COFF: list is target neutral, process all syms.
+- util: properly set weak aliases of strong symbols.
+- ar: yaml output: initial implementation.
+- ar: internally bind the meta ctx to the archive ctx.
+- ar: sort the syminfo vector in a coff-aware manner.
+- ar: PE/COFF: properly set weak aliases of strong symbols.
+- ar: symbol mapfile: properly set strong aliases of weak symbols.
+- ar: symbol vector: include weak aliases of strong symbols.
+- ar: symbol file: include weak aliases of strong symbols.
+
0.5.36:
This (pinky promise, for real now) absolutely final patch release
diff --git a/THANKS b/THANKS
index 4b27103..9088dc3 100644
--- a/THANKS
+++ b/THANKS
@@ -1,3 +1,10 @@
+0.6.0:
+
+The project owes much of the progress leading to this slibtool[ize]
+release to @orbea, who contineus to tirelessly test, identify bugs
+and areas for improvement, and bring all the dots together. So once
+again, thank you so much!
+
0.5.36:
Getting slibtool to the point where it could build a vast number of
diff --git a/aux/ar-lib b/aux/ar-lib
new file mode 100755
index 0000000..3ef4a41
--- /dev/null
+++ b/aux/ar-lib
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+#####################################################################
+## slibtool: a strong libtool implementation, written in C ##
+## Copyright (C) 2016--2024 SysDeer Technologies, LLC ##
+## Released under the Standard MIT License; see COPYING.SLIBTOOL. ##
+#####################################################################
+
+#####################################################################
+## ar-lib: a placeholder script, currently not implemented ##
+## ------------------------------------------------------- ##
+#####################################################################
+
+set -eu
+
+error_msg()
+{
+ printf '%s\n' "$@" >&2
+}
+
+error_not_implemented()
+{
+ error_msg 'ar-lib: this script is a placeholder.'
+ exit 2
+}
+
+error_not_implemented
diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h
index f05de74..9336728 100644
--- a/include/slibtool/slibtool.h
+++ b/include/slibtool/slibtool.h
@@ -72,6 +72,9 @@ extern "C" {
#define SLBT_DRIVER_EXPORT_DYNAMIC SLBT_DRIVER_XFLAG(0x0010)
#define SLBT_DRIVER_STATIC_LIBTOOL_LIBS SLBT_DRIVER_XFLAG(0x0100)
+#define SLBT_DRIVER_OUTPUT_SHARED_EXT SLBT_DRIVER_XFLAG(0x0400)
+#define SLBT_DRIVER_OUTPUT_STATIC_EXT SLBT_DRIVER_XFLAG(0x0800)
+
#define SLBT_DRIVER_OUTPUT_MACHINE SLBT_DRIVER_XFLAG(0x1000)
#define SLBT_DRIVER_OUTPUT_CONFIG SLBT_DRIVER_XFLAG(0x2000)
#define SLBT_DRIVER_OUTPUT_AUX_DIR SLBT_DRIVER_XFLAG(0x4000)
diff --git a/m4/slibtool.m4 b/m4/slibtool.m4
index 25c37a3..e2e6ad5 100644
--- a/m4/slibtool.m4
+++ b/m4/slibtool.m4
@@ -260,6 +260,17 @@ slibtool_set_flavor()
enable_win32_dll=${slibtool_enable_win32_dll}
enable_fast_install=${slibtool_enable_fast_install}
pic_mode=${slibtool_pic_mode}
+
+ # suffix variables
+ if [[ -n "${host}" ]]; then
+ shrext_cmds="$($_slibtool -print-shared-ext --host=${host})"
+ libext="$($_slibtool -print-static-ext --host=${host})"
+ libext="${libext#[.]}"
+ else
+ shrext_cmds="$($_slibtool -print-shared-ext)"
+ libext="$($_slibtool -print-static-ext)"
+ libext="${libext#[.]}"
+ fi
}
])
@@ -402,8 +413,11 @@ if [[ -z "${LEX}" ]]; then
AC_CHECK_PROG([LEX],[lex],[lex])
fi
+slibtool_lex_output_root="${ac_cv_prog_lex_root:-lex.yy}"
+
AC_SUBST([LEX])
AC_SUBST([LEXLIB])
+AC_SUBST([LEX_OUTPUT_ROOT],["${slibtool_lex_output_root}"])
])
diff --git a/project/extras.mk b/project/extras.mk
index ba3ff0f..a254d9c 100644
--- a/project/extras.mk
+++ b/project/extras.mk
@@ -109,5 +109,6 @@ install-slibtoolize:
cp -p $(SOURCE_DIR)/m4/slibtool.m4 $(DESTDIR)$(DATADIR)/$(PACKAGE)
cp -p $(SOURCE_DIR)/aux/ltmain.sh $(DESTDIR)$(DATADIR)/$(PACKAGE)
cp -p $(SOURCE_DIR)/aux/slibtool.sh $(DESTDIR)$(DATADIR)/$(PACKAGE)
+ cp -p $(SOURCE_DIR)/aux/ar-lib $(DESTDIR)$(DATADIR)/$(PACKAGE)
.PHONY: install-slibtoolize
diff --git a/project/tagver.mk b/project/tagver.mk
index 2595fde..f22212f 100644
--- a/project/tagver.mk
+++ b/project/tagver.mk
@@ -1,5 +1,5 @@
VER_NAMESPACE = SLBT
VER_MAJOR = 0
-VER_MINOR = 5
-VER_PATCH = 36
+VER_MINOR = 6
+VER_PATCH = 0
diff --git a/src/driver/slbt_amain.c b/src/driver/slbt_amain.c
index e0f4241..a9cc118 100644
--- a/src/driver/slbt_amain.c
+++ b/src/driver/slbt_amain.c
@@ -67,6 +67,16 @@ static ssize_t slbt_print_m4_dir(int fdout)
return slbt_dprintf(fdout,"%s\n",SLBT_PACKAGE_DATADIR);
}
+static ssize_t slbt_print_shared_ext(int fdout, struct slbt_driver_ctx * dctx)
+{
+ return slbt_dprintf(fdout,"%s\n",dctx->cctx->settings.dsosuffix);
+}
+
+static ssize_t slbt_print_static_ext(int fdout, struct slbt_driver_ctx * dctx)
+{
+ return slbt_dprintf(fdout,"%s\n",dctx->cctx->settings.arsuffix);
+}
+
static void slbt_perform_driver_actions(struct slbt_driver_ctx * dctx)
{
if (dctx->cctx->drvflags & SLBT_DRIVER_INFO)
@@ -219,6 +229,18 @@ int slbt_main(char ** argv, char ** envp, const struct slbt_fd_ctx * fdctx)
? slbt_exit(dctx,SLBT_ERROR)
: slbt_exit(dctx,SLBT_OK);
+ /* -print-shared-ext must be the first (and only) action */
+ if (dctx->cctx->drvflags & SLBT_DRIVER_OUTPUT_SHARED_EXT)
+ return (slbt_print_shared_ext(fdout,dctx) < 0)
+ ? slbt_exit(dctx,SLBT_ERROR)
+ : slbt_exit(dctx,SLBT_OK);
+
+ /* -print-static-ext must be the first (and only) action */
+ if (dctx->cctx->drvflags & SLBT_DRIVER_OUTPUT_STATIC_EXT)
+ return (slbt_print_static_ext(fdout,dctx) < 0)
+ ? slbt_exit(dctx,SLBT_ERROR)
+ : slbt_exit(dctx,SLBT_OK);
+
/* perform all other actions */
slbt_perform_driver_actions(dctx);
diff --git a/src/driver/slbt_driver_ctx.c b/src/driver/slbt_driver_ctx.c
index 76c7c4a..09adb68 100644
--- a/src/driver/slbt_driver_ctx.c
+++ b/src/driver/slbt_driver_ctx.c
@@ -440,6 +440,7 @@ int slbt_lib_get_driver_ctx(
sargv.cargv = 0;
objlistv = 0;
ndlopen = 0;
+ lflags = 0;
switch (slbt_split_argv(argv,flags,&sargv,&objlistv,fdctx->fderr,fdctx->fdcwd)) {
case SLBT_OK:
@@ -617,6 +618,14 @@ int slbt_lib_get_driver_ctx(
cctx.drvflags |= SLBT_DRIVER_OUTPUT_M4_DIR;
break;
+ case TAG_PRINT_SHARED_EXT:
+ cctx.drvflags |= SLBT_DRIVER_OUTPUT_SHARED_EXT;
+ break;
+
+ case TAG_PRINT_STATIC_EXT:
+ cctx.drvflags |= SLBT_DRIVER_OUTPUT_STATIC_EXT;
+ break;
+
case TAG_DEBUG:
cctx.drvflags |= SLBT_DRIVER_DEBUG;
break;
@@ -1004,7 +1013,8 @@ int slbt_lib_get_driver_ctx(
if (cctx.drvflags & SLBT_DRIVER_HEURISTICS) {
if (slbt_get_lconf_flags(&ctx->ctx,lconf,&lflags,false) < 0)
- return slbt_lib_get_driver_ctx_fail(&ctx->ctx,0);
+ if (!(cctx.drvflags & SLBT_DRIVER_OUTPUT_MASK))
+ return slbt_lib_get_driver_ctx_fail(&ctx->ctx,0);
} else {
switch (cctx.mode) {
case SLBT_MODE_UNKNOWN:
diff --git a/src/driver/slbt_split_argv.c b/src/driver/slbt_split_argv.c
index 8fd131a..f9828f1 100644
--- a/src/driver/slbt_split_argv.c
+++ b/src/driver/slbt_split_argv.c
@@ -60,6 +60,7 @@ slbt_hidden int slbt_split_argv(
struct argv_entry * ccwrap;
struct argv_entry * dumpmachine;
struct argv_entry * printdir;
+ struct argv_entry * printext;
struct argv_entry * aropt;
struct argv_entry * stoolieopt;
const struct argv_option ** popt;
@@ -67,7 +68,7 @@ slbt_hidden int slbt_split_argv(
const struct argv_option * optv[SLBT_OPTV_ELEMENTS];
struct argv_ctx ctx = {ARGV_VERBOSITY_NONE,
ARGV_MODE_SCAN,
- 0,0,0,0,0,0,0};
+ 0,0,0,0,0,0,0,0};
program = slbt_program_name(argv[0]);
@@ -126,7 +127,7 @@ slbt_hidden int slbt_split_argv(
/* missing all of --mode, --help, --version, --info, --config, --dumpmachine, --features, and --finish? */
/* as well as -print-aux-dir and -print-m4-dir? */
- mode = help = version = info = config = finish = features = ccwrap = dumpmachine = printdir = aropt = stoolieopt = 0;
+ mode = help = version = info = config = finish = features = ccwrap = dumpmachine = printdir = printext = aropt = stoolieopt = 0;
for (entry=meta->entries; entry->fopt; entry++)
if (entry->tag == TAG_MODE)
@@ -151,6 +152,10 @@ slbt_hidden int slbt_split_argv(
printdir = entry;
else if (entry->tag == TAG_PRINT_M4_DIR)
printdir = entry;
+ else if (entry->tag == TAG_PRINT_SHARED_EXT)
+ printext = entry;
+ else if (entry->tag == TAG_PRINT_STATIC_EXT)
+ printext = entry;
/* alternate execusion mode? */
if (!altmode && mode && !strcmp(mode->arg,"ar"))
@@ -175,7 +180,7 @@ slbt_hidden int slbt_split_argv(
return -1;
}
- if (!mode && !help && !version && !info && !config && !finish && !features && !dumpmachine && !printdir && !altmode) {
+ if (!mode && !help && !version && !info && !config && !finish && !features && !dumpmachine && !printdir && !printext && !altmode) {
slbt_dprintf(fderr,
"%s: error: --mode must be specified.\n",
program);
@@ -183,7 +188,7 @@ slbt_hidden int slbt_split_argv(
}
/* missing compiler? */
- if (!ctx.unitidx && !help && !info && !config && !version && !finish && !features && !dumpmachine && !printdir) {
+ if (!ctx.unitidx && !help && !info && !config && !version && !finish && !features && !dumpmachine && !printdir && !printext) {
if (!altmode && !aropt && !stoolieopt) {
if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
slbt_dprintf(fderr,
@@ -345,7 +350,7 @@ slbt_hidden int slbt_split_argv(
if (ctx.unitidx) {
(void)0;
- } else if (help || version || features || info || config || dumpmachine || printdir || altmode) {
+ } else if (help || version || features || info || config || dumpmachine || printdir || printext || altmode) {
for (i=0; i<argc; i++)
sargv->targv[i] = argv[i];
diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h
index d17865b..0b9def7 100644
--- a/src/internal/argv/argv.h
+++ b/src/internal/argv/argv.h
@@ -13,6 +13,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include <unistd.h>
#define ARGV_VERBOSITY_NONE 0x00
@@ -57,16 +58,27 @@
#define ARGV_OPTION_HYBRID_EQUAL 0x04
#define ARGV_OPTION_HYBRID_COMMA 0x08
#define ARGV_OPTION_HYBRID_JOINED 0x10
+
+#define ARGV_OPTION_KEYVAL_PAIR 0X20
+#define ARGV_OPTION_KEYVAL_ARRAY 0X40
+#define ARGV_OPTION_KEYVAL_MASK (ARGV_OPTION_KEYVAL_PAIR \
+ | ARGV_OPTION_KEYVAL_ARRAY)
+
#define ARGV_OPTION_HYBRID_CIRCUS (ARGV_OPTION_HYBRID_SPACE \
| ARGV_OPTION_HYBRID_JOINED)
+
#define ARGV_OPTION_HYBRID_DUAL (ARGV_OPTION_HYBRID_SPACE \
| ARGV_OPTION_HYBRID_EQUAL)
+
#define ARGV_OPTION_HYBRID_SWITCH (ARGV_OPTION_HYBRID_ONLY \
| ARGV_OPTION_HYBRID_SPACE \
| ARGV_OPTION_HYBRID_EQUAL \
| ARGV_OPTION_HYBRID_COMMA \
| ARGV_OPTION_HYBRID_JOINED)
+#define ARGV_KEYVAL_ASSIGN 0x01
+#define ARGV_KEYVAL_OVERRIDE 0x02
+
enum argv_optarg {
ARGV_OPTARG_NONE,
ARGV_OPTARG_REQUIRED,
@@ -92,6 +104,9 @@ enum argv_error {
ARGV_ERROR_HYBRID_SPACE,
ARGV_ERROR_HYBRID_EQUAL,
ARGV_ERROR_HYBRID_COMMA,
+ ARGV_ERROR_KEYVAL_KEY,
+ ARGV_ERROR_KEYVAL_VALUE,
+ ARGV_ERROR_KEYVAL_ALLOC,
};
struct argv_option {
@@ -105,13 +120,20 @@ struct argv_option {
const char * description;
};
+struct argv_keyval {
+ const char * keyword;
+ const char * value;
+ int flags;
+};
+
struct argv_entry {
- const char * arg;
- int tag;
- bool fopt;
- bool fval;
- bool fnoscan;
- enum argv_error errcode;
+ const char * arg;
+ struct argv_keyval * keyv;
+ int tag;
+ bool fopt;
+ bool fval;
+ bool fnoscan;
+ enum argv_error errcode;
};
struct argv_meta {
@@ -129,6 +151,7 @@ struct argv_ctx {
const char * errch;
const struct argv_option * erropt;
const char * program;
+ size_t keyvlen;
};
#ifdef ARGV_DRIVER
@@ -136,6 +159,8 @@ struct argv_ctx {
struct argv_meta_impl {
char ** argv;
char * strbuf;
+ char * keyvbuf;
+ char * keyvmark;
struct argv_meta meta;
};
@@ -305,12 +330,131 @@ static inline const struct argv_option * option_from_tag(
return 0;
}
+static inline int argv_scan_keyval_array(struct argv_meta_impl * meta, struct argv_entry * entry)
+{
+ const char * ch;
+ char * dst;
+ int ncomma;
+ int cint;
+ struct argv_keyval * keyv;
+
+ /* count key[val] elements, assume no comma after last element */
+ for (ch=entry->arg,ncomma=1; *ch; ch++) {
+ if ((ch[0]=='\\') && (ch[1]==',')) {
+ ch++;
+
+ } else if ((ch[0]==',')) {
+ ncomma++;
+ }
+ }
+
+ /* keyval string buffer */
+ dst = meta->keyvmark;
+
+ /* allocate keyval array */
+ if (!(entry->keyv = calloc(ncomma+1,sizeof(*entry->keyv))))
+ return ARGV_ERROR_KEYVAL_ALLOC;
+
+ /* create keyval array */
+ entry->keyv->keyword = dst;
+
+ for (ch=entry->arg,keyv=entry->keyv; *ch; ch++) {
+ if ((ch[0]=='\\') && (ch[1]==',')) {
+ *dst++ = ',';
+ ch++;
+
+ } else if ((ch[0]==':') && (ch[1]=='=')) {
+ if (!keyv->keyword[0])
+ return ARGV_ERROR_KEYVAL_KEY;
+
+ keyv->flags = ARGV_KEYVAL_OVERRIDE;
+ keyv->value = ++dst;
+ ch++;
+
+ } else if ((ch[0]=='=')) {
+ if (!keyv->keyword[0])
+ return ARGV_ERROR_KEYVAL_KEY;
+
+ keyv->flags = ARGV_KEYVAL_ASSIGN;
+ keyv->value = ++dst;
+
+ } else if ((ch[0]==',')) {
+ for (; isblank(cint = ch[1]); )
+ ch++;
+
+ if (ch[1]) {
+ keyv++;
+ keyv->keyword = ++dst;
+ }
+ } else {
+ *dst++ = *ch;
+ }
+ }
+
+ /* keyval string buffer */
+ meta->keyvmark = ++dst;
+
+ return ARGV_ERROR_OK;
+}
+
+static inline int argv_scan_keyval_pair(struct argv_meta_impl * meta, struct argv_entry * entry)
+{
+ const char * ch;
+ char * dst;
+ struct argv_keyval * keyv;
+
+ /* keyval string buffer */
+ dst = meta->keyvmark;
+
+ /* allocate keyval array */
+ if (!(entry->keyv = calloc(2,sizeof(*entry->keyv))))
+ return ARGV_ERROR_KEYVAL_ALLOC;
+
+ /* create keyval array */
+ entry->keyv->keyword = dst;
+
+ for (ch=entry->arg,keyv=entry->keyv; *ch && !keyv->flags; ch++) {
+ if ((ch[0]=='\\') && (ch[1]==',')) {
+ *dst++ = ',';
+ ch++;
+
+ } else if ((ch[0]==':') && (ch[1]=='=')) {
+ if (!keyv->keyword[0])
+ return ARGV_ERROR_KEYVAL_KEY;
+
+ keyv->flags = ARGV_KEYVAL_OVERRIDE;
+ keyv->value = ++dst;
+ ch++;
+
+ } else if ((ch[0]=='=')) {
+ if (!keyv->keyword[0])
+ return ARGV_ERROR_KEYVAL_KEY;
+
+ keyv->flags = ARGV_KEYVAL_ASSIGN;
+ keyv->value = ++dst;
+
+ } else {
+ *dst++ = *ch;
+ }
+ }
+
+ for (; *ch; )
+ *dst++ = *ch++;
+
+ /* keyval string buffer */
+ meta->keyvmark = ++dst;
+
+ return ARGV_ERROR_OK;
+}
+
static void argv_scan(
char ** argv,
const struct argv_option ** optv,
struct argv_ctx * ctx,
struct argv_meta * meta)
{
+ struct argv_meta_impl * imeta;
+ uintptr_t addr;
char ** parg;
const char * ch;
const char * val;
@@ -324,6 +468,9 @@ static void argv_scan(
bool fhybrid;
bool fnoscan;
+ addr = (uintptr_t)meta - offsetof(struct argv_meta_impl,meta);
+ imeta = (struct argv_meta_impl *)addr;
+
parg = &argv[1];
ch = *parg;
ferr = ARGV_ERROR_OK;
@@ -495,13 +642,20 @@ static void argv_scan(
if (!option && !ctx->unitidx)
ctx->unitidx = parg - argv;
+ if (ferr == ARGV_ERROR_OK)
+ if (option && (option->flags & ARGV_OPTION_KEYVAL_MASK))
+ if (ctx->mode == ARGV_MODE_SCAN)
+ ctx->keyvlen += strlen(ch) + 1;
+
if (ferr != ARGV_ERROR_OK) {
ctx->errcode = ferr;
ctx->errch = ctx->errch ? ctx->errch : ch;
ctx->erropt = option;
ctx->erridx = parg - argv;
return;
- } else if (ctx->mode == ARGV_MODE_SCAN) {
+ }
+
+ if (ctx->mode == ARGV_MODE_SCAN) {
if (!fnoscan)
ctx->nentries++;
else if (fval)
@@ -511,12 +665,12 @@ static void argv_scan(
parg++;
ch = *parg;
}
+
} else if (ctx->mode == ARGV_MODE_COPY) {
if (fnoscan) {
if (fval) {
mentry->arg = ch;
mentry->fnoscan = true;
- mentry++;
}
parg++;
@@ -526,7 +680,6 @@ static void argv_scan(
mentry->tag = option->tag;
mentry->fopt = true;
mentry->fval = fval;
- mentry++;
if (fval) {
parg++;
@@ -534,11 +687,28 @@ static void argv_scan(
}
} else {
mentry->arg = ch;
- mentry++;
parg++;
ch = *parg;
}
}
+
+ if (option && (option->flags & ARGV_OPTION_KEYVAL_PAIR))
+ if (ctx->mode == ARGV_MODE_COPY)
+ ferr = argv_scan_keyval_pair(imeta,mentry);
+
+ if (option && (option->flags & ARGV_OPTION_KEYVAL_ARRAY))
+ if (ctx->mode == ARGV_MODE_COPY)
+ ferr = argv_scan_keyval_array(imeta,mentry);
+
+ if (ferr != ARGV_ERROR_OK) {
+ ctx->errcode = ferr;
+ ctx->errch = ctx->errch ? ctx->errch : ch;
+ ctx->erropt = option;
+ ctx->erridx = parg - argv;
+ return;
+ }
+
+ mentry++;
}
}
@@ -663,6 +833,14 @@ static void argv_show_error(int fd, struct argv_ctx * ctx)
break;
+ case ARGV_ERROR_KEYVAL_KEY:
+ argv_dprintf(fd,"illegal key detected in keyval argument\n");
+ break;
+
+ case ARGV_ERROR_KEYVAL_VALUE:
+ argv_dprintf(fd,"illegal value detected in keyval argument\n");
+ break;
+
case ARGV_ERROR_INTERNAL:
argv_dprintf(fd,"internal error");
break;
@@ -678,8 +856,10 @@ static void argv_show_status(
struct argv_ctx * ctx,
struct argv_meta * meta)
{
+ int i;
int argc;
char ** argv;
+ struct argv_keyval * keyv;
struct argv_entry * entry;
const struct argv_option * option;
char short_name[2] = {0};
@@ -698,7 +878,7 @@ static void argv_show_status(
argv_dprintf(fd,"argv[%d]: %s\n",argc,*argv);
argv_dprintf(fd,"\n\nparsed entries:\n");
- for (entry=meta->entries; entry->arg || entry->fopt; entry++)
+ for (entry=meta->entries; entry->arg || entry->fopt; entry++) {
if (entry->fopt) {
option = option_from_tag(optv,entry->tag);
short_name[0] = option->short_name;
@@ -709,14 +889,48 @@ static void argv_show_status(
else
argv_dprintf(fd,"[-%s,--%s]\n",
short_name,option->long_name);
- } else
+
+ if (entry->keyv) {
+ for (i=0,keyv=entry->keyv; keyv->keyword; i++,keyv++) {
+ switch (keyv->flags) {
+ case ARGV_KEYVAL_ASSIGN:
+ argv_dprintf(fd,"\tkeyval[%d]: <%s>=%s\n",
+ i,keyv->keyword,keyv->value);
+ break;
+
+ case ARGV_KEYVAL_OVERRIDE:
+ argv_dprintf(fd,"\tkeyval[%d]: <%s>:=%s\n",
+ i,keyv->keyword,keyv->value);
+ break;
+
+ default:
+ argv_dprintf(fd,"\tkeyval[%d]: <%s>\n",
+ i,keyv->keyword);
+ break;
+ }
+ }
+ }
+ } else {
argv_dprintf(fd,"<program arg> := %s\n",entry->arg);
+ }
+ }
argv_dprintf(fd,"\n\n");
}
static struct argv_meta * argv_free_impl(struct argv_meta_impl * imeta)
{
+ struct argv_entry * entry;
+ void * addr;
+
+ if (imeta->keyvbuf)
+ for (entry=imeta->meta.entries; entry->fopt || entry->arg; entry++)
+ if (entry->keyv)
+ free((addr = entry->keyv));
+
+ if (imeta->keyvbuf)
+ free(imeta->keyvbuf);
+
if (imeta->argv)
free(imeta->argv);
@@ -750,7 +964,8 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx)
if (!(imeta->argv = calloc(argc+1,sizeof(char *))))
return argv_free_impl(imeta);
- else if (!(imeta->strbuf = calloc(1,size+1)))
+
+ if (!(imeta->strbuf = calloc(1,size+1)))
return argv_free_impl(imeta);
for (i=0,dst=imeta->strbuf; i<argc; i++) {
@@ -760,15 +975,27 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx)
}
imeta->meta.argv = imeta->argv;
- } else
+ } else {
imeta->meta.argv = argv;
+ }
- if (!(imeta->meta.entries = calloc(
- ctx->nentries+1,
- sizeof(struct argv_entry))))
+ imeta->meta.entries = calloc(
+ ctx->nentries+1,
+ sizeof(struct argv_entry));
+
+ if (!imeta->meta.entries)
return argv_free_impl(imeta);
- else
- return &imeta->meta;
+
+ if (ctx->keyvlen) {
+ imeta->keyvbuf = calloc(
+ ctx->keyvlen,
+ sizeof(char));
+
+ if (!(imeta->keyvmark = imeta->keyvbuf))
+ return argv_free_impl(imeta);
+ }
+
+ return &imeta->meta;
}
static struct argv_meta * argv_get(
@@ -778,7 +1005,7 @@ static struct argv_meta * argv_get(
int fd)
{
struct argv_meta * meta;
- struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0};
+ struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0,0};
argv_scan(argv,optv,&ctx,0);
@@ -833,6 +1060,7 @@ static void argv_usage_impl(
{
const struct argv_option ** optv;
const struct argv_option * option;
+ int nlong;
bool fshort,flong,fboth;
size_t len,optlen,desclen;
char cache;
@@ -865,7 +1093,7 @@ static void argv_usage_impl(
if (header)
argv_dprintf(fd,"%s",header);
- for (optlen=0,optv=options; *optv; optv++) {
+ for (optlen=0,nlong=0,optv=options; *optv; optv++) {
option = *optv;
/* indent + comma */
@@ -884,6 +1112,11 @@ static void argv_usage_impl(
/* optlen */
if (len > optlen)
optlen = len;
+
+ /* long (vs. hybrid-only) option? */
+ if (option->long_name)
+ if (!(option->flags & ARGV_OPTION_HYBRID_ONLY))
+ nlong++;
}
if (optlen >= optcap) {
@@ -904,7 +1137,7 @@ static void argv_usage_impl(
/* color */
if (fcolor) {
color = (color == ccyan) ? cblue : ccyan;
- argv_dprintf(fd,color);
+ argv_dprintf(fd,color,0);
}
/* description, using either paradigm or argname if applicable */
@@ -916,7 +1149,11 @@ static void argv_usage_impl(
/* long/hybrid option prefix (-/--) */
prefix = option->flags & ARGV_OPTION_HYBRID_ONLY
- ? " -" : "--";
+ ? " -" : " --";
+
+ /* avoid extra <stace> when all long opts are hybrid-only */
+ if (nlong == 0)
+ prefix++;
/* option string */
if (fboth && option->short_name && option->long_name)
diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h
index 429cdc4..7b6114d 100644
--- a/src/internal/slibtool_driver_impl.h
+++ b/src/internal/slibtool_driver_impl.h
@@ -20,6 +20,11 @@
#define SLBT_OPTV_ELEMENTS 128
+#define SLBT_DRIVER_OUTPUT_MASK (SLBT_DRIVER_OUTPUT_M4_DIR \
+ | SLBT_DRIVER_OUTPUT_AUX_DIR \
+ | SLBT_DRIVER_OUTPUT_SHARED_EXT \
+ | SLBT_DRIVER_OUTPUT_STATIC_EXT)
+
extern const struct argv_option slbt_default_options[];
enum app_tags {
@@ -32,6 +37,8 @@ enum app_tags {
TAG_DUMPMACHINE,
TAG_PRINT_AUX_DIR,
TAG_PRINT_M4_DIR,
+ TAG_PRINT_SHARED_EXT,
+ TAG_PRINT_STATIC_EXT,
TAG_DEBUG,
TAG_DRY_RUN,
TAG_FEATURES,
diff --git a/src/internal/slibtool_lconf_impl.c b/src/internal/slibtool_lconf_impl.c
index ffe92b0..7f43034 100644
--- a/src/internal/slibtool_lconf_impl.c
+++ b/src/internal/slibtool_lconf_impl.c
@@ -545,6 +545,7 @@ static int slbt_lconf_open(
fdcwd = slbt_driver_fdcwd(dctx);
fdlconfdir = fdcwd;
fsilent |= (dctx->cctx->drvflags & SLBT_DRIVER_SILENT);
+ fsilent |= (dctx->cctx->drvflags & SLBT_DRIVER_OUTPUT_MASK);
if (lconf) {
mconf = 0;
@@ -629,15 +630,21 @@ static int slbt_lconf_open(
if (stparent.st_dev != stcwd.st_dev) {
trace_result(dctx,fdparent,fdparent,".",EXDEV,lconfpath);
close(fdparent);
- return SLBT_CUSTOM_ERROR(
- dctx,SLBT_ERR_LCONF_OPEN);
+
+ return (dctx->cctx->drvflags & SLBT_DRIVER_OUTPUT_MASK)
+ ? (-1)
+ : SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_OPEN);
}
if (stparent.st_ino == stinode) {
trace_result(dctx,fdparent,fdparent,".",ELOOP,lconfpath);
close(fdparent);
- return SLBT_CUSTOM_ERROR(
- dctx,SLBT_ERR_LCONF_OPEN);
+
+ return (dctx->cctx->drvflags & SLBT_DRIVER_OUTPUT_MASK)
+ ? (-1)
+ : SLBT_CUSTOM_ERROR(
+ dctx,SLBT_ERR_LCONF_OPEN);
}
fdlconfdir = fdparent;
@@ -766,7 +773,8 @@ slbt_hidden int slbt_get_lconf_flags(
/* open relative libtool script */
if ((fdlconf = slbt_lconf_open(dctx,lconf,fsilent,&val)) < 0)
- return SLBT_NESTED_ERROR(dctx);
+ return (dctx->cctx->drvflags & SLBT_DRIVER_OUTPUT_MASK)
+ ? (-1) : SLBT_NESTED_ERROR(dctx);
/* cache the configuration in library friendly form) */
if (slbt_lib_get_txtfile_ctx(dctx,val,&ctx->lconfctx) < 0)
diff --git a/src/logic/slbt_exec_stoolie.c b/src/logic/slbt_exec_stoolie.c
index 698faaa..779146a 100644
--- a/src/logic/slbt_exec_stoolie.c
+++ b/src/logic/slbt_exec_stoolie.c
@@ -88,6 +88,7 @@ static int slbt_exec_stoolie_perform_actions(
char auxdir[PATH_MAX];
char slibm4[PATH_MAX];
char ltmain[PATH_MAX];
+ char arlib [PATH_MAX];
bool fslibm4;
bool fltmain;
@@ -101,11 +102,17 @@ static int slbt_exec_stoolie_perform_actions(
return SLBT_BUFFER_ERROR(dctx);
if (slbt_snprintf(
- ltmain,sizeof(slibm4),"%s/%s",
+ ltmain,sizeof(ltmain),"%s/%s",
SLBT_PACKAGE_DATADIR,
"ltmain.sh") < 0)
return SLBT_BUFFER_ERROR(dctx);
+ if (slbt_snprintf(
+ arlib,sizeof(arlib),"%s/%s",
+ SLBT_PACKAGE_DATADIR,
+ "ar-lib") < 0)
+ return SLBT_BUFFER_ERROR(dctx);
+
/* --force? */
if (dctx->cctx->drvflags & SLBT_DRIVER_STOOLIE_FORCE) {
if (ictx->fdm4 >= 0)
@@ -115,6 +122,9 @@ static int slbt_exec_stoolie_perform_actions(
if (slbt_exec_stoolie_remove_file(dctx,ictx->fdaux,"ltmain.sh") < 0)
return SLBT_NESTED_ERROR(dctx);
+ if (slbt_exec_stoolie_remove_file(dctx,ictx->fdaux,"ar-lib") < 0)
+ return SLBT_NESTED_ERROR(dctx);
+
fslibm4 = (ictx->fdm4 >= 0);
fltmain = true;
} else {
@@ -158,6 +168,9 @@ static int slbt_exec_stoolie_perform_actions(
if (slbt_util_copy_file(ectx,ltmain,auxdir) < 0)
return SLBT_NESTED_ERROR(dctx);
+
+ if (slbt_util_copy_file(ectx,arlib,auxdir) < 0)
+ return SLBT_NESTED_ERROR(dctx);
}
} else {
/* default to symlinks */
@@ -170,7 +183,7 @@ static int slbt_exec_stoolie_perform_actions(
SLBT_SYMLINK_LITERAL) < 0)
return SLBT_NESTED_ERROR(dctx);
- if (fltmain)
+ if (fltmain) {
if (slbt_create_symlink_ex(
dctx,ectx,
ictx->fdaux,
@@ -178,6 +191,15 @@ static int slbt_exec_stoolie_perform_actions(
"ltmain.sh",
SLBT_SYMLINK_LITERAL) < 0)
return SLBT_NESTED_ERROR(dctx);
+
+ if (slbt_create_symlink_ex(
+ dctx,ectx,
+ ictx->fdaux,
+ arlib,
+ "ar-lib",
+ SLBT_SYMLINK_LITERAL) < 0)
+ return SLBT_NESTED_ERROR(dctx);
+ }
}
return 0;
diff --git a/src/skin/slbt_skin_default.c b/src/skin/slbt_skin_default.c
index 07f099d..8ae0833 100644
--- a/src/skin/slbt_skin_default.c
+++ b/src/skin/slbt_skin_default.c
@@ -46,6 +46,16 @@ const slbt_hidden struct argv_option slbt_default_options[] = {
"for additional information, see the slibtoolize(1) "
"manual page."},
+ {"print-shared-ext", 0,TAG_PRINT_SHARED_EXT,ARGV_OPTARG_NONE,
+ ARGV_OPTION_HYBRID_ONLY,0,0,
+ "print the shared library extension for the specified "
+ "(or otherwise detected) host."},
+
+ {"print-static-ext", 0,TAG_PRINT_STATIC_EXT,ARGV_OPTARG_NONE,
+ ARGV_OPTION_HYBRID_ONLY,0,0,
+ "print the static library extension for the specified "
+ "(or otherwise detected) host."},
+
{"finish", 0,TAG_FINISH,ARGV_OPTARG_NONE,0,0,0,
"same as --mode=finish"},