在不应该应用生成文件规则时应用
makefile rules being applied when they shouldn't
我有一个用于某些C++代码的makefile(粘贴在下面),它有一个烦人的问题,当我make clean
时,依赖项文件被编译(在再次删除之前),这使得make clean
太慢了。依赖关系规则是
$(DEPENDDIR)%.d: %.cpp
@mkdir -p $(DEPENDDIR)
$(CXX) -M -MG -MT $(OBJECTDIR)$*.o $(CXXFLAGS) $< > $@
谁能看出问题出在哪里?
我尝试将依赖项移动到编译对象的部分,即:
$(OBJECTDIR)%.o: %.cpp
@mkdir -p $(OBJECTDIR) # $(dir $@)
@echo " "
$(CXX) -M -MG -MT $@ $(CXXFLAGS) $<
-MF $(patsubst $(OBJECTDIR)%.o, $(DEPENDDIR)%.d, $@)
但随后没有创建头文件 version.hpp(编译失败)
KERNEL := $(shell uname -s)
PROGNAME=nextsim.exec
CXX = g++
# setting the C++ standard according to the gcc compiler version (from gcc-5.2, the default is C++14)
ifeq ($(shell echo `$(CXX) -dumpversion | cut -f1-2 -d.` >= 5.2 | sed -e 's/.//g' | bc),1)
CXXFLAGS += -std=c++14
else
CXXFLAGS += -std=c++11
endif
# add g++ option flags
CXXFLAGS += -ftemplate-depth-256 -Wno-inline
-fPIC -fopenmp
-DHAVE_CONFIG_H -D_MULTITHREADING_
ifdef NEXTSIM_COMPILE_VERBOSE
CXXFLAGS += -v
endif
ifdef USE_OASIS
CXXFLAGS += -DOASIS
CXXFLAGS += -I $(NEXTSIMDIR)/modules/oasis/include
LDFLAGS += -lgfortran
LDFLAGS += -L $(NEXTSIMDIR)/lib -loasis
CHAN = MPI1
#LIBPSMILE = $(OASIS_DIR)/lib/libpsmile.${CHAN}.a $(OASIS_DIR)/lib/libmct.a $(OASIS_DIR)/lib/libmpeu.a $(OASIS_DIR)/lib/libscrip.a
endif
ifneq (,$(strip $(filter DEBUG Debug debug PROFILE Profile profile,$(NEXTSIM_BUILD_TYPE))))
#ifeq ($(NEXTSIM_BUILD_TYPE),$(filter $(NEXTSIM_BUILD_TYPE),Debug debug))
CXXFLAGS := $(filter-out -O3 -pthread,$(CXXFLAGS))
CXXFLAGS += -g -O0 -DNDEBUG
ifneq (,$(strip $(filter PROFILE Profile profile,$(NEXTSIM_BUILD_TYPE))))
CXXFLAGS += -DWITHGPERFTOOLS
endif
ifneq ($(KERNEL),Linux)
CXXFLAGS += -Wl,-no_pie
endif
else
CXXFLAGS += -O3 -pthread
endif
# add include paths
CXXFLAGS += -I $(NEXTSIMDIR)/core/include
CXXFLAGS += -isystem $(NEXTSIMDIR)/contrib/bamg/include # suppress annoying compilation warnings from -I
CXXFLAGS += -isystem $(NEXTSIMDIR)/contrib/mapx/include # suppress annoying compilation warnings from -I
# CXXFLAGS += -I $(NEXTSIMDIR)/contrib/interp/include
ifdef USE_ENSEMBLE
CXXFLAGS += -DENSEMBLE
CXXFLAGS += -I $(NEXTSIMDIR)/modules/enkf/perturbation/include
endif
ifdef USE_AEROBULK
CXXFLAGS += -I $(AEROBULK_DIR)/include
CXXFLAGS += -DAEROBULK
endif
# openmpi
CXXFLAGS += -I $(OPENMPI_INCLUDE_DIR)/
# petsc
CXXFLAGS += -I $(PETSC_DIR)/include
# boost
CXXFLAGS += -I $(BOOST_INCDIR)/ -I .
# netcdf
CXXFLAGS += -I $(NETCDF_DIR)/include
# gmsh
CXXFLAGS += -I $(GMSH_DIR)/include/gmsh
CXXFLAGS += -I /opt/local/include
ifeq ($(KERNEL),Linux)
#CXXFLAGS += -std=c++0x -std=c++11 -pedantic -ftemplate-depth-256 -Wno-inline -fPIC -g -lm -pthread -v #-MMD -MP -lm -pthread -v
else
ifeq ($(CXX),clang)
CXXFLAGS += -stdlib=libc++
endif
CXXFLAGS += -I /usr/local/include #-I /opt/local/include/openmpi-mp
#LDFLAGS += -Wl,-rpath,/usr/local/lib #-Wl,-rpath,/opt/local/lib/openmpi-mp
#LDFLAGS += -L /usr/local/lib #-L /opt/local/lib/openmpi-mp -lmpi_cxx -lmpi -ldl -lstdc++ -lpthread
ifeq ($(CXX),clang)
LDFLAGS += -stdlib=libc++
endif
endif
LDFLAGS += -L /usr/local/lib
LDFLAGS += -Wl,-rpath,$(OPENMPI_LIB_DIR)/
ifndef MACHINE_HEXAGON
LDFLAGS += -L $(OPENMPI_LIB_DIR)/ -lmpi_cxx -lmpi -ldl -lstdc++ #-lpthread
else
LDFLAGS += -L $(OPENMPI_LIB_DIR)/ -lmpichcxx -lmpich -ldl -lstdc++ #-lpthread #-lssl -luuid -lpthread -lrt
LDFLAGS += -Wl,-rpath,$(BLAS_LAPACK_DIR)/lib
LDFLAGS += -L $(BLAS_LAPACK_DIR)/lib -lsci_gnu_mp
endif
LDFLAGS += -Wl,-rpath,$(NETCDF_DIR)/lib -L $(NETCDF_DIR)/lib -lnetcdf_c++4
LDFLAGS += -Wl,-rpath,$(BOOST_LIBDIR)
LDFLAGS += -L $(BOOST_LIBDIR) -lboost_program_options -lboost_filesystem -lboost_system -lboost_serialization -lboost_mpi -lboost_date_time
LDFLAGS += -Wl,-rpath,$(PETSC_DIR)/lib
LDFLAGS += -L $(PETSC_DIR)/lib -lpetsc
LDFLAGS += -Wl,-rpath,$(NEXTSIMDIR)/lib
LDFLAGS += -L $(NEXTSIMDIR)/lib -lbamg
#LDFLAGS += -L $(NEXTSIMDIR)/lib -linterp
LDFLAGS += -L $(NEXTSIMDIR)/lib -lmapx
#LDFLAGS += -L $(NEXTSIMDIR)/lib -loasis
ifdef USE_ENSEMBLE
LDFLAGS += -L $(NEXTSIMDIR)/lib -lpseudo2D
LDFLAGS += -lgfortran
endif
ifdef USE_AEROBULK
LDFLAGS += -L $(AEROBULK_DIR)/lib -laerobulk_cxx -laerobulk
LDFLAGS += -lgfortran
endif
ifneq (,$(strip $(filter DEBUG Debug debug PROFILE Profile profile,$(NEXTSIM_BUILD_TYPE))))
#ifeq ($(NEXTSIM_BUILD_TYPE),$(filter $(NEXTSIM_BUILD_TYPE),Debug debug))
LDFLAGS += -Wl,-rpath,/opt/local/lib
ifneq (,$(strip $(filter PROFILE Profile profile,$(NEXTSIM_BUILD_TYPE))))
LDFLAGS += -L /opt/local/lib -lprofiler
endif
endif
LDFLAGS += -L $(NEXTSIMDIR)/lib -lnextsim
OBJECTDIR=$(NEXTSIMDIR)/objs/
DEPENDDIR=$(NEXTSIMDIR)/.deps/
BINARYDIR=bin/
# C++ files
CXXSRCDIR=.
CXXHDRDIR=.
CXXSRC=$(wildcard $(CXXSRCDIR)/*.cpp)
# We must exclude the version.hpp file from the list of header files because otherwise we get a circular dependency
CXXHDR=$(filter-out $(CXXHDRDIR)/version.hpp, $(wildcard $(CXXHDRDIR)/*.hpp))
OBJS=$(CXXSRC:%.cpp=$(OBJECTDIR)%.o)
DEPS=$(CXXSRC:%.cpp=$(DEPENDDIR)%.d)
# Rules to always execute.
.PHONY: exec clean mrproper all cleanall mrproperall
# Default action.
exec: $(PROGNAME)
# Create a header file with the git version
version.hpp: version.sh $(CXXSRC) $(CXXHDR)
$(SHELL) -x $<
# Delete the object files.
clean:
@echo " "
$(RM) $(OBJS) $(DEPS)
@echo " "
mrproper: clean
$(RM) $(BINARYDIR)$(PROGNAME)
@echo " "
# Rule for making the actual target
lines="=========="
Lines=$(lines)$(lines)$(lines)$(lines)$(lines)$(lines)$(lines)$(lines)
$(PROGNAME): $(OBJS) #$(CCOBJS)
@mkdir -p $(BINARYDIR)
@echo " "
@echo $(Lines)$(Lines)
@echo "Creating executable: $(BINARYDIR)$(PROGNAME)"
@echo $(Lines)$(Lines)
@echo " "
$(CXX) $(CXXFLAGS) -o $(BINARYDIR)$@ $^ $(LDFLAGS)
@echo " "
@echo $(Lines)$(Lines)
@echo "Created executable: $(BINARYDIR)$(PROGNAME)"
@echo $(Lines)$(Lines)
@echo " "
# Rules for object files from cpp files
$(OBJECTDIR)%.o: %.cpp
@mkdir -p $(OBJECTDIR) # $(dir $@)
@echo " "
$(CXX) -o $@ -c $< $(CXXFLAGS)
# Make dependancy rules
$(DEPENDDIR)%.d: %.cpp
@mkdir -p $(DEPENDDIR)
$(CXX) -M -MG -MT $(OBJECTDIR)$*.o $(CXXFLAGS) $< > $@
# The compilation depends on this Makefile.
$(OBJS): Makefile
# Make everything
all:
cd ..; $(MAKE) all
# Clean everything
cleanall:
cd ..; $(MAKE) clean
# Properly clean everything
mrproperall:
cd ..; $(MAKE) mrproper
# Properly clean & recompile
fresh:
cd ..; $(MAKE) fresh
-include $(DEPS)
它之所以被构建,是因为您正在使用-include $(DEPS)
.
请参阅包括其他生成文件
如果在这些目录中找不到包含的生成文件,则 生成警告消息,但不是立即致命的 错误;继续处理包含的生成文件。 读取完makefile后,make将尝试重新制作任何 已过时或不存在的内容。了解如何重新制作生成文件。 只有在它试图找到一种方法来重新制作一个makefile并失败之后, 将使将丢失的生成文件诊断为致命错误。
然后它继续说:
如果你想简单地忽略一个不存在的制作文件,或者 无法重新制作,没有错误消息,请使用 -include 指令 而不是包含,如下所示:
-include filenames…
这就像在各个方面都包含,除了如果任何文件名(或任何 任何文件名的先决条件)不存在或不能 重制。
诚然,这可能以不同的方式解释。 我刚刚验证了它确实尝试在具有明确规则要重新制作的-include
行上重新制作文件:
all:
@echo building $@
foo.d :
@echo building $@
@touch $@
-include foo.d bar.d
这给了:
tmp> make all
building foo.d
building all
因此,这留下了一个有关如何解决您的问题的有趣案例。 为依赖项文件设置单独的规则确实会增加编译时间 - 您现在分析每个源文件两次 - 一次用于生成 .d,一次用于编译。 这不好。 我相信将依赖关系和 .o 规则结合起来符合您的最佳利益。 然后使依赖于 version.hpp 的$(OBJS)
子集显式依赖于它,你应该很好。
您应该将-include $(DEPS)
行设置为条件 - 当MAKECMDGOALS
仅包含"干净"目标时,将其从 makefile 中排除:
ifneq(,$(filter-out clean distclean clobber,$(MAKECMDGOALS)))
-include $(DEPS)
endif
顺便说一句,请注意假设cd
会成功 - 在它之后使用&&
- 或者,如果在不同的目录中调用 Make,只需使用其-C
选项。
- 试图在visual studio上用C++创建一个桌面应用程序
- 此代码是否违反一个定义规则
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- c++r值引用应用于函数指针
- 在C应用程序中运行C++(带有STL)函数
- 模板模板参数:以下示例中应用了什么规则
- 在 Objective-C++ 中应用于__weak指针时,通过关键字推导类型"auto"规则是什么?
- 使用继承和虚拟功能应用五个规则
- 在不应该应用生成文件规则时应用
- 如何在C 中应用ODR(一个定义规则)
- 如何正确地将规则 5(或零?)应用于包含带有字符串的自定义对象向量的类
- 这里应用了哪条过载解决规则
- 不应用提升精神解析规则
- 应用有关如何递增枚举的规则
- C++ 设计一个对象,使其采用变量值和规则来应用于它们
- 指针别名规则的应用(指向自身地址的指针)
- C++,元胞自动机在应用规则时遇到问题
- 填充矩形,并在opengl中应用非零绕线规则
- 为什么在推导模板参数时应用 §5/5?规则不能不同吗?
- 为什么Xcode 4.2为.cpp文件应用C文件构建规则脚本?