我是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
答案 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