Debian packaging - how to automate "Depends:" list
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Thanks coralfang, that is useful. Still need to add version numbers (a similar approach would work).
Since this is an issue every packager faces, there must be a canned solution.
Mike
Actually ldd gives too much information: libraries linked from other libraries are included. For packaging dependencies, only the first level is needed and readelf does that (If I understand adequately).
#!/bin/bash
# Copyright 2009-2011 Gilbert Ashley <amigo@ibiblio.org>
# re-written from an idea by
# Ricardo Garcia Gonzalez.
# His version needed bash-4, awk, cat, cut, grep and tr -plus objdump
# This only needs bash >=3.0 and objdump :-)
# I added the "not found" report
# version 0.1
if [[ -n $1 ]] ; then
declare MY_LIBS="$(objdump -p $@ |grep NEEDED)"
# Library directories.
LIBDIRS=${LD_LIBRARY_PATH//:/ }"/lib$LIBDIRSUFFIX /usr/lib$LIBDIRSUFFIX"
if [[ -r /etc/ld.so.conf ]] ; then
while read LINE ; do
LIBDIRS=${LIBDIRS}" $LINE"
done < /etc/ld.so.conf
fi
#LIBDIRS=${LIBDIRS}${LD_LIBRARY_PATH//:/ }
for LINE in $(echo $MY_LIBS) ; do
HAVE_LIB=0
if [[ $LINE != "NEEDED" ]] ; then
for LIBDIR in $LIBDIRS ; do
if [[ -e "$LIBDIR/$LINE" ]] ; then
# don't use '-x' which requires the lib to be executable
HAVE_LIB=1
echo "$LIBDIR/$LINE"
# for an output more like the real ldd:
# echo "$LINE => $LIBDIR/$LINE"
break
else
continue
fi
done
if [[ $HAVE_LIB != 1 ]] ; then
echo "$LINE"" not found"
# for an output more like the real ldd:
# echo "$LINE => not found"
fi
fi
done
fi
Similar to the OP's use of readelf, it shows only directly-linked dependencies, and only those which are actually needed by the bin/lib being checked.
I think I likely reinvented the wheel, but I now have a solution.
I wrote a c program that generates the "Depends" text directly.
I put it here in case someone else needs it.
/**************************************************************************
getdeps.cc v.01
find all package dependencies of a binary executable program
usage: $ getdeps program
STDOUT: "Depends packname1 (>= N.N), packname2 ... "
Copyright 2011 Michael Cornelison
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 3 of the License, 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.
***************************************************************************/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int cc, ii, jj, Npkg = 0;
char *program, *pp1, *pp2;
char command[100], buff[200];
char libname[100][100], package[100][100], version[100][100];
FILE *fid;
if (argc < 2) {
printf("usage: $ getdeps program \n");
return 1;
}
program = argv[1];
snprintf(command,100,"readelf -d %s", program); // get linked dynamic libraries
fid = popen(command,"r");
if (! fid) {
printf("getdeps, %s not found \n",program);
return 1;
}
while ((fgets(buff,200,fid))) // process readelf outputs, formatted
{ // ... Shared library: [filename]
pp1 = strstr(buff,"Shared library:");
if (! pp1) continue;
pp1 = strstr(pp1,"[");
if (! pp1) continue;
pp2 = strstr(pp1,"]");
if (! pp2) continue;
cc = pp2 - pp1 - 1;
if (cc > 99) continue;
strncpy(libname[Npkg],pp1+1,cc); // isolate filename
libname[Npkg][cc] = 0;
Npkg++;
if (Npkg > 99) {
printf("over 100 libraries, stop here \n");
break;
}
}
pclose(fid);
for (ii = 0; ii < Npkg; ii++) // find packages containing lib files
{
snprintf(command,100,"dpkg-query -S %s",libname[ii]);
fid = popen(command,"r");
fgets(buff,200,fid);
pclose(fid);
pp1 = strstr(buff,":"); // format is packagename: ...
if (pp1) {
*pp1 = 0;
strncpy(package[ii],buff,100); // isolate packagename
buff[99] = 0;
}
else strcpy(package[ii],"??");
}
for (ii = 0; ii < Npkg; ii++) // get package versions
{
snprintf(command,100,"dpkg-query -W %s",package[ii]);
fid = popen(command,"r");
fgets(buff,200,fid);
pclose(fid);
pp1 = strstr(buff,"\t"); // format is packagename <tab> version
if (pp1) {
strncpy(version[ii],pp1+1,100); // isolate version
version[ii][99] = 0;
cc = strlen(version[ii]);
version[ii][cc-1] = 0; // get rid of trailing \n
}
else strcpy(version[ii],"??");
}
printf("\n %-30s %-30s %-30s \n","LIBRARY","PACKAGE","VERSION"); // print libraries and corresp. packages
for (ii = 0; ii < Npkg; ii++)
printf(" %-30s %-30s %-30s \n",
libname[ii], package[ii], version[ii]);
for (ii = 0; ii < Npkg; ii++) // eliminate duplicates
{
for (jj = ii+1; jj < Npkg; jj++)
{
if (strcmp(package[jj],package[ii]) == 0 &&
strcmp(version[jj],version[ii]) == 0) *package[jj] = 0;
}
}
for (ii = 0; ii < Npkg; ii++) // eliminate distro version appendages
{
pp1 = strrchr(version[ii],'-');
if (pp1) *pp1 = 0;
}
printf("\n\n %-30s %-30s \n","PACKAGE","VERSION"); // print packages and versions
for (ii = 0; ii < Npkg; ii++)
if (*package[ii])
printf(" %-30s %-30s \n",package[ii], version[ii]);
printf("\n\nDepends: "); // print Depends: package (>= version), ...
for (ii = 0; ii < Npkg; ii++)
if (*package[ii])
printf("%s (>= %s), ",package[ii], version[ii]);
printf("\n\n");
return 0;
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.