scons tips

env

查看所有的env 环境变量

for k, v in env.items():
	print(k,v)

options

profiling

  • –debug=time
    http://nitrozark.free.fr/scons/bench1/benchmark-gfw-20090702.html

API

COMMAND_LINE_TARGETS

http://www.scons.org/doc/2.3.4/HTML/scons-user.html#sect-command-line-targets

ARGUMENTS

http://www.scons.org/doc/1.1.0/HTML/scons-user/x2361.html

builder

Command

官文手册上原文:

env.Command(target, source, action, [key=val, ...])
Executes a specific action (or list of actions) to build a target file or files. This is more convenient than defining a separate Builder object for a single special-case build.
As a special case, the source_scanner keyword argument can be used to specify a Scanner object that will be used to scan the sources. (The global DirScanner object can be used if any of the sources will be directories that must be scanned on-disk for changes to files that aren't already specified in other Builder of function calls.)

Any other keyword arguments specified override any same-named existing construction variables.
 
An action can be an external command, specified as a string, or a callable Python object; see "Action Objects," below, for more complete information. Also note that a string specifying an external command may be preceded by an @ (at-sign) to suppress printing the command in question, or by a - (hyphen) to ignore the exit status of the external command.

Examples:

env.Command('foo.out', 'foo.in',
            "$FOO_BUILD < $SOURCES > $TARGET")

env.Command('bar.out', 'bar.in',
            ["rm -f $TARGET",
             "$BAR_BUILD < $SOURCES > $TARGET"],
            ENV = {'PATH' : '/usr/local/bin/'})

def rename(env, target, source):
    import os
    os.rename('.tmp', str(target[0]))

env.Command('baz.out', 'baz.in',
            ["$BAZ_BUILD < $SOURCES > .tmp",
             rename ])

Note that the Command() function will usually assume, by default, that the specified targets and/or sources are Files, if no other part of the configuration identifies what type of entry it is. If necessary, you can explicitly specify that targets or source nodes should be treated as directoriese by using the Dir() or env.Dir() functions.
Examples:

env.Command('ddd.list', Dir('ddd'), 'ls -l $SOURCE > $TARGET')

env['DISTDIR'] = 'destination/directory'
env.Command(env.Dir('$DISTDIR')), None, make_distdir)

(Also note that SCons will usually automatically create any directory necessary to hold a target file, so you normally don't need to create directories by hand.)

千万注意:
Note that the Command() function will usually assume, by default, that the specified targets and/or sources are Files
如果是目录,一定要 :
you can explicitly specify that targets or source nodes should be treated as directoriese by using the Dir()

tar 打包

  • 实现1
env.Append(BUILDERS = {'mPackage_' : Builder(suffix =  '_' + env['mode'] + env['target'] + '.tar.gz', 
                                             action='tar czf ${TARGET} -C ${__ext} . --exclude=*.pyc --exclude=*.log* --exclude=*.LOG*') })

def mPackage(self, package_name, src_list, dir_in_package = None):
    package_dir = os.path.join(env['ABS_BUILD_DIR'], 'package/')
    content_dir = package_dir + 'temp/' + package_name + '/'

    pg = self.mPackage_(target =  package_dir + package_name, source=[], __ext = content_dir )
    env.aDoNothing(package_dir + package_name, pg)
    if type(src_list) == str:
        src_list = [src_list]

    for source in src_list:
        if os.path.isdir(source):
            dis = content_dir + dir_in_package + '/' if dir_in_package is not None else content_dir 
            t = dis + source.rstrip('/').split('/')[-1]
            cmd = 'cp -pfr %s %s' % (source , dis)
            env.Depends(pg, env.Command(source = Dir(source), target = t, action = cmd))
        else:
            t = dir_in_package if dir_in_package is not None else '' 
            env.Depends(pg, env.Install(target = content_dir + t, source = source)) 
    #env.Alias('package', pg)
    return pg

env.AddMethod(mPackage)

env.mPackage(env['package'], os.path.join(env['TOP_DIR'], 'libs'))
env.mPackage(env['package'], os.path.join(env['BIN_DIR'], 'msadmin'))
env.mPackage(env['package'], os.path.join(env['BIN_DIR'], 'ms_cli'))
    
  • 实现2
def aPackage(self, target, sources, **kwargs):
    temp_dir = os.path.join(env['PACKAGE_DIR'], 'temp/')
    _tarflags = kwargs.get('TARFLAGS') # 支持tar的参数
    if not _tarflags:
        if isinstance(_tarflags, list): 
            _tarflags = ' '.join(_tarflags) 
    _tarflags = '-zc ' + _tarflags if _tarflags else '-zc'
    
    pkg = self.Command(target = os.path.join(self['PACKAGE_DIR'], target), source = None,
                       action = 'tar {0} -C {1} -f $TARGET `ls {1}`'.format(_tarflags, temp_dir)) 

    for s in sources:
    	# source 可能是str, 也可能是scons.Node, 所以用Entry().path 获取地址str 
        name = os.path.basename(Entry(s).path) 
        # scons 默认 source\target 都是文件, 这里*_factory=Entry 显式指定 s/t 可以是文件,也可以是目录 
        t = self.Command(source = s, target = temp_dir + name, 
                         action = 'cp -a ${SOURCE} ${TARGET}',
                         source_factory=Entry, target_factory = Entry) 
        self.Depends(pkg, t)
        # 在 clean pkg 的时候也清理掉安装在临时目录中的entry 
        Clean(pkg, t) 

    self.Alias('package', pkg)
    return pkg

env.AddMethod(aPackage)

# 用法 
env.aPackage(target = 'helloworld-1.0.tar.gz', 
             sources = [env['BUILD_DIR'] + '/version', '#helloworld', '#env'], 
             TARFLAGS = '--exclude=*.pyc --exclude=*.lock --exclude=*.mylock --exclude=*.log'
             )

Link flags

ORIGIN

在b_lib 的 rpath 中使用 $ORIGIN, 让其在bin可以所在位置搜索 a_lib
env.Literal(string) 的意思是 不展开特定的string

env.SharedLibrary(target = "b_lib", 
                  source = ['test_b_lib.cpp'], 
                  LIBS = ['a_lib'], 
                  RPATH = [env.Literal('\\$$ORIGIN')]
                  )

参考:https://www.technovelty.org/linux/exploring-origin.html

自定义工具路径

工程中使用第三方的scons tool, 可以不用安装到 scons的安装路径下(e.g. /usr/local/lib/scons/SCons/Tool/) ,
可以放在代码工程(site_scons)中的site_tools 这个目录下, 参考https://scons.org/doc/3.1.2/HTML/scons-man.html
示例工程如下

├── SConscript
├── SConstruct
├── build
├── libs
├── src
└── site_tools
   ├── archive.py
   └── documents.py

SConstruct 部分

env = Environment(variables=vars,
                  tools=['default', 
                        'archive', 	# non-build-in tool 
                        'documents',
                        ],
                  toolpath=['site_tools'],
                  )

依赖检查

build 要用到一些机器上的工具、库等等, 可以使用 Configure.checkXXX(), 例如

conf = Configure(env)
if not conf.CheckLib('m'):
    print 'Did not find libm.a or m.lib, exiting!'
    Exit(1)
env = conf.Finish()

ref:

  • https://scons.org/doc/3.1.2/HTML/scons-user/ch23s04.html
  • https://scons.org/doc/3.1.2/HTML/scons-user.html - 23.4. Checking for the Availability of a Library

构建扩展

https://github.com/dholth/enscons
可以构建python wheel


Ref

  • https://scons.org/doc/3.1.2/HTML/scons-man.html
  • scons-time : https://linux.die.net/man/1/scons-time
  • https://github.com/DLR-RY/scons-build-tools
  • https://github.com/SCons/scons-contrib
  • https://github.com/SCons/scons/wiki
  • https://github.com/ptomulik/scons-tool-gcccov
  • https://github.com/DLR-RY/scons-build-tools
  • https://www.jianshu.com/p/c28609d9e559
  • https://stackoverflow.com/questions/tagged/scons?tab=newest&page=5&pagesize=15
  • https://scons-cookbook.readthedocs.io/en/latest/
  • https://github.com/alberts/goscons
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值