• SCons的使用


    一、概述

        scons是一个Python写的自动化构建工具,和GNU make相比优点明显:
        1、 移植性:python能运行的地方,就能运行scons
        2、 扩展性:理论上scons只是提供了python的类,scons使用者可以在这个类的基础上做所有python能做的事情。比如想把一个已经使用 了Makefile大型工程切换到scons,就可以保留原来的Makefile,并用python解析Makefile中的编译选项、源/目标文件等, 作为参数传递给scons,完成编译。
        3、 智能:Scons继承了autoconf/automake的功能,自动解析系统的include路径、typedef等;“以全局的观点来看所有的依赖关系”

    二、scons文件

        scons中可能出现的文件:
            SConstruct,Sconstruct,sconstruct,SConscript

      

        scons将在当前目录以下次序 SConstruct,Sconstruct,sconstruct 来搜索配置文件,从读取的第一个文件中读取相关配置。
        在配置文件SConstruct中可以使用函数SConscript()函数来定附属的配置文件。按惯例,这些附属配置文件被命名为”SConscript”,当然也可以使用任意其它名字。

    三、scons的命令行参数
        scons: 执行SConstruct中脚本
        scons -c   clean
        scons -Q  只显示编译信息,去除多余的打印信息
        scons -Q   --implicit-cache hello 保存依赖关系
                       --implicit-deps-changed   强制更新依赖关系
                       --implicit-deps-unchanged  强制使用原先的依赖关系,即使已经改变

    四、SConstruct提供的方法

    1、Program:生成可执行文件

        Program('hello.c')  编译hello.c可执行文件,根据系统自动生成(hello.exe on Windows; hello on POSIX)
        Program('hello','hello.c') 指定Output文件名(hello.exe on Windows; hello on POSIX)
        Program(['hello.c', 'file1.c', 'file2.c']) 编译多个文件,Output文件名以第一个文件命名
        Program(source = "hello.c",target = "hello")
        Program(target = "hello" , source = "hello.c")
        Program('hello', Split('hello.c file1.c file2.c')) 编译多个文件

        Program(Glob("*.c"))
        src = ["hello.c","foo.c"];Program(src)
     
    2、Object:生成目标文件

        Object('hello.c') 编译hello.c目标文件,根据系统自动生成(hello.obj on Windows; hello.o on POSIX)
     
    3、Library:生成静态/动态库文件

        Library('foo', ['f1.c', 'f2.c', 'f3.c']) 编译library
        SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c']) 编译 shared library
        StaticLibrary('bar', ['f4.c', 'f5.c', 'f6.c']) 编译 static library

        库的使用:

        Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') 连接库,不需加后缀或是前缀

    4、SourceSignatures:判断源文件是否修改
        SourceSignatures('MD5')     根据内容是否改变,默认方式
        SourceSignatures('timestamp') 根据修改时间

    5、TargetSignatures:判断目标文件是否改变
        TargetSignatures('build')   根据编译结果
        TargetSignatures('content')  根据文件内容,如果只是加了句注释,将不会被重新编译
     
    6、Ignore:忽略依赖关系

        Ignore(hello, 'hello.h')  忽略某个依赖关系

    7、Depends:明确依赖关系

        Depends(hello, 'other_file') 明确依赖关系 

    8、SConscript:scons的配置文件。

        源文件的目录结构如下:
        src:
        |    SConstruct
        |    test.cpp
        |    mA(目录):
             |     SConscript
             |     func.cpp
        其中test.cpp为主文件,中调用func.cpp中定义的函数
     
        SConstruct内容如下:

            <textarea cols="57" rows="1" name="code" class="cpp"> subobj = SConscript(['mA/SConscript']) obj = subobj + Object(Glob("*.cpp")) Program("test",list(obj)) </textarea>  
        SConscript内容 :
            <textarea cols="57" rows="1" name="code" class="cpp"> obj = Object(Glob("*.cpp")) Return("obj") </textarea>    
        上例中,在主目录中执行 scons就可以编译整个"工程"。SConstruct编译主目录中的test.cpp,并通过SConscript编译mA目录下的源文件,并最终生 成可执行文件;SConscript用于编译mA中的func.cpp并把生成的func.o传递给主目录的SConstruct。

     
    10.env:环境变量
         环境变量用于设置在编译过程中的各种参数,可以用下面的SConstruct打印环境变量的所有信息(实际上env就是一个python字典)
         可以使用如下的SConstruct查看环境变量的内容:
           <textarea cols="73" rows="6" name="code" class="cpp">env = Environment() dict = env.Dictionary() keys = dict.keys() keys.sort() for key in keys: print "construction variable = '%s', value = '%s'" % (key, dict[key]) </textarea>      
         环境变量的使用:
             env = Environment()   #创建默认的环境变量,默认scons会按编译器的默认选项来进行编译
             import os
             env = Environment(CC = 'gcc',CCFLAGS = '-O2') #创建并设置环境 变量
             env.Program('foo.c')

         环境变量的复制:
             env = Environment(CC = 'gcc')
             opt = env.Clone(CCFLAGS = '-O2')
             dbg = env.Clone(CCFLAGS = '-g')

         环境变量的替换:
             env = Environment(CCFLAGS = '-DDEFINE1')
             env.Replace(CCFLAGS = '-DDEFINE2')
             env.Program('foo.c') 
         环境变量的输入输出:用于统一多目录源文件的编译选项,如:
         src:
         |    SConstruct
         |    libstlport.a
         |    test.cpp
         |     include(目录):
              |    foo.h
         |    mA(目录):
              |    SConscript
              |    func.cpp
       

         test.cpp和mA/func.cpp都引用了include/foo.h,test.cpp调用了mA/func.cpp的功能函数,其中include/foo.h中定义了一个包含string类型的类。

         SConstruct如下:
           <textarea cols="72" rows="4" name="code" class="cpp">env = Environment() flags = env.ParseFlags(['-pthread -I/usr/include/stlport ',' -L .']) env.MergeFlags(class_flags) subobj = SConscript(['mA/SConscript']) obj = subobj + env.Object(Glob("*.cpp")) env.Program("test",list(obj),LIBS = ['libstlport.a']) </textarea>

        mA/SConscrip如下:
           <textarea cols="73" rows="1" name="code" class="cpp">obj = Object(Glob("*.cpp")) Return("obj") </textarea>  


          不出意外的话上边的工程编译可以通过,但是运行的时候会Aborted。因为test.cpp,mA/func.cpp都使用了包含string类型的那 个类,但是由于编译环境的不同,test.cpp认为string变量的大小是24字节, mA/func.cpp认为string变量的大小是4个字节(libstlport.a捣的鬼)。
         

         解决问题的办法就是环境变量输出,修改SConstruct和mA/SConscript如下:
        SConstruct:
           <textarea cols="72" rows="5" name="code" class="cpp">env = Environment() flags = env.ParseFlags(['-pthread -I/usr/include/stlport ',' -L .']) env.MergeFlags(class_flags) Export('env') subobj = SConscript(['mA/SConscript'],exports = 'env') obj = subobj + env.Object(Glob("*.cpp")) env.Program("test",list(obj),LIBS = ['libstlport.a']) </textarea> 
        mA/SConscript:
           <textarea cols="73" rows="2" name="code" class="cpp">Import('env') obj = env.Object(Glob("*.cpp")) Return("obj")</textarea>

    from:http://blog.csdn.net/sealyao/article/details/6402257

  • 相关阅读:
    多线程 线程队列的实现
    如何使用vagrant在虚拟机安装hadoop集群
    【leetcode】Rotate List
    麒麟(Kylin)与Ubuntu的寓意相通
    山寨APP恶意吸费隐患 门槛底致监管盲点
    2013年软件设计师之考前复习笔记:IP地址
    .gitkeep
    cmd 里面运行git提示“不是内部或外部命令,也不是可运行的程序”的解决办法...
    windows常用命令行命令
    PhpStorm terminal无法输入命令的解决方法
  • 原文地址:https://www.cnblogs.com/jiu0821/p/5642678.html
Copyright © 2020-2023  润新知