3

I'm working on a C project, and I decided to put the source code and its objects in different directories. The root directory has something like that:

SmartC  ▶ tree -L 1
.
├── built
├── doc
├── Makefile
├── README.md
├── src
├── tests
└── trash

So, inside both src and built directories, I put two others Makefiles to do the compile and link jobs.

The src directory (where I put the source code) has the following structure:

src
├── graph.c
├── graph.h
├── list.c
├── list.h
├── main.c
├── Makefile
├── node.c
├── node.h
├── tree.c
├── tree.h
└── types
    ├── complex.c
    ├── complex.h
    ├── matrix.c
    └── matrix.h

and the built has the same structure, but it is intended to store all objects made by compilation.

My question is about my src/Makefile:

BINDIR = ../built/src                

CC = gcc

CFLAGS = -g -Wall -O3

OBJECTS = \
          $(BINDIR)/main.o          \
          $(BINDIR)/node.o          \
          $(BINDIR)/list.o          \
          $(BINDIR)/graph.o         \
          $(BINDIR)/tree.o          \
          $(BINDIR)/types/complex.o \
          $(BINDIR)/types/matrix.o  \


compile: $(OBJECTS)

$(BINDIR)/%.o: %.c
    $(CC) -c $< -o $@ $(CFLAGS)

This Makefile creates all the objects of the source code, inside src directory, and move them to built/src. But, every time I create a new source code file (*.c), I have to put the name of its object in this makefile, so it can be compiled. I'd like to do an automatic search, inside the src directory, and fill the "OBJECTS" variable with this search.

Is anyone has some idea of how to accomplish this? I mean, automatic search for source code inside an specific directory?

I even accept any other strategy rather than what I'm making.

=========== Answer ===============

I got the tip (in comments) about wildcards. So I did. Here is the solution I found.

src/Makefile

BINDIR = ../built/src                                         

CC = gcc                                                      

CFLAGS = -g -Wall -O3                                         


OBJECTS := $(patsubst %.c,$(BINDIR)/%.o,$(wildcard *.c */*.c))

compile: $(OBJECTS)                                           

$(BINDIR)/%.o: %.c                                            
    $(CC) -c $< -o $@ $(CFLAGS)                               
  • You may be interested in [this question](http://stackoverflow.com/questions/29357259/gnu-make-wildcard-alternative). – Diego Aug 12 '15 at 19:55
  • Thanks. I'll do my search about wildcards. I wasn't aware of it! –  Aug 12 '15 at 20:09
  • @Diego. Thanks brow. Wildcards are awesome. –  Aug 12 '15 at 21:20
  • Make is a lot easier to handle if the Makefile itself is in your build tree rather than the source tree (see how GMake builds them, for example). – Lee Daniel Crocker Aug 12 '15 at 21:44
  • @LeeDanielCrocker: I have another Makefile in the my built directory. I have one in the root directory that give orders to src//Makefile and built/Makefile depending on the type of target I want to call. src/Makefile is only for compilation and built/Makefile is for link and clean operations. I'm plenty new on Make world, so I'll see what I can learn from GMake, as you said. Thanks. –  Aug 13 '15 at 11:57
  • 1
    Rather than putting the answer in the question, post it separately as an answer to your own question and accept it. – dbush Sep 21 '15 at 17:19
  • Good one @dbush. Thanks! –  Sep 22 '15 at 12:07

1 Answers1

1

EDIT [Solved]

I like to do the following.

Create Variables to Each Directory of the Project

SRCDIR = src                                                           
OBJDIR = obj
LIBDIR = lib
DOCDIR = doc
HDRDIR = include

CFLAGS = -g -Wall -O3

Get Only the Internal Structure of SRCDIR Recursively

STRUCTURE := $(shell find $(SRCDIR) -type d)     

Get All Files inside the STRUCTURE Variable

CODEFILES := $(addsuffix /*,$(STRUCTURE))
CODEFILES := $(wildcard $(CODEFILES))            

Filter Out Only Specific Files

# Filter Only Specific Files                                
SRCFILES := $(filter %.c,$(CODEFILES))
HDRFILES := $(filter %.h,$(CODEFILES))
OBJFILES := $(subst $(SRCDIR),$(OBJDIR),$(SRCFILES:%.c=%.o))

# Filter Out Function main for Libraries
LIBDEPS := $(filter-out $(OBJDIR)/main.o,$(OBJFILES))

Now it is Time to create the Rules

compile: $(OBJFILES)

$(OBJDIR)/%.o: $(addprefix $(SRCDIR)/,%.c %.h)
    $(CC) -c $< -o $@ $(CFLAGS) 

With this approach, you can see that I'm using the STRUCTURE variable only to get the files inside the SRCDIR directory, but it can be used for others purposes as well, like mirror the SRCDIR inside OBJDIR once STRUCTURE stores only the internal sub-directories. It is quite useful after clean operations like:

clean:
    -rm -r $(OBJDIR)/*

NOTE: The compile rule only works well if for each *.c there is the corresponding *.h file (with the same base name, I mean).