如何防止我的makefile由于静态库而重新链接
Posted
技术标签:
【中文标题】如何防止我的makefile由于静态库而重新链接【英文标题】:How to prevent my makefile to relink due to static library 【发布时间】:2017-02-19 16:51:07 【问题描述】:我有一个 Makefile,它在没有要编译的静态库时运行良好:
CC = g++ -std=c++11
RM = rm -f
NAME = hello
SRCS = Main.cpp \
srcs/Controller.cpp \
...
srcs/Parser.cpp
OBJS = $(SRCS:.cpp=.o)
CPPFLAGS += -W -Wall -Wextra -Werror
all : $(NAME)
$(NAME) : $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(OBJS) -I./inc
clean :
$(RM) $(OBJS)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
这个makefile可以工作并且不会重新链接(当我输入两次“make”时,它不会重新编译并输出“Nothing to be done for all”)
但是当我想编译一个静态库时,“make”命令重新编译库而不输出“Nothing to be done for all”,这里是包含静态库的新Makefile:
CC = g++ -std=c++11
RM = rm -f
NAME = hello
LIBNAME = libhello.a
SRCS = srcs/Controller.cpp \
...
srcs/Parser.cpp
OBJS = $(SRCS:.cpp=.o)
CPPFLAGS += -W -Wall -Wextra -Werror
all : $(NAME)
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
clean :
$(RM) $(OBJS)
$(RM) $(LIBNAME)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
当静态库已经编译并且不需要重新编译时,我该如何解决这个问题以防止重新编译makefile?
非常感谢
【问题讨论】:
【参考方案1】:关于这个食谱:
$(NAME) : $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(OBJS) -I./inc
预计默认编译语句将用于生成目标文件,make
将在执行规则之前生成这些目标文件。并且由于它没有在这个秘籍中执行任何编译,所以不需要参数-I./inc
。
如果头文件没有在依赖项中列出,更改头文件将导致关联的源文件重新编译失败。
建议:
HEADERS := ..
$(name): $(OBJS)
<tab> $(CC) -o $@ $(OBJS) $(LFLAGS)
%.o:%.cpp $(HEADERS)
<tab> $(CC) $(CPPFLAGS) -c $< -o $@ -I./inc
行内注:
CPPFLAGS += -W -Wall -Wextra -Werror
-W
关闭所有以前启用的警告,可能不是您想要的,建议删除该参数。
创建静态库时需要考虑类似的问题,类似于:
这一行:
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
变成:
HEADER := ...
all: $(LIBNAME) $(NAME)
$(LIBNAME): $(OBJS)
<tab> ar rc -o $@ $^
%.o:%.cpp
<tab> $(CC) $(CPPFLAGS) -c $< -o $@ -I./inc
$(NAME): main.o $(LIBNAME)
<tab> $(CC) $< -o $@ $(LFLAGS) -l$(LIBNAME)
【讨论】:
非常感谢您的回答以及您对 -W 标志的说明! @user3629249 你所说的 -W 标志是完全错误的!正如您在man make
中看到的那样:-w Inhibit all warning messages.
和:-Wextra This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)
所以-W
标志只是-Wextra
的旧名称(所以把-W
和-Wextra
放在同一行是没用的,所有Epitech ' 学生犯了同样的错误,因为他们无法自己思考,他们只是复制了 Intranet 的 Makefile 的示例。
@Paul-Marie,此选项:-W 导致:禁止所有警告消息。这可以在网页上找到:-W
@user3629249 是的,但就像我告诉你的那样,你正在交换 -w
和 -W
,-w
标志有效地导致“禁止所有警告”,但 -W
(所以大写)只是-Wextra
的旧名称,仍然受到支持,但不能保证它在未来会保持这种状态! (请参阅您网页上的第一行描述)。最佳后卫。
现在我明白了,大写字母 'W' .vs.小写“w”。我的错误【参考方案2】:
问题在于 $NAME
由于这条规则而成为虚假目标:
all : $(NAME)
我认为可以通过将其更改为实际目标来解决该问题:
all : $(LIBNAME)
另外,你有这个规则:
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
这有点令人困惑:该库构建为$LIBNAME
,但随后它继续链接名为$NAME
的可执行文件。因此,每次您对Main.cpp
进行更改时,都必须重新构建库。
【讨论】:
【参考方案3】:您对$(NAME)
的规则实际上并没有创建一个名为$(NAME)
的文件(即hello
),因此make 每次都会尝试重新制作它。配方必须符合规则(这就是为什么您应该使用自动变量,如下面的最后一个示例):
all: $(LIBNAME)
$(LIBNAME): $(OBJS)
ar rc $(LIBNAME) $(OBJS)
GNU make 也有内置的归档功能,虽然它不能很好地与并行 make 配合使用:
ARFLAGS := rc
all: $(LIBNAME)($(OBJS))
一种更惯用的、并行安全的方式类似于
ARFLAGS := rc
.PHONY: all
all: $(LIBNAME)
$(LIBNAME): $(OBJS)
$(AR) $(ARFLAGS) $@ $^
【讨论】:
以上是关于如何防止我的makefile由于静态库而重新链接的主要内容,如果未能解决你的问题,请参考以下文章
当目标是静态库而目标链接是静态库时,target_link_libraries 会做啥
Linux2.6 如何编写Makefile,使驱动程序能够编译链接静态库