Событие после сборки с несколькими комбинациями if/copy выполняется только в том случае, если первый файл не существует

Учитывая bin\ каталог внутри проекта Delphi содержит файлы Cert.pem а также Key.pemПриведенное ниже событие после сборки Delphi копирует оба файла, только если C:\Binaries\Cert.pem не существует:

if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR))
if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR))

Как только C:\Binaries\Cert.pem существует, Key.pem файл никогда не копируется.

Как я могу решить эту проблему в событии после сборки?

Изменить: в отличие от моего поста 2014 года, это действительно возможно с помощью скобок. Смотрите мой ответ ниже.

2 ответа

Проблема с событиями Delphi после сборки заключается в том, что они не являются пакетными файлами.

Это означает, что операторы, которые выглядят как строки, объединяются в Delphi IDE в один большой & амперсанд отдельное утверждение. Это гарантирует, что команды выполняются в последовательности, согласно Перенаправлению команд, Pipes - Windows CMD - SS64.com:

commandA &  commandB      Run commandA and then run commandB

Так что это фактический оператор, который выполняется:

if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR))&if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR))

Проблема здесь в том, что теперь второй if рассматривается как продолжение "тогда" части первого if утверждение: второе if никогда не выполняется, когда $(OUTPUTDIR)Cert.pem существует.

Помогает малоизвестная особенность, заключающаяся в том, что вы можете заключить каждую команду в скобки. Обычно это позволяет одной команде занимать несколько строк (особенно для if, а также for..do петли), но это также работает на одной строке.

Заворачивание каждой строки, имеющей if оператор в круглых скобках гарантирует, что они станут автономными операторами, не влияющими на другие строки, даже если они объединяются с & амперсанд сепараторы.

В диалоге это выглядит так:

(if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR)))
(if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR)))

Таким образом, IDE переводит это в одно утверждение:

(if not exist $(OUTPUTDIR)Cert.pem (copy bin\Cert.pem $(OUTPUTDIR)))&(if not exist $(OUTPUTDIR)Key.pem (copy bin\Key.pem $(OUTPUTDIR)))

Теперь это работает как задумано:

  • когда $(OUTPUTDIR)Cert.pem существует, но $(OUTPUTDIR)Key.pem не только $(OUTPUTDIR)Cert.pem копируется
  • когда $(OUTPUTDIR)Cert.pem существует, но $(OUTPUTDIR)Key.pem только $(OUTPUTDIR)Key.pem копируется
  • когда ни один не существует, оба копируются
  • когда оба существуют, ни один не копируется

Я не знал этого "трюка" при написании событий prebuild / prelink / postbuild после публикации в 2014 году, поэтому мне нужно написать для него обновление.

Поиск по скобкам на сайте:microsoft.com -site:social.technet.microsoft.com -site:answers.microsoft.com не обнаружил его в официальной документации, но я не удивлен, что он вырос истерически, вместо того, чтобы быть разработан. Или как атрибуты Старого Нового Вещи h2g2:

Как и во вселенной, если кто-то когда-либо полностью поймет Пакет, тогда язык будет немедленно заменен бесконечно более странной и более сложной версией самого себя. Это, очевидно, произошло, по крайней мере, один раз раньше;)

Лучшая документация, которую я смог найти, была в скобках / скобках - Windows CMD - SS64.com:

Скобки можно использовать для разделения команд на несколько строк. Это может сделать код более читабельным. Переменные будут оцениваться для блока кода так же, как если бы команда была одной строкой.

 (command)

 (
  command
  command )

Вещи, которые ломаются в круглых скобках Оболочка CMD не использует какой-либо большой интеллект при оценке круглых скобок, поэтому, например, приведенная ниже команда завершится ошибкой:

IF EXIST MyFile.txt (ECHO Some(more)Potatoes)

...

Используйте несколько событий сборки вместо помещения обеих команд в одно и то же событие.


Выполнение исходных строк события сборки.

Я могу сократить это очень легко: события сборки не являются пакетными файлами.

Что происходит, так это то, что все строки в вашем событии сборки соединяются вместе, используя знаки амперсанда (&), которые используются для выполнения нескольких команд в одной командной строке.

Это означает, что все причудливые структуры управления (операторы if, setlocal, for loop) невозможны внутри событий сборки.


ref: Вставлено из поста в блоге: события Delphi prebuild/prelink/postbuild, написанные Jeroen W. Pluimers

Меня удивляет, почему вы спросили, так как похоже, что вы написали ответ в 2014 году.:)

Другие вопросы по тегам