为什么Scons关心我的目标是只读的,我怎么能说服它忽略它呢?

时间:2009-12-14 23:01:53

标签: scons

我正在尝试整合一个特别困难的项目布局的调试版本。我需要做的一件事是将最近构建的DLL复制到Source Safe控制下的现有DLL上,因此是只读的。我希望使用Scons来管理它,但如果你的目标是只读的,Scons就会出错。我的命令的一部分是将其设置为可读,但我的命令永远不会执行,因为scons首先出错。无论如何都要覆盖这种行为?

这是一个演示。如您所见,如果设置了只读位,我的“关闭只读位”命令永远不会运行:

C:\scs\dev\test>type Sconstruct
env = Environment()

env.Command(
    "b.txt", "a.txt",
        [
        r"if exist $TARGET c:\windows\system32\attrib -r $TARGET",
        Copy("$TARGET", "$SOURCE")
        ]
    )

C:\scs\dev\test>echo "test" > a.txt

C:\scs\dev\test>scons -Q b.txt
if exist b.txt c:\windows\system32\attrib -r b.txt
Copy("b.txt", "a.txt")

C:\scs\dev\test>echo "test2" > a.txt

C:\scs\dev\test>attrib +r b.txt

C:\scs\dev\test>scons -Q b.txt
scons: *** [b.txt] C:\scs\dev\test\b.txt: Access is denied

更新

好的 - 我已经通过踩踏Scons来解决这个问题。看起来Scons在构建之前会删除目标(请参阅FS.py中的_rmv_existing,以及scons文档页面中的this页面)。如果遇到此问题,可以将目标标记为“Precious”,但如果使用“-c”,则仍然会遇到问题。

这里没有真正好的解决方案。哦,好吧。

2 个答案:

答案 0 :(得分:1)

使用NoClean(目标)在运行scons -c时禁用删除生成的文件。

答案 1 :(得分:0)

这是与this question相关的Windows特定问题。当文件是只读文件时,Python os.unlink()/os.remove()会在Windows上引发异常,但它们不会在Linux上运行。为了保持一致的行为,我使用了猴子修补os.unlink()。这涵盖了我在构建和清理时发现的所有问题(-c选项)。

import os, stat
def _os_force_unlink(path):
    """Monkey-patch for os.unlink() to enable removing read-only files. 
    Need for consistency between platforms: os.unlink raises exception on Windows 
    (but not on Linux), when path is read-only.
    Unfixed SCons bug: http://scons.tigris.org/issues/show_bug.cgi?id=2693

    SCons uses os.unlink in several places. To avoid patching multiple functions,
    we patch the os function and use the lucky fact that os.remove does the same,
    so we can still get the normal OS behavior. SCons also uses os.remove(), 
    but not in places that affect this particular issue, so os.remove() stays as is.

    Note: this affects os.unlink() in all user code that runs in context of this set-up.
    """
    if not os.access(path, os.W_OK):
        os.chmod(path, stat.S_IWRITE)
    return os.remove(path) 

# Put this in some common place, like top of SConstruct
if <determine that platform is Windows>
    # Sufficient for SCons 2.5.0. We may need to patch more, if future SCons changes things
    os.unlink = _os_force_unlink

有关猴子修补的更多内容:https://filippo.io/instance-monkey-patching-in-python/