【问题标题】:How to prevent my makefile to relink due to static library如何防止我的makefile由于静态库而重新链接
【发布时间】: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?

非常感谢

【问题讨论】:

    标签: c++ c 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) $@ $^
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-05
        • 2018-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多