Thread: Makefile problem; create obj file outside the src folder

  1. #1
    Registered User
    Join Date
    Jun 2012
    Posts
    11

    Makefile problem; create obj file outside the src folder

    Hi.. I am totally new here.. and totally new using the "makefile".. my problem is I try to "make" the makefile and create the obj files outside the /src folder (makefile is inside the src folder) istead of it create inside the /src folder... here is my tree level directory..

    Code:
    .
    ├── include
    │   ├── def.h
    │   └── h_TmrSbc.h
    ├── lib
    ├── obj
    └── src
        ├── f_TmrSbc.c
        ├── Makefile
        └── m_TmrSbc.c
    I already read the manual.. and it is really big and hard to understand for me.. I also have surfing all over the internet but unlucky.. hope you all can help and teach me this stuff..

    Here are my current makefile source code:

    Code:
    CC = gcc
    CFLAGS = -g -Wall
    INCL = -I../include
    EXEC = TmrSbc
    
    $(EXEC): m_$(EXEC).o f_$(EXEC).o
        $(CC) -o $@ $^  
    
    %.o: %.c
        $(CC) $(CFLAGS) -c $< $(INCL)
    
    .PHONY: clean
    clean:
        rm -f *.o *$(EXEC) core *~
        rm -f timelog.txt
    I also try to modified the
    Code:
    %.o: %.c
    part to
    Code:
    obj/%.o:%.c
    but got the compiler error state the location of header cannot be found to create the object files...

    I also try to change the location of INCL...

    Please help...

  2. #2
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    1/
    You should move your makefile at the root of the hierarchy instead of the src/ directory, that would be more logical from the user standpoint.
    When do it, adjust your INCL variable to -Iinclude

    2/
    What you've tried to do (obj/%.o: %.c) doesn't work because of makefile built-in rules.
    There's already a built-in rule "%.o: %.c" that exist that will built objects where the source is.

    Make is an amazing tool and I'm sure you can achieve what you want more easily with some makefile magic but for the moment, here's what I propose.
    Code:
    CC = gcc
    CFLAGS = -g -Wall
    INCL = -Iinclude
    EXEC = TmrSbc
     
    $(EXEC): obj/m_$(EXEC).o obj/f_$(EXEC).o
        $(CC) -o $@ $^  
     
    obj/%.o: src/%.c
        $(CC) $(CFLAGS) -c $< $(INCL) -o $@
     
    ...
    By defining the specialized template "obj/%.o: src/%.c" you avoid to use the built-in one.
    However in order for it to work, you have to explicitely prefix the object names with the directory in the main rule: $(EXEC): obj/... obj/...
    otherwise make will look for a pattern like "%.o:..." and fall back on the built-in one.

    Alternatively you could also do that:
    Code:
    ...
    VPATH := src
    
    $(EXEC): obj/m_$(EXEC).o obj/f_$(EXEC).o
        $(CC) -o $@ $^  
     
    obj/%.o: %.c
        $(CC) $(CFLAGS) -c $< $(INCL) -o $@
     
    ...
    This is almost what you've tried earlier, but notice the VPATH variable that tells make where to look for files (assuming the makefile is at the root).
    Last edited by root4; 09-12-2012 at 10:08 AM.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    The exact error message(s) would help, and the source code (.c and .h files you're using), but I'm guessing it's something like:
    Code:
    main.c: In function ‘main’:
    main.c:6: warning: implicit declaration of function ‘foo’
    Your makefile looks correct in terms of specifying a location for include files. Perhaps you're missing a declaration/prototype in one of the .h files, or you forgot to #include it in one of your .c files. Hard to say without the code.

    As for putting the .o files in a specific location, you need to use that location everywhere you reference a .o file. I would modify your make file like so:
    Code:
    OBJ_LOC=../obj
    
    $(EXE): $(OBJ_LOC)/m_$(EXEC).o $(OBJ_LOC)/f_$(EXEC).o
        $(CC) -o $@ $^
    
    $(OBJS)/%.o: %.c
        $(CC) $(CFLAGS) -o $@ -c $< $(INCL)
    • That defines a variable, so you can move the object file location around by only changing one line.
    • Those tells the linker that it must look for the object files in their proper location, otherwise it defaults to looking in the current directory.
    • That tells the compiler that the name of the make target includes the object file directory, i.e. ../obj/foo.o.
    • That tells the compiler that the output of gcc -c should be the name of the target, i.e. the object file in it's proper directory.




    Make sure to adjust your 'clean' target accordingly too.

  4. #4
    Registered User
    Join Date
    Jun 2012
    Posts
    11
    Quote Originally Posted by root4 View Post
    1/
    You should move your makefile at the root of the hierarchy instead of the src/ directory, that would be more logical from the user standpoint.

    ...

    Make is an amazing tool and I'm sure you can achieve what you want more easily with some makefile magic but for the moment, here's what I propose.
    Code:
    CC = gcc
    CFLAGS = -g -Wall
    INCL = -Iinclude
    EXEC = TmrSbc
     
    $(EXEC): obj/m_$(EXEC).o obj/f_$(EXEC).o
        $(CC) -o $@ $^  
     
    obj/%.o: src/%.c
        $(CC) $(CFLAGS) -c $< $(INCL) -o $@
     
    ...
    ...

    Alternatively you could also do that:
    Code:
    ...
    VPATH := src
    
    $(EXEC): obj/m_$(EXEC).o obj/f_$(EXEC).o
        $(CC) -o $@ $^  
     
    obj/%.o: %.c
        $(CC) $(CFLAGS) -c $< $(INCL) -o $@
     
    ...
    This is almost what you've tried earlier, but notice the VPATH variable that tells make where to look for files (assuming the makefile is at the root).
    Thank you clear explanation root4...

    1. The reason my Makefile inside the src/ is because I planning to create a recursive Makefile.. Module by module program src/TmrSbc, src/Xxx, src/???... I stuck at that "test program" before proceed to create another module...

    2. What is makefile magic?

    3. What is ":=" meaning and how to use that?? Also could you explain about VPATH?? I do find this "VPATH" and also "pathsubst" that maybe are related to my problem.. but don't understand them very well even after review some example and do some reading..

  5. #5
    Registered User
    Join Date
    Jun 2012
    Posts
    11
    Quote Originally Posted by anduril462 View Post
    The exact error message(s) would help, and the source code (.c and .h files you're using), but I'm guessing it's something like:
    Code:
    main.c: In function ‘main’:
    main.c:6: warning: implicit declaration of function ‘foo’
    ...

    As for putting the .o files in a specific location, you need to use that location everywhere you reference a .o file. I would modify your make file like so:
    Code:
    ...
    $(OBJS)/%.o: %.c
        $(CC) $(CFLAGS) -o $@ -c $< $(INCL)
    • That tells the compiler that the name of the make target includes the object file directory, i.e. ../obj/foo.o.
    • That tells the compiler that the output of gcc -c should be the name of the target, i.e. the object file in it's proper directory.

    Thank you anduril462,

    1. Sorry a little bit confius, $(OBJS), do you mean $(OBJS_LOC)??
    2. -o $@, is this necessary?? without -o $@ I still have the object name same as target files. I do not put -o because, I think -o will create execution files.. the $(EXEC) is need to create this exec file that's I ignore to put that thing...

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by sangelion View Post
    1. Sorry a little bit confius, $(OBJS), do you mean $(OBJS_LOC)??
    Yes, that was a typo on my part, sorry. It should be
    Code:
    $(OBJ_LOC)/%.o: %.c
    2. -o $@, is this necessary?? without -o $@ I still have the object name same as target files. I do not put -o because, I think -o will create execution files.. the $(EXEC) is need to create this exec file that's I ignore to put that thing...
    Yes, it's necessary. The -o option tells gcc the name of the output file. When using the -c option you are only compiling, not linking. The output of compiling a .c file is a .o file, thus you want to name the output object file the same as the target name, which is ../obj/foo.o. Without the -o $@, gcc will just put the object file in the same directory as the make file

    Quote Originally Posted by sangelion View Post
    I try to change the makefile.. but still don't change the location of Makefile (still inside the src\ folder...)
    Code:
    OBJ_DIR = ../obj
    ...
    $(OBJ_DIR)%.o: %.c
        $(CC) $(CFLAGS) -c $< $(INCL) -o $@
    Notice, that has no trailing slash, therefore you need a slash between the object directory and the object file wildcard.
    Code:
    $(OBJ_DIR)/%.o: %.c

  7. #7
    Registered User
    Join Date
    Jun 2012
    Posts
    11
    Quote Originally Posted by anduril462 View Post
    Code:
    $(OBJ_LOC)/%.o: %.c
    Notice, that has no trailing slash, therefore you need a slash between the object directory and the object file wildcard.
    Code:
    $(OBJ_DIR)/%.o: %.c
    I just noticed it.. sorry...

  8. #8
    Registered User
    Join Date
    Jun 2012
    Posts
    11
    Thank you anduril462 and root4... basically my problem already solve.. eventhough I still really don't get about VPATH and pathsubst function... how do I change to [SOLVED] thread... I still need to learn more about this Makefile.. It was quite interested..

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You're welcome. This forum doesn't have a "mark solved" mechanism. This thread will just become quiet, since you now have all your answers.

  10. #10
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    VPATH specifies where Make can look for files; it's a list of directories like PATH for your shell, separated by semi-colons.
    When you have a rule X: Y, you don't necessarily specify the full path of X or Y for instance, in this case, make will look in all the directories specified by VPATH to find them.

    ":=" is an assignment operator, like "=", except it's evaluated only once. You have a chapter dedicated to it in the documentation (flavor of variables if I remember correctly).

    When I said "makefile magic" I was referring to a lot of mechanisms (implicit rules, templates, predefined variables, functions, special operators ...) that can all make your makefile pretty short but powerful. You can just stick to basic things when writing a makefile but as soon as you dig in the documentation you can discover another unexpected interesting way to do it.
    Last edited by root4; 09-12-2012 at 11:58 AM.

  11. #11
    Registered User
    Join Date
    Jun 2012
    Posts
    11
    VPATH specifies where Make can look for files; it's a list of directories like PATH for your shell, separated by semi-colons.
    When you have a rule X: Y, you don't necessarily specify the full path of X or Y for instance, in this case, make will look in all the directories specified by VPATH to find them.
    Ok.. I understand when you tell me about VPATH is quite similar with PATH in the shell.. so listing VPATH will "transparently" generalize all part into one current file? So listing src, obj, inc to VPATH is like put them into one big folder without subfolder? Wow..

    ":=" is an assignment operator, like "=", except it's evaluated only once. You have a chapter dedicated to it in the documentation (flavor of variables if I remember correctly).
    So := is better than = ... so can we change all = to :=??

    When I said "makefile magic" I was referring to a lot of mechanisms (implicit rules, templates, predefined variables, functions, special operators ...) that can all make your makefile pretty short but powerful. You can just stick to basic things when writing a makefile but as soon as you dig in the documentation you can discover another unexpected interesting way to do it
    I usually dig into the documentation when facing the related problem... Yes.. people always ask to read the manual.. but you know.. the manual is a really big documentation.. reading without doing or facing is sometimes useless..

    Anyway thanks for your explaination.. It helps a lots..

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. problem including .h file thats in its own folder
    By Anddos in forum C++ Programming
    Replies: 2
    Last Post: 03-25-2007, 04:22 PM
  2. How to create a folder
    By andreas_nordman in forum C++ Programming
    Replies: 1
    Last Post: 06-14-2004, 06:25 AM
  3. create dir in makefile
    By rotis23 in forum Linux Programming
    Replies: 5
    Last Post: 11-15-2002, 04:10 AM
  4. Create folder
    By toby1909 in forum Windows Programming
    Replies: 1
    Last Post: 01-29-2002, 01:57 AM
  5. using MAKE with makefile to create executable file
    By sballew in forum C Programming
    Replies: 1
    Last Post: 11-19-2001, 12:49 PM