GNU make使用(二)
[时间:2017-06] [状态:Open]
[关键词:makefile,gcc,编译,shell命令,目标文件]
0 引言及目标
之前使用Makefile都是把源文件和目标文件放到同一个目录编译。近期看到有些编译工具支持将目标文件放到独立的目录,将源代码和目标文件(*.o)分开,这样查看代码以及目录结构也会相对清晰些。
下面我们开始展开这个过程。
1 准备工作
我们的目录结构是这样的
src
|---- audio
|--- audio.h
|--- audio.cpp
|---- video
|--- video.h
|--- video.cpp
|---- main.cpp
Makefile
obj
obj目录用于存放编译之后的目标文件,这个是自动生成的目录。src目录包含需要编译的源代码。相关代码及Makefile都可以从我的SampleCode-git下载。
常规的情况是把*.o目标文件和源代码放到同一个目录。
2 单Makefile编译整个工程
注意这个Makefile和目标文件输出目录在同一级。
OBJ_FOLDER := objs
vpath %.cpp src/audio src/video
#源文件,自动找所有.cpp文件,并将目标定义为同名.o文件
SOURCE := $(wildcard src/*.cpp) $(wildcard src/audio/*.cpp) $(wildcard src/video/*.cpp)
OBJS := $(SOURCE:%.cpp=${OBJ_FOLDER}/%.o)
#目标文件名,输入任意你想要的执行文件名
TARGET := separator
#编译参数
CC := g++
LIBS :=
LDFLAGS :=
DEFINES :=
INCLUDE := -I.
CFLAGS := -g -Wall -O3 $(DEFINES) $(INCLUDE)
CXXFLAGS:= $(CFLAGS)
#下面的基本上不需要做任何改动了
.PHONY : everything objs clean veryclean rebuild
everything : $(TARGET)
all : $(TARGET)
${OBJS} : $(OBJ_FOLDER)/%.o : %.cpp
mkdir -p $(OBJ_FOLDER)/$(<D)
$(CC) -c $(CXXFLAGS) $< -o $@
rebuild: veryclean everything
clean :
rm -fr *.so
rm $(OBJS)
veryclean : clean
rm -fr $(TARGET)
$(TARGET) : $(OBJS)
$(CC) $(CXXFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)
相比于常规情况,主要修改如下:
OBJS := $(SOURCE:%.cpp=${OBJ_FOLDER}/%.o)目标文件列表换到单独的目录。${OBJS} : $(OBJ_FOLDER)/%.o : %.cpp设置依赖规则
mkdir -p \((OBJ_FOLDER)/\)(<D) # 创建对应的目录,\((<D)表示\)<所在目录名。
$(CC) -c $(CXXFLAGS) $< -o $@ # 编译规则
3 多层嵌套的Makefile
先更新下目录结构:
src
|---- audio
|--- audio.h
|--- audio.cpp
|---- video
|--- video.h
|--- video.cpp
|---- main.cpp
|---- Makefile
Makefile
obj
这里在src目录下添加一个Makefile文件。我们的顶级Makefile相对会比较简单,但是为了避免遇到例如:./../obj/xxx.o的文件系统报错,因为../不是一个有效的目录名称,需要从主Makefile中传到参数到子目录的Makefile中。其实现如下:
SOURCE_DIR := src
export LOCAL_PATH := $(shell pwd)
$(warning ${LOCAL_PATH})
.PHONY: all everything clean veryclean rebuild
all:
$(MAKE) -C ${SOURCE_DIR}
everything:
$(MAKE) -C ${SOURCE_DIR} $@
clean:
$(MAKE) -C ${SOURCE_DIR} $@
veryclean:
$(MAKE) -C ${SOURCE_DIR} $@
rebuild:
$(MAKE) -C ${SOURCE_DIR} $@
子目录的实现相对简单点,就是把第一句OBJ_FOLDER更新下,修改如下:
OBJ_FOLDER := $(LOCAL_PATH)/objs
#目标文件名,输入任意你想要的执行文件名
TARGET := $(LOCAL_PATH)/separator
这里主要有一个知识点,从主Makefile传递到子文件夹的Makefile中的参数。有三种方式:
- 在上层Makefile中使用”export”关键字对需要传递的变量进行声明。比如:
DEBUG_SYMBOLS = TRUE
export DEBUG_SYMBOLS
当不希望将一个变量传递给子makefile时,可以使用指示符 unexport来声明这个变量。
2. export一般用法是在定义变量的同时对它进行声明。如下:
export DEBUG_SYMBOLS = TRUE
3. 在命令行上指定变量。比如:
$(MAKE) -C xxx DEBUG_SYMBOLS = TRUE
这样在进入子目录xxx执行make时该变量也有效。
4 小结
至此,最初的问题基本解决了。本文主要参考如下资料:
GNU make使用(二)的更多相关文章
- GNU make 总结 (二)
规则描述了在何种情况下使用什么命令来创建或者更新一个目标.如果在makefile中第一个规则有多个目标的话,那么多个目标中的第一个将会作为make的“终极目标”. 3.1 规则语法 TARGETS : ...
- 从零开始之uboot、移植uboot2017.01(二、从入口分析流程)
原创: To_run_away 从零开始学linux 本节的开始之前,先看一下uboot的链接脚本. 一.链接脚本 /* * Copyright (c) 2004-2008 Texas Instrum ...
- 查看centos版本号
--写在开始-- 玩Linux,不同的版本会有一些细微区别: so,经常需要查看服务器版本号: --正文-- 有以下命令可以查看linux服务器版本号: # lsb_release -a LSB Ve ...
- 在Linux下怎么确定哪个网卡对应哪个接口?
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...
- [Linux Kernel]查看CentOS版本方法
查看CentOS版本方法 有以下命令可以查看: # lsb_release -a LSB Version: :core-3.1-ia32:core-3.1-noarch:graphics- ...
- buildroot构建项目(三)--- u-boot 2017.11 适配开发板修改 1
当前虽然编译成功了,但是对于我们自己的目标板并不太适用.还得做一系列得修改. 一.lds 文件分析 u-boot 中最重要得链接文件即是,u-boot.lds.我们可以查看我们编译出来得 u-boot ...
- npm 版本问题
STF之问题篇 https://yq.aliyun.com/articles/221602 装完成后输入stf doctor查看工具依赖是否正确,安装教程可以参考我之前写的,这里不再多说,直接说问题. ...
- 给广大码农分享福利:一个业界良心的github仓库,中文计算机资料
我今天查资料时无意发现的,https://github.com/CyC2018/CS-Notes 这个仓库包含了下列几个维度的计算机学习资料: 深受国内程序员喜爱,已经有超过3万多star了. 1. ...
- Yum三方仓库——RPMForge
参考:How to Enable RPMForge Repository in RHEL/CentOS 7.x/6.x/5.x RPMForge / RepoForge这两个项目已经死亡,不应该使用 ...
随机推荐
- moodleform -转载于blfshiye
Form API 表单API 文件夹 1.概述 2.亮点 3.使用方法 4.表单元素 4.1 基本表单元素 4.2 定制表单元素 5.经常使用函数 5.1 add_action_buttons($c ...
- hdu 2126 Buy the souvenirs 【输出方案数】【01背包】(经典)
题目链接:https://vjudge.net/contest/103424#problem/K 转载于:https://blog.csdn.net/acm_davidcn/article/detai ...
- 关于 tensorflow-gpu 中 CUDA 和 CuDNN 版本适配问题
问题 今天在使用 tensorflow-yolov3 的时候,发现报错 Loaded runtime CuDNN library: but source was compiled with: . Cu ...
- 如何成为java高手
成为Java高手是每个Java学习者的梦想,但目前Java知识分支众多,我们该如何学习?本文介绍成为Java高手需要注意的25个学习目标,希望对正在成为Java高手的您有所帮助. 1.你需要精通面向对 ...
- 16,EasyNetQ-群集支持
EasyNetQ支持RabbitMQ群集,无需部署负载均衡器. 只需在连接字符串中列出群集的节点... var bus = RabbitHutch.CreateBus("host=ubunt ...
- 1013 ACM 杭电 root
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1013 题意:求两个数的根 如: 12->3,99->9,80->8 注意题目没有限制数的 ...
- 潭州课堂25班:Ph201805201 爬虫高级 第二课 sclapy 框架 (课堂笔记)
win 下安装 sclapy 先安装 pip install wheel py 库下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 在这 ...
- 潭州课堂25班:Ph201805201 爬虫基础 第一课 (课堂笔记)
爬虫的概念: 其实呢,爬虫更官方点的名字叫数据采集,英文一般称作spider,就是通过编程来全自动的从互联网上采集数据.比如说搜索引擎就是一种爬虫.爬虫需要做的就是模拟正常的网络请求,比如你在网站上点 ...
- 在web.xml中添加配置解决hibernate 懒加载异常
在web.xml添加如下,注意:在配置在struts2的拦截器之前,只能解决请求时出现的懒加载异常:如果没有请求,还需要lazy属性的添加(比如过滤器) <!-- 配置Spring的用于解决懒加 ...
- JDBC(2)—Statement
介绍: 获取到数据库连接之后,就可以对数据库进行一些增.删.改操作,但是却不能进行查询操作. 增删改操作是程序到数据库的一个操作过程,但是查询是程序到数据库--数据库返回到程序的一个过程. 步骤: 步 ...