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