Странная проблема перенаправления с gnumake

У меня есть система, в которой я генерирую make-файл и которая отлично работает под Mac OS X. Когда я запускаю ее под Linux, у меня возникает странная проблема. Мне удалось сократить мой make-файл до очень простого примера:

    compile:
        gcc -o prog *.c &> compile__

    chm:
        chmod u=rwx,g=rwx,o= prog

    both0:
        gcc -o prog *.c &> compile__ ;  \
        chmod u=rwx,g=rwx,o= prog

    both1:
        gcc -o prog *.c ;  \
        chmod u=rwx,g=rwx,o= prog

Идея состоит в том, чтобы скомпилировать файл, а затем изменить его разрешения. Если я выполню последовательность команд:

    make compile
    make chm

все работает нормально. Однако, если я выполню:

    make both0

Я получаю сообщение:

    chmod: cannot access `prog': No such file or directory

и права не меняются. С другой стороны, если я выполню:

    make both1

права изменены правильно. Единственная разница заключается в перенаправлении «&> compile__» под обоими0, которое я удалил для обоих1.

Любые идеи?


person Tsf    schedule 14.04.2011    source источник
comment
Я забыл упомянуть, что запускаю gnumake версии 3.81 под Ubuntu Linux.   -  person Tsf    schedule 14.04.2011
comment
У меня работает: CentOS версии 5.4 (Final); GNU Make 3.81; gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46); Привет;   -  person Chen Levy    schedule 14.04.2011
comment
Я тестировал его на другом Linux: Fedora релиз 9 (Sulphur) и тот же GNU Make 3.81. Без проблем! Кажется, это происходит только при моей установке: Ubuntu 10.04.2 LTS, ядро ​​​​2.6.32-30.   -  person Tsf    schedule 14.04.2011


Ответы (2)


&> compile__

не является переносимым перенаправлением. В bash он перенаправляет как стандартную ошибку, так и стандартный вывод, что, как я полагаю, является вашим намерением. Другие оболочки, вероятно, будут делать с ним разные вещи. В частности, тире выполняет команду в фоновом режиме (&) и перенаправляет стандартный вывод (> compile__). chmod выполняется до завершения компиляции и создает prog. Перенаправление как стандартной ошибки, так и стандартного вывода может быть выполнено переносимым образом с помощью cc -o prog *.c > compile__ 2>&1.

(Почему это работало на Mac? Возможно, другая оболочка, которая интерпретирует &> по-другому, возможно, компилятор открыл файл раньше, возможно, состояние гонки вышло немного по-другому.)

person wnoise    schedule 14.04.2011
comment
В bash '&>' перенаправляет и stdout, и stderr в один и тот же файл; он не имеет фонового эффекта. - person Jonathan Leffler; 15.04.2011
comment
Три протестированные мной системы (Mac OS, Fedora и Ubuntu) используют один и тот же GNU Bash, поэтому они не должны вести себя по-разному. - person Tsf; 15.04.2011
comment
Make использует системный /bin/sh, который может не быть bash. Системы Ubuntu обычно используют тире для /bin/sh. Dash действительно работает в фоновом режиме и запускает пустую команду, перенаправляя ее на compile__ @Tsf: развеселите меня и попробуйте переключить ее на «›compile__ 2›&1», стандартный способ сделать это перенаправление. - person wnoise; 15.04.2011
comment
Я пошутил над тобой, и это сработало, но я до сих пор не понимаю, почему! Если мой синтаксис неверен, то целевой компилятор моего make-файла не должен работать. С другой стороны, в моем руководстве по bash сказано: существует два формата для перенаправления стандартного вывода и стандартной ошибки: &›word и ›&word. Из двух форм предпочтительнее первый. Это семантически эквивалентно ›word 2›&1. Насколько я знаю, моя система использует bash, а не dash. Спасибо за решение моей непосредственной проблемы, но я все же хотел бы понять, что происходит! - person Tsf; 15.04.2011
comment
@Tsf: разные оболочки поддерживают разный синтаксис. Ваша оболочка user, несомненно, является bash, которая поддерживает этот синтаксис. Make (во всяком случае, по умолчанию) использует системную оболочку, которая, похоже, не поддерживает этот синтаксис в Ubuntu. Синтаксис корректен в той мере, в какой его поддерживает bash, но неверен в той мере, в какой другие оболочки этого не делают. Что можно определенно сказать, так это то, что этот синтаксис нестандартен. Этой части синтаксиса не было в исходных оболочках Bourne, а пришло из csh. Ну, >& сделал, bash также добавил &> - он менее широко поддерживается, и я не знаю, почему руководство по bash рекомендует его. - person wnoise; 16.04.2011
comment
Цель compile работает, потому что синтаксис не является синтаксической ошибкой, он интерпретируется не так, как вы предполагали. - person wnoise; 16.04.2011
comment
@wnoise: я не уверен, что понимаю вас: цель compile делает именно то, что я хочу, независимо от выбранного синтаксиса! - person Tsf; 16.04.2011
comment
@wnoise: я думаю, что, возможно, я был слишком быстр в своем ответе - кажется, есть разница в интерпретации! Думаю, я буду придерживаться scons вместо make всякий раз, когда смогу. - person Tsf; 16.04.2011
comment
@Tsf: Нет, это не так, но разницу трудно увидеть, когда выполняется только одна команда. Команда работает в фоновом режиме и не перенаправляет стандартную ошибку. Фоновая обработка не имеет большого значения, когда это единственная команда в правиле, и вы вызываете ее непосредственно из командной строки — в конце концов она завершается. Проблемы возникают, когда от этого вывода зависит какая-то другая команда, либо в том же правиле (как вы это заметили), либо в другом правиле. - person wnoise; 16.04.2011