Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am trying to implement a makefile for my C project which has a directory structure as follows:

PROJECT_FOLDER:
    folder1
    folder2
    folder // n number of folders
    main.c

FOLDER1:
    subfolder1
    subfolder // n number of subfolders

And subfolder 1 can have further subfolders etc.. etc..

I don't intend on being stupid with my directory structure, the deepest I may go is 1-2 MAYBE 3.

Thus far I have:

# A Makefile to build our First_Game_2 project

dirs = * */parse

PROJECT =  main
HEADERS =  $(PROJECT).h
OBJ     =  $(foreach dirz, $(dirs), \
        \
        $(patsubst %.c,%.o,$(wildcard $(dirz).c)) \
        \
    )

C99     =  gcc -std=c99
CFLAGS  =  -Wall -pedantic -Werror 

$(PROJECT) : $(OBJ)
        $(C99) $(CFLAGS) -o $(PROJECT) $(OBJ)


%.o : %.c $(HEADERS)
        $(C99) $(CFLAGS) -c $<

clean:
        rm -f $(PROJECT) $(OBJ)

My problem is if parse contains a subfolder, say test to give the structure

PROJECT_FOLDER/parse/test

In such a case, nothing is returned from

$(foreach dirz, $(dirs), \
        \
        $(patsubst %.c,%.o,$(wildcard $(dirz).c)) \
        \
    )

I tested the output of the function with the following makefile

# A Makefile to build our First_Game_2 project

dirs = * */parse

PROJECT =  main
HEADERS =  $(PROJECT).h
OBJ     =  

C99     =  gcc -std=c99
CFLAGS  =  -Wall -pedantic -Werror 

$(foreach dirz, $(dirs), \
        \
        $(patsubst %.c,%.o,$(wildcard $(dirz).c)) \
        \
    )

Which, given a structure of:

dirs = * */parse */parse/test

Produces an output of:

main.o parse/parse.o

Ignoring */parse/test

Why is this the case, what can I do to fix my OBJ assignment to recognize */parse/test or otherwise?

share|improve this question
    
What make is it? Incredible, but there are waaaaay more make variants out there than RMS wants to make us believe ;) –  0xC0000022L Feb 22 '13 at 20:29

1 Answer 1

up vote 2 down vote accepted

You have the wildcard in the dirs pattern backward. You wanted:

dirs = * parse/* parse/test/*

As written, your pattern above expanded to: *.c (good), */parse.c (lucky!), and */parse/test.c, which would have confused you even more if that file existed. The only reason it looked like it worked for the first level directory is because you used the same filename, 'parse', as the directory name.

share|improve this answer
    
I think VPATH, assuming GNU make` might also make a difference here. But so far I always went with schemes such as $(wildcard ...) or $(shell find -...) to include the correct files. One just has to be careful if out-of-tree builds are intended. +1 –  0xC0000022L Feb 22 '13 at 20:50
    
@ckchan oh wow, that's was silly of me :S - It seems my clean function isn't being implemented now, as I was hoping to replace $(OBJ) with my ~$(foreach` logic, any ideas why clean: isn't running? –  tsujp Feb 23 '13 at 5:37
    
@tsujp: seems like that would be unrelated to clean; if it's really not running at all, make sure it isn't something obvious like a file/dir called "clean". If not, try make -d to get more detail on what make is considering. –  ckhan Feb 23 '13 at 6:12
    
It seems that having a file main.h results in object files being created in the root directory, no matter what directory they come from. E.g. main.o and parse.o are inside the same folder instead of parse.o being inside the parse folder. Conversely renaming main.h to say... includes.h results in ISO C90 warnings, even though I clearly state -std=c99. The makefile is UNCHAINED except for your answer. As for clean near this line from make -d : Successfully remade target file main'.` there is no mention of clean, neither does scrolling through the terminal. This is annoying. –  tsujp Feb 23 '13 at 6:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.