Почему Scons заботится о том, что моя цель доступна только для чтения, и как я могу убедить ее игнорировать ее? - PullRequest
4 голосов
/ 15 декабря 2009

Я пытаюсь собрать отладочную версию особенно сложного макета проекта. Одна из вещей, которые мне нужно сделать, - это скопировать недавно созданные библиотеки DLL поверх существующих библиотек, которые находятся под контролем Source Safe и поэтому доступны только для чтения. Я надеялся использовать 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 удаляет цели перед их созданием (см. _rmv_existing в FS.py, а также эту страницу на странице документации scons). Если вы столкнулись с этой проблемой, вы можете пометить цель как «Драгоценную», но у вас все равно будут проблемы, если вы используете «-c».

Здесь нет действительно хорошего решения. Ну хорошо.

Ответы [ 2 ]

1 голос
/ 24 декабря 2009

используйте NoClean (target), чтобы отключить удаление сгенерированных файлов при запуске scons -c.

0 голосов
/ 07 июля 2016

Это специфичная для 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/

...