makefile在源未更改时避免重新编译

时间:2015-10-27 06:01:26

标签: makefile

我是makefile的新手,我从在线示例中编写这个makefile来构建我的项目并且它有效。事实证明,当我再次运行它而不更改任何源代码时,所有目标文件都被重新编译。我认为make应该只重新编译那些改变了输入文件的目标。为什么会这样? =。=

#makefile
ROOTDIR = $(dir $(CURDIR))

icc iccclean: PLAT = icc
gcc gccclean: PLAT = gcc
clang clangclean: PLAT = clang

icc: CC = icpc
gcc: CC = g++
clang: CC = clang-omp++

#these are not important and I removed the details
LIBS = 
INC = 
FLAG = 
DEF = 

icc gcc clang:  run_de

SRCDIR = $(ROOTDIR)source   #path to all .cpp .h files
OBJDIR = $(ROOTDIR)build/$(PLAT)   #path of output .o files
TARGET = $(ROOTDIR)run_de.$(PLAT)  #final executable product

#the final product depends on object files core.o eval.o file_processing.o

run_de: $(OBJDIR)/core.o $(OBJDIR)/eval.o $(OBJDIR)/file_processing.o
    cd $(OBJDIR); $(CC) $(LIBS) $(FLAG) $(INC) $(DEF) -o $(TARGET) core.o eval.o file_processing.o

#rules of making the object files

$(OBJDIR)/core.o:   $(SRCDIR)/core.cpp
    $(CC) -c $(FLAG) $(LIBS) $(INC) $(DEF) $(SRCDIR)/core.cpp -o $(OBJDIR)/core.o
$(OBJDIR)/eval.o:   $(SRCDIR)/eval.cpp
    $(CC) -c $(FLAG) $(LIBS) $(INC) $(DEF) $(SRCDIR)/eval.cpp -o $(OBJDIR)/eval.o
$(OBJDIR)/file_processing.o:    $(SRCDIR)/file_processing.cpp
    $(CC) -c $(FLAG) $(LIBS) $(INC) $(DEF) $(SRCDIR)/file_processing.cpp -o $(OBJDIR)/file_processing.o

gccclean iccclean clangclean:
    $(RM) $(OBJDIR)/*.o $(TARGET)

.Phony: icc gcc clang iccclean gccclean clangclean

2 个答案:

答案 0 :(得分:2)

如评论中所述,我可能不会打扰目标文件的子目录。使用它会使makefile更难写,而且我很懒,并且没有找到任何比必要更努力工作的重大好处。

注意CC是C编译器的宏; CXX通常是C ++编译器的宏。

我在当前目录中有目标文件和源文件。然后我会使用makefile类似于:

icc   iccclean:   PLAT = icc
gcc   gccclean:   PLAT = gcc
clang clangclean: PLAT = clang

icc:   CXX = icpc
gcc:   CXX = g++
clang: CXX = clang-omp++

LDLIBS = 
LDFLAGS = 

SOURCE = eval.cpp core.cpp file_processing.cpp
OBJECT = ${SOURCE:.cpp=.o}
TARGET = run_de.${PLAT}

icc gcc clang:  ${TARGET}

${TARGET}: ${OBJECT}
    ${CXX} -o $@ ${OBJECT} ${LDFLAGS} ${LDLIBS}

gccclean iccclean clangclean:
    $(RM) ${OBJECT}

.PHONY: icc gcc clang iccclean gccclean clangclean

当你开始工作时,你可以以任何你想要的方式开始改进它。您需要查看用于将C ++源代码编译为目标文件的相关标志。如果您愿意,可以将目标文件放在其他目录中。您甚至可以将源文件放在不同的目录中。但是在开始跑步之前学会走路。

并且将宏用于文件列表等,因此您不必重复自己。

答案 1 :(得分:0)

我花了很多时间来发布一个功能正常的Makefile ...问题是有很多关于makefile的细节会导致很难注意到的错误。

将内容放在不同的目录中并不容易。最好将所有内容保存在一个文件夹中,除非有很强的理由。

#makefile
#One lesson learnt is that the makefile scope and shell command scope are different variable workspaces.
#Commands that are after a rule name is within shell command scope.
#variables in makefile scope are transparenet in the shell command scope. But not vice-versa.
#variables defined or modified in shell command scope cannot be correctly retrived in the makefile scope......
#This is a bloody source of bugs which is v difficult to debug.

icc iccclean: PLAT = icc
gcc gccclean: PLAT = gcc
clang clangclean: PLAT = clang

icc: CC = icpc
gcc: CC = g++
clang: CC = clang-omp++

TARGET = ../run_de.$(MAKECOMGOALS)
SOURCE = $(wildcard ../source/*.cpp)

OBJECT_temp = $(subst ../source/,$(MAKECMDGOALS)/,$(SOURCE))
OBJECT = $(subst .cpp,.o,$(OBJECT_temp))

LIBS = -lgsl -lgslcblas

gcc clang: LIBS += -lm

INC = 
clang: LIBS += -L/usr/local/Cellar/gsl/1.16/lib
clang: INC += -I/usr/local/Cellar/boost/1.58.0/include
clang: INC += -I/usr/local/Cellar/gsl/1.16/include -Wall -Wno-format-extra-args

FLAG = -std=c++11
clang gcc: FLAG += -fopenmp
icc: FLAG += -openmp

DEF = 
gcc icc: DEF += -DLenovoDebian
clang: DEF += -DyuMac
icc gcc clang:  $(TARGET)

$(TARGET): $(OBJECT)
    $(CC) -o $(TARGET) $(OBJECT) $(LIBS) $(INC) $(FLAG) $(DEF)

$(MAKECMDGOALS)/%.o: ../source/%.cpp
    $(CC) -c $< -o $@ $(LIBS) $(INC) $(FLAG) $(DEF)

gccclean iccclean clangclean:
$(RM) $(PLAT)/*.o $(TARGET)

.PHONY: icc gcc clang iccclean gccclean clangclean