1

I found two contradicting answers how to handle common includes(one, two), so I decided to describe my case...

I have a small project, which originally contains 4 small apps. Assume that I have files A.c, B.c, C.c and D.c. To improve the state of code, I decided to separate common source code. I created Common.h and Common.c. Each app now is dependent on Common.o. Please check below makefile:

OBJ := $(OBJDIR)/A.o $(OBJDIR)/B.o $(OBJDIR)/C.o $(OBJDIR)/D.o
HEADERS := $(SRCDIR)/common.h
MODULES := $(BUILDDIR)/A $(BUILDDIR)/B $(BUILDDIR)/C $(BUILDDIR)/D


all: dir $(OBJ) $(MODULES)
dir :
    mkdir -p $(BUILDDIR)
$(BUILDDIR)/A : $(OBJDIR)/A.o $(OBJDIR)/common.o
    $(CC) $^ -o $@ $(CFLAGS)
$(BUILDDIR)/B : $(OBJDIR)/B.o $(OBJDIR)/common.o
    $(CC) $^ -o $@ $(CFLAGS)
$(BUILDDIR)/C : $(OBJDIR)/C.o $(OBJDIR)/common.o
    $(CC) $^ -o $@ $(CFLAGS)
$(BUILDDIR)/D : $(OBJDIR)/D.o $(OBJDIR)/common.o
    $(CC) $^ -o $@ $(CFLAGS)
$(OBJDIR)/%.o : $(SRCDIR)/%.c $(HEADERS)
    $(CC) -c $< -o $@ $(CFLAGS)
.PHONY: clean
clean:
    rm -rf $(BUILDDIR)

In each file *.c I had includes: #include<stdio.h>, #include <stdlib.h>, #include <string.h> Should I keep these includes in each .c file separately? or is it good practice to put it in common.h?

It seems to me that I can keep these headers in common.h, due to the fact that each application depends on common.o. Is it a proper approach? stdlib.h, stdio.h and string.h are needed in A.c, B.c, C.c, D.c and Common.c (declarations of Common.h do not require any of these files), but putting them in common.h and not including them in each .c file is logical... is this approach correct?

summary: if in each .c file I have malloc (in common.c too), can I put #include <stdlib.h> only in common.h and then include common.h in all .c files?

flamingo
  • 148
  • 1
  • 11
  • 2
    `common.h` should declare the functions and variables that are defined in `common.c` and are needed by callers of its code. – Barmar Jan 22 '20 at 22:29
  • 2
    A rule of thumb (which is not necessarily the only one that has to exist) is that you include the immediate dependencies where these are needed without relying on indirect inclusion. – Eugene Sh. Jan 22 '20 at 22:39
  • @EugeneSh. what if my indirect inclusion comes from Makefile? (dependency to common.o). From your comment, I understand that It doesn't change anything? – flamingo Jan 22 '20 at 22:50
  • No, no. object files is a separate story, I was talking about `#include`s – Eugene Sh. Jan 22 '20 at 22:51
  • In general, keep the standard C headers in the main source files. If `common.h` needs information from standard C headers (e.g. `size_t` or `FILE *`), then include appropriate headers in `common.h` so that the header is self-contained. Don't include unnecessary headers (`common.h` should be minimal). The header should also be idempotent so that there are no problems even if it is included multiple times in a single translation unit. See [Should I use `#include` in headers](https://stackoverflow.com/a/1804719/15168) for an answer detailing why NASA GSFC said "yes, you should include headers". – Jonathan Leffler Jan 22 '20 at 22:52
  • @EugeneSh. Yup. I've seen nightmare cases where the extreme opposite was done and a header file didn't include what it used. I don't know if something changed at one point that removed a needed header from its include tree and was masked by the needed header being included ahead of it wherever it was used or if it was always broken. The house of cards eventually fell as the result of a bug-fix elsewhere. – Christian Gibbons Jan 22 '20 at 22:52
  • @EugeneSh. I understand general rule, but I was curious about "my" specific case (strong indissolubility with common.h / common.o which is specified in Makefile). Aren't they connected? why this is "separate story"? – flamingo Jan 22 '20 at 23:20

1 Answers1

0

I am closing this question. Thank you for all the answers in comments. To sum up:

A rule of thumb (which is not necessarily the only one that has to exist) is that you include the immediate dependencies where these are needed without relying on indirect inclusion.

flamingo
  • 148
  • 1
  • 11