作为SCons目标运行avrdude命令

问题描述:

我希望能够从SCons中调用avrdude作为目标。例如,运行scons erase-device应该运行avrdude命令来执行此操作。作为SCons目标运行avrdude命令

我正在尝试通过创建调用avrdude并将它们添加到环境中的Builder对象来执行此操作。

# a string forming a base avrdude command that we can just add on to in the targets 
avrdude_base = 'avrdude -p ' + env['MCU'] + ' -c ' + icspdevice 

# target to erase everything--flash, EEPROM, and lock bits (but not fuse bits) 
erase_dev = Builder(action = avrdude_base + ' -e') 
env.Append(BUILDERS = {'EraseDevice' : erase_dev}) 
ed = env.EraseDevice() 
eda = env.Alias('erase-device', ed) 
env.AlwaysBuild(eda) 

# target to write the AVR fuses and lock bits 
write_fuse = Builder(action = avrdude_base + ' -U lfuse:w:' + lfuse + ':m -U hfuse:w:' + hfuse + 
        ':m -U efuse:w:' + efuse + ':m -U lock:w:' + lockbits + ':m') 
env.Append(BUILDERS = {'WriteFuses' : write_fuse}) 
wf = env.WriteFuses() 
wfa = env.Alias('write-fuses', wf) 
env.AlwaysBuild(wfa) 

有了这段代码,scons总是退出,说没有什么可做的。我认为这是因为,代码的显示方式,我不给任何源文件这些建设者(env.EraseDevice()env.WriteFuses());因此,SCons认为他们不需要被叫。

这就是我接下来的尝试。我只是将一个现有的文件名传递给这两个构建者,以使scons高兴,尽管它不是必需的。现在的问题是,无论我想运行scons write-fuses,scons erase-flash还是其他使用avrdude的目标,scons都会像我试图编写保险丝一样行事。例如,如果我传入的文件名是foo.hex,则scons现在认为它每次都必须运行write-fuses目标,因为scons认为'avrdude'应该生成一个名为的输出文件foo ,但该文件永远不会生成。

另外,这样做意味着我必须在擦除器件或编程熔丝位之前构建hex文件,这通常不是必需的。

如何在SCons中创建不需要任何输入源并且不会生成任何输出的目标?

谢谢!

你说的是scons没有运行任何东西,因为它没有任何资源可以转化为输出,但关键在于scons想要生成目标,但它并不认为它存在是任何建立。

一个简单的解决方法是给erase-devicewrite-fuse命令虚拟目标。这些目标文件永远不会生成,所以如果scons确定需要构建此目标(因为它已在命令行中指定,或者是命令行中的某个依赖项),则scons将始终运行相应的avrdude ...命令。

我认为建筑者的使用会增加你不需要的额外复杂性。建设者很适合为目标映射创建新的源,但您并不需要涉及文件。

ed = env.Command('erase.dummy', [], avrdude_base + ' -e') 
ed = env.EraseDevice() 
env.AlwaysBuild(ed) 
env.Alias('erase-device', ed) 
... 

作为一个方面说明,scons --tree=all是一个很好的方法,看看scons的计算的依赖关系树。如果你对scons的做法感到困惑,看到依赖关系树可以帮助调试你的模型与scons分离的地方。

+0

呵呵,现在看起来很明显,现在你说出来了!我很快修改了我的代码,为源代码传入一个空的列表并创建一个虚拟输出,它似乎工作正常。我也会将我的代码转换为使用Command()方法,因为这看起来更容易。谢谢您的帮助! – 2010-11-04 23:36:11