From 198205f4097928184ed5bfa288bb4dfbba1e2b5f Mon Sep 17 00:00:00 2001 From: midipix Date: Wed, 13 Mar 2024 05:00:06 +0000 Subject: link mode: properly support dependency derivation in static-only build projects. --- src/logic/linkcmd/slbt_linkcmd_argv.c | 18 ++++- src/logic/linkcmd/slbt_linkcmd_deps.c | 132 ++++++++++++++++++++++++++++++---- 2 files changed, 136 insertions(+), 14 deletions(-) diff --git a/src/logic/linkcmd/slbt_linkcmd_argv.c b/src/logic/linkcmd/slbt_linkcmd_argv.c index a7c0777..71f4a00 100644 --- a/src/logic/linkcmd/slbt_linkcmd_argv.c +++ b/src/logic/linkcmd/slbt_linkcmd_argv.c @@ -516,7 +516,7 @@ slbt_hidden int slbt_exec_link_adjust_argument_vector( darg += dlen; darg[-1] = 0; - /* handle -L... as needed */ + /* handle -L... and ::... as needed */ if ((mark[0] == '-') && (mark[1] == 'L') && (mark[2] != '/')) { @@ -537,6 +537,22 @@ slbt_hidden int slbt_exec_link_adjust_argument_vector( "%s/%s",lib,depdir)) < 0) return ret; + } else if ((mark[0] == ':') && (mark[1] == ':')) { + if (strlen(mark) >= sizeof(depdir) - 1) + return slbt_linkcmd_exit( + depsmeta, + SLBT_BUFFER_ERROR(dctx)); + + darg = mark; + strcpy(depdir,&mark[2]); + + sprintf(darg,"%s/%s", + mark[2] == '/' ? "" : lib, + depdir); + + darg += strlen(darg); + darg++; + } else if ((mark[0] == '-') && (mark[1] == 'L')) { if ((ret = slbt_emit_fdwrap_amend_dl_path( dctx,ectx,depsmeta, diff --git a/src/logic/linkcmd/slbt_linkcmd_deps.c b/src/logic/linkcmd/slbt_linkcmd_deps.c index 66b831c..3f2f42e 100644 --- a/src/logic/linkcmd/slbt_linkcmd_deps.c +++ b/src/logic/linkcmd/slbt_linkcmd_deps.c @@ -98,6 +98,7 @@ static int slbt_exec_link_normalize_dep_file( int fdtgt; char * dot; char * slash; + const char * base; const char * mark; struct slbt_txtfile_ctx * tctx; const char ** pline; @@ -111,6 +112,7 @@ static int slbt_exec_link_normalize_dep_file( char deppath [PATH_MAX]; char pathbuf [PATH_MAX]; char depsbuf [PATH_MAX]; + char basebuf [PATH_MAX]; char relapath[PATH_MAX]; /* fdcwd */ @@ -180,8 +182,14 @@ static int slbt_exec_link_normalize_dep_file( /* normalize dependency lines as needed */ for (pline=tctx->txtlinev; *pline; pline++) { if ((mark = *pline)) { - if ((mark[0] == '-') && (mark[1] == 'L')) + if ((mark[0] == '-') && (mark[1] == 'L')) { mark = &mark[2]; + base = 0; + + } else if ((mark[0] == ':') && (mark[1] == ':')) { + mark = &mark[2]; + base = mark; + } if ((mark > *pline) && (mark[0] == '/')) mark = *pline; @@ -198,9 +206,23 @@ static int slbt_exec_link_normalize_dep_file( else strcpy(depsbuf,deppath); + + if ((mark > *pline) && base) { + slash = strrchr(deppath,'/'); + *slash = '\0'; + + slash = strrchr(deppath,'/'); + *slash = '\0'; + + base = basebuf; + slash = &depsbuf[slash - deppath]; + + strcpy(basebuf,++slash); + strcpy(depsbuf,deppath); + } } - if ((mark > *pline) && strcmp(tgtpath,deppath)) { + if (mark > *pline) { tgtmark = tgtpath; depmark = deppath; @@ -254,14 +276,23 @@ static int slbt_exec_link_normalize_dep_file( strcpy(relmark,depmark); } - mark = relapath; + if (base) { + relapath[0] = ':'; + relapath[1] = ':'; + } - } else if (mark > *pline) { - strcpy(relapath,"-L."); mark = relapath; } - ret = mark ? slbt_dprintf(deps,"%s\n",mark) : (-1); + if ((mark == relapath) && base) { + ret = slbt_dprintf(deps,"%s/%s\n",mark,base); + + } else if (mark) { + ret = slbt_dprintf(deps,"%s\n",mark); + + } else { + ret = (-1); + } if (ret < 0) { close(deps); @@ -334,6 +365,25 @@ static int slbt_exec_link_compact_dep_file( } +static bool slbt_archive_is_convenience_library(int fdcwd, const char * arpath) +{ + int fd; + char laipath[PATH_MAX]; + char * dot; + + strcpy(laipath,arpath); + dot = strrchr(laipath,'.'); + strcpy(dot,".lai"); + + if ((fd = openat(fdcwd,laipath,O_RDONLY,0)) >= 0) { + close(fd); + return false; + } + + return true; +} + + slbt_hidden int slbt_exec_link_create_dep_file( const struct slbt_driver_ctx * dctx, struct slbt_exec_ctx * ectx, @@ -361,6 +411,7 @@ slbt_hidden int slbt_exec_link_create_dep_file( char pathbuf[PATH_MAX]; struct stat st; int ldepth; + int fardep; int fdyndep; struct slbt_map_info * mapinfo; bool is_reladir; @@ -528,8 +579,20 @@ slbt_hidden int slbt_exec_link_create_dep_file( mark = strrchr(mark,'.'); strcpy(mark,dctx->cctx->settings.dsosuffix); + fardep = 0; fdyndep = !fstatat(fdcwd,depfile,&st,0); + if (fdyndep && farchive) { + mark = strrchr(mark,'.'); + strcpy(mark,dctx->cctx->settings.arsuffix); + + if (fstatat(fdcwd,depfile,&st,0) < 0) { + strcpy(mark,dctx->cctx->settings.dsosuffix); + } else { + fdyndep = 0; + } + } + /* [-L... as needed] */ if (fdyndep && (ectx->ldirdepth >= 0)) { if (slbt_dprintf(deps,"-L") < 0) { @@ -564,6 +627,43 @@ slbt_hidden int slbt_exec_link_create_dep_file( } *popt = '.'; + } else { + strcpy(depfile,*parg); + + slbt_adjust_wrapper_argument( + depfile,true, + dctx->cctx->settings.arsuffix); + + + fardep = farchive; + fardep |= !slbt_archive_is_convenience_library(fdcwd,depfile); + } + + if (fardep) { + if (slbt_dprintf(deps,"::") < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + + for (ldepth=ectx->ldirdepth; ldepth; ldepth--) { + if (slbt_dprintf(deps,"../") < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + + + if (ectx->ldirdepth >= 0) { + if (slbt_dprintf(deps,"%s\n",depfile) < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } else { + if (slbt_dprintf(deps,"::./%s\n",depfile) < 0) { + close(deps); + return SLBT_SYSTEM_ERROR(dctx,0); + } + } } /* [open dependency list] */ @@ -582,7 +682,7 @@ slbt_hidden int slbt_exec_link_create_dep_file( mark = strrchr(mark,'.'); size = sizeof(depfile) - (mark - depfile); - if (!farchive) { + if (!fardep) { slen = slbt_snprintf(mark,size, "%s.slibtool.deps", dctx->cctx->settings.dsosuffix); @@ -636,15 +736,21 @@ slbt_hidden int slbt_exec_link_create_dep_file( return SLBT_NESTED_ERROR(dctx); } - ret = ((deplib[0] == '-') - && (deplib[1] == 'L') - && (deplib[2] != '/')) - ? slbt_dprintf( + if ((deplib[0] == '-') && (deplib[1] == 'L') && (deplib[2] != '/')) { + ret = slbt_dprintf( deps,"-L%s%s/%s", - deppref,reladir,&deplib[2]) - : slbt_dprintf( + deppref,reladir,&deplib[2]); + + } else if ((deplib[0] == ':') && (deplib[1] == ':') && (deplib[2] != '/')) { + ret = slbt_dprintf( + deps,"::%s%s/%s", + deppref,reladir,&deplib[2]); + + } else { + ret = slbt_dprintf( deps,"%s", deplib); + } if (ret < 0) { close(deps); -- cgit v1.2.3