cdepend

This post was written by eli on January 1, 2009
Posted Under: Linux

Introduction

2022 update: This is probably quite pointless today, but that’s not reason enough to delete this post.

cdepend is a cross-reference utility, whose main purpose is mapping which function calls which in a C language project.

As projects grow and develop, it becomes harder and harder to keep track of which functions are actually used. Unused functions may exist in the project without anyone noticing.

Sometimes we want to change a function, but we’re not sure how this change will affect the entire project.

Another feature of cdepend is getting details about where library functions are called. This is important when porting a project to a non-UNIX environment, where the most basic library functions may be absent.

cdepend addresses these issues. A simple example of how it’s used and the output it generates is given below.

Project status

The project works well on my own computer. If you’re running a recent i386-Linux distro, you have good chances of having it up quickly as well. If not, you may run into trouble. If you do, I will most probably help you, assuming that you’ll supply me with sufficient information. Especially if you’re running on a recent version of Linux.

Download & Install

First you’d like to download the tarball (or get it at SourceForge). Then you do something like:

[eli@localhost cdepend]$ tar -xzf cdepend-0.02.tar.gz
[eli@localhost cdepend]$ cd cdepend-0.02
[eli@localhost cdepend-0.02]$ perl Makefile.PL
Checking if your kit is complete...
Looks good
Writing Makefile for cdepend
[eli@localhost cdepend-0.02]$ make
(... snipped ...)
[eli@localhost cdepend-0.02]$ su
[root@localhost cdepend-0.02]# make install
[eli@localhost cdepend-0.02]$ man cdepend

Note that there is a man page. Read it!

Example of use

Suppose that we have two files, mainfile.c and funcfile.c.

mainfile.c goes as follows:

void f1(int); 

int main() {
  f1(3);
}

and funcfile.c:

void f2(int);

void f1(int num) {
  if (num > 0)
    f2(num);
}

void f2(int num) {
  printf("Hello World %d\n", num);
  f1(num-1);
}

What these functions do is really not interesting. Just for reference, here’s how we would probably compile this “project”:

[eli@localhost example]$ gcc -c mainfile.c -o mainfile.o
[eli@localhost example]$ gcc -c funcfile.c -o funcfile.o
[eli@localhost example]$ gcc mainfile.o funcfile.o -o try

Nothing new so far. Now let’s try cdepend!

First, we have to partially compile the files: We want assembly code, not object files. So we add the -S flag. We also must have the -gstabs+ flag, so debugging information is written to the assembly files. Then we run cdepend, giving it both assembly files (*.S) as input data:

[eli@localhost example]$ gcc -S -gstabs+ mainfile.c -o mainfile.S
[eli@localhost example]$ gcc -S -gstabs+ funcfile.c -o funcfile.S
[eli@localhost example]$ cdepend -o report.txt -d funcdir *.S

The report.txt is not interesting in this case, because all functions are used and declared. It’s basically empty.

But cdepend generated a directory, funcdir at our request. Let’s see what we have in the file funcdir/f1 (generated by cdepend, of course):

Variable's name: f1()
Declared at /home/eli/example/funcfile.c:3
Varible/function is recursive (indirectly)

Functions/Variables used directly:
==================================
f2() at line(s): 5

Functions/Variables using directly:
===================================
f2() at /home/eli/example/funcfile.c:10
main() at /home/eli/example/mainfile.c:4

From this file we can learn where the function is declared, and that there is a recursive connection from f1() back to itself. Then we see that f1() is calls f2() at line 5, and that f1() is called by f2() and main().

There are similar files for f2() and main(). But we shall have a look on funcdir/printf:

Variable's name: (printf)
Found in linkable library /lib/i686/libc.so.6

Functions/Variables using directly:
===================================
f2() at /home/eli/example/funcfile.c:9

This information is important when porting a project to an environment where there is no printf. Here we can tell who uses this function.

Note that on some platforms library functions will be displayed as undeclared. This behaviour does not impact the reliabilty of the rest of the information.

And once again: There is a UNIX manual page for cdepend. man cdepend should work after installation.

Add a Comment

required, use real name
required, will not be published
optional, your blog address

Previose Post: