Makefile编译所有src并生成静态库

问题描述 投票:0回答:1

我有一个很大的C项目,我想使用我的include /路径中的include和我的RTOS的其他includes从src /文件中的所有源生成一个静态库。

我在行命令中有一套有效的步骤:

gcc src/drivers/* src/packets/* (...more files) -c -I ./include -I ../SatelliteSim/Source/include/ -I ../SatelliteSim/Project/ -I ../SatelliteSim/Source/portable/GCC/POSIX/ -m32 -DDEBUG=1 -g -UUSE_STDIO -D__GCC_POSIX__=1 -pthread

然后,ar -rsc telecommands.a *.o

我目前在Makefile中的尝试如下所示:

CXXFLAGS := -I./include -I../SatelliteSim/Source/include/ -I../SatelliteSim/Project/ -I../SatelliteSim/Source/portable/GCC/POSIX/ -m32 -DDEBUG=1 -g -UUSE_STDIO -D__GCC_POSIX__=1 -pthread


MODULES := commands/commands \
    driver_toolkit/driver_toolkit \
    (... more 'modules')

SOURCES := src/$(MODULES).c
OBJS := bin/$(MODULES).o

all: telecommands.a

telecommands.a: $(OBJS)
    ar -rsc $@ $^

$(OBJS): $(SOURCES)
    $(CXX) $(CXXFLAGS) -c $^ -o $@

但是在编译步骤中我的包含文件出现问题。

希望有人可以指出我做错了:)

提前感谢!

c makefile compilation include archive
1个回答
1
投票

您至少有两个主要问题。

首先是您的SOURCESOBJS变量分配错误。当扩展变量时,Make会直接进行文本替换。因此:

MODULES := foo bar biz

SOURCES := src/$(MODULES).c
OBJS := bin/$(MODULES).o

展开为简单:

SOURCES := src/foo bar biz.c
OBJS := bin/foo bar biz.o

这显然是不正确的。如果您愿意使用针对变量中每个word单独运行的GNU make特定功能,则可以得到所需的内容:

SOURCES := $(patsubst %,src/%.c,$(MODULES))
OBJS := $(patubst %,bin/%.o,$(MODULES))

下一个问题是:

$(OBJS): $(SOURCES)
        $(CXX) $(CXXFLAGS) -c $^ -o $@

扩展为类似这样的内容:

bin/foo.o bin/bar.o bin/biz.o : src/foo.c src/bar.c src/biz.c
        $(CXX) $(CXXFLAGS) -c $^ -o $@

同样,make不会以某种方式使用某些字符串匹配试探法来推断您希望左侧的每个目标文件与右侧的某些源文件进行匹配。那不是make的工作方式。如果左侧有多个目标,make将为每个目标创建一个单独的规则,其中每个目标都包含右侧的所有先决条件。因此以上内容与您编写的内容相同:

bin/foo.o : src/foo.c src/bar.c src/biz.c
        $(CXX) $(CXXFLAGS) -c $^ -o $@
bin/bar.o : src/foo.c src/bar.c src/biz.c
        $(CXX) $(CXXFLAGS) -c $^ -o $@
bin/biz.o : src/foo.c src/bar.c src/biz.c
        $(CXX) $(CXXFLAGS) -c $^ -o $@

这意味着它将编译所有源文件以创建每个目标文件。

在makefile中,您必须编写一个规则,该规则根据该目标的先决条件一次构建one目标。因此,例如,您可以使用模式规则:

bin/%.o : src/%.c
        $(CXX) $(CXXFLAGS) -c $< -o $@

注意,我只使用$<而不是$^,因为您只想编译源文件。请注意,这会为每个源文件调用一次编译器,以生成该输出文件。 Make不适用于单次调用生成工具会产生许多不同输出的环境(尽管如果您愿意将自己限制为GNU make 4.3或更高版本,则可以根据需要进行操作。)>

如果头文件发生更改,这将不会重建任何目标文件,因为您没有列出任何头文件作为先决条件。

您提到在编译步骤中遇到我的包含文件的问题

,但这对我们没有帮助。如果修复了makefile之后仍然存在编译问题,则可以打开一个新问题,但请准确(剪切并粘贴)您看到的错误类型以及用于生成产生这些错误的打印的编译行。
© www.soinside.com 2019 - 2024. All rights reserved.