您现在的位置是:首页 > 正文

构建工具scons让一切变得简单

2024-02-29 11:39:26阅读 0
你曾经为繁琐的makefile语法纠结过吗?你有想要摆脱VS的束缚,自己构建工程却又苦于无从下手吗?你有为同一个工程要在不同操作系统或不同平台下构建编译环境而苦恼过吗? 本文有我的选择,你的答案。

最近小试了一把用scons来构建编译环境,感觉很不错,跟大家分享一下。
先说明下什么是scons,scons是一个Python写的自动化构建工具,就比如老牌的cmake,或者如果经常跟google一些开源项目打交道的话,那肯定知道新近开始流行的gyp(google内部用的构建工具),scons实现跟它们有类似的功能。而scons又有区别于其他构建工具的特点,不得不承认,这些特点让我喜欢上了这个工具。
先简单总结下吸引我的几点:
1. 自动依赖分析
2. 工具本身由python实现,跨平台
3. 基于MD5识别构建文件的改变,并且可以自定义和扩展
4. 构建文件逻辑用python来写,功能强大,扩展性超强,跨平台
5. 简单易用(半小时内可以学会如何构建中小规模编译环境)
6. 官方提供的文档详细易理解(如果看过google的gyp的文档,那叫一个坑爹)

好了,进入正题,就让我们来循序渐进的来领略下scons的魅力吧。
首先是安装环境,
第一步当然是要保证系统中安装了python,貌似2.6和2.7下scons都没有问题,其他的自己尝试下吧。
第二步,安装scons。windows环境的话直接去官网下载exe直接安装即可。linux Debian系统下则更方便,可以直接用如下命令来安装:sudo apt-get install scons
安装完成后,在命令行验证一下,输入scons -v, 如果没有提示scons命令不存在则说明安装成功。不幸的是,windows下还真提示不存在了,怎么办?其实在python安装路径C:\Python27\Scripts下(我的python安装在C:\Python27)有个scons.bat,以后运行这个命令就可以(/scons.bat -v),为了方便可以把该路径追加到环境变量PATH中。
ok,环境搞定。

接着,一起来细细品味下scons吧。
1. 假设有如下【helloScons.c】文件:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
        printf("Hello, SCons!\n");
        return 0;
} 
用scons怎么编译它呢?首先在helloScons.c相同路径下新建【SConstruct】文件,内容如下:
Program('helloScons.c')

命令行,进入该文件相同路径,运行‘scons’(windows下运行scons.bat)。可以看到如下运行结果:
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o helloScons.o -c helloScons.c
gcc -o helloScons helloScons.o
scons: done building targets.
编译完成,得到helloScons可执行文件。
如果我们希望生成其他名字的可执行文件呢?很简单,把【SConstruct】改成如下内容就可:
Program('newName', 'helloScons.c')
 
2. 我们稍微改动下,比如相同路径下再新建个文件extScons.c, extScons.h:
extScons.h
int add(int x, int y);

extScons.c
int add(int x, int y)
{
     return x + y;
}

然后修改下【helloScons.c】:
#include <stdio.h> 
#include <stdlib.h>
#include “extScons.h”
int main(int argc, char* argv[]) 
{ 
        printf("Hello, SCons %d!\n", add(1, 2)); 
        return 0; 
} 

SConstruct】文件怎么改呢?
Program(['helloScons.c', 'extScons.c'])
那如果你整个工程中有上百个.c,难道都要在SConstruct中一个一个写出来吗?当然不需要,下面这样也能达到跟上面一样的功能:
Program(Glob('*.c'))

3. 假设我们再变化一下,在当前路径下创建ext文件夹,把extScons.h和extScons.c移到ext文件夹里,【SConstruct】怎么写:
Program(['helloScons.c', 'ext/extScons.c'])
类似如果希望设置为文件夹下所有文件,也可以写成:
Program([Glob('*.c'), Glob('ext/*.c')])

4. 那么如果要把extScons.c编译成动态链接库.so,怎么做?
【SConstruct】文件如下:
SharedLibrary('ext/extScons.c')
Program(['helloScons.c'], LIBS=['extScons'], LIBPATH='./ext')
解释一下,SharedLibrary()指定把ext/extScons.c编译成动态链接库,如果想编译为静态链接库则使用StaticLibrary()。Program方法中,LIBS指定的是主程序helloScons.c需要使用的动态链接库libextScons.so,LIBPATH则指定的是libextScons.so的路径。
运行scons后,可以看到ext文件夹下生成了libextScons.so,主文件夹下生成了可执行程序helloScons。

5. 如果要把编译和链接两个步骤分开呢?没问题,scons提供了Object方法来编译生成.o(windows下为.obj)文件。
【SConstruct】文件如下:
import os
Object('ext/extScons.c')
Library('ext/extScons.o')
Object('helloScons.c')
Program(['helloScons.o'], LIBS=['extScons'], LIBPATH='./ext')
Object方法用来编译生成.o文件,Library和Program则用来链接.o生成静态链接库和可执行文件。
还可以再改善下如上构建代码:
import os
ext = Object('ext/extScons.c')
Library(ext)
main = Object('helloScons.c')
Program(main, LIBS=['extScons'], LIBPATH='./ext')
Object会返回编译产生的.o文件列表,可以直接把这个返回值传给Library和Program方法。在需要编译许多代码文件时,这点还是很有用的。

6. 如果需要在不同操作系统下编译链接不同的代码文件呢?scons可以很简单就实现。
我们再创建一个文件【helloSconsForWin.c】,作为windows环境下使用的主程序:
#include <stdio.h>
#include <stdlib.h>
#include "ext/extScons.h"
int main(int argc, char* argv[])
{
        printf("Hello, SCons in Windows %d!\n", add(1, 2));
        return 0;
}

同时,假设我们又希望在Linux下以动态链接的形式,而在windows下以静态链接的形式使用extScons【SConstruct】文件如下:
import os
if os.name == "posix":
     SharedLibrary('ext/extScons.c')
     Program(['helloScons.c'], LIBS=['extScons'], LIBPATH='./ext')
elif os.name == "nt":
     StaticLibrary('ext/extScons.c')
     Program(['helloSconsForWin.c'], LIBS=['extScons'], LIBPATH='./ext')
纯粹的python语法,使用了os模块,如果你熟悉python的话,编译和链接的逻辑你可以随心所欲的写。其实这一点是最吸引我的,因为我算是个python的fan,呵呵。

本文其实只是一些关于scons的最基本的说明,在这里我也只是抛砖引玉,scons还有很多很好的特性,大家可以参考官方的文档,如果有什么新体会新发现,也别忘了留言分享下吧。

转载于:https://www.cnblogs.com/secbook/archive/2012/08/01/2655097.html

网站文章

  • java单例_最好懂的Java单例模式,没有之一

    单例(Singleton)模式 也叫单态模式,是java的23种设计模式之一。网上很多介绍,我就言简意赅点了。一、单例模式的应用场景1.整个程序的运行中只允许有一个类的实例;2.需要频繁实例化然后销毁...

    2024-02-29 11:39:19
  • ssm 开发maven项目jar包不能用的问题

    这里写自定义目录标题新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPan...

    2024-02-29 11:38:49
  • 原来编码就是这么简单

    原来编码就是这么简单

    日期:2019年12月26日作者:Commas注释:对于编码,我知道什么?对于编码,我不知道什么?文章目录一、什么是编码?二、为什么是编码?三、怎么样是编码?一、什么是编码?编码在我们生活中无处不在,暂且我们先不讨论计算机编码,举几个生活中的例子:身份证号码:前两位代表省、自治区、直辖市,比如说“44…”,代表广东省,而“43…”,代表湖南省;车牌号:第一个汉字代表车户口所...

    2024-02-29 11:38:42
  • DOM破坏绕过XSSfilter例题

    DOM破坏绕过XSSfilter例题

    DOM破坏(DOM Clobbering)指的是对网页上的DOM结构进行不当的修改,导致页面行为异常、性能问题、安全风险或其他不良影响的情况。就是⼀种将 HTML 代码注⼊⻚⾯中以操纵 DOM 并最终...

    2024-02-29 11:38:34
  • 如何判断链表有环的三种解法(Python)

    一、问题描述 二、解题思路 三、最优解的代码实现 一、问题描述 有一个单向链表,链表中有可能出现环,如何判断链表是否有环? 二、解题思路 方法一: 首先从头节点开始,依次遍历单链表中的每一个节点。每遍...

    2024-02-29 11:38:04
  • 全国计算机考试实验室建设,实验室介绍

    1.2001年计算中心验室被辽宁省教委授予“合格实验室”称号2.2009年东北大学秦皇岛分校考点被教育部评为“全国计算机等级考试优秀点。3.2010年获辽宁省教学厅“2009-2010年度辽宁省普通高...

    2024-02-29 11:37:58
  • C#-2 C#程序

    C#-2 C#程序

    一 C#程序是一组类型声明C#程序或DLL的源代码是一组一种或多种类型声明。对于可执行程序,类型声明中必须有一个包含Main方法的类。命名空间是一种把相关的类型声明分组并命名的方法。是类在程序集中逻辑...

    2024-02-29 11:37:44
  • 用java语言求前50个素数_显示前50个素数

    package my.group.mapreduce1;import java.util.Scanner;public class Djsi {public static void main(String[] args){int NUMBER_OF_PRIMES = 50; //设置输出素数的个数int count = 0; //计数int number = 2; //从2开始查找Syst...

    2024-02-29 11:37:14
  • 记录网页制作中遇到的问题及解决办法(长期更新)

    1.html在浏览器打开后出现"白边"原因:浏览器默认边距值不是0解决:在<head></head>内加入以下内容:<style type="text/css">*{margin:0;padding:0;}</style>

    2024-02-29 11:37:08
  • 【Python】实现csv文件转json文件

    import json import pandas as pd # 读取CSV文件 csvData = pd.read_csv(r&#39;testData.csv&#39;, header = 0)...

    2024-02-29 11:37:02