路径包含和src目录makefile

问题描述 投票:5回答:3

遵循本教程:

http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/

它有3个文件,其中2个是.c文件和1个.h文件。本教程是关于设置makefile的,前几个步骤正在运行。最后一步涉及为.h.c文件设置目录路径。我已经将.c文件放在一个src文件中,并将.h文件放在一个包含文件中。

看起来像/home/bob/testcode/src .c个文件。

/home/bob/testcode/include .h文件。

代码:

IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR)

ODIR=obj
LDIR =../lib

_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

_OBJ = hellomake.o hellofunc.o 
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))


$(ODIR)/%.o: %.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
    gcc -o $@ $^ $(CFLAGS)

.PHONY: clean

clean:
    rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ 

我想了解它的工作原理,然后在正在使用的库中使用它。有人可以指出我如何设置此代码吗?我已经尝试了很多选项,例如"/home/bob/testcode/include/" w /和[/ 0] "/,但仍然无法正常工作。

目标是要使用一个包含60多个头文件和30个源文件的库,从这些文件中我将必须运行1个main,因此我确实需要使此基本makefile起作用,以便可以对其进行扩展。

一般的问题是,这两行都保持打开状态:

IDIR =../include
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))

为此,我尝试了多种不同的路径替代方法,但产生的错误提示:

gcc -o hellomake  -I../include
gcc: fatal error: no input files
compilation terminated.
make: *** [hellomake] Error 4

请帮助,谢谢。

c++ c makefile
3个回答
37
投票
根据您的规则:

$(ODIR)/%.o: %.c $(DEPS)

您告诉make在源文件位于src目录中时在当前目录中查找,因此从不使用此模式,并且您没有合适的模式。

确保您这样组织项目目录:


+ include/ |-- all .h files here + lib/ |-- all thirdparty library files (.a files) here + obj/ |-- all .o files will be placed here + src/ |-- all .c files here + Makefile

然后,使用良好实践逐步进行此过程。

首先,如果不需要,请不要定义任何内容。 Make具有许多预定义的变量和函数,您在尝试手动进行操作之前应使用它们。实际上,他有很多东西,您甚至可以在目录中根本没有Makefile的情况下编译一个简单的项目!

    [命名您的最终目标,即您的可执行文件:
  1. EXE := hellomake

列出您的源代码并构建输出目录:
  • SRC_DIR := src OBJ_DIR := obj
  • 列出您的源文件:
  • SRC := $(wildcard $(SRC_DIR)/*.c)
  • 从源文件中列出目标文件:
  • OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) # patsubst is far less readable imo # You can also do it like that OBJ := $(addprefix $(OBJ_DIR)/, $(notdir $(SRC)))
  • 还有一些预处理器标志要传递吗?继续。
  • CPPFLAGS := -Iinclude # -I is a preprocessor flag, not a compiler flag
  • 要添加一些编译器标志吗?给你。
  • CFLAGS := -Wall # some warnings about bad code
  • 有一些链接器标志吗?
  • LDFLAGS := -Llib # -L is a linker flag
  • 还有一些第三方库可以链接吗?
  • LDLIBS := -lm # Left empty if no libs are needed
  • 好,现在我们的变量已正确填写,现在该滚动一些食谱了。

    已经广泛传播,默认目标应称为all,并且它应该是Makefile中的第一个目标。当在命令行上只写make时,它的前提条件应该是您要构建的目标:

    all: $(EXE)

    现在列出构建可执行文件的先决条件,并填写其配方以告诉他们如何使用这些文件:

    $(EXE): $(OBJ)
        $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
    

    一些注意事项:

    $(CC)是一个内置变量,已经包含在C中进行编译和链接时所需的内容,

      为了避免链接器错误,您
    • 应该将$(LDFLAGS)
    • 之前放在目标文件中,然后将$(LDLIBS) 之后放入。
    • [$(CPPFLAGS)$(CFLAGS)在这里无用,编译阶段已经结束,在这里是链接阶段。
  • 下一步,由于您的源文件和目标文件不共享相同的前缀,由于其内置规则不能满足您的特定情况,因此您需要确切说明要做什么:$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

    好吧,现在可执行文件应该可以很好地构建,如果需要,我们可以清理构建目录:

    clean:
        $(RM) $(OBJ)
    

    最后一件事。您应该使用.PHONY分隔规则指出规则何时不产生任何目标输出:

    .PHONY: all clean
    

    最终结果:
    EXE := hellomake SRC_DIR := src OBJ_DIR := obj SRC := $(wildcard $(SRC_DIR)/*.c) OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) CPPFLAGS := -Iinclude CFLAGS := -Wall LDFLAGS := -Llib LDLIBS := -lm .PHONY: all clean all: $(EXE) $(EXE): $(OBJ) $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ clean: $(RM) $(OBJ)

  • 0
    投票
    $(ODIR)/%.o: %.c $(DEPS) $(CC) $(CFLAGS) -c -o $@ $< hellomake: $(OBJ) gcc $(CFLAGS) -o $@ $^

    您需要从源目录运行make


    0
    投票
    第一个目标通常被命名为'all'

    对于发布的文件,将创建目标文件,并且在命令行中未指定目标时将不再继续生成可执行文件

    建议以下内容:

    SHELL := /bin/sh # following so could define executable name on command line # using the '-D' parameter #ifndef $(NAME) NAME := hellomake #endif # use ':=' so macros only evaluated once MAKE := /usr/bin/make CC := /usr/bin/gcc CFLAGS := -g -Wall -Wextra -pedantic LFLAGS := ODIR := obj IDIR := ../include LIBS := LIBPATH := ../lib DEPS := $(wildcard $(IDIR)/*.h) SRCS := $(wildcard *.c) OBJS := $(SRCS:.c=.o) .PHONY: all all: $(NAME) $(OBJS) $(ODIR)/%.o: %.c $(DEPS) $(CC) $(CFLAGS) -c -o $@ $< -I$(DEPS) $(NAME): $(OBJS) $(CC) $(LFLAGS) -o $@ $^ -L$(LIBPATH) -l$(LIBS) .PHONY: clean clean: rm -f $(ODIR)/*.o rm -f $(NAME) however, in your proposed project, not every source file needs every header file so should use either gcc or sed to generate the dependency files then use makefile rules similar to the following, which may need a little 'tweaking' for your project because the include files are not in the same directory as the source files: DEP := $(SRCS:.c=.d) # #create dependency files # %.d: %.c # # ========= START $< TO $@ ========= $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ # ========= END $< TO $@ ========= # # compile the .c files into .o files using the compiler flags # %.o: %.c %.d # # ========= START $< TO $@ ========= $(CC) $(CCFLAGS) -c $< -o $@ -I$(IDIR) # ========= END $< TO $@ ========= # # include the contents of all the .d files # note: the .d files contain: # <filename>.o:<filename>.c plus all the dependencies for that .c file # I.E. the #include'd header files # wrap with ifneg... so will not rebuild *.d files when goal is 'clean' # ifneq "$(MAKECMDGOALS)" "clean" -include $(DEP) endif

    © www.soinside.com 2019 - 2024. All rights reserved.