【问题标题】:Performing an action over each source file with make使用 make 对每个源文件执行操作
【发布时间】:2016-09-22 17:10:12
【问题描述】:

我已经创建了一个这样的 Makefile

CC = sdcc
SRCS = $(PNAME).c\
    ../../src/gpio.c
    ../../src/timers.c
    ../../src/i2c.c
$HDRS = -I../../headers

all:
    mkdir -p ./output
    $(CC) $(SRCS) -lstm8 -mstm8 $(HDRS)

问题是,sdcc 一次只能编译一个源。所以我需要对我在SRCS 变量中定义的每个源执行类似 foreach 的操作。如何在 gnu-make 中做到这一点?

【问题讨论】:

  • sdcc 是否有一个选项可以将其编译为目标文件,但不尝试将其链接以制作程序?如果它不能在同一个编译命令中处理多个源文件,我想它必须这样做。对于gcc,该选项拼写为-c
  • 如果sdcc 在同一命令中不接受多个源文件,那么您应该如何使用它从多个源构建程序?它的工具链是否有单独的链接器?它是否依赖外部链接器,例如 GNU ld
  • -mstm8 是编译选项还是链接选项?
  • @JohnBollinger yes -c 仅用于编译,但我还不确定链接过程!
  • @JohnBollinger yes -mstm8 -lstm8 是要编译的平台

标签: makefile gnu-make sdcc


【解决方案1】:

根据the docs,你必须单独编译包含main()以外的文件,生成.rel文件,然后将这些文件包含在主文件的编译命令中。关于如何做到这一点有几种变化。以下内容避免了特定于 GNU make 的特性:

# We're assuming POSIX conformance
.POSIX:

CC = sdcc

# In case you ever want a different name for the main source file    
MAINSRC = $(PMAIN).c

# These are the sources that must be compiled to .rel files:
EXTRASRCS = \
    ../../src/gpio.c \
    ../../src/timers.c \
    ../../src/i2c.c

# The list of .rel files can be derived from the list of their source files
RELS = $(EXTRASRCS:.c=.rel)

INCLUDES = -I../../headers
CFLAGS   = -mstm8 
LIBS     = -lstm8 

# This just provides the conventional target name "all"; it is optional
# Note: I assume you set PNAME via some means not exhibited in your original file
all: $(PNAME)

# How to build the overall program
$(PNAME): $(MAINSRC) $(RELS)
    $(CC) $(INCLUDES) $(CFLAGS) $(MAINSRC) $(RELS) $(LIBS)

# How to build any .rel file from its corresponding .c file
# GNU would have you use a pattern rule for this, but that's GNU-specific
.c.rel:
    $(CC) -c $(INCLUDES) $(CFLAGS) $<

# Suffixes appearing in suffix rules we care about.
# Necessary because .rel is not one of the standard suffixes.
.SUFFIXES: .c .rel

如果你仔细看的话,顺便说一下,你会发现该文件没有明确地对源文件执行任何循环,或者任何类似的事情。它只是描述了如何构建每个目标,包括中间目标。 make 自己计算出如何组合这些规则以从源代码到最终程序(或从您教它构建的目标中指定的任何其他目标)。

【讨论】:

  • 请注意,我猜测-lstm8 选项的含义以及它应该去哪里。我没有找到记录的特定选项或其一般形式的选项。它看起来像是一个向链接添加库的选项,但sdcc 的做法似乎有所不同。
  • 还要注意构建规则的缩进应该是一个,或者至少从一个开始。这没有反映在示例中,因为很难将制表符插入 HTML 表单。
  • 非常感谢您抽出宝贵时间! $(PNAME) 是包含 main 函数的源文件的名称。它会改变你的回答方式吗?
  • @SaeidYazdani,我对$(PNAME) 的看法是,您必须在某处分配其值,而我提出的 Makefile 遵循您的示例,没有这样做。您可以通过环境变量指定该值,或者如果您使用的是 GNU make,则可以通过命令行参数指定该值。或者您可以只向 makefile 添加一个分配。
【解决方案2】:

使用patsubst。通常是这样的:

SOURCES := $(wildcard *.c)
OBJECTS := $(patsubst %.c,%.o,${SOURCES})
prog: ${OBJECTS}
        cc $^ -o $@
%.o: %.c
        cc $< -c -o $@

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多