今天是中秋佳节,但是写完已经是第二天凌晨了,还是祝大家中秋快乐!

VS对C++的支持相较GCC太弱了,连续几个VS版本对C++的改进都很小、很少。对Cpper也许是一种痛,我们也许希望能使用VS的强大编辑功能,组合GCC以及GDB的强大编译器以及调试功能进行开发。自从有了VisualGDB,这一切都变成真的了,那VS默认会有预编译头,GCC呢?VisualGDB呢?我们只能手动去写Makefile,不错,手动去写,下面就与大家分享VisualGDB中的预编译头设置。

在之前的博客(VisualGDB使用随笔)中提到,我初尝螃蟹,发现了VisualGDB这个超级好用的VS插件后,一直是爱不释手。但后面的几年时间里一直没新项目可以使用这个工具,一展其光辉。博客最后也提到了要分享VisualGDB中添加预编译以及类似VS的Compile输出而不是一长串命令行的修改。实在不好意思,事隔三年了,今天才将它分享出来。

在大项目中添加预编译头的好处,我就不多说了。

说起预编译头,让我想起了一个我亲身经历的事:前几年初到一家公司做项目,由于该项目比较庞大,机器配置也比较差,当时要全部重新编译一次项目大概需要半小时(也许有人说可以使用联合编译,确实,公司就是使用的联合编译,但编译一次也得在十几分钟的样子),为什么会这样,我看了一下项目配置,居然没配置预编译头。对我而言,编译一次需要最少需要10几分钟,去上个厕所,去冲杯咖啡回来都还没编译完成,我实在是受不了。于是我决定加上预编译头,由于项目比较大,文件比较多,头文件的包含顺序错综复杂,不想手工去一个一个理(估计得理个几天吧),就写了一个小工具去整理这些包含顺序,自动生成
一个预编译头文件。最后弄下来,编译速度得到了极大提高,直接单机编译只需要三五几分钟就编译完成(为此公司还给我发了一笔奖金)。

好了,言归正传,我们知道VisualGDB自动生成的Makefile中并不包括预编译头的任何选项,只能通过自己修改Makefile来达到目的。对于初学者或者根本不懂Makefile的同学来说是有一定难度的。使用过VS的同学一定知道,VS的项目配置中一个项目只能配置一个预编译头,如果这个项目既使用了C又使用了C++那么两者是不能同时生成预编译头的。而GCC,准确的说应该是使用Makefile的方式就可以做到,下面就为大家分享VisualGDB项目生成的Makefile如何同时生成和使用C以及C++的预编译头。

关于普通的GCC项目使用预编译头加快编译速度可以参考之前我转的一篇文章《使用 GNU CC 的预编译头文件加快编译速度》,VisualGDB生成的Makefile与文中所示的Makefile类似,只是VisualGDB的Makefile会根据项目中的文件自动修改其中的SOURCEFILES参数,但规则部分是一经生成就不会被修改,而我们要做的也是修改规则。

BTW:当然如果不想让VisualGDB自动添加项目文件到SOURCEFILES项,可以把Makefile中的

#VisualGDB: AutoSourceFiles		#<--- remove this line to disable auto-updating of SOURCEFILES and EXTERNAL_LIBS

删除掉即可(不建议删除)

我们看一下VisualGDB自动生成的Makefile编译规则部分:

#VisualGDB: FileSpecificTemplates		#<--- VisualGDB will use the following lines to define rules for source files in subdirectories
$(BINARYDIR)/%.o : %.cpp $(all_make_files) |$(BINARYDIR)
$(CXX) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.c $(all_make_files) |$(BINARYDIR)
$(CC) $(CFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.S $(all_make_files) |$(BINARYDIR)
$(CC) $(CFLAGS) $(ASFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.s $(all_make_files) |$(BINARYDIR)
$(CC) $(CFLAGS) $(ASFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.cc $(all_make_files) |$(BINARYDIR)
$(CC) $(CFLAGS) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.cxx $(all_make_files) |$(BINARYDIR)
$(CC) $(CFLAGS) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) #VisualGDB: GeneratedRules #<--- All lines below are auto-generated

这里列出了以下几种源文件的编译规则:

1.扩展名为cpp、cc、cxx的C++源文件

2.扩展名为c的C源文件

3.扩展名为s、S的汇编源文件,这种汇编文件一般是AT&T格式的汇编文件而不是Intel格式的汇编文件。

为了让项目同时支持C以及C++的预编译头,首先我们假定C及C++的头文件使用如下选项来定义:

# C Header
PCH_H = prec.h
PCH = prec.h.gch # C++ Header
PCH_X_H = prec.hpp
PCH_X = prec.hpp.gch

这部分代码可以放在Makefile的生成规则之前的某个适当位置,也可以放在debug.mak和release.mak中,需要特别注意的是预编译生成的文件一定是在预编译头文件后加gch后缀,同时要求预编译文件与头文件在同一个目录,不然GCC找不到预编译文件。然后在Makefile

#VisualGDB: GeneratedRules				#<--- All lines below are auto-generated

这行之前加上生成预编译头的规则,

# C Prec Header Rule
$(BINARYDIR)/$(PCH) : $(PCH_H)
$(CC) $(CFLAGS) $> $^ # C++ Prec Header Rule
$(BINARYDIR)/$(PCH_X) : $(PCH_X_H)
$(CXX) $(CXXFLAGS) $> $^

添加好预编译头的规则后,我们还需要使用生成的预编译头,注意C与C++的预编译头不能混合使用,不能编译会报错。例如添加cpp以及c源文件的预编译头使用规则:

$(BINARYDIR)/%.o : %.cpp $(all_make_files) |$(BINARYDIR) $(BINARYDIR)/$(PCH_X)
$(CXX) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.c $(all_make_files) |$(BINARYDIR) $(BINARYDIR)/$(PCH)
$(CC) $(CFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep)

此时我们在项目中添加两个头文件prec.h以及prec.hpp就可以自动生成并使用各自的预编译头了。

最后,使用惯了VS的同学可能不太习惯编译时的一大串命令行,没关系,我们也可以通过修改Makefile来做到只显示简要信息。我们规则部分的命令使用@符号作前缀即可,知道DOS命令的同学应该比较熟悉如下命令

@echo off
@echo on

然后加上我们想要显示的信息比如Compile XXX

好了,下面我就直接把完整的Makefile规则部分贴出来:

#VisualGDB: FileSpecificTemplates		#<--- VisualGDB will use the following lines to define rules for source files in subdirectories
$(BINARYDIR)/%.o : %.cpp $(all_make_files) |$(BINARYDIR) $(BINARYDIR)/$(PCH_X)
@$(CXX) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep)
@echo Compile $< $(BINARYDIR)/%.o : %.c $(all_make_files) |$(BINARYDIR) $(BINARYDIR)/$(PCH)
@$(CC) $(CFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep)
@echo Compile $< $(BINARYDIR)/%.o : %.S $(all_make_files) |$(BINARYDIR)
$(CC) $(CFLAGS) $(ASFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.s $(all_make_files) |$(BINARYDIR)
$(CC) $(CFLAGS) $(ASFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.cc $(all_make_files) |$(BINARYDIR) $(BINARYDIR)/$(PCH_X)
$(CC) $(CFLAGS) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) $(BINARYDIR)/%.o : %.cxx $(all_make_files) |$(BINARYDIR) $(BINARYDIR)/$(PCH_X)
$(CC) $(CFLAGS) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep) # C Prec Header Rule
$(BINARYDIR)/$(PCH) : $(PCH_H)
@$(CC) $(CFLAGS) $> $^
@echo Compile $^ # C++ Prec Header Rule
$(BINARYDIR)/$(PCH_X) : $(PCH_X_H)
@$(CXX) $(CXXFLAGS) $> $^
@echo Compile $^ #VisualGDB: GeneratedRules #<--- All lines below are auto-generated

祝大家玩得愉快!

在VisualGDB中配置预编译头加快编译速度的更多相关文章

  1. 在Editplus中配置java的(带包)编译(javac)和运行(java)的方法

    配置的前提是电脑安装了JDK并且配置好了相关的环境变量(JAVA_HOME,path和classpath). 配置好后在命令行中输入javac和java验证是否配置成功: 如果出现上面的情况则说明配置 ...

  2. 在eclipse中配置android ndk的自动编译环境builders

    无论linux还是mac在jni目录中直接运行  ndk-build 就可以生成 lib目录及所需要的 so文件: windows 装上lnx模拟器也是一样: 每次修改完 c++代码, 都要运行一下 ...

  3. 在Editplus中配置java的(带包)编译(javac)和执行(java)的方法

    配置的前提是电脑安装了JDK而且配置好了相关的环境变量(JAVA_HOME,path和classpath). 配置好后在命令行中输入javac和java验证是否配置成功: 假设出现上面的情况则说明配置 ...

  4. 在Ubuntu14.4(32位)中配置I.MX6的QT编译环境

    1,开发工具下载 一,下载VMware Workstation虚拟机 地址:http://1.xp510.com:801/xp2011/VMware10.7z 二,下载Ubuntu 14.04.5 L ...

  5. 在 .pro里加入 QMAKE_CXXFLAGS += /MP 将并行编译,加快编译速度(姚冬的办法)

    但是只对VC编译器有效果. 另外还可以自己设置stdafx.h文件 http://www.zhihu.com/question/23045749

  6. SASS环境搭建及HBuilder中sass预编译配置

    ---------------------------------Ruby环境安装-------------------------------- 至于为什么要安装ruby环境请移步:https:// ...

  7. QT:提高QT Creator编译速度,配置预编译头Stable.h

    提高QT Creator编译速度,配置预编译头Stable.h QT Creator支持预编译头提高编辑速度,网上有些教程写得不详细,走了弯路,具体实现方法如下. (1)工程.PRO文件加入下面代码 ...

  8. 带你玩转Visual Studio——带你理解微软的预编译头技术

    原文地址:http://blog.csdn.net/luoweifu/article/details/49010627 不陌生的stdafx.h 还记得带你玩转Visual Studio——带你新建一 ...

  9. fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "StdAfx.h"”? 解决方法

    错误描述: fatal error C1010: 在查找预编译头时遇到意外的文件结尾.是否忘记了向源中添加“#include "StdAfx.h"”? 错误分析:     此错误发 ...

随机推荐

  1. Python之os.path.join()

    os.path.join()函数用于路径拼接文件路径. os.path.join()函数中可以传入多个路径: 会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃. 以上一种情况为先.在上一种情况 ...

  2. django 内置server 外网不能访问, 报连接超时

    按照官网教程,以 python manage.py runserver 其访问url为 http://127.0.0.1:8000,意味着只能本机访问,而我的django app 部署在 阿里云上面 ...

  3. Vue_子级组件调用主组件函数

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  4. LeetCode Array Easy 118. Pascal's Triangle

    Description Given a non-negative integer numRows, generate the first numRows of Pascal's triangle. I ...

  5. python_django_富文本

    下载富文本: pip install django-tinymce 一.配置 在settings.py文件INSTALLED_APPS中添加:'tinymce': 二.应用 1.在admin中使用 a ...

  6. appium1.4+华为8.0执行自动化脚本,报启动session失败,原因是unicode_ime_apk\Uni codeIME-debug.apk在手机上已存在,再次安装失败,导致启动session失败,解决办法:换高版本的appium

    最开始做Android自动化测试时,通过执行脚本发现报,已安装UnicodeIME-debug.apk,再次安装失败,当时觉得这个apk对我来说没用,就把D:\Program Files (x86)\ ...

  7. springBoot框架在idea中创建流程 同时存在一个项目中

    1.新建普通maven工程 2.在父级pom中按需修改 3.删除父级src目录 4.创建公共模块common,里面只有service接口和实体类 5.构建微服务模块,provider 6.引用Zook ...

  8. 获取微信企业的corpID,sercret,access_token,部门设置列表

    获取微信企业的corpID,sercret,access_token,部门设置列表   zabbix调用微信发短信可能用到的一些变量,获取方式如下: 1.corpID(公司ID) 在我的企业--企业信 ...

  9. Yii2中自定义表单样式

    use yii\widgets\ActiveForm; <?php $form = ActiveForm::begin([ 'options' => ['class' => 'for ...

  10. Shiro学习(24)在线回话管理

    有时候需要显示当前在线人数.当前在线用户,有时候可能需要强制某个用户下线等:此时就需要获取相应的在线用户并进行一些操作. 本章基于<第十六章 综合实例>代码构建. 会话控制器 Java代码 ...