使所有C文件递归

使所有C文件递归,c,makefile,C,Makefile,我真的无法进入makefiles。在以前的项目中,我在生成文件中硬编码了所有编译任务: all: compile_a compile_b compile_c compile_a: ${CC} ${CFLAGS} ${A_SRC} -o ${A_OUT} 等等 但是,由于最新的项目比以前的每个项目都有更多的文件,我想写更好的make任务,当然也要写更少的字符,因为make对我的眼睛并不友好(这让他们很痛苦)!:-P 我想要的是: 一项任务可以管理所有项目(只需makeprojectn

我真的无法进入makefiles。在以前的项目中,我在生成文件中硬编码了所有编译任务:

all: compile_a compile_b compile_c

compile_a:
    ${CC} ${CFLAGS} ${A_SRC} -o ${A_OUT}
等等

但是,由于最新的项目比以前的每个项目都有更多的文件,我想写更好的make任务,当然也要写更少的字符,因为make对我的眼睛并不友好(这让他们很痛苦)!:-P

我想要的是:

  • 一项任务可以管理所有项目(只需
    makeprojectname
    makeall
    ,你知道吗?)
  • 每个要编译的C文件都有一个任务(我读了一些关于
    %.o:%.C
    语法的内容,但没有真正理解)
  • 一个链接任务(如何获取所有.o文件并链接它们而不进行硬编码?)
  • 一项清洁任务(哦,我能做到!)
项目结构为:

bin (binary goes here!)
src
  some
  directories 
  are
  here
我不知道我是否需要对象文件的目录,我把它们放在
/bin
中,我认为这已经足够好了,不是吗

也许我只是需要一个能用简单的语言解释的人

编辑: 正如有人指出的那样,没有真正的问题,所以这里是:

  • 如何将所有C文件递归编译到
    bin/(文件名).o
  • 如何在不知道文件名的情况下链接“bin/”中的所有
    .o
    文件

也许这会有所帮助。

不必讨论makefiles的细节,请使用*作为您的优势

i、 e

试试这个:

CC = gcc
CFLAGS = -c -Wall -g -Os
LD = $(CC)
LDFLAGS = -lfoo

TARGET = MyProject

OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))

all: $(TARGET)

$(TARGET): $(OBJECTS)
        $(LD) -o $@ $^ $(LDFLAGS)

# You don't even need to be explicit here,
# compiling C files is handled automagically by Make.
%.o: %.c
        $(CC) $(CFLAGS) $^ -o $@

clean:
        rm $(TARGET) $(OBJECTS)

我经常将
通配符
函数与
foreach
函数结合使用,以实现您想要实现的功能

如果源代码位于
src/
中,并且希望将二进制文件放入
bin/
中,则my
Makefile
的基本结构如下所示:

SOURCES=$(shell find src -type f -iname '*.c')

OBJECTS=$(foreach x, $(basename $(SOURCES)), $(x).o)

TARGET=bin/MyProject

$(TARGET): $(OBJECTS)
    $(CC) $^ -o $@

clean:
    rm -f $(TARGET) $(OBJECTS)

我通常利用make内置的隐式规则和预定义变量()。

您实际上并没有问任何问题。你在哪一部分有问题?你真正想做什么?用makefile建立一个像样的构建系统要比看起来的工作量大得多。尝试使用CMake或SCons之类的构建工具。编辑:最困难的部分是将
.c
.h
文件之间的依赖关系放入Makefile,有一些工具可以帮助实现这一点,但这很麻烦。嗯,我想我现在理解了
%.o
语法,但是如何调用它,比如说
/src/foo/bar/somefile.c
?-编辑:算了吧,我想我有这个角色!我认为应该是
$(TARGET):$(OBJECTS)
,链接发生在该配方中,然后是
all:$(TARGET)
,没有显式配方。否则,就没有构建MyProject的方法,而“所有”都依赖于此。这并不能完全回答OP的问题,后者要求递归生成文件。这将只编译顶级文件夹中的所有内容。@JamieBullock这很容易修复:可以使用
$(shell find.-name“*.c”)
,而不是
$(通配符…
),这将把所有
.o
文件放在源代码树中,但我认为最好将它们放在
bin/
中,不是吗?我不认为所有对象文件都位于单独的文件夹中有什么好处。如果只是为了在
ls
之后看不到人口过多的文件夹,还有其他方法。此外,我不记得我编译的任何程序都有单独的目标文件文件夹。不起作用:1)第二行将只使用碰巧在那里的
*.o
文件2)它假定所有内容都在同一目录中。此外,输出文件应该是规则的目标。
SOURCES=$(shell find src -type f -iname '*.c')

OBJECTS=$(foreach x, $(basename $(SOURCES)), $(x).o)

TARGET=bin/MyProject

$(TARGET): $(OBJECTS)
    $(CC) $^ -o $@

clean:
    rm -f $(TARGET) $(OBJECTS)