'how to find the dependencies of a source code?

Let say I have a simple c-library project, the layout is as follows

- src/
      - square_root.c
      - log.c
      - power.c
      - newton_method.c
- include/
      - square_root.h
      - log.h
      - power.h
      - newton_method.h

Now, I want to create a simple program(main.c) to call square_root()

# main.c
# include "square_root.h" 
int main()
{
  printf("%f\n", square_root(4.0));
  return 0;
}

To compile the main.c, newton_method.c have to be included to the build.

gcc main.c src/square_root.c src/newton_method.c -o main

In this case, newton_method.c is a dependency of square_root.c. Finding dependencies for a source code becomes hard if the library is large or poorly written. Of course, one can include all *.c during the build, but it will make the build process slow and clumsy.

I tried

gcc -H -MM -M main.c

but it gave me only the *.h not *.c

Are there any tools for finding the dependencies of a source code ?



Solution 1:[1]

Solution

The standard way of doing it is the one described in this paper written by Paul Smith (the current maintainer of GNU Make). This method uses the GCC options -MMD -MP -MF -MT to detect the dependencies of each object file *.o. Then, it creates dependency files *.d and fills them with rules to build each object, including all the necessary dependencies (sources and headers). Refer to this page if you want to know more about the GCC options. In your case, the following makefile should be enough:

SRCS := main.c square_root.c newton_method.c
BIN := main

SRCS := $(SRCS:%=src/%)
OBJS := $(SRCS:src/%.c=obj/%.o)
DEPS := $(OBJS:%.o=%.d)

all: $(BIN)

$(BIN): $(OBJS)
    gcc -o $@ $^

obj/%.o: src/%.c obj/%.d
    gcc -c -I include -MMD -MP -MF $(patsubst obj/%.o,obj/%.d,$@) -MT $@ -o $@ $<

$(DEPS):
-include $(DEPS)

Observations about the makefile:

  • You have to put the makefile in the root directory.
  • When you copy the code to your makefile, please pay attention to the indented parts (recipe of each rule). Each command line must start with a TAB character, not spaces.
  • I am assuming that all the source files *.c are in the directory src/, and all the header files *.h are in the directory include/.
  • The compiler will put all object files *.o and dependency files *.d in the directory obj/. I am assuming that this directory already exists.
  • You can choose the source files involved by modifying the variable SRCS, however only one of them can contain a main() function.
  • You can choose the executable's name by modifying the variable BIN.
  • The executable will be created in the root directory.

Test Setup

I tried to reproduce your scenario based on what you said. To test the makefile, I used the following source and header files.

src/main.c

#include <stdio.h>
#include "square_root.h"
int main()
{
    printf("%f\n", square_root(4.0));
    return 0;
}

include/square_root.h

float square_root(float x);

src/square_root.c

#include "square_root.h"
#include "newton_method.h"
float square_root(float x)
{
    return newton_method(x);
}

include/newton_method.h

float newton_method(float x);

src/newton_method.c

#include "newton_method.h"
float newton_method(float x)
{
    return x;
}

Dependency Files

Below are the dependency files created by the compiler. You will see that each file has one rule to build the object file with all the dependencies (sources and headers) as prerequisites. The compiler also adds a target for each dependency other than the main source file, causing each to depend on nothing. These dummy rules work around errors that GNU Make gives if you remove header files without updating the makefile to match. All this is done automatically. Pretty cool, huh? :)

main.d

obj/main.o: src/main.c include/square_root.h

include/square_root.h:

square_root.d

obj/square_root.o: src/square_root.c include/square_root.h \
 include/newton_method.h

include/square_root.h:

include/newton_method.h:

newton_method.d

obj/newton_method.o: src/newton_method.c include/newton_method.h

include/newton_method.h:

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 LucasJ