【问题标题】:makefile avoid recompilation when source is unchanged当源代码未更改时,makefile 避免重新编译
【发布时间】:2015-10-27 06:01:26
【问题描述】:

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

【问题讨论】:

  • 请注意 make 对待 .PHONY.Phony 完全不同。
  • 您的run_de 规则不会创建文件,因此每次都执行命令(创建run_de.iccrun_de.gccrun_de.clang)徒劳地希望它会创建run_de。它没有,所以下一次,它会再试一次。重新考虑您的链接规则。
  • 你的意思是规则'run_de'的名字也应该是输出文件的名字吗? @JonathanLeffler
  • 要么,要么您需要将规则设为$(TARGET): …
  • 我将规则名称更改为 $(TARGET) 但没有运气..@JonathanLeffler

标签: makefile


【解决方案1】:

如 cmets 中所述,我可能不会为目标文件的子目录而烦恼。使用它会使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++ 源代码编译为目标文件的相关标志。如果您愿意,可以将目标文件放在其他目录中。您甚至可以将源文件放在不同的目录中。但是在开始跑步之前先学会走路。

并且对文件列表等使用宏,所以你不必重复自己。

【讨论】:

  • 缺少生成目标文件的规则?
  • 好的,这意味着 CXX LDFLAGS LDLIBS 是自动与内置规则关联的常规宏名称。
  • 或多或少,是的。您可以通过运行 make -p 检查您的 make 定义的内容,这应该打印宏和规则(可能很多)。
【解决方案2】:

我花了很多时间才完成了一个按预期运行的 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

【讨论】:

    猜你喜欢
    • 2014-08-29
    • 2019-03-25
    • 2020-12-31
    • 1970-01-01
    • 2014-05-03
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多