How can I make my Makefiles better?

前端 未结 3 652
心在旅途
心在旅途 2021-01-23 18:04

I\'ve trying to learn the \"best practice\" makefile\'s for a project.

Please review my Makefile file below and suggest changes to enhance it.

The dir layout:

相关标签:
3条回答
  • 2021-01-23 18:17

    If you expect other people to use your Makefile, always include a help target that prints out a message detailing the various targets that are sensible to call from the command line, and the various environment vars which can be reasonably set to do various things...

    0 讨论(0)
  • 2021-01-23 18:18

    See this and that answers for examples about Makefile. Also run make -p to understand the builtin rules inside GNU make, so use $(LINK.cc) for e.g. your bin/tengine target.

    For complex builds, consider upgrading to GNU make 4.0 and use its Guile ability.

    You may want to generate automatically dependencies. Read automatic prerequisites and about autodependencies; read also about GCC preprocessor options like -M or -MD etc etc ....

    0 讨论(0)
  • 2021-01-23 18:28

    Here is a suggestion for a revised makefile, tested slightly on a 7-year-old version of Linux (RHEL 5):

    # Generic makefile
    
    TARGETS=tengine test2
    
    all: ${TARGETS}
    
    help:
            @echo ""
            @echo "make         - builds ${TARGETS}"
            @echo "make tengine - builds tengine"
            @echo "make test2   - builds test2"
            @echo "make clean   - deletes prior build"
            @echo "make help    - prints this help"
    
    # Switches:
    
    INC=-I/usr/include/hiredis
    LIB=-lhiredis
    SUBDIRS=obj deps bin
    LNK=gcc -g -Wl,--warn-common
    DEBUG=1
    
    ifdef DEBUG
            CFLAGS=-Wall -Winline -pipe -g -DDEBUG #-pedantic -pg 
    else
            CFLAGS=-Wall -Winline -pipe -O3 -march=native -funroll-all-loops \
                       -finline-functions #-pedantic 
    endif
    
    #CXXFLAGS=$(CFLAGS)
    
    # Generic rules:
    
    obj/%.o: src/%.c
            @echo Compiling $@
            @mkdir -p $(SUBDIRS)
            $(CC) $(CFLAGS) $(INC) -MMD -MF '$(patsubst src/%.c,deps/%.d,$<)' -o $@ -c $< 
    
    obj/%.o: src/%.cc 
            @echo Compiling $@
            @mkdir -p $(SUBDIRS)
            $(CXX) $(CXXFLAGS) $(INC) -MMD -MF '$(patsubst src/%.c,deps/%.d,$<)' -o $@ -c $<
    
    ${TARGETS}: %:bin/%
    
    # Specific target rules:
    
    bin/tengine: obj/main.o obj/tengine.o
            $(LNK) $^ $(LIB) -o $@ 
    
    bin/test2: obj/main.o obj/test2.o
            $(LNK) $^ $(LIB) -o $@ 
    
    clean:
            rm -f *~ src/*~ gmon.out
            rm -fr $(SUBDIRS)
    
    -include deps/*.d
    

    Some notes:

    • A key problem with the original was that the dependency were generated, but not used. This has been fixed using -include deps/*.d (at the end).

    • Now that deps/*.d is used, the makefile doesn't need to have the src/%.h cases.

    • The original was also putting garbage into these files: in $(patsubst src/%,obj/%,%(patsubst %.cc,%.o,$<)) the third % should have been a $.

    • In the revised version, the dependencies are generated at the same time as the object, using -MMD. This is quicker, shortens the makefile, and adds some DRY.

    • Shortened INC: why bother including the standard system include directories? And in fact gcc will apparently ignore your -I /usr/include -I /usr/local/include anyway.

    • Removed your two different definitions of OBJS. Not needed, and potentially confusing. Used $^ instead.

    • It is always a good idea for make clean to completely undo everything make does, so you are left with what you started. But the sub-directories obj/ and deps/ were being created, and never deleted. Also, bin/ was pre-supposed to exist.

    • For the linking, added $(LNK), with LNK=gcc -g -Wl,--warn-common (but you may not want the warnings). AFAIK, all the other usual $(CFLAGS) are ignored for links.

    • Removed comments, which were (mostly) distracting.

    • Repeated twice make;make now gives make: Nothing to be done for ....

    See also gcc dependency generation for a different output directory.

    0 讨论(0)
提交回复
热议问题