我已经坚持了一段时间了,所以真的希望有人可以提供帮助!我有一系列C / C ++源文件夹,它们是几个项目的通用代码,还有一些文件夹(在其他文件夹的旁边)包含项目本身。
当我构建一个项目时,我希望能够从外部文件夹中包含sources.mk,并让这些包含的源的对象进入项目目录的子文件夹,以免混乱公共文件夹使用项目特定的对象(每个项目可以有不同的标志,优化等)。
例如,这是一个文件夹结构:
source/common.mk
source/common/stuff/aaa.c
source/common/stuff/sources.mk
source/projects/thing/main.c
source/projects/thing/Makefile
项目/事物中的Makefile将包含../../common/stuff/sources.mk以获取该文件夹中的源列表(将附加到Makefile中已有的源列表),并且包括../../common.mk以获取从.c。
制作.o的规则sources.mk中的源代码前面有Makefile和sources.mk之间的相对路径,如下所示:
THIS_TOP := $(dir $(lastword $(MAKEFILE_LIST)))
SOURCES_C += $(THIS_TOP)/aaa.c
我希望所有对象都进入(dir我正在构建)/ objdir /,最好使用基于源路径的子文件夹,例如:
cd projects/thing; make
应该创建:
projects/thing/objdir/main.o
projects/thing/objdir/common/stuff/aaa.o
因此,我制作了一个目标文件列表,并将../从相对路径中删除,如下所示:
__OBJECTS=$(SOURCES_C:.c=.o) $(SOURCES_CPP:.cpp=.o)
_OBJECTS = $(subst ../,,$(__OBJECTS))
OBJECTS = $(patsubst %,$(OBJDIR)/%,$(_OBJECTS))
这个批次列出了我希望我的对象制作的确切方式,没有问题。我可以根据列表的内容制作objdir及其子文件夹,我可以提供此列表作为最终可执行文件的依赖项。如果对象实际上在那里我会没事的!
我遇到的问题是我似乎无法提出一个规则(进入common.mk)从远程.c创建本地.o!我尝试过第二次扩展尝试制定一个规则,在.c文件列表中搜索与所需的.o相对应的规则,但由于缺少多个通配符而无法使其工作滤波器...
.SECOND_EXPANSION:
$(OBJDIR)/%.o: $$(filter %$$(addsuffix .c,$$(subst .o,,$$(notdir $$@))),$$(SOURCES_C))
$(CC) -o $@ $< $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEPGENFLAGS)
我真的在这个上撕开我的头发......有没有人管理类似的东西?如果所有其他方法都失败了,我只会将它们构建为静态库(已经有像我想要的那样在项目文件夹的子目录中构建库)但是由于这会创建额外的makefile来维护我真的想避免它。
任何帮助都非常感谢!
奥利
答案 0 :(得分:0)
V'been在你的问题上摸不着头脑,最后决定用一个.o:.c
模式规则似乎不可能做你想做的事。您必须依赖每个库目录的一个模式规则。
我的建议是在每个sources.mk
文件中定义一个模式规则,它将使用由 main Makefile
提供的两个变量:
TOPDIR = ../..
OBJDIR = objdir
将模式规则定义到sources.mk
文件中,如下所示:
$(OBJDIR)/$(THIS_TOP)/*.o: $(TOPDIR)/$(THIS_TOP)/*.c
$(CC) -o $@ $< $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEPGENFLAGS)
答案 1 :(得分:0)
您是否尝试过vpath
?
我会尝试写一些像
这样的东西vpath %.c <path/to/source/common/relative/to/your/objdir/common>
我不确定这是否可行,因为%-pattern可能是一个带有路径的文件,它来自您使用的复杂的.o:.c规则。
另一种可能的方法是提供两个不同的隐式规则,使$(OBJDIR)/common/%.o
和$(OBJDIR)/%.o
具有相同的配方:
COMPILE_C = $(CC) -o $@ $< $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEPGENFLAGS)
$(OBJDIR)/common/%.o : <relative/path/to/source/common>/%.c
$(COMPILE_C)
$(OBJDIR)/%.o : ../%.c
$(COMPILE_C)