scons编译

1. 基本使用
SConstruct文件就功能而言相当于Makefile文件,就内容而言则是Python脚本,scons读入它时,会把脚本的命令都执行一遍,但具体编译过程则有scons自己相机而定。
Program('hello.c')
Program('new_hello','hello_c')   前为目标,后为源文件
Program(['prog.c','file1.c','file2.c'])  多个源文件
Program(‘program',['prog.c','file1.c','file2.c'])   指定目标文件,多个源文件
Program('program‘,Glob('*.c'))
Program('program',Split('main.c file.c file2.c'))  多个原文件更清晰的写法
src_files=Split("""main.c
                           file1.c
                           file2.c""")
Program(target='program',source=src_files)

2. 编译多个目标文件就多次调用Program()

3.8  多个程序共享源文件
eg.1  
       Program(Split('foo.c common1.c common2.c'))
       Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
eg.2    
       common = ['common1.c', 'common2.c']
       foo_files = ['foo.c'] + common
       bar_files = ['bar1.c', 'bar2.c'] + common
       Program('foo', foo_files)
       Program('bar', bar_files)

4. 库编译和链接
4.1 库编译
    Library('foo', ['f1.c', 'f2.c', 'f3.c'])
4.1.1  你甚至可以在文件List里混用源文件和.o文件
    Library('foo', ['f1.c', 'f2.o', 'f3.c', 'f4.o'])
4.1.2  显式编译静态库
    StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
4.1.3 编译动态库
    SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
4.2 库链接
    Library('foo', ['f1.c', 'f2.c', 'f3.c'])
        Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')
    不用指明库的前缀和后缀,如lib,.a等。
4.3 找到库:$LIBPATH变量
      Program('prog.c', LIBS = 'm',
                        LIBPATH = ['/usr/lib', '/usr/local/lib'])
    Unix上     LIBPATH = '/usr/lib:/usr/local/lib'
    Windows上  LIBPATH = 'C:\\lib;D:\\lib'

5. 节点对象(nodes)
 SCons把所有知道的文件和目录表示为节点。
5.1 builder方法的返回值都是节点对象List,这一点很重要,在python中List+List还是List,下面可以看到应用。
      hello_list = Object('hello.c', CCFLAGS='-DHELLO')
      goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
      Program(hello_list + goodbye_list)
    这里如果不使用变量的话,就不能跨平台使用了,因为不同系统object扩展名是不同的

5.2 显示创建文件和目录节点
      hello_c = File('hello.c')
      Program(hello_c)
      classes = Dir('classes')
      Java(classes, 'src')
    一般,你不用显式调用他们,因为builder方法会自动处理文件名字符串并转换为节点的。
    当你不知道目标是文件还是目录时:
    xyzzy = Entry('xyzzy')

5.3 打印节点文件名
      hello_c = File('hello.c')
      Program(hello_c)

      classes = Dir('classes')
      Java(classes, 'src')

      object_list = Object('hello.c')
      program_list = Program(object_list)
      print "The object file is:", object_list[0]
      print "The program file is:", program_list[0]
5.4 把节点文件名当作字符串来使用
      imp

ort os.path
      program_list = Program('hello.c')
      program_name = str(program_list[0])
      if not os.path.exists(program_name):
          print program_name, "does not exist!"
    此例判断了文件是否存在


6. 依赖关系
6.1 
Decider函数,确定文件是否被修改
6.1.1 默认使用MD5检查源文件内容而不是时间戳,用touch不算修改过
      显示调用
    Program('hello.c')
        Decider('MD5')
6.1.2 使用时间戳
        Program('hello.c')
        Decider('timestamp-newer')
      与下面语句等价
        Program('hello.c')
        Decider('make')
      更详细的检查
        Program('hello.c')
        Decider('timestamp-match')
6.1.3 两者同时使用
        Program('hello.c')
        Decider('MD5-timestamp')
6.3 $CPPPATH 隐含依赖关系
       Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
    会在编译时加 -I

6.4 缓冲隐式依赖关系
     % scons -Q --implicit-cache hello  运行选项
    SetOption('implicit_cache', 1)      写在脚本里
    这样下次就不用从头开始找依赖关系了
         % scons -Q --implicit-deps-changed hello
    再打开

6.5 显式依赖关系: Depends函数
    当Scons没有找到关系时
       hello = Program('hello.c')
       Depends(hello, 'other_file')
6.9    总是编译 
      hello = Program('hello.c')
      AlwaysBuild(hello)

7. 环境
7.2 创建环境
7.2.1
     imp
 ort os

         env = Environment(CC = 'gcc',
                           CCFLAGS = '-O2')

         env.Program('foo.c')
 % scons -Q
7.2.2 获取环境变量
         env = Environment()
         print "CC is:", env['CC']
         % scons -Q
         CC is: cc
         scons: `.' is up to date.
         env = Environment(FOO = 'foo', BAR = 'bar')
         dict = env.Dictionary()
         for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
             print "key = %s, value = %s" % (key, dict[key])
      

This SConstruct file will print the specified dictionary items for us on POSIX systems as follows:

         % scons -Q
         key = OBJSUFFIX, value = .o
         key = LIBSUFFIX, value = .a
         key = PROGSUFFIX, value = 
         scons: `.' is up to date.
13. Install安装文件至其他文件夹
     env = Environment()
     hello = env.Program('hello.c')
     env.Install('/usr/bin', hello)
13.1 在目录里安装多个文件
       env = Environment()
       hello = env.Program('hello.c')
       goodbye = env.Program('goodbye.c')
       env.Install('/usr/bin', [hello, goodbye])
       env.Alias('install', '/usr/bin')
13.2 一个文件不同存放
       env = Environment()
       hello = env.Program('hello.c')
       env.InstallAs('/usr/bin/hello-new', hello)
       env.Alias('install', '/usr/bin')

       % scons -Q install
       cc -o hello.o -c hello.c
       cc -o hello hello.o
       Install file: "hello" as "/usr/bin/hello-new"

14 平台独立的文件系统操作
14.1 复制
        Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
     或者
        Command("file.out", [], Copy("$TARGET", "file.in"))

16. 多层目录构建
Sconconstruct在最顶层
16.1 SConscript文件可以层层包含
      SConscript(['drivers/SConscript',
                  'parser/SConscript',
                  'utilities/SConscript'])
在drivers下:
      SConscript(['display/SConscript',
                  'mouse/SConscript'])
16.2 对文件SConscript的相对目录
      SConscript(['prog1/SConscript',
                  'prog2/SConscript'])

<think>好的,我现在需要帮助用户了解如何使用SCons编译生成HEX文件。首先,我得确认用户的需求。他们可能正在开发嵌入式系统,需要将代码编译成HEX格式,通常用于微控制器,比如AVR或ARM芯片。SCons是一个基于Python的构建工具,用户可能已经有一定的使用经验,但需要具体的配置示例来生成HEX文件。 首先,我应该回忆SCons的基本工作原理。SCons使用SConstruct或SConscript文件作为构建脚本,通过定义构建规则和环境变量来控制编译过程。生成HEX文件通常涉及在链接后的步骤中使用objcopy工具,将ELF或bin文件转换为HEX格式。 接下来,我需要考虑用户可能的工具链。例如,如果使用AVR-GCC,可能需要指定特定的参数。但为了保持通用性,应该提供一个适用于常见情况的示例。此外,需要确保用户安装了必要的工具,比如GCC工具链中的objcopy。 然后,我需要构建一个示例的SConstruct文件。步骤可能包括:创建编译环境,指定编译器,编译源文件生成目标文件,链接生成ELF文件,然后使用Objcopy生成HEX文件。同时,需要处理不同平台的路径问题,比如工具的位置是否在系统PATH中。 还要考虑用户可能遇到的常见问题,比如工具未找到,或者生成步骤的顺序错误。因此,在示例中需要添加检查工具是否存在的逻辑,并确保构建顺序正确,即先编译链接,再转换格式。 另外,用户可能需要知道如何自定义输出路径或文件名,所以示例中可以展示如何通过环境变量或构建参数来调整。同时,是否需要清理生成的文件,可能需要添加Clean命令。 最后,生成相关问题,帮助用户进一步学习,比如如何添加调试符号、优化构建速度、处理依赖等。这些问题应该与SCons的高级用法相关,帮助用户深入使用该工具。 总结一下,我需要提供一个清晰的步骤说明,示例代码,并解释每个部分的作用。同时,确保示例代码符合SCons的语法,并处理可能的错误情况,比如工具缺失。此外,添加相关问题引导用户扩展知识。</think>### 如何使用SCons编译生成HEX文件 #### 1. 基础配置步骤 SCons通过`SConstruct`文件定义构建规则。生成HEX文件需使用`objcopy`工具,将ELF或BIN文件转换为HEX格式。以下是具体步骤: ```python # SConstruct示例 env = Environment(tools=['default', 'gnulink']) # 指定编译器和编译选项 env.Replace(CC='arm-none-eabi-gcc', # 根据实际芯片选择编译器 OBJCOPY='arm-none-eabi-objcopy') # 编译源文件生成目标文件 objects = env.Object(source=['main.c', 'driver.c']) # 链接生成ELF文件 elf = env.Program(target='firmware.elf', source=objects) # 使用objcopy生成HEX文件 hex_file = env.Command( target='firmware.hex', source=elf, action='$OBJCOPY -O ihex $SOURCE $TARGET' # ihex表示Intel HEX格式 ) # 设置默认构建目标 Default(hex_file) ``` #### 2. 关键配置解析 - **工具链选择**:`arm-none-eabi-gcc`适用于ARM Cortex-M芯片,若使用AVR芯片需替换为`avr-gcc`[^1] - **格式转换参数**:`-O ihex`指定输出为Intel HEX格式,若需Motorola S-record格式则用`srec` - **依赖检查**:需确保系统PATH包含`objcopy`工具路径,否则需显式指定绝对路径如`/usr/bin/arm-none-eabi-objcopy` #### 3. 增强健壮性配置 添加工具存在性检查: ```python if not env.Detect('arm-none-eabi-objcopy'): print("Error: arm-none-eabi-objcopy not found in PATH") Exit(1) ``` #### 4. 完整构建流程 执行命令: ```bash scons -Q # -Q启用安静模式,隐藏冗余输出 ``` 将依次执行: 1. 编译`.c`文件生成`.o` 2. 链接生成`.elf` 3. 转换生成`.hex` #### 5. 扩展应用 可通过`AddOption`实现参数化配置: ```python AddOption('--board', dest='board_type', type='string', default='stm32f4', help='Target board type') env.Append(CPPDEFINES={'BOARD_TYPE': '"${BOARD_TYPE}"'}) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值