实例解析 SCons 的使用 转

实例解析 SCons 的使用 ( 2007-6-1 17:31 )

摘要: 本文主要是通过示例来介绍一种构建程序的新脚本. 它能完成编译和链接的工作. 而且这种脚本的书写更类似于普通的编程语言. 较之Makefile的书写要来的简单.

关键词: Scons, SConstruct, SConscriptt, Makefile

以下是欲构建程序的目录结构:

Scons

| ------ bin

| ------ include

/ ------ lovers

           | ----- include

           | ----- mm1

           / ----- mm2

下面是各个目录所在的程序源文件和 Scons相关脚本.

Scons: SConstruct,  goodbye.c,  hello.c,  hello_1.c,  list_combine.c,  test.h

include: hello.h

bin: nothing

lovers: SConscriptt

mm1: banana.c,  SConscriptt

mm2: apple.c,  SConscriptt

Scons dic:


SConstruct:

# This file is to describe how to use Scons.
# I hope you can get something here.
#
# created by skybird

# Import python modules
import os
import os.path

# Create a Construct environment.
env = Environment(ENV = os.environ)

# Process keyword arguments
debug = ARGUMENTS.get('debug', 0)
env['arch'] = ARGUMENTS.get('arch', 'i386')

if int(debug):
 env.Append(CCFLAGS = '-g')

# Show values of all of construction variables
dict = env.Dictionary()
keys = dict.keys()
keys.sort()
# this can't work rightly
#for key in keys:
# print "construction variable = 's%', value = '%s'" % (key, dict[key])
print "calling Program('hello.c')..."
#Program('Hello_Zhao','hello.c')
#print "calling Program('goodbye.c')..."
#Program('Goodbye_Zhao','goodbye.c')
# Here we combine the two source files

#--------------------------------------------------------------
#Common_Sources = ['list_combine.c']
#Program('Test_Icons', ['hello.c','goodbye.c'] + Common_Sources)

#--------------------------------------------------------------
# Here use another mothod to list multy files
#list = Split('hello.c goodbye.c list_combine.c')
target_name = 'Test_Icons'
common_files = Split('''
                     goodbye.c
                     list_combine.c
                     '''
                     )
#Program('Test_Icons', common_files)
#using keyword
#Program(target='Test_Icons', source=common_files + ['hello.c'])
#Program('hello_1.c')
#--------------------------------------------------------------
lib = env.Library('test_icon',common_files)

#To prevent SCons from removing the target before it is built.
env.Precious(lib)
source = Split('''
               hello.c
               '''
              )
program_list = env.Program(target=target_name, source=source, CPPPATH= ['./include'],LIBS=['test_icon'], LIBPATH='.')
env.Install('./bin', program_list)
env.Alias('install', './bin')

subdirs = [
    './lovers',
    ]
   
for i in subdirs:
    m = env.SConscriptt(
        '%s/SConscriptt' % (i),)
        #build_dir = '%s/%s' % (i, env['arch']),
        #src = i,
        #)
   
Depends(target_name, 'test.h')

# when stdio.h change,don't rebuild target
Ignore(target_name, '/usr/include/stdio.h')

#SourceSignatures('MD5')
#TargetSignatures('build')

TargetSignatures('content')
SourceSignatures('timestamp')

program_name = str(program_list[0])
#if not os.path.exists(program_name)
# print program_name, "does not exist!"
print "The program file is:"
#--------------------------------------------------------------

goodbye.c:

#include

void test_scons_goodbye(){
  printf("Good Bye/n");
}

hello.c:

#include
#include "hello.h"

extern void test_scons_goodbye();
extern void test_scons_list_combine();

int main(){
  printf("Hello %s!/n", string);
  test_scons_goodbye();
  test_scons_list_combine();
}

hello_1.c:

#include

int main(){
  printf("Hello_2!/n");
  return 0;
}

list_combine.c:

#include

void test_scons_list_combine(){
  printf("list combine.../n");
}

test.h:

#include


Scons/include/hello.h:

#define string "world"


lovers/SConscriptt:

SConscriptt(['mm1/SConscriptt',
            'mm2/SConscriptt',])


mm1/SConscriptt:

env = Environment()
env.Program('banana',['banana.c'])

mm1/banana.c:

#include
#include

int main(int argc, char* argv[]){
 printf("My name is banana./n");
 return(0);
}


mm2/SConscriptt:

env = Environment()
env.Program('apple', ['apple.c'])

mm2/apple.c:

#include
#include

int main(int argc, char* argv[]){
 printf("My name is apple./n");
 return(0);
}

 

 

实例解析 SCons 的使用 [续] ( 2007-6-4 16:19 )

在上一篇文章中(基本上是代码文章了^^) 我们通过一个实例介绍了Scons的一些功能, 并切身体会到了它的一些功能, 如果你曾经书写过 Makefile, 你就能立马感觉出二者的区别来. (只是应用表面的). 那么在本文中呢, 还是通过上个程序来更加充分的对SCons加以认识.

在上个例子中,我们实现了以下要素:

1.程序是多层次组织的, 但是文件夹的层次不是很清晰.

2.利用了SConscriptt脚本, 但是在个脚本中重复创建结构环境.

3. build是在脚本所在目录进行,没有提到同一的文件夹下.

在本例中,我们要对上面所述不足加以修改,并同时增加下列功能:

1.增加了python语言的更多使用.

2. 增加了安装的过程.

3. 增加了配置文件的生成过程(但是存在一点问题).

 那么我们先说明下新程序的组织结构:

Scons                            : SConstruct

/ ------lovers                   : SConscriptt

          | ----- include       : hello.h, test.h

          |------ mm1          : banana.c, SConscriptt

          | ----- mm2          : apple.c, SConscriptt

          / ----- src              : goodbye.c, hello_1.c, hello.c, list_combine.c

以上是手工创建的文件, 在执行 ./scons 命令之后呢, 会在Scons目录下生成个 Export的目录来存放生成的执行文件, 库 和配置文件. 在lovers下还会生成 i386的 build目录. 这些生成的文件在当你执行 scons -c 时并不会清除掉, 这个命令只是清除生成的文件而已,并不清除目录.

现在我们把以上各个文件的内容说明如下:(按从上而下, 自左而右)

SConstruct:

# This file is to describe how to use Scons.
# I hope you can get something here.
#
# created by skybird

# Import python modules
import os
import os.path

# Create a Construct environment.
# env = Environment(ENV = os.environ)
# Can do it so
# SConscriptt(['lovers/mm1/SConscriptt',
# 'lovers/mm1/SConscriptt'], exports='env')

# Process keyword arguments
debug = ARGUMENTS.get('debug', 0)

include = '#lovers/include'
lib = '#export/$arch/lib'
bin = '#export/%s/bin' % ('$arch')
pcdir = '%s/pkgconfig' % (lib)
# You can do above like this, but the precondithion is that env's been defined.
# bin = '#export/%s/bin' % (env[arch])

env = Environment(BINDIR = bin,
                  INCDIR = include,
                  LIBDIR = lib,
                  CPPPATH = [include],
                  LIBPATH = [lib],
                  LIBS = 'test_icon')

env['arch'] = ARGUMENTS.get('arch', 'i386')
env['pcdir'] = pcdir
# Set the system environment variable.
env['ENV']['PKG_CONFIG_PATH'] = env['pcdir']
env['BUILDERS']['MakeDirectory'] = Builder(action=Mkdir('$TARGET'), target_factory=Dir)

Export('debug')
Export('env')

if int(debug):
 env.Append(CCFLAGS = '-g')

# Show values of all of construction variables
dict = env.Dictionary()
keys = dict.keys()
keys.sort()
# this can't work rightly
#for key in keys:
# print "construction variable = 's%', value = '%s'" % (key, dict[key])
print "calling Program('hello.c')..."

#--------------------------------------------------------------
# Here use another mothod to list multy files
#list = Split('hello.c goodbye.c list_combine.c')
#target_name = 'Test_Icons'
#common_files = Split('''
#                     goodbye.c
#                     list_combine.c
#                     '''
#                     )
#Program('Test_Icons', common_files)
#using keyword
#Program(target='Test_Icons', source=common_files + ['hello.c'])
#Program('hello_1.c')
#--------------------------------------------------------------
#lib = env.Library('test_icon',common_files)

#To prevent SCons from removing the target before it is built.
#env.Precious(lib)
#source = Split('''
#               hello.c
#               '''
#              )
#program_list = env.Program(target=target_name, source=source, CPPPATH= ['./include'],LIBS=['test_icon'], LIBPATH='.')
#env.Install('./bin', program_list)
#env.Alias('install', './bin')

subdirs = [
    './lovers',
    ]
bins = []   
for i in subdirs:
    m = env.SConscriptt(
        '%s/SConscriptt' % (i),
        build_dir = '%s/%s' % (i, env['arch']),
        #src = i,
        duplicate = 0
        )
    bins.append(m)
   
# This get varible from the sub SConscriptt, but it can't work rightly.   
# env.Install('./bin', bins)
# env.Alias('install', './bin')   
   
# when stdio.h change,don't rebuild target
#Ignore(target_name, '/usr/include/stdio.h')

#SourceSignatures('MD5')
#TargetSignatures('build')

TargetSignatures('content')
SourceSignatures('timestamp')

#program_name = str(program_list[0])
#if not os.path.exists(program_name)
# print program_name, "does not exist!"
print "The program file is:"
#--------------------------------------------------------------


lovers                   : SConscriptt

# This file is to describe how to use Scons.
# I hope you can get something here.
#
# created by skybird

import os
Import('env','debug')
env = env.Copy(DEBUG = debug)

env.SConsignFile( '%s/.sconsign' % (os.getcwd()))
lovers_env = env
# Compile the static library.
common_files = Split('''
                     src/goodbye.c
                     src/list_combine.c
                     '''
                     )
lib = env.Library('test_icon',common_files)
env.Precious(lib)

# Compile the source code.
target_name = 'Test_Icons'
source = Split('''
               src/hello.c
               '''
              )
Depends(target_name, 'include/test.h')
program_list = env.Program(target=target_name, source=source)

# Install the program.
lib_install = env.Install('$LIBPATH', lib)
main_install = env.Install('$BINDIR', program_list)
env.Alias('install', '$LIBPATH')
env.Alias('install', '$BINDIR')
env.Default(
    lib_install,
    main_install
    )

# Build the sub SConscriptt.
subdirs = ['mm1/SConscriptt',
           'mm2/SConscriptt']
for sub_sconscipt in subdirs:
    SConscriptt(sub_sconscipt, exports = 'lovers_env')


hello.h:

#define string "world"


test.h: 应包含的文件:

#include


banana.c:

#include
#include

int main(int argc, char* argv[]){
 printf("My name is banana./n");
 return(0);
}


mm1    :SConscriptt

# This file is to describe how to use Scons.
# I hope you can get something here.
#
# created by skybird

# env = Environment()
# Here export the Construct environment from top-level SConstruct.
import os
# Athough can import env, but suppose not to do so.
Import('lovers_env','debug')

lovers_env.SConsignFile( '%s/.sconsign' % (os.getcwd()))
lovers_env = lovers_env.Copy(DEBUG = debug)

class banana:
    target = 'girl-banana'
    source = ['banana.c']
    version_major = 0
    version_minor = 1
    version_revision = 0
    version = '%d.%d.%d' % (version_major,
                            version_minor,
                            version_revision,
                            )
    cppdefines  = []
    cpppath = []
    cppflags = ''
   
    # C & C++ compiler general options
    ccflags = ''
    cxxflags = ''
    pkgs = []
    # Linker
    libs = []
    libpath = []
    linkflags = ''
   
    result = []
   
    pc_str = """
prefix=%s
exec_prefix=%s
libdir=%s
includedir=%s

Name: girl-banana
Descripttion: girl-banana
Version: %s

Libs: -L%s -lgirl-banana
Cflags: -I%s
""" % (
     lovers_env['BINDIR'],
     lovers_env['BINDIR'],
     lovers_env['LIBDIR'],
     lovers_env['INCDIR'],
     version,
     lovers_env['LIBDIR'],
     lovers_env['INCDIR'],
      )

# Build process                           
#bin_mm1 = env.Program('banana',['banana.c'])
banana.result = lovers_env.Program(
    banana.target,
    banana.source,
    CCFLAGS    = banana.ccflags,
    CPPDEFINES = banana.cppdefines,
    CPPFLAGS   = banana.cppflags,
    CPPPATH    = banana.cpppath,
    CXXFLAGS   = banana.cxxflags,
    LINKFLAGS  = banana.linkflags,
    LIBPATH    = banana.libpath,
    LIBS       = banana.libs,   
    )

# Write some pc files.
def write_pc(target, source, env=lovers_env):
    fd = open(str(target[0]), 'w')
    fd.write(banana.pc_str)
    fd.close()
    return 0
  
pc_file_gen = lovers_env.Command(
    'banana.pc',
    '',
    Action(write_pc)
    )

# Set install path
pc_install_path = ['%s' % (lovers_env['pcdir']),]
exe_install_path = ['%s' % (lovers_env['BINDIR'])]
      
#Return('bin')
# Install pc and exe to the top level bin directory.
#env.Install('$BINDIR', bin_mm1)
#env.Alias('install', '$BINDIR')
banana_pc_install = lovers_env.Install(
    pc_install_path, [pc_file_gen]
    )
banana_exe_install = lovers_env.Install(
    exe_install_path, [banana.result]
    )
lovers_env.Alias ('install', pc_install_path)
lovers_env.Alias ('install', exe_install_path)

lovers_env.Default (
    banana_pc_install,
    banana_exe_install,
    )  


apple.c:

#include
#include

int main(int argc, char* argv[]){
 printf("My name is apple./n");
 return(0);
}


mm2    : SConscriptt

# This file is to describe how to use Scons.
# I hope you can get something here.
#
# created by skybird

# env = Environment()
# Here export the Construct environment from top-level SConstruct.
import os
Import('lovers_env', 'debug')

lovers_env.SConsignFile( '%s/.sconsign' % (os.getcwd()))
lovers_env = lovers_env.Copy(DEBUG = debug)
bin_mm2 = lovers_env.Program('apple', ['apple.c'])

#Return('bin')
# Install the exe to the top level bin directory.
mm2_install = lovers_env.Install('$BINDIR', bin_mm2)
lovers_env.Alias('install', '$BINDIR')
lovers_env.Default(mm2_install)


goodbye.c:

#include

void test_scons_goodbye(){
  printf("Good Bye/n");
}

hello_1.c:

#include

int main(){
  printf("Hello_2!/n");
  return 0;
}

 hello.c:

should include headers: sys/types.h, unistd.h, stdio.h, stdlib.h, string.h, fcntl.h, errno.h, assert.h,
#include "hello.h"

extern void test_scons_goodbye();
extern void test_scons_list_combine();

int main(){
  int fd;
  int rval;

  printf("Hello %s!/n", string);
  test_scons_goodbye();
  test_scons_list_combine();
 
  //test strerror
  fd = open ("inputfile.txt", O_RDONLY);

#if 0
  if (fd == -1){
 /* The open failed. Print an error message and exit. */
   fprintf (stderr, "error opening file: %s/n", strerror (errno));
   exit (1);
  }
#endif

   /*
    *  Descriptte how to take action according to errno.
    */
   rval = chown ("usr/zhao", -1, -1);
   if (rval != 0){
    /* Save errno because it's clobbered by the next system call */
    int error_code = errno;
    /* The operation didn't succeed; chown should return -1 on error. */
    assert (rval == -1);
    /* Check the value of errno, and take appropriate action. */
    switch (error_code){
  case EPERM:         /* Permission denied. */
  case EROFS:         /* PATH is on a read-only file system. */
  case ENAMETOOLONG:  /* PATH is too long. */
  case ENOENT:        /* PATH does not exit. */ 
  case ENOTDIR:       /* A component fo PATH is not a directory. */
  case EACCES:        /* A component of PATH is not accessible. */
  /* Something's wrong with the file. Print an error message. */
   fprintf (stderr, "error changing ownership of usr/zhao %d: %s/n",
    error_code, strerror (error_code));
  /* Don't end the program; perhaps give the user a chance to choose another file... */
   break;
  case EFAULT:
   /* PATH contains an invalid memory address. This is probably a bug. */
   abort ();
  case ENOMEM:
   /* Ran out of kernel memory. */
   fprintf (stderr, "%s/n", strerror (error_code));
   exit (1);

  default:
   /* Some other, unexpected, error code. We've tried to handle all
   possible error codes; if we've missed one, that's a bug! */
   abort ();
    };  
  }
   printf ("Here:[%s, %d]/n", __FILE__, __LINE__);
   return (0);
}

 list_combine.c:

#include

void test_scons_list_combine(){
  printf("list combine.../n");
}

shit, i can't type in chinese!!

OK, let's in english.

This demo is tested in Linux platform. If you run it sucessfully, you will find the banana.pc produced is not correct. And this bug will be fixed laterly. If you know why, please tell me. Thanks. 

[125] 阅读 |  [1] 评论 |  推荐  |  引用  |  有奖投诉  |  计算机程序设计 | 分享

<script type=text/javascript> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript> </script>

评论

guest 游客37

你好,请问你用过scons 吗?

2008-8-1 16:53 | 主页  |  邮件  | 

添加评论

昵 称
电 邮 (可选)
主 页 (可选)
评 论

验证码  

<script language=javascript type=text/javascript> function valCommentForm(form) { if(trim(form.content.value).length==0) { alert('请输入评论'); text_focus(form.content); return false; } if(form.checkCode.value == "") { alert('请输入图中4位数字验证码!'); text_focus(form.checkCode); return false; } document.getElementById("idpub").disabled=true; showTipInfo("正在发表评论......"); return true; } </script>

写新文章

基本信息

skybird99054

skybird99054 星级用户 未绑定手机

姓名:zyongliang
用户ID:19032712
城市: 江苏 南京
性别:
积分:1772
级别:5级
头衔:挂名弟子

关注我 发消息 打招呼 加为好友 屏蔽此人

我要留言

您还没有登录,现在不能留言,请先登录!

用户名 密码 自动登录 - 快速注册 - 找回密码

<script type=text/javascript> function textCheck(){ if(0==0) { alert('您不能给该用户留言!'); return false; } else { if(document.leavewordForm.leave_word.value == ''){ alert('留言内容不能为空!'); leavewordForm.leave_word.focus(); return false; } if(document.leavewordForm.checkCode.value == ''){ alert('请输入图中4位数字验证码!'); leavewordForm.checkCode.focus(); return false; } return true; } } function bytes(str) { if(typeof(str)!='string'){ str = str.value; } var len = 0; for(var i = 0; i < str.length; i++){ if(str.charCodeAt(i) > 127){ len++; } len++; } return len; } function textLimitCheck(thisArea,maxLength){ if(bytes(thisArea.value) > maxLength){ alert(maxLength + '个字限制.//r超出的将自动去除.'); thisArea.value=thisArea.value.substring(0,maxLength); thisArea.focus(); return false; } return true; } </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值