怎么快速构建自己的C/C++程序?——有关编译、静态链接和SCons
怎么快速构建自己的C/C++程序?——有关编译、静态链接和SCons
1. 写在前面
最初写C++是在Visual Studio这个IDE里,那时我并没有makefile的概念,对程序的编译和链接的一些概念也是比较模糊。在VS下,随便增加h/cpp文件,基本上按下编译运行只要不报错就能运行。
后来开始尝试在linux平台写程序时,为避免编写makefile,曾经一度在Ubuntu里使用Code Block这个IDE。
使用IDE也有很多不爽的地方。再后来我就习惯于在Win下用Sublime的文本编辑器写程序,因为它有很好的目录层级,然后扔到linux上去编译。发现不用makefile基本控制不了不断膨胀的代码,然而又发现即便用各种自动工具去生成makefile学习曲线依然有些陡峭。
在探索cmake、autuomake的途中,了解到了SCons。这是一个可以用python去编写类似makefile的工具,它的使用难度相比cmake和automake都要简单不少。有了SCons这一神器,makefile便不再可怕,而是一件很简单的事情了。
本文首先简单介绍有关编译和静态链接的相关知识,不去涉及更复杂的动态链接等知识,真的是简单介绍;再介绍如何用SCons简单且快速地去构建自己的程序。对编译和链接过程有所了解,可以在构建过程更清楚发生了什么,明白链接时报错的意思。
2. 编译与静态链接
2.1 编译Hello World
当我们编写最简单的"Hello World"代码后,将它编译运行。
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
gcc hello.c
这时会经过四个步骤,分别是预处理、编译、汇编和链接。
- 预处理:处理掉源代码文件中那些“#”号开始的预编译指令,删除掉注释等。
- 编译:最复杂的部份,经过词法分析、语法分析、语义分析及优化产生相应的汇编语言文件。
- 汇编:将汇编代码转换机器语言,生成可重定位目标文件,也就是构建过程中常见的.o文件。
- 链接:将必要的目标文件组合起来,生成可执行文件。
2.2 目标文件
目标文件有三种:
- 可重定位目标文件。在Linux是常见的.o文件。包含二进制代码和数据,可以在链接时与其他可重定位目标文件合并,创建可执行目标文件。
- 可执行目标文件。包含了二进制代码,可以被拷贝至内存并执行。
- 共享目标文件。特殊类型的可重定位目标文件,可以在加载或者运行时被动态地加载到内存中并链接。
在程序构建的过程,编译器和汇编器生成可重定位目标和共享目标文件,链接器生成可执行文件。它们在Linux下使用ELF格式存储,是可执行和可链接格式(Executable and Linkable Format, ELF)的缩写。
2.2.1 可重定位目标文件
目标文件中有变量定义在别的模块中。在C/C++中模块之间可以通过函数调用,可以去使用别的模块定义的全局变量。
2.3 静态链接
2.3.1 符号解析
2.2.2 重定位
3. 使用Scons构建自己的程序
以下是scons编译panguan的脚本
#!/usr/bin/scons -f
# coding:utf-8
import os
process_name = 'panguan-v0.1'
def all_dir(ori_dir):
src_set = []
for root, dirs, files in os.walk(ori_dir):
for dir in dirs:
path = os.path.join(root, dir)
src_set.append(path)
return src_set
def all_src_file(dir):
src_set = []
for root, dirs, files in os.walk(dir):
for file in files:
path = os.path.join(root, file)
if file.lower().endswith(('.cpp', '.c')):
src_set.append(path)
return src_set
def main():
env = Environment(ENV=os.environ)
# add the gcc complie(above 4.8) pos
env.PrependENVPath('PATH', '/usr/local/gcc-4.8.5/bin')
env.PrependENVPath('LIBRARY_PATH', '/usr/local/gcc-4.8.5/lib64')
env.PrependENVPath('CPLUS_INCLUDE_PATH',
'/usr/local/gcc-4.8.5/include/c++/4.8.5')
# add the nanomsg lib pos
# env.PrependENVPath('CPLUS_INCLUDE_PATH', 'lib/include')
# env.PrependENVPath('LIBRARY_PATH', 'lib/lib')
# env.PrependENVPath('LD_LIBRARY_PATH', 'lib/lib')
# modify argues
env.Replace(CCFLAGS='-Wl,--no-as-needed -std=c++11 -Wall -g -Wno-reorder -lpthread -pthread')
env.Replace(LINKFLAGS='-Wl,--no-as-needed -std=c++11 -Wall -g -Wno-reorder -lpthread -pthread')
header_path = []
header_path += all_dir('common')
env.Prepend(CPPPATH=header_path)
common_src = []
common_src += all_src_file('common')
env.StaticLibrary('common/common', common_src)
env.Prepend(LIBPATH=['common'])
env.Prepend(LIBS=['common'])
header_path += all_dir('src')
env.Prepend(CPPPATH=header_path)
src_file = []
src_file += all_src_file('src')
env.Program(process_name, src_file)
if __name__ != '__main__':
main()
怎么快速构建自己的C/C++程序?——有关编译、静态链接和SCons的更多相关文章
- C程序的编译与链接
编译器驱动程序 编译器驱动程序可以在用户需要时调用语言预处理器.编译器.汇编器和链接器. 例如使用GNU编译系统,我们需要使用如下命令来调用GCC驱动程序: gcc -o main main.c 编译 ...
- 窥探C语言程序的编译、链接与.h文件
概述 C语言程序从源文件经过编译.链接生成可执行文件.那么编译与链接分别做了什么? 开发中为什么使用.h编写函数的声明?接下来使用案例说清楚为什么这样编写代码. C语言程序的编译和链接 C语言程序从源 ...
- C/C++程序从编译到链接的过程
编译器是一个神奇的东西,它能够将我们所编写的高级语言源代码翻译成机器可识别的语言(二进制代码),并让程序按照我们的意图按步执行.那么,从编写源文件代码到可执行文件,到底分为几步呢?这个过程可以总结为以 ...
- Linux中程序的编译和链接过程
1.从源码到可执行程序的步骤:预编译.编译.链接.strip 预编译:预编译器执行.譬如C中的宏定义就是由预编译器处理,注释等也是由预编译器处理的. 编译: 编译器来执行.把源码.c .S编程机器码. ...
- 原创 C++应用程序在Windows下的编译、链接:第一部分 概述
本文是对C++应用程序在Windows下的编译.链接的深入理解和分析,文章的目录如下: 我们先看第一章概述部分. 1概述 1.1编译工具简介 cl.exe是windows平台下的编译器,link.ex ...
- 关于一个程序的编译过程 zkjg面试
http://blog.csdn.net/gengyichao/article/details/6544266 一 以下是C程序一般的编译过程: 从图中看到: 将编写的一个c程序(源代码 )转换成可以 ...
- C++应用程序在Windows下的编译、链接(一)概述
C++应用程序在Windows下的编译.链接(一)概述 本文是对C++应用程序在Windows下的编译.链接的深入理解和分析,文章的目录如下: 我们先看第一章概述部分. 1概述 1.1编译工具简介 c ...
- 13_传智播客iOS视频教程_OC程序的编译链接
C程序的编译.链接.执行怎么来的?在.C文件里面写上符合C语言部分的源代码.OC也是一样的.记住:OC程序的后缀名是.m. 为什么要链接?第一个.o的目标文件里面它启动不了.因为它没有启动代码我们要加 ...
- Java Swing快速构建窗体应用程序
以前接触java感觉其在桌面开发上,总是不太方便,没有一个好的拖拽界面布局工具,可以快速构建窗体. 最近学习了一下NetBeans IDE 8.1,感觉其窗体设计工具还是很不错的 , 就尝试一下做了一 ...
随机推荐
- swift学习第十天:函数
函数的介绍 函数相当于OC中的方法 函数的格式如下 func 函数名(参数列表) -> 返回值类型 { 代码块 return 返回值 } func是关键字,多个参数列表之间可以用逗号(,)分隔, ...
- UVA 10106 Product (大数相乘)
Product The Problem The problem is to multiply two integers X, Y. (0<=X,Y<10250) The Input The ...
- error C2220: warning treated as error - no 'object' file generated warning C4819: The file contains a character that cannot be represented in the current code page (936).
用Visual Studio2015 编译时,遇到如下编译错误: error C2220: warning treated as error - no 'object' file generated ...
- js页面载入特效如何实现
js页面载入特效如何实现 一.总结 一句话总结:可以加选择器(里面的字符串)作为参数,这样函数就可以针对不同选择器,就很棒了. 1.特效的原理是什么? 都是通过标签的位置和样式来实现特效的. 二.js ...
- tp5 thinkphp5 index.php隐藏 iis 重写 伪静态
面临的问题如下: 网上找了个源码,tp5的,公司服务器是iis,源码是隐藏index.php使用了路由,iis默认去找那个路径的文件了,找不到,所以报错了 如果没有iis没有安装"url重写 ...
- 使用ionic3快速开发webapp(一)
Ionic可以让我们使用web技术快速构建接近原生体验的跨平台移动应用. 一.安装ionic 1.需要先安装 Node.js(版本8.x之上): 2.安装cordova 和 ionic: $ npm ...
- [Angular Directive] 2. Add Inputs to Angular 2 Directives
The @Input decorator allows you to pass values into your @Directive so that you can change the value ...
- js进阶 10-6 jquery中的属性选择器有哪些
js进阶 10-6 jquery中的属性选择器有哪些 一.总结 一句话总结: 1.第一遍能学会么? 一遍是肯定学不会的,要多学几遍,所以想着怎么加快速度,减少学习的遍数 2.属性选择器是干嘛的? 选择 ...
- 【BZOJ 1023】[SHOI2008]cactus仙人掌图
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1023 [题意] [题解] 如果不考虑有环的情况; 那么有一个经典的求树的直径的方法; ...
- 手机预览微信小程序
1. 获取微信小程序的 AppID 登录 https://mp.weixin.qq.com ,就可以在网站的“设置”-“开发者设置”中,查看到微信小程序的 AppID 了,注意不可直接使用服务号或订阅 ...