如何将目标文件放在单独的子目录中

我在尝试使用make将目标文件放在单独的子目录中时遇到麻烦,这可能是一种非常基本的技术。我试图使用此页面中的信息:http : //www.gnu.org/software/hello/manual/make/Prerequisite-Types.html#Prerequisite-Types


我从make得到以下输出:


make: *** No rule to make target `ku.h', needed by `obj/kumain.o'.  Stop.

但是ku.h不是目标而是依赖关系(尽管它显然已#include在c源文件中)。当我不尝试使用子目录存储目标文件时(即错过OBJDIR部分),它可以正常工作。为什么使ku.h是目标?


我的makefile是这样的:(样式是在阅读了各种信息源之后的)


.SUFFIXES:

.SUFFIXES: .c .o


CC=gcc 

CPPFLAGS=-Wall

LDLIBS=-lhpdf

VPATH=%.c src

VPATH=%.h src

VPATH=%.o obj

OBJDIR=obj


objects= $(addprefix $(OBJDIR)/, kumain.o kudlx.o kusolvesk.o kugetpuz.o kuutils.o \

  kurand.o kuASCboard.o kuPDFs.o kupuzstrings.o kugensud.o \

  kushapes.o )


ku : $(objects)

  $(CC) $(CPPFLAGS) -o ku $(objects) $(LDLIBS)


$(objects) : ku.h kudefines.h kuglobals.h kufns.h | $(OBJDIR)


$(OBJDIR):

  mkdir $(OBJDIR)


.PHONY: clean

clean :

  rm $(objects)

编辑:我应用更改以使用vpath指令。我的版本是VPATH = xxx和vpath%.c xxx的不良混合。但是,我现在遇到了另一个问题(这是我添加错误的vpath之前的原始问题)。现在是输出:


    gcc  -o ku -lhpdf obj/kumain.o obj/kudlx.o obj/kusolvesk.o ..etc

    gcc: obj/kumain.o: No such file or directory

    gcc: obj/kudlx.o: No such file or directory

    gcc: obj/kusolvesk.o: No such file or directory

    gcc: obj/kugetpuz.o: No such file or directory

    gcc: obj/kuutils.o: No such file or directory

    gcc: obj/kurand.o: No such file or directory

    gcc: obj/kuASCboard.o: No such file or directory

    gcc: obj/kuPDFs.o: No such file or directory

    gcc: obj/kupuzstrings.o: No such file or directory

    gcc: obj/kugensud.o: No such file or directory

    gcc: obj/kushapes.o: No such file or directory

    make: *** [ku] Error 1

尽管手册中说“隐式规则告诉make如何使用惯用技术,以便您不必在使用它们时详细指定它们,但make似乎并未将隐式规则应用于目标文件。是C编译的隐式规则,文件名决定运行哪些隐式规则,例如,C编译通常需要一个.c文件并创建一个.o文件,因此当make看到此组合时,make将隐式规则应用于C编译。文件名结尾。” 以及“在考虑隐式规则的过程中也会发生在VPATH或vpath中指定目录的搜索(请参阅使用隐式规则)。”


再次在此处“例如,当文件foo.o没有显式规则时,make考虑隐式规则,例如内置规则,以编译foo.c(如果该文件存在。如果当前目录中缺少该文件,在适当的目录中进行搜索。如果在任何目录中都存在foo.c(或在makefile中提到),则将应用C编译的隐式规则。”


在使隐式规则适用于我的makefile方面的任何帮助将不胜感激。

翻翻过去那场雪
浏览 1003回答 3
3回答

当年话下

由于您使用的是GNUmake,因此请使用模式规则来编译目标文件:$(OBJDIR)/%.o: %.c&nbsp; &nbsp; $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<

慕哥6287543

这是我用于大多数项目的makefile,它允许将源文件,头文件和内联文件放在子文件夹以及子文件夹的子文件夹等中,并会自动为每个对象生成一个依赖文件。这意味着对头文件和内联文件的修改将触发对相关文件的重新编译。通过shell find命令检测到源文件,因此无需明确指定,只需对您的内容进行编码即可。编译项目时,它还将所有文件从“资源”文件夹复制到bin文件夹中,而我在大多数情况下都很方便。为了提供应有的信誉,自动依赖功能主要基于Scott McPeak的页面(可在此处找到),并进行了一些其他修改/调整以满足我的需求。示例文件#Compiler and LinkerCC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; := g++-mp-4.7#The Target Binary ProgramTARGET&nbsp; &nbsp; &nbsp; := program#The Directories, Source, Includes, Objects, Binary and ResourcesSRCDIR&nbsp; &nbsp; &nbsp; := srcINCDIR&nbsp; &nbsp; &nbsp; := incBUILDDIR&nbsp; &nbsp; := objTARGETDIR&nbsp; &nbsp;:= binRESDIR&nbsp; &nbsp; &nbsp; := resSRCEXT&nbsp; &nbsp; &nbsp; := cppDEPEXT&nbsp; &nbsp; &nbsp; := dOBJEXT&nbsp; &nbsp; &nbsp; := o#Flags, Libraries and IncludesCFLAGS&nbsp; &nbsp; &nbsp; := -fopenmp -Wall -O3 -gLIB&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:= -fopenmp -lm -larmadilloINC&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;:= -I$(INCDIR) -I/usr/local/includeINCDEP&nbsp; &nbsp; &nbsp; := -I$(INCDIR)#---------------------------------------------------------------------------------#DO NOT EDIT BELOW THIS LINE#---------------------------------------------------------------------------------SOURCES&nbsp; &nbsp; &nbsp;:= $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))OBJECTS&nbsp; &nbsp; &nbsp;:= $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))#Defauilt Makeall: resources $(TARGET)#Remakeremake: cleaner all#Copy Resources from Resources Directory to Target Directoryresources: directories&nbsp; &nbsp; @cp $(RESDIR)/* $(TARGETDIR)/#Make the Directoriesdirectories:&nbsp; &nbsp; @mkdir -p $(TARGETDIR)&nbsp; &nbsp; @mkdir -p $(BUILDDIR)#Clean only Objecstclean:&nbsp; &nbsp; @$(RM) -rf $(BUILDDIR)#Full Clean, Objects and Binariescleaner: clean&nbsp; &nbsp; @$(RM) -rf $(TARGETDIR)#Pull in dependency info for *existing* .o files-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))#Link$(TARGET): $(OBJECTS)&nbsp; &nbsp; $(CC) -o $(TARGETDIR)/$(TARGET) $^ $(LIB)#Compile$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)&nbsp; &nbsp; @mkdir -p $(dir $@)&nbsp; &nbsp; $(CC) $(CFLAGS) $(INC) -c -o $@ $<&nbsp; &nbsp; @$(CC) $(CFLAGS) $(INCDEP) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT)&nbsp; &nbsp; @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp&nbsp; &nbsp; @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)&nbsp; &nbsp; @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)&nbsp; &nbsp; @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp#Non-File Targets.PHONY: all remake clean cleaner resources
打开App,查看更多内容
随时随地看视频慕课网APP