LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-13-2011, 04:19 AM   #1
kornelix
Member
 
Registered: Oct 2005
Location: Germany
Distribution: Ubuntu
Posts: 58

Rep: Reputation: 24
Debian packaging - how to automate "Depends:" list


There must be an elegant way to do this but I have not found one.

I cobbled together something that seems to work:

1. $ readelf -d <binary executable>
Get the list of dynamically linked library files

2. $ dpkg-query -S <library file>
Find the debian package containing a library file

3. $ dpkg-query -W <package name>
Find the installed version of a package

4. Use the outputs from (3) and (4) to construct the text
in the debian control file: "Depends: package (>= version), ..."

There must be a better way. True?

thanks
Mike
 
Old 10-13-2011, 06:40 AM   #2
coralfang
Member
 
Registered: Nov 2010
Location: Bristol, UK
Distribution: Slackware, FreeBSD
Posts: 836
Blog Entries: 3

Rep: Reputation: 297Reputation: 297Reputation: 297
Have a look at
Code:
man ldd
Not sure if this is what you're after. You could parse the output using awk for example:
Code:
$ ldd /usr/bin/htop | awk '{ print $1 }'
linux-vdso.so.1
libncursesw.so.5
libm.so.6
libc.so.6
/lib/ld-linux-x86-64.so.2
And if you wanted to strip the numbers off the end (could be useful):
findlibs.sh
Code:
#!/bin/bash
for lib in $(ldd $1 | awk '{ print $1 }'); do
        echo ${lib%.*}
done
Code:
$ ./findlibs.sh /usr/bin/htop
linux-vdso.so
libncursesw.so
libm.so
libc.so
/lib/ld-linux-x86-64.so
Etc.
 
1 members found this post helpful.
Old 10-13-2011, 10:25 AM   #3
kornelix
Member
 
Registered: Oct 2005
Location: Germany
Distribution: Ubuntu
Posts: 58

Original Poster
Rep: Reputation: 24
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
 
Old 10-13-2011, 10:30 AM   #4
kornelix
Member
 
Registered: Oct 2005
Location: Germany
Distribution: Ubuntu
Posts: 58

Original Poster
Rep: Reputation: 24
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).
 
Old 10-13-2011, 02:52 PM   #5
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,928

Rep: Reputation: 612Reputation: 612Reputation: 612Reputation: 612Reputation: 612Reputation: 612
Here's an alternate 'ldd' which I use:

Code:
#!/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.
 
1 members found this post helpful.
Old 10-14-2011, 07:19 AM   #6
kornelix
Member
 
Registered: Oct 2005
Location: Germany
Distribution: Ubuntu
Posts: 58

Original Poster
Rep: Reputation: 24
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.

Here is a sample output:

Code:
$: getdeps /usr/bin/mashup

 LIBRARY                        PACKAGE                        VERSION                        
 libgtk-x11-2.0.so.0            libgtk2.0-0                    2.24.6-0ubuntu5                
 libgdk-x11-2.0.so.0            libgtk2.0-0                    2.24.6-0ubuntu5                
 libgdk_pixbuf-2.0.so.0         libgdk-pixbuf2.0-0             2.24.0-1ubuntu1                
 libcairo.so.2                  libcairo2                      1.10.2-6ubuntu3                
 libpango-1.0.so.0              libpango1.0-0                  1.29.3+git20110916-0ubuntu1    
 libgobject-2.0.so.0            libglib2.0-dev                 2.30.0-0ubuntu4                
 libglib-2.0.so.0               libglib2.0-0                   2.30.0-0ubuntu4                
 libstdc++.so.6                 libstdc++6                     4.6.1-9ubuntu3                 
 libm.so.6                      libc6                          2.13-20ubuntu5                 
 libgcc_s.so.1                  libgcc1                        1:4.6.1-9ubuntu3               
 libpthread.so.0                libc6                          2.13-20ubuntu5                 
 libc.so.6                      libc6                          2.13-20ubuntu5                 


 PACKAGE                        VERSION                        
 libgtk2.0-0                    2.24.6                         
 libgdk-pixbuf2.0-0             2.24.0                         
 libcairo2                      1.10.2                         
 libpango1.0-0                  1.29.3+git20110916             
 libglib2.0-dev                 2.30.0                         
 libglib2.0-0                   2.30.0                         
 libstdc++6                     4.6.1                          
 libc6                          2.13                           
 libgcc1                        1:4.6.1                        


Depends: libgtk2.0-0 (>= 2.24.6), libgdk-pixbuf2.0-0 (>= 2.24.0), 
libcairo2 (>= 1.10.2), libpango1.0-0 (>= 1.29.3+git20110916), 
libglib2.0-dev (>= 2.30.0), libglib2.0-0 (>= 2.30.0), 
libstdc++6 (>= 4.6.1), libc6 (>= 2.13), libgcc1 (>= 1:4.6.1),
And here is the source code:

Code:
/**************************************************************************
   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;
}
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
debian deb packaging: how to detect "--purge"-switch t0bias Debian 1 06-28-2010 05:24 AM
"Multicolumn" or "tiles", or even "list" icon view on desktop, in any DE? the dsc Linux - Desktop 3 02-20-2010 09:25 AM
How to find out "depends" of slack 12.2 pkg's?? linus72 Slackware 4 08-01-2009 02:28 AM
"list dynamic dependency" of an executable using command other than "ldd" Amrita@3086 Solaris / OpenSolaris 3 04-04-2007 04:56 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:59 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration