Thread: makefile problems

  1. #1
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545

    makefile problems

    Hi,
    I'm playing around with makefiles on Linux and I can't quite figure out what's wrong with this one:
    Code:
    # makefile for test build.
    ###########################################################
    
    CC = g++
    CDEBUG = -g3
    CRELEASE = -O3
    DEFS =
    CFLAGS = -I. $(DEFS) -c -pedantic-errors
    LDFLAGS =
    OBJS = main.o
    DEBUG_PATH = debug
    RELEASE_PATH = release
    TARGET = main
    
    clean:
    	rm -f $(DEBUG_PATH)/*.o  $(DEBUG_PATH)/$(TARGET)
    	rm -f $(RELEASE_PATH)/*.o  $(RELEASE_PATH)/$(TARGET)
    	rmdir $(DEBUG_PATH)
    	rmdir $(RELEASE_PATH)
    
    all:	debug release
    
    debug:	$(DEBUG_PATH)  $(DEBUG_PATH)/$(OBJS)
    	cd $(DEBUG_PATH)
    	$(CC) $(LDFLAGS) $(OBJS) -o $(TARGET)
    
    release:	$(RELEASE_PATH)  $(RELEASE_PATH)/$(OBJS)
    	cd $(RELEASE_PATH)
    	$(CC) $(LDFLAGS) $(OBJS) -o $(TARGET)
    
    $(DEBUG_PATH):
    	mkdir $(DEBUG_PATH)
    
    $(RELEASE_PATH):
    	mkdir $(RELEASE_PATH)
    
    $(DEBUG_PATH)/main.o:	main.cpp
    	cd $(DEBUG_PATH)
    	$(CC) $(CDEBUG) $(CFLAGS) ../main.cpp
    
    $(RELEASE_PATH)/main.o:	main.cpp
    	cd $(RELEASE_PATH)
    	$(CC) $(CRELEASE) $(CFLAGS) ../main.cpp
    If I run make debug it barfs out all these errors:
    Code:
    makefile:32: warning: overriding commands for target `debug'
    makefile:24: warning: ignoring old commands for target `debug'
    makefile:35: warning: overriding commands for target `release'
    makefile:28: warning: ignoring old commands for target `release'
    make: Circular debug <- debug dependency dropped.
    cd debug
    /bin/sh: line 0: cd: debug: No such file or directory
    make: *** [debug/main.o] Error 1
    Here's main.cpp in case it matters:
    Code:
    // main.cpp
    /////////////////////////////////////////////////////////////////////
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	cout << "Hello World!" << endl;
    	return 0;
    }
    Can someone explain what those warnings mean and especially why the debug directory isn't being created?

  2. #2
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    You have a circular reference, and that's why make drops the target. This is in your makefile, although not explicitly:
    Code:
    debug : debug
    It actually looks like this:
    Code:
    debug:	$(DEBUG_PATH)  $(DEBUG_PATH)/$(OBJS)
    Remember, DEBUG_PATH=debug
    Ditto for release.
    You'll probably have to rename one of those...

    Also, I've run into problems using directories as targets like that in makefiles under Windows. Seems whenever a file inside of that directory (but not subdirs) is modified, so is the directory. This made make always want to rebuild a fair portion of the project incorrectly.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Damn, I didn't even think of that... Thanks.
    I also noticed another problem where I did cd debug on one line, then compiled on the next line, but I needed to do them on the same line (separated by a semicolon).
    This works perfectly now:
    Code:
    # makefile for test build.
    ###########################################################
    
    CC = g++
    CDEBUG = -g3
    CRELEASE = -O3
    DEFS =
    CFLAGS = -I. $(DEFS) -c -pedantic-errors
    LDFLAGS =
    OBJS = main.o
    DEBUG_PATH = Debug
    RELEASE_PATH = Release
    TARGET = main
    
    clean:
    	rm -f $(DEBUG_PATH)/*.o $(DEBUG_PATH)/$(TARGET)
    	rm -f $(RELEASE_PATH)/*.o $(RELEASE_PATH)/$(TARGET)
    	rmdir $(DEBUG_PATH)
    	rmdir $(RELEASE_PATH)
    
    all:	debug release
    
    debug:	$(DEBUG_PATH) $(DEBUG_PATH)/$(OBJS)
    	cd $(DEBUG_PATH) ; $(CC) $(LDFLAGS) $(OBJS) -o $(TARGET)
    
    release:	$(RELEASE_PATH) $(RELEASE_PATH)/$(OBJS)
    	cd $(RELEASE_PATH) ; $(CC) $(LDFLAGS) $(OBJS) -o $(TARGET)
    
    $(DEBUG_PATH):
    	mkdir $(DEBUG_PATH)
    
    $(RELEASE_PATH):
    	mkdir $(RELEASE_PATH)
    
    $(DEBUG_PATH)/main.o:	main.cpp
    	cd $(DEBUG_PATH) ; $(CC) $(CDEBUG) $(CFLAGS) ../main.cpp
    
    $(RELEASE_PATH)/main.o:	main.cpp
    	cd $(RELEASE_PATH) ; $(CC) $(CRELEASE) $(CFLAGS) ../main.cpp

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    BTW, since I'm not very experienced with writing makefiles, I'd like to know if the way I'm doing it here is the right way for making debug/release builds (i.e. two sections for each object file) or if there's a simpler way to do it that doesn't involve as much duplication?
    I could imagine it getting very tedious and error prone to write it like this if you're working with a very large project with dozens or hundreds of files.

  5. #5
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Having build variants in makefiles is generally tedious. The GNU autotools way is to have only one build target, and make the configure script set the necessary flags to switch between debug and release, then just run configure from different directories, i.e.
    Code:
    $ mkdir obj-debug
    $ cd obj-debug
    $ ../src/configure --enable-debug
    $ make
    $ cd ..
    $ mkdir obj-release
    $ cd obj-release
    $ ../src/configure --enable-optimize
    $ make
    I don't think plain makefiles properly support this, although there are ways of passing variables from one target to another that may help you in streamlining the process a bit - look for Target-specific Variable Values in the make manual.

    Other build systems have this stuff built in. Boost.Build, for example, has a feature called build variants which solves exactly the debug/release issue, as well as the single-threaded/multi-threaded and the static/dynamic linking issues, and probably some more.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with makefile
    By New_Programmer in forum C++ Programming
    Replies: 5
    Last Post: 03-31-2009, 04:55 PM
  2. problems with makefile
    By bartleby84 in forum C Programming
    Replies: 4
    Last Post: 02-16-2009, 09:02 AM
  3. Building a project using a Makefile
    By starcatcher in forum Windows Programming
    Replies: 2
    Last Post: 11-23-2008, 11:50 PM
  4. makefile blues....
    By WaterNut in forum C Programming
    Replies: 6
    Last Post: 05-30-2005, 08:22 PM
  5. Need help with Makefile
    By xshapirox in forum C++ Programming
    Replies: 14
    Last Post: 09-28-2004, 03:32 PM