make子目录常用方法

一般是

SUB_DIR =  lib_src service

.PHONY: subdirs $(SUB_DIR)

subdirs: $(SUB_DIR)

$(SUB_DIR):
@+make -C $@ foo: baz

或者

subdirs:
for dir in $(SUB_DIR); do \
@+make -C $$dir; \
done

使用循环的方式比较直观,但是会有这样的问题

  • 当submake报错的时候不会停止,其他submake会继续执行
  • 不能体验到make的并行编译 即-j选项
  • 子目录之间的依赖不好表示

所以,一般来说会选择第一种来写.但是,当用第一种书写时,怎么表达make子命令(即:make install)呢?

make子命令书写


SUB_DIR_TEST = $(SUB_DIR:%=%_test) test: $(SUB_DIR_TEST)
$(SUB_DIR_TEST):
@+make -C $(@:%_test=%) test .PHONY: test subdirs $(SUB_DIR_TEST)

核心就是对子目录名字进行包裹一下,把包裹后的名字当作新的伪目标进行构建

实例

以下是我从工作项目中拷出来的

总共三个级别的目录

  • 根目录
  • lib_src service
  • 实际编译目录:game gate

所以列举了3个makefile

项目目录大致结构

目录做了一些删减

bin输出目录:deploy/bin

├── deploy
│   └── bin
├── deps
│   └── tinyxml
│   ├── include
│   │   └── tinyxml
│   │   └── tinyxml.h
│   └── lib
│   └── libtinyxml.a
├── lib_src
│   ├── auth
│   │   ├── auth.cpp
│   │   └── auth.h
│   ├── common
│   │   ├── common.cpp
│   │   └── common.h
│   └── lib
└── service
├── game
│   └── game.cpp
└── gate

项目根目录下的Makefile

MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
SUB_DIR = lib_src service
SUB_DIR_TEST := $(SUB_DIR:%=%_test)
SUB_DIR_CLEAN := $(SUB_DIR:%=%_clean) all : $(SUB_DIR) lib_src:
@+make -C $@ service:lib_src
@+make -C $@ clean:$(SUB_DIR_CLEAN)
#$(foreach N, $(SUB_DIR),make clean -C $(N);) $(SUB_DIR_CLEAN):
@+make clean -C $(@:%_clean=%) test:$(SUB_DIR_TEST)
@echo $(MKFILE_PATH) $(SUB_DIR_TEST):
@+make test -C $(@:%_test=%) .PHONY: all test clean $(SUB_DIR) $(SUB_DIR_TEST) $(SUB_DIR_CLEAN)

lib_src下的Makefile

MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
SUB_DIR = auth common
SUB_DIR_CLEAN := $(SUB_DIR:%=%_clean)
SUB_DIR_TEST := $(SUB_DIR:%=%_test) all : |mk_dir $(SUB_DIR) $(SUB_DIR): mk_dir
@+make -C $@ mk_dir:
@mkdir -p bin clean:$(SUB_DIR_CLEAN)
#$(foreach N, $(SUB_DIR),make clean -C $(N);) $(SUB_DIR_CLEAN):
@+make clean -C $(@:%_clean=%) test:$(SUB_DIR_TEST)
@echo $(MKFILE_PATH) $(SUB_DIR_TEST):
@+make test -C $(@:%_test=%) .PHONY: all test clean mk_dir $(SUB_DIR) $(SUB_DIR_TEST) $(SUB_DIR_CLEAN)

game下的Makefile

编译选项这些忽略吧

MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
include ../../global.mk
TARGET := $(BIN_DIR)/game_svr$(BIN_TAG)
CUR_INC_FLAGS := -I$(FRAME_INC) -I./ -I$(MYSQL_INC)
CUR_LINK_FLAGS := $(LDFLAGS) -L$(MYSQL_LIB)
CUR_CPPFLAGS := $(CPPFLAGS) $(CUR_INC_FLAGS)
SUB_DIR := app bll dal db thread config
ALL_OBJS = $(wildcard $(OBJ_DIR)/*.o) all : |$(OBJ_DIR) $(TARGET) $(TARGET) : $(TARGET_OBJS) $(SUB_DIR)
$(CXX) -o $@ $(ALL_OBJS) $(CUR_LINK_FLAGS)
@echo "#### compile ok "$(TARGET) "####" $(OBJ_DIR)/%.o : %.cpp
$(CXX) $(CUR_CPPFLAGS) -c $< -o $@ $(OBJ_DIR):
@mkdir $@ $(SUB_DIR):
@echo "#### compile sub dir start ####" $@
@+make -C $@
@echo "#### compile sub dir end ####" $@ clean: @rm -f $(wildcard $(OBJ_DIR)/*.o) $(TARGET) test:
@echo $(MKFILE_PATH) .PHONY: all test clean
.PHONY: $(SUB_DIR)

简要语法说明

$(SUB_DIR:%=%_test)

表示文件名加后缀,结果为lib_src_test service_test

$(@:%_test=%)

表示去掉后缀,结果为lib_src service

=

在真正执行命令的时候才会对变量求值,所以变量值可能会在中间因为其他引用的其他变量被改变而不是预期的

=:

在赋值的时候直接对变量求值,以后如果不重新赋值是不会变化的

makefile编译子目录的更多相关文章

  1. live555学习(一)通读Makefile编译live555

    live555学习(一)通读Makefile编译live555 live555 编译live555 学习开源 live555学习(一)通读Makefile编译live555 前言 live555简介 ...

  2. C++---初识《通过g++ / makefile 编译和调用动态库so文件》(ubuntu)

    C++---初识<通过g++ / makefile  编译和调用动态库so文件>(ubuntu) ------------------------目录------------------- ...

  3. gcc与makefile编译 BY 四喜三顺

    gcc编译控制过程:(假设源代码为a.c)(1)源文件到预处理文件:    gcc -E -o a.cxx a.c    a.cxx显示调用哪些头文件(2)生成汇编代码:              g ...

  4. 【Linux学习】 写一个简单的Makefile编译源码获取当前系统时间

    打算学习一下Linux,这两天先看了一下gcc的简单用法以及makefile的写法,今天是周末,天气闷热超市,早晨突然发现住处的冰箱可以用了,于是先出去吃了点东西,然后去超市买了一坨冰棍,老冰棍居多, ...

  5. Linux Makefile 编译速度的优化【转】

    转自:https://blog.csdn.net/QQ1452008/article/details/51851801 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog. ...

  6. makefile 编译指定目录

    makefile 编译指定目录 sub1=test1 sub2=test2 subs = sub1 sub2 SUBDIRS =$(foreach i, $(subs), $($(i))) .PHON ...

  7. CMake 工程调用 Makefile 编译项目

    本文主要介绍如何将一个依赖 Makefile 项目(MIDG)移植到 CMake 上. 首先介绍项目文件结构,文件主要由三个目录组成 3rdParty include src 其中,3rdParty ...

  8. 由于makefile编译所有子目录中 sed 's,/($*/)/.o[ :],/1.o $@ : ,g' <$@ > $@ 的解释

    这个语句分为好几层,我们一层一层来看 1. sed 's,/($*/)/.o[ :],/1.o $@ : ,g' <$@ > $@ 首先看加粗这一层,$@表示目标参数中的.d文件, '&l ...

  9. Makefile编译库

    funs.h: #ifndef __FUNS_H__ #define __FUNS_H__ void fun1(); #endif funs.c #include "funs.h" ...

随机推荐

  1. 🧚‍♂️全套Java教程_Java基础入门教程,零基础小白自学Java必备教程👨‍💻004 # 第四单元 流程控制语句上 #

    一.本单元知识点概述 二.本单元目标 (Ⅰ)重点知识目标 1.if语句的格式及执行流程2.switch语句的格式及执行流程 (Ⅱ)能力目标 1.掌握if语句的格式及执行流程2.掌握switch语句的格 ...

  2. 大前端快闪二:react开发模式 一键启动多个服务

    最近全权负责了一个前后端分离的web项目,前端使用create-react-app, 后端使用golang做的api服务. npx create-react-app my-app cd my-app ...

  3. Django整理(五) - 请求与响应 - request对象

    请求对象 一.客户端传参的几种方式 1. 通过URL路径(path)传递,例如:http://127.0.0.1:8000/news/1/2,两个参数:id和page 2. 通过 query stri ...

  4. FastAPI(62)- FastAPI 部署在 Docker

    Docker 学习 https://www.cnblogs.com/poloyy/p/15257059.html 项目结构 . ├── app │   ├── __init__.py │ └── ma ...

  5. Java程序的种类

    Java程序的种类 Application:Java应用程序,是可以由Java解释器直接运行的程序. Applet:即Java小应用程序,是可随网页下载到客户端由浏览器解释执行的Java程序. Ser ...

  6. Windows下node-gyp查找VS安装路径简单解析

    node-gyp的作用我已经不想赘述了,这里给一个我之前文章的链接:cnblogs看这里,知乎看这里.本文主要从源码入手,介绍node-gyp查找VisualStudio的过程 为了方便我们研究nod ...

  7. 沟谷网络的提取及沟壑密度的计算(ArcPy实现)

    一.背景 沟壑密度是描述地面被水道切割破碎程度的一个指标.沟壑密度是气候.地形.岩性.植被等因素综合影响的反映.沟壑密度越大,地面越破碎,平均坡度增大,地表物质稳定性降低,且易形成地表径流,土壤侵蚀加 ...

  8. Apache Common-collection 反序列化利用链解析--TransformedMap链

    Apache Common-collection 反序列化利用链解析 TransformedMap链 参考Java反序列化漏洞分析 - ssooking - 博客园 (cnblogs.com) poc ...

  9. javascript-jquery的ajax

    用一个例子来说明: html部分  <form action="name1"> <input class="class1" type=&quo ...

  10. Vue3学习(七)之 列表界面数据展示

    一.前言 昨晚可能是因为更新完文章后,导致过于兴奋睡不着(写代码确实太容易让人兴奋了),结果两点多才睡着,大东北果然还是太冷了. 不知道是不是因为膝盖和脚都是冰凉的,所以才导致很晚才能入睡? 刚眯了一 ...