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 06-08-2011, 10:35 AM   #1
freeindy
Member
 
Registered: Nov 2002
Posts: 207

Rep: Reputation: 32
Recursive Makefile


Hi,

I'm trying to make recursive makefile work but it's giving me two problems. I have a top folder with the main Makefile and one Makefile for each sub folder 'one' and 'two'. Makefile in subfolder 'one' and 'two' are identical.

The top Makefile (still a bit messy) looking like this:
Code:
# Directories                                                                                                  

CC = gcc
CFLAGS = -Wall -Wextra

TARGET_DIR = bin
MAIN_FILE = one.c
DIRS = one two
PATHS= $(PWD)/one:$(PWD)/two

OBJS = $(SOURCES:.c=.o)

.PHONY: all
all: $(DIRS) target

.PHONY: $(DIRS)
$(DIRS):
        $(MAKE) $(CFLAGS) --directory=$@

target: $(OBJS)
#       for d in $(DIRS); do (cd $$d; OBJS=$(wildcard *.o)); done#                                             
#       @echo $(OBJS)                                                                                          
#       $(CC) $(CFLAGS) -o bin/oas -I .                                                                        

clean:
        @echo "Cleaning up..."
        for d in $(DIRS); do (cd $$d; $(MAKE) clean); done
And makefile in each subfolder 'one' and 'two' looks like:

Code:
SRCS=$(wildcard *.c)

ifndef NDEBUG
BUILD_TYPE=debug
else
BUILD_TYPE=release
endif
#OBJS =$(addprefix $(OS_TARGET)/$(BUILD_TYPE)/, $(SRCS:.c=.o))                                                 
OBJS = $(SRCS:.c=.o)

.PHONY: all

all: os_target build place

os_target:
ifeq ($(OS_TARGET),)
        @echo "No OS target supplied... aborting."
        @exit 1
endif
        mkdir -p $(OS_TARGET)/$(BUILD_TYPE)

build: $(OBJS)
        @echo "*** Compiling $(CURDIR) for $(OS_TARGET) ***"
	$(MAKE) $(OBJS) $(CFLAGS)

place:
        mv -f *.o $(OS_TARGET)/$(BUILD_TYPE)
	@echo "*** Compiling $(CURDIR) for $(OS_TARGET) COMPLETED ***"

clean:
ifeq ($(OS_TARGET),)
	@echo "No OS target supplied... aborting."
	@exit 1
endif
     	${RM} -frv $(PWD)/$(OS_TARGET)/$(BUILD_TYPE)/*.o
First problem is that if I only have variable 'DIRS = one' then I get the following output:

Code:
make -Wall -Wextra --directory=one
make[1]: Entering directory `/home/indy/development/tmp/top/one'
mkdir -p hasse/debug
cc    -c -o one.o one.c
cc    -c -o zero.o zero.c
*** Compiling /home/indy/development/tmp/top/one for hasse ***
make one.o zero.o 
make[2]: Entering directory `/home/indy/development/tmp/top/one'
make[2]: `one.o' is up to date.
make[2]: `zero.o' is up to date.
make[2]: Leaving directory `/home/indy/development/tmp/top/one'
mv -f *.o hasse/debug
*** Compiling /home/indy/development/tmp/top/one for hasse COMPLETED ***
make[1]: Leaving directory `/home/indy/development/tmp/top/one'
It seems to try to compile twice. I don't understand why. If I change variable 'DIRS = one two'. The make goes one in infinite loop. I guess the problem is related to same error. Anyone can see why?

Thanks a million.
Indy
 
Old 06-08-2011, 01:19 PM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
I cannot tell from your top-level Makefile whether you are attempting to build object files in directories 'one' and 'two', and then combine all objects files to build one executable, or if you are building two executables.

If it is the latter, then I would suggest that you keep the top-level Makefile real simple; something like:
Code:
DIRS = one two

all clean:
        @ for dir in $(DIRS); do \
                $(MAKE) -C $$dir $@; \
          done
For the Makefile in directory 'one':
Code:
APP = one

SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)

DEBUG  = -g
CFLAGS = -Wall -pedantic $(DEBUG)

LDFLAGS =

.PHONY: all clean


all : $(APP)

$(APP) : $(OBJS)
        $(CC) $^ $(LDFLAGS) -o $@

clean :
        $(RM) $(OBJS)
        $(RM) $(APP)
The Makefile in directory 'two' should be quite similar to the above, with the exception being the value assigned to APP.

Last edited by dwhitney67; 06-08-2011 at 01:21 PM.
 
Old 06-09-2011, 02:44 AM   #3
freeindy
Member
 
Registered: Nov 2002
Posts: 207

Original Poster
Rep: Reputation: 32
Thanks dwhitney67,

Sorry for misinformation. I'm trying to build object files in all sub directories and then link them to one executable into a different folder.

The example you gave me above is the one I started from.
 
Old 06-09-2011, 04:10 AM   #4
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by freeindy View Post
I'm trying to build object files in all sub directories and then link them to one executable into a different folder.
Roger that... try the following Makefile. It will locate all of your C modules, so that it can generate the dependency and object file for each (all of which is placed in OBJDIR). If you keep header files in a separate directory (from where the .c files reside), then define the value for INCLUDE; otherwise leave it unassigned. And if you have any external library dependencies, then define LDFLAGS. Of course, adjust the value for APP. Other than that, you should not have to modify anything else.
Code:
APP      = myapp

OBJDIR   = .srcobjs

SRCS    := $(shell find . -name '*.c')
SRCDIRS := $(shell find . -name '*.c' -exec dirname {} \; | uniq)
OBJS    := $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
DEPS    := $(patsubst %.c,$(OBJDIR)/%.d,$(SRCS))

DEBUG    = -g
INCLUDES =
CFLAGS   = $(DEBUG) -Wall -pedantic $(INCLUDES) -c
LDFLAGS  =

DEPENDS  = -MT $@ -MD -MP -MF $(subst .o,.d,$@)

SHELL    = /bin/bash

.PHONY: all clean distclean


all: buildrepo $(APP)

$(APP): $(OBJS)
	$(CC) $^ $(LDFLAGS) -o $@

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

clean:
	$(RM) -r $(OBJDIR)

distclean: clean
	$(RM) $(APP)

buildrepo:
	@$(call make-repo)

define make-repo
   for dir in $(SRCDIRS); \
   do \
	mkdir -p $(OBJDIR)/$$dir; \
   done
endef

ifneq "$(MAKECMDGOALS)" "distclean"
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEPS)
endif
endif
 
1 members found this post helpful.
Old 06-10-2011, 10:02 AM   #5
freeindy
Member
 
Registered: Nov 2002
Posts: 207

Original Poster
Rep: Reputation: 32
Thanks!

Nice solution :-). However, I have a different setting in my tree structure and the project has to compile for two different targets. But your solution gave the was. once again, thanks.

Regards
Indy
 
  


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
[SOLVED] How to write non recursive makefile tushs Programming 5 01-07-2012 11:04 AM
[SOLVED] Recursive Makefile freeindy Programming 5 05-25-2011 08:19 AM
Is it mandatory to have the name of the makefile as 'Makefile' for kernal module comp narender.d Linux - Kernel 3 05-29-2009 06:26 AM
how to get (makefile -f makefile )output into the textview widget in Pygtk sailu_mvn Programming 3 02-28-2005 03:57 AM

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

All times are GMT -5. The time now is 05:21 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