【问题标题】:Out of tree builds with makefiles and static pattern rules使用 makefile 和静态模式规则构建树外
【发布时间】:2011-02-04 03:15:24
【问题描述】:

我正在开发一些在 ARM 上运行的裸机嵌入式代码,因此必须处理整个 ARM 与 THUMB 模式的区别。当前的构建系统使用静态模式规则来确定是以 ARM 模式还是 THUMB 模式编译文件。

$(ACOBJS) : %.o : %.c
    @echo
    $(CC) -c $(CFLAGS) $(AOPT) -I . $(IINCDIR) $< -o $@
$(TCOBJS) : %.o : %.c
    @echo
    $(CC) -c $(CFLAGS) $(TOPT) -I . $(IINCDIR) $< -o $@

其中 ACOBJS 是应处于 ARM 模式的输出对象列表,对于 TCOBJS 和 Thumb 模式也是如此。这些列表是以通常的方式从源列表创建的

ACOBJS   = $(ACSRC:.c=.o)
TCOBJS   = $(TCSRC:.c=.o)

目前,这会导致构建中的目标文件散布在源代码树上,我并不特别希望这样做。我一直在尝试将其设置为树外构建,但无法使其正常工作。我不一定需要完全摆脱树构建的工作,但我希望至少能够使用一个输出目录,所有中间文件最终都会在该目录下运行。在这些限制条件下实现这一目标的最佳策略是什么?

我正在考虑的一个选项是使用 automake 或整个 autotools 工具链来构建 makefile。这似乎支持创建我想要的 makefile 类型,但似乎有点矫枉过正。似乎在为便携式构建而设计的自动工具和裸机嵌入式系统之间存在固有的阻抗不匹配,其中主机元组之类的东西由目标微决定。

【问题讨论】:

  • 您希望所有的目标文件、可执行文件和库都进入同一个输出目录吗?
  • 将所有内容都放在同一个目录中是可以的,尽管不是最好的情况。我目前通过将静态模式规则替换为目标特定的适当标志添加到 CFLAGS 来完成这项工作。 github.com/MegabytePhreak/power_supply/blob/master/rules.mk 显示我目前的工作方式。

标签: build-process makefile gnu-make


【解决方案1】:

这有点老了,但我只是想做同样的事情,这是谷歌第一次点击。我认为值得分享另一种方法,因为如果您不使用 autotools 并且希望能够使用单个命令在任何目录中构建,然后就删除该目录,那么这两种方法都不方便。

这是一个 Makefile 示例,它引用相对于包含 Makefile 的目录的文件。

MAKEFILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
MFD := $(MAKEFILE_DIR)

CXX=g++
CXXFLAGS=-std=c++14 -Wall -Wextra -pedantic -c

test: test.o adjacency_pointers_graph.o
    $(CXX) $^ -o $@

%.o: $(MFD)/%.cpp $(MFD)/adjacency_pointers_graph.h
    $(CXX) $(CXXFLAGS) $< -o $@

然后进行某种源代码构建:

mkdir build
cd build
make -f ../Makefile

【讨论】:

  • lastword 返回列表中的最后一个元素,因此这不适用于放置在某个 obj 子目录中的生成的 .d(依赖项)文件,或者除此之外的目录中包含的任何其他文件一个与 Makefile。要修复它,请在第一行使用 firstword 而不是 lastword
【解决方案2】:

考虑/假设您不关心可移植性并且正在使用 GNU make,您可以使用VPATH feature

  • 创建要在其中进行构建的目录。
  • 在该目录中创建一个包含(大约)以下内容的“Makefile”:

    path_to_source = ..
    VPATH = $(path_to_source)
    include $(path_to_source)/Makefile
  • 将 path_to_source 变量更改为指向源代码树的根。

此外,您可能需要调整原始 Makefile 以确保它支持源外构建。例如,您不能从构建规则中引用先决条件,而必须使用 $^ 和 $GNU make - Writing Recipes with Directory Search)您可能还需要修改 vpath-makefile。例如:添加CFLAGS+=-I$(path_to_source) 可能会有用。

另外请注意,如果文件同时在您的源目录和构建目录中,make 将使用您的构建目录中的文件。

【讨论】:

    【解决方案3】:

    开启automake

    如果您使用automake,您几乎可以使用整个自动工具。没有autoconfautomake 无法工作。

    automake 生成的Makefiles 支持源外构建和交叉编译,因此您应该能够创建子目录arm/thumb/ 并在arm/ 中运行../configure --host=arm-host-prefix 和在thumb/ 中运行../configure --host=thumb-host-prefix。 (我不知道您将用于每个编译器的实际主机元组。)

    使用 GNU make

    由于您使用的是 GNUMake,因此您可以执行以下操作:

    ACOBJS := $(addprefix arm/,$(ACSRC:.c=.o))
    TCOBJS := $(addprefix thumb/,$(TCSRC:.c=.o))
    

    使用this answer 之类的东西来确保arm/thumb/ 目录(以及任何子目录)存在。

    【讨论】:

    • 对于 ARM 与 THUMB 输出,使用相同的编译器,在这种情况下,主机元组是 arm-none-eabi。为了控制生成哪种类型的代码,使用标志 -mthumb。
    • 那么如果你使用automake,你会做类似../configure --host=arm-none-eabi CFLAGS='-mthumb'的事情。添加其他 CFLAGS 以进行优化 &c。像往常一样。
    • @Jack:你不是更愿意先使用../configure --host=arm-none-eabi,然后使用libfoo_la_CFLAGS += -mthumb 来获取thumb 代码的便利库,然后使用libbar_la_CFLAGS += ... 来获取本机ARM 代码的便利库吗?毕竟,全局设置CFLAGS=-mthumb 将强制所有代码编译为拇指代码。
    • @ndim:取决于构建的细节。我不太了解arm交叉编译的细节,但你说得很好。我的想法是你会有两个独立的树外构建:一个用于 arm 代码,一个用于 thumb 代码。
    • 对于嵌入式系统上的裸机代码,我实际上更喜欢 libtool-less 链接 (libfoo_a_CFLAGS),因为直接使用 ld 可以更直接地影响链接器脚本和内存布局。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多