Gnu Makefile - Handling dependencies

后端 未结 12 2506
滥情空心
滥情空心 2021-02-07 20:24

What approach do C++ programmers on Unix platform use to create and manage Makefiles?

I was using hand made Makefiles for my projects but they don\'t handle header file

相关标签:
12条回答
  • 2021-02-07 21:03

    I use BSD make (pmake?) which does lot of work for me (my lang is C, but I think no difference here). This is my common 'local.prog.mk', I never change it:

    .PHONY: tags .depend
    
    # .depend depends only on $(SRCS) in bsd.dep.mk, so we can't track changes of
    # header's own dependencies properly. so .depend is .PHONY target here.
    
    CSTD    ?=c99
    WARNS   ?=9
    .if !empty(PC_LIST)
    PC_CF   !=pkg-config --cflags $(PC_LIST)
    PC_LD   !=pkg-config --libs   $(PC_LIST)
    .endif
    CFLAGS  +=$(PC_CF) -fgnu89-inline
    .if !defined(NO_DEBUG)
    CFLAGS  +=-O0 -ggdb3
    .endif
    LDFLAGS +=$(PC_LD)
    CTAGS   =exctags
    
    NO_MAN=
    NO_OBJ=
    CLEANFILES+=$(PROG).core
    
    .include <bsd.prog.mk>
    $(PROG): $(SUBDIR)
    build: clean cleandepend depend all
    run: $(PROG)
        ./$(PROG)
    

    Note 'bsd.prog.mk' inclusion -- this handles all, build, depend, clean targets. Project-specific BSDmakefiles are simple:

    .SILENT:
    
    PROG    =hello
    SRCS    =hello.c world.c
    PC_LIST =gtk+-2.0 gnet-2.0
    
    .include "../local.prog.mk"
    
    proto:
        cproto -siv `pkg-config --cflags $(PC_LIST)` $(SRCS) > prototypes
    CLEANFILES+=prototypes
    

    I just make depend every time I insert/remove any #include directives.

    0 讨论(0)
  • 2021-02-07 21:03

    gcc/g++ can generate dependencies for you with the -M family of options. The following works by specifying how to generate .depends files given a source file. By doing -include $(DEPS) $(DEPS) is recognized as a target and will be built/rebuilt when the source files change.

    CXX      = g++
    CXXFLAGS = -Wall -O3
    LDFLAGS  =
    
    TARGET = testcpp
    SRCS   = main.cc x.cc foo.cc
    OBJS   = $(SRCS:.cc=.o)
    DEPS   = $(SRCS:.cc=.depends)
    
    
    .PHONY: clean all
    
    all: $(TARGET)
    
    $(TARGET): $(OBJS)
            $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET)
    
    .cc.o:
            $(CXX) $(CXXFLAGS) -c $< -o $@
    
    %.depends: %.cc
            $(CXX) -M $(CXXFLAGS) $< > $@
    
    clean:
            rm -f $(OBJS) $(DEPS) $(TARGET)
    
    -include $(DEPS)
    
    0 讨论(0)
  • 2021-02-07 21:04

    The makedepend utility is installed on many systems and can be quite useful for generating dependency information.

    Here is an example Makefile that uses the include directive (plus a little Perl magic) to incorporate the output from makedepend:

    # the name of the executable that we'll build
    TARGET = foo_prog
    # our .cc source files
    SRCS = foo.cc main.cc
    
    # the .o versions of our source files
    OBJS := $(patsubst %.cc, %.o, $(filter %.cc, $(SRCS)))
    # some flags for compiling
    CXXFLAGS = -Wall -Werror
    
    # In order to build $(TARGET), we first build each of the $(OBJS).
    # Then we use the given command to link those $(OBJS) into our
    # $(TARGET) executable.  $^ is a shortcut for $(OBJS).  $@ is a
    # shortcut for $(TARGET).
    #
    # The default compile rule will compile each of the $(OBJS) for us.
    $(TARGET): $(OBJS)
            $(CXX) $(CXXFLAGS) $^ -o $@
    
    # Use "make clean" to remove all of the support files.
    clean:
            rm -f $(OBJS) $(TARGET) Makefile.depend *~
    
    # This automatically uses the 'makedepend' utility to add any
    # dependencies that our source files have, namely .h files.  This way,
    # if the .h files change, the code will be re-compiled.
    include Makefile.depend
    Makefile.depend: $(SRCS)
            makedepend -f- -Y $(SRCS) 2> /dev/null | \
            perl -p -e "s/(^.*?:)/Makefile.depend \1/" > Makefile.depend
    

    If both foo.cc and main.cc depend on foo.h, then the contents of Makefile.depend would be:

    Makefile.depend foo.o: foo.h
    Makefile.depend main.o: foo.h
    

    The end result is that the dependency information from makedepend is injected into the Makefile as a series of rules. It's similar to the approach of using a .d file for each .cc file, but keeps the dependency information in one file instead of scattered all over the place.

    0 讨论(0)
  • 2021-02-07 21:05

    In a make file anything you list on the dependency line is a dependency header files or other files included.

    BSD tutorial on make Note: you can auto generate header dependency info with the -MM switch of GCC.

    0 讨论(0)
  • 2021-02-07 21:05

    I prefer to use CMake, even though it's not strictly the solution to your problem.

    It's a project description language that'll generate your Makefiles, Visual Studio Project, Eclipse Project, KDevelop, etc for you. All the dependencies are done for you:

    CMakeLists.txt

    add_executable(my_exe file1.c file2.c)
    target_link_libraries(my_exe my_library)
    add_subdirectory(lib)
    

    In lib/CMakeLists.txt

    add_library(my_library file3.c file4.c)
    

    This creates a my_exe from file1.c file2.c linked against my_library. I find this much simpler. It also has things like package discovery:

    find_package(Qt4)
    
    0 讨论(0)
  • 2021-02-07 21:06

    I top tip that I have found useful when building dependency files is to include the dependency file as a target in the generated rule:

    file.d file.o : file.c header.h header2.h ...
    

    Thus make will regenerate the dependencies if the source or any of the headers change. Including phony targets for the headers (GCC -MP) should then allow stable builds when headers are removed - the absense of required header remains a compilation error, not a make dependency error.

    Assuming that dependency files are generated into the same directory as the object files, the following should work for GCC on Unix:

    -include $(OBJ:.o=.d)
    
    $(OBJDIR)/%d : $(SRCDIR)/%.cpp
            mkdir -p $(@D)
            echo -n "$@ " > $@.tmp
            $(CXX) $(CPPFLAGS) -MM -MP -MT $(@:.d=.o) $< >> $@.tmp
            mv $@.tmp $@
    

    (from memory)

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