• scons笔记


    一、SConstruct File {{{1
        1. Sconstruct 文件 是scons用来控制编译的文件
        2. Sconstruct 文件 是一个python脚本
        3. SConstruct 文件 是一个类似于makefile一样的东西, 告诉 scons做什么,而不是严格的规定soncs做这件事的步骤

    二、scons选项 {{{1
        -c      Cleaning up After a Build
        -Q      Making the scons output less verbose

    三、SConstruct 脚本的编写基础 {{{1
        
    1. builder method {{{2
        Program      : generate executable file
        Object       : generate Object file
        Java         : 编译java程序, User Guide 2.3, Chapter 25
        Library      : 静态库,   也可以使用 StaticLibrary替代
        SharedLibrary: 动态库

    2. 指定目标名 {{{2
        Program('hello.c')                # 生成 hello.exe
        Program('new_hello', 'hello.c')   # 生成 new_hello.exe

    3. 编译多个文件 {{{2
        Program(['prog.c', 'file1.c', 'file2.c'])             # 生成 prog.exe
        Program('program', ['prog.c', 'file1.c', 'file2.c'])  # 生成program.exe
        Program('program', ['prog.c', 'file1.obj', 'file2.obj'])  # 可以在文件列表中指定.obj文件

        3.1 使用Glob 编译所有匹配的文件
            Program('program', Glob('*.c') )

            Glob原型为:Glob(self, pattern, ondisk=True, source=False, strings=False)
                其中pattern 支持unix系统下的文件名匹配: *(任意多个字符), ?(单个字符) 和 [](括号中的任一字符)
        3.2 使用Split
            Program('program', Split('main.c file1.c file2.c'))

            Split以空白字符为分隔符,将字符串分割,因此,你也可以这样写:
            Program('program', Split("""
                                        main.c
                                        file1.c
                                        file2.c
                                     """) )
        3.3 使用关键字参数
            Program(target = 'program', source = 'hello.c')
            

    4. 指定编译选项 {{{2
        $CPPFLAGS  指定编译选项
        $LINKFLAGS 指定链接选项, 如 /DEBUG
        $CPPDEFINES指定预编译器

        $LIBS      指定所需要链接的库文件
        $LIBPATH   指定库文件(.lib)的搜索目录
        $CPPPATH   指定[.h, .c, .cpp]等文件搜索路径

        例如:
            Library('foo', Split('f1.c f2.c f3.c') )
            Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')

            注:LIBS和LIBPATH若为一个可以使用字符串,若为多个则使用列表

    四、使用Environments {{{1
        一个environment是一个影响程序执行的值得集合。
        (1) 外部环境 External Environment
            外部环境是运行Scons时 用户的环境变量。它们可以通过os.environ获取

        (2) 构建环境 Construction Environment
            它包含一些变量,这些变量会影响Scons构建目标的行为
        (3) 执行环境 Execution Environment
            执行环境用于Scons执行外部命令(external command), 以构建一个或多个目标。
            注意:它与外部环境不相同

    1. Construction Environment {{{2
        > 创建 construction Environment
            env = Environment()
            一个Environment是一个 (name,value)的集合,可以这样查看它的内容:
                for item in env.Dictionary():
                    print '(%s:%s)' % (item, env[item])

        > 查看变量
            env['CC'] #查看 CC ,即C语言编译器
            env.subst('$CC') # 功能同上
                它的优势在于,它会将出现在结果中的环境变量转换成最终的值
                使用AllowSubstException()函数,使得当subst中的变量不存在时报告错误,
                    AllowSubstException()
                    env.subst('$missing') # 出现异常,NameError
        > 修改环境变量
            拷贝一个环境变量
                使用env.Clone #详见user guide 7.2.7
            替换一个已经存在的环境变量
                env.Replace
            为一个没有被定义的变量设置默认值
                env.SetDefault
            为一个已存在的环境变量增加一个值
                env.Append, 例如:
                env.Append(CCFLAGS = '-option -O3 -O1')
                env.Append(CCFLAGS = ['-option', 'O3'])
            为一个环境变量增加一个唯一的值
                env.AppendUnique
            在最前边添加一个值
                env.Prepend
            在最前边添加一个唯一的值
                env.PrependUnique
            合并环境变量
                env.MergeFlags, 例如:
                flags = {'CCFLAGS':'-option -O3 -O1'}
                env.MergeFlags(flags)
                flags = {'CPPPATH' : ['/user/opt/include', 'user/local/include']}
                env.MergeFlags(flags)

                #若参数不是Dictionary, 内部调用ParseFlags将其转化为Dictionary
                env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include')

        > 一些实用的变量
            判断是否是windows: 
                env['PLATFORM'] == 'win32'

    2. Execution Environment {{{2
        当scons构建一个目标文件时,它所使用的外部环境和执行scons时的环境变量是不同的。
        scons使用$ENV 构建变量 中 存储的目录 作为它执行命令的外部环境变量

        > PATH 
            POSIX 系统中默认的PATH是 /user/local/bin:/user/bin
            Window系统中默认的PATH是 command interpreter在注册表中的值

            1. 在构建环境中显示初始化PATH
                path = ['/user/local/bin', '/bin', '/user/bin']
                env = Environment(ENV = {'PATH':path})
            上面这种方式,只设置了ENV,如果你想保留其他的变量,可以这么做:
                env['ENV']['PATH'] = ['/user/local/bin', '/bin', '/user/bin']
            2. 从 外部环境 初始化 PATH
                import os
                env = Environment(ENV = {'path' : os.environ['PATH']})

                你也可以将完整的外部变量传递给执行环境变量:
                import os
                env = Environment(ENV = os.environ)
                这样做的缺点是:如果环境变量目录中,有多个目录包含编译器如gcc,那么,
                                scons将执行第一个被找到的gcc

            3. 使用env.PrependENVPath 和 env.AppendENVPath
                例如:将'/user/local/bin' 插入 $PATH中第一个位置
                    env.PrependENVPath('PATH', '/user/local/bin')
                例如:将'/user/local/bin' 插入 $LIB中最后一个位置
                    env.AppendENVPath('lib', '/user/local/lib')

    五、Controlling Build Output {{{1
    1. 使用Help 函数 来说明SConstruct脚本
        例如:
        Help('this is a debug version')

        在控制台上使用 scons -h 命令查看此帮助信息

        你可以在脚本中多次使用Help,帮助信息会被连接到一起

    六、scons 命令行参数 {{{1
        用户可以为scons指定三种类型的参数:
        > Options    : 以 一个或两个(-) 开头 , 详细参考 User Guide 10.1
        > Variables  : 形式为:variable=value, 详细参考            10.2
        > Target     : 如果不是一个 Option 或 Variable ,那么就是一个Target , 详细参考 User Guide 10.3

    1. 读取命令行的Variable参数
        命令行:scons debug=1
        SConstruct脚本如下:
        debug = ARGUMENTS.get('debug', 0)
        if int(debug) :
            pass # do something

    2. Command-Line Targets
        scons提供 COMMAND_LINE_TARGETS 供用户访问命令行参数中的 Targets列表,例如:
        if 'bar' in COMMAND_LINE_TARGETS:
            print "Don't forget to copy 'bar' to the archivel"
        Default(Program('foo.c'))
        Program('bar.c')

        > 使用 Default函数 定义 默认目标
            当你没有在命令行参数中指定目标时,scons会编译每一个目标
            例子:
            env = Environment()
            hello = env.Program('hello.c')
            env.Program('goodbye.c')
            Default(hello)      #如果没有在命令行指定Target,则会编译hello

            使用DEFAULT_TARGETS获取 默认目标, 例如:
                prog1 = Program('prog1.c')
                Default(prog1)
                print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)

            使用 BUILD_TARGETS 获取要编译的目标

    七、控制目标文件的路径 {{{1
    1. BINDIR {{{2
      >使用Install:如,
          test = env.Program('test.cpp')
          env.Install('bin', 'test.exe') #表示要将test.exe 放到bin目录下
          或
          env.Install('bin', test)

      >在指定目标名的时候指定其目录,如:
          env.Program('bin/test', 'test.cpp')

      >将目标放到其他目录下,并修改名字
          test = env.Program('test.cpp')
          env.InstallAs('bin/testapp.exe', 'test.exe') #表示将test.exe 拷贝到 bin/testapp.exe
          或 这样写
          env.InstallAs('bin/testapp', test)
          
          当 需要对多个目标做此操作时,可以这样做:
               env = Environment()
               hello = env.Program('hello.c')
               goodbye = env.Program('goodbye.c')
               env.InstallAs(['/usr/bin/hello-new', '/usr/bin/goodbye-new'], [hello, goodbye]) #多个目标
               env.Alias('install', '/usr/bin')
          

    2. obj文件路径 {{{2
        使用VariantDir函数指定
    3. 一份代码构建多个版本的Target {{{2
        通常会有这样的需求,一份源码,既要构建它的debug版本,又要构建它的release版本,这种情况下,

        >我们需要为不同版本指定不能的obj名字,否则就会产生冲突,导致scons不能工作。简单的示例如下:
            opt = Environment(CCFLAGS = '-O2')
             dbg = Environment(CCFLAGS = '-g')

             o = opt.Object('foo-opt', 'foo.c')  // 生成 foo-opt.o
             opt.Program(o)

             d = dbg.Object('foo-dbg', 'foo.c')  // 生成 foo-dbg.o
             dbg.Program(d)

         >或者将不同版本的obj放到不同的路径下:
             o = opt.Object('opt/foo', 'foo.c')  // 生成 foo-opt.o
             opt.Program(o)

             d = dbg.Object('dbg/foo', 'foo.c')  // 生成 foo-dbg.o
             dbg.Program(d)
        
  • 相关阅读:
    关于IP4上WIFI设置静态IP的一点经验
    迷你MVVM框架 avalonjs 1.1发布
    r.js合并实践
    IE6的checkbox, radio是通过defaultChecked决定是否选中
    2013年最后的收成:avalon1.0正式发布
    还要多少年, 前端开发才能像后端那样轻松
    JavaScript Promise:去而复返
    JavaScript 18岁生日快乐
    web界面上的字体兼容方案
    键盘钩子原理----开发按键发音程序
  • 原文地址:https://www.cnblogs.com/hdtianfu/p/2708857.html
Copyright © 2020-2023  润新知