• 第24课


    1.问题:如果我们正在进行的项目需要使用第三方库,那么前几节的makefile能胜任吗?

      答案:是否定的。

    2.经验假设

    本节我们研究第三方库的使用。使makefile支持第三方库。

    经验假设:

    • 第三方库通过函数调用的方式提供库中的功能

    • 库文件发布时都附带了声明库函数原型头文件

    • 编译阶段使用头文件链接阶段使用库文件

    第三方库在项目中的位置:

        

      libs第三方库一般和其他模块是并列的关系。因此,libs文件夹和commommodule等文件夹是同等地位的。动态链接库静态链接库都有对应的头文件

    3.第三方库编译阶段支持

        

    注意事项:

        

      实际工程先将第三方库拷贝到编译文件夹再进行链接,libs文件夹和其他模块地位等同,把它当做源文件夹使用,拷贝的结果当做编译结果。

    4.第三方库的链接阶段支持

    链接阶段:

        

    第三方库必须当做最后一个依赖,这是为了处理一种极端的情况:我们的一个子模块和库文件的名字相同。

    在这种情况下,我们优先使用自己的模块而不是第三方库模块。

    5.代码架构

    代码结构:

          

    libs/lib下的内容:

          

    顶层makefile:

    1 include pro-cfg.mk
    2 include cmd-cfg.mk
    3 include pro-rule.mk

    cmd-cfg.mk:

    复制代码
     1 AR := ar
     2 ARFLAGS := crs
     3 
     4 CC := gcc
     5 LFLAGS := 
     6 CFLAGS := -I$(DIR_INC) -I$(DIR_COMMON_INC) -I$(DIR_LIBS_INC)
     7 
     8 ifeq ($(DEBUG),true)
     9 CFLAGS += -g
    10 endif
    11 
    12 MKDIR := mkdir
    13 RM := rm -fr
    14 CP := cp
    复制代码

     第六行加上了第三方库相关的支持。

    pro-cfg.mk:

    复制代码
     1 MODULES := common 
     2            module 
     3            main
     4            
     5 MOD_CFG := mod-cfg.mk
     6 MOD_RULE := mod-rule.mk
     7 CMD_CFG := cmd-cfg.mk
     8 
     9 DIR_BUILD := build
    10 DIR_COMMON_INC := common/inc
    11 DIR_LIBS_INC := libs/inc
    12 DIR_LIBS_LIB := libs/lib
    13 
    14 APP := app.out
    复制代码

     第11、12行新增了第三方库相关的变量。

    pro-rule.mk:

    复制代码
     1 .PHONY : all compile link clean rebuild $(MODULES)
     2 
     3 DIR_PROJECT := $(realpath .)
     4 DIR_BUILD_SUB := $(addprefix $(DIR_BUILD)/, $(MODULES))
     5 MODULE_LIB := $(addsuffix .a, $(MODULES))
     6 MODULE_LIB := $(addprefix $(DIR_BUILD)/, $(MODULE_LIB))
     7 EXTERNAL_LIB := $(wildcard $(DIR_LIBS_LIB)/*)
     8 EXTERNAL_LIB := $(patsubst $(DIR_LIBS_LIB)/%, $(DIR_BUILD)/%, $(EXTERNAL_LIB))
     9 
    10 APP := $(addprefix $(DIR_BUILD)/, $(APP))
    11 
    12 define makemodule
    13     cd $(1) && 
    14     $(MAKE) all 
    15             DEBUG:=$(DEBUG) 
    16             DIR_BUILD:=$(addprefix $(DIR_PROJECT)/, $(DIR_BUILD)) 
    17             DIR_COMMON_INC:=$(addprefix $(DIR_PROJECT)/, $(DIR_COMMON_INC)) 
    18             DIR_LIBS_INC:=$(addprefix $(DIR_PROJECT)/, $(DIR_LIBS_INC)) 
    19             CMD_CFG:=$(addprefix $(DIR_PROJECT)/, $(CMD_CFG)) 
    20             MOD_CFG:=$(addprefix $(DIR_PROJECT)/, $(MOD_CFG)) 
    21             MOD_RULE:=$(addprefix $(DIR_PROJECT)/, $(MOD_RULE)) && 
    22     cd .. ; 
    23 endef
    24 
    25 all : compile $(APP)
    26     @echo "Success! Target ==> $(APP)"
    27 
    28 compile : $(DIR_BUILD) $(DIR_BUILD_SUB)
    29     @echo "Begin to compile ..."
    30     @set -e; 
    31     for dir in $(MODULES); 
    32     do 
    33         $(call makemodule, $$dir) 
    34     done
    35     @echo "Compile Success!"
    36     
    37 link $(APP) : $(MODULE_LIB) $(EXTERNAL_LIB)
    38     @echo "Begin to link ..."
    39     $(CC) -o $(APP) -Xlinker "-(" $^ -Xlinker "-)" $(LFLAGS)
    40     @echo "Link Success!"
    41     
    42 $(DIR_BUILD)/% : $(DIR_LIBS_LIB)/%
    43     $(CP) $^ $@
    44     
    45 $(DIR_BUILD) $(DIR_BUILD_SUB) : 
    46     $(MKDIR) $@
    47     
    48 clean : 
    49     @echo "Begin to clean ..."
    50     $(RM) $(DIR_BUILD)
    51     @echo "Clean Success!"
    52     
    53 rebuild : clean all
    54 
    55 $(MODULES) : $(DIR_BUILD) $(DIR_BUILD)/$(MAKECMDGOALS)
    56     @echo "Begin to compile $@"
    57     @set -e; 
    58     $(call makemodule, $@)
    59     
    复制代码

     第7、8行新增了第三方库文件列表,第18行将第三方库相关的变量传到模块的makefile。第45、46行是库文件的拷贝操作。

    mod-cfg.mk:

    复制代码
    1 DIR_SRC := src
    2 DIR_INC := inc
    3 
    4 TYPE_INC := .h
    5 TYPE_SRC := .c
    6 TYPE_OBJ := .o
    7 TYPE_DEP := .dep
    复制代码

    mod-rule.mk:

    复制代码
     1 .PHONY : all
     2 
     3 MODULE := $(realpath .)
     4 MODULE := $(notdir $(MODULE))
     5 DIR_OUTPUT := $(addprefix $(DIR_BUILD)/, $(MODULE))
     6 
     7 OUTPUT := $(MODULE).a
     8 OUTPUT := $(addprefix $(DIR_BUILD)/, $(OUTPUT))
     9 
    10 SRCS := $(wildcard $(DIR_SRC)/*$(TYPE_SRC))
    11 OBJS := $(SRCS:$(TYPE_SRC)=$(TYPE_OBJ))
    12 OBJS := $(patsubst $(DIR_SRC)/%, $(DIR_OUTPUT)/%, $(OBJS))
    13 DEPS := $(SRCS:$(TYPE_SRC)=$(TYPE_DEP))
    14 DEPS := $(patsubst $(DIR_SRC)/%, $(DIR_OUTPUT)/%, $(DEPS))
    15 
    16 vpath %$(TYPE_INC) $(DIR_INC)
    17 vpath %$(TYPE_INC) $(DIR_COMMON_INC)
    18 vpath %$(TYPE_INC) $(DIR_LIBS_INC)
    19 vpath %$(TYPE_SRC) $(DIR_SRC)
    20 
    21 -include $(DEPS)
    22 
    23 all : $(OUTPUT)
    24     @echo "Success! Target ==> $(OUTPUT)"
    25     
    26 $(OUTPUT) : $(OBJS)
    27     $(AR) $(ARFLAGS) $@ $^
    28     
    29 $(DIR_OUTPUT)/%$(TYPE_OBJ) : %$(TYPE_SRC)
    30     $(CC) $(CFLAGS) -o $@ -c $(filter %$(TYPE_SRC), $^)
    31     
    32     
    33 $(DIR_OUTPUT)/%$(TYPE_DEP) : %$(TYPE_SRC)
    34     @echo "Creating $@ ..."
    35     @set -e; 
    36     $(CC) $(CFLAGS) -MM -E $(filter %$(TYPE_SRC), $^) | sed 's,(.*).o[ :]*,$(DIR_OUTPUT)/1$(TYPE_OBJ) $@ : ,g' > $@
    复制代码

    common文件夹下的makefile:

    复制代码
     1 include $(MOD_CFG)
     2 
     3 # Custmization Begin
     4 # 
     5 # DIR_SRC := src
     6 # DIR_INC := inc
     7 #
     8 # TYPE_INC := .h
     9 # TYPE_SRC := .c
    10 # TYPE_OBJ := .o
    11 # TYPE_DEP := .dep
    12 #
    13 # Custmization End
    14 
    15 include $(CMD_CFG)
    16 
    17 include $(MOD_RULE)
    复制代码

    main文件夹下的makefile:

    复制代码
     1 include $(MOD_CFG)
     2 
     3 # Custmization Begin
     4 # 
     5 # DIR_SRC := src
     6 # DIR_INC := inc
     7 #
     8 # TYPE_INC := .h
     9 # TYPE_SRC := .c
    10 # TYPE_OBJ := .o
    11 # TYPE_DEP := .dep
    12 #
    13 # Custmization End
    14 
    15 include $(CMD_CFG)
    16 
    17 include $(MOD_RULE)
    复制代码

    module文件夹下的makefile:

    复制代码
     1 include $(MOD_CFG)
     2 
     3 # Custmization Begin
     4 # 
     5 # DIR_SRC := src
     6 # DIR_INC := inc
     7 #
     8 # TYPE_INC := .h
     9 # TYPE_SRC := .c
    10 # TYPE_OBJ := .o
    11 # TYPE_DEP := .dep
    12 #
    13 # Custmization End
    14 
    15 include $(CMD_CFG)
    16 
    17 include $(MOD_RULE)
    复制代码

    如果我们突然不使用第三方库了,则只需删掉libs文件夹下的内容即可,而makefile无需改动。

    6.小结:

    • 编译环境必须支持第三方库的使用(静态库或动态库

    • 工程开发中一般会使用特殊的文件夹存放第三方库

    • 第三方库所附带的头文件用于声明库文件(编译阶段需要

    • 链接阶段先将库文件拷贝到build文件夹,在进行链接链接阶段需要

  • 相关阅读:
    Matplotlib如何绘制子图
    数据挖掘的葵花宝典
    Matplotlib如何显示中文
    python绘制WordCloud词云图
    Selenium实现微博自动化运营:关注、点赞、评论
    从小白视角理解<数据挖掘十大算法>
    Laravel模型自动转换类型
    python数据分析常用图大集合
    数据分析常见概念
    Pandas数据分析基础之时间序列
  • 原文地址:https://www.cnblogs.com/hoiday/p/10306649.html
Copyright © 2020-2023  润新知