Makefile 未定义引用

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

在很长一段时间没有使用 C 进行编码后,我试图创建一个简单的 makefile,但我陷入了困境。

编译后我只能访问第一个函数(这里是ft_isalpha),但我不知道为什么。

这是生成文件:

  1 SRC =           ft_isalpha.c \                                                                                                                        
  2                 ft_strlen.c
  3 
  4 SRC_DIR =       src/
  5 
  6 SRC_PREFIXED =  $(addprefix $(SRC_DIR), $(SRC))
  7 
  8 NAME =          libft.a
  9 
 10 OBJS_DIR =      objs/
 11 
 12 OBJS =          $(SRC:.c=.o)
 13 
 14 OBJS_PREFIXED = $(addprefix $(OBJS_DIR), $(OBJS))
 15 
 16 CC =            gcc
 17 
 18 FLAGS =         -Wall -Wextra -Werror
 19 
 20 
 21 $(OBJS_DIR)%.o : $(SRC_PREFIXED)
 22     @mkdir -p $(OBJS_DIR)
 23     gcc $(FLAGS) -c $< -o $@
 24 
 25 $(NAME): $(OBJS_PREFIXED)
 26     ar r $(NAME) $(OBJS_PREFIXED)
 27     @echo $(SRC_PREFIXED)
 28 
 29 all: $(NAME)
 30 
 31 
 32 clean:
 33     @rm -rf $(OBJS_DIR)
 34     @echo "objects directory deleted"
 35 
 36 fclean: clean
 37     @rm -rf $(NAME)
 38     @echo ".a file deleted"

我已经检查了使用这些变量生成的变量和命令行的内容,但一切看起来都很好。当我切换 ft_isalpha 和 ft_strlen 时,ft_strlen 是可访问的,而不是 isalpha ad 等等。

c bash shell gcc makefile
1个回答
0
投票

你的错误是...

$(OBJS_DIR)%.o : $(SRC_PREFIXED)    # ... <- here (A)
    @mkdir -p $(OBJS_DIR)
    gcc $(FLAGS) -c $< -o $@        # ... <- and here (B)
    

模式规则 (A) 表示 each 目标文件

objs/(ft_isalpha.o|ft_strlen.o)
取决于所有源文件
src/ft_isalpha.c
src/ft_strlen.c
。的 当然这是假的。

那么命令(B)意味着每个目标目标文件

$@
将由 编译源文件
$<
。根据 GNU Make 手册:10.5.3 自动变量
$<
的意思是:

$<

第一个先决条件的名称。 ...[切]...

所以每个目标目标文件

objs/(ft_isalpha.o|ft_strlen.o)
都是通过编译生成的 相同源文件
src/ft_isalpha.c

因此您创建了一个库

libft.a
,其中包含两个目标文件
ft_isalpha.o
ft_strlen.o
两者都定义了相同的函数
ft_isalpha
并且都没有定义
ft_strlen.o

您的链接将失败,并出现对

ft_strlen
的未定义引用。您的链接不会产生
ft_isalpha
的多重定义错误,因为链接器满足了程序的引用
ft_isalpha
通过提取和链接
libft.a(ft_isalpha.o)
然后没有理由链接
libft.a(ft_strlen.o)
:库中没有定义更多未解析的符号。

当您颠倒

ft_isalpha.c
ft_strlen.c
的顺序时,会发生相反的事情,因为您 观察到 - 因为所有目标文件现在都是从
ft_strlen.c
编译的。

要纠正此特定错误,请更改:

$(OBJS_DIR)%.o : $(SRC_PREFIXED)

至:

$(OBJS_DIR)%.o : $(SRC_DIR)%.c

这使得每个目标文件仅依赖于对应的源文件;第一个先决条件

$<
成为唯一先决条件,每个目标文件都将从正确的源进行编译。

© www.soinside.com 2019 - 2024. All rights reserved.