3

我希望能够从 SCons 调用 avrdude 作为目标。例如,运行scons erase-device应该运行 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 假定它们不需要被调用。

所以这就是我接下来尝试的。我只是将一个现有的文件名传递给这两个 Builders 以使 scons 高兴,即使它不是必需的。现在的问题是,无论我是要运行scons write-fusesscons erase-flash还是其他使用 avrdude 的目标,scons 的行为就像我在尝试编写保险丝一样。例如,如果我传入的文件名是foo.hex,那么 scons 现在认为它必须write-fuses每次都运行目标,因为 scons 认为 'avrdude' 应该生成一个名为foo的输出文件,但该文件是从未产生。

此外,这样做意味着我必须在擦除设备或对熔丝位进行编程之前构建十六进制文件,这通常是不必要的。

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

谢谢!

4

1 回答 1

1

你说 scons 没有运行任何东西是正确的,因为它没有任何源可以转化为输出,但关键是 scons 想要生成目标并且它认为没有任何东西可以构建.

一种简单的解决方法是为erase-deviceandwrite-fuse命令提供虚拟目标。这些目标文件永远不会生成,因此如果 scons 确定需要构建此目标(因为它是在命令行上指定的或者是命令行上某些内容的依赖项),scons 将始终运行适当的avrdude ...命令。

我认为使用 Builders 会增加您不需要的额外复杂性。构建器非常适合创建新的源到目标映射,但您并不需要真正涉及文件。

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 不同的地方。

于 2010-11-04T06:42:05.800 回答