Я хочу собрать свою программу с помощью make, а затем запустить созданный исполняемый файл с помощью сценария bash, но bash не может найти исполняемый файл, хотя он был создан, и я могу запустить его вручную. Проблема существует только в Linux Mint 19 в Gnome-терминале. Обновлено: точное сообщение об ошибке: «/path/to/my/executable: нет такого файла или каталога»
У меня есть кроссплатформенный проект, в котором мне нужно запустить cmake, затем собрать проект и, наконец, запустить созданный исполняемый файл. У меня есть bash-скрипт для автоматизации процесса: Обновлено: это только та часть, которая вызывает проблемы;)
for TASK in $@; do
if [[ $TASK == "make" ]]; then
call cmake here, this creates a .sln or a make file
elif [[ $TASK == "build" ]]; then
if [[ $OS == 'CYGWIN_NT-10.0' ]]; then
MSBuild.exe "./build/debug/myproject.sln"
elif [[ $OS == 'Linux' ]]; then
cd ./build/debug/ && make
else
error...
fi
elif [[ $TASK == "run" ]]; then
if [[ $OS == 'CYGWIN_NT-10.0' ]]; then
./build/debug/Debug/program.exe
elif [[ $OS == 'Linux' ]]; then
./build/debug/program
else
error...
fi
else
error...
fi
done
Вызов «./script.sh make build run» должен, например, вызвать cmake для создания файлов сборки, затем вызвать программу сборки (make в Linux или msbuild в Windows), а затем запустить созданный исполняемый файл. Это отлично работает на Windows 10 в терминале cygwin. В Linux вызов «./script.sh build run» завершается ошибкой, так как не удается найти исполняемый файл. Однако "./script.sh build && ./build/debug/program" прекрасно работает. Удивительно, но «./script.sh build && ./script.sh run» работает так, как ожидалось. Почему это? Есть ли ошибка в скрипте bash? И почему это работает на Cygwin, но не на Linux Mint?
Если вы разрабатывали сценарий для Windows, EOL, вероятно, является первой проблемой. См. также Как использовать Дос2Юникс?, Как использовать Шеллчек, Как отлаживать bash-скрипт? (U&L.SE), Как отлаживать bash-скрипт? (SO), Как отлаживать bash-скрипт? (AskU), Отладка Bash-скриптов и т. д.
Конструкция if [[ TASK == .. ]]; ...; elif [[ TASK == ...; elif [[ TASK ...
отчаянно хочет быть заменена утверждением case
.
Какова первая строка вашего сценария оболочки и/или как вы ее вызываете? Если вместо #!/bin/sh
написано #!/bin/bash
, то это ваша проблема. Вы написали сценарий, который явно использует не-POSIX, нестандартные расширения, которые существуют только в оболочке bash. Если вы используете #!/bin/sh
, то он не будет работать ни в одной системе, где /bin/sh
на самом деле не является bash (что верно, например, для всех систем Debian и Ubuntu).
конечно, это не весь сценарий, а только та его часть, которая вызывает проблемы. Я подумал, что было бы хорошо максимально упростить ;)
Добавлю уточнений, спасибо за подсказку! И спасибо @WilliamPursell за совет использовать оператор case :)
@jww я использую его на cygwin bash, который также использует LF вместо CRLF. Если бы проблема заключалась в концах строк, скрипт вообще не запустился бы.
@MadScientist я использую #!/bin/bash
нет проблем;)
Хорошо, я решил это. Задавать вопросы, кажется, первый шаг к поиску решения. Проблема, похоже, в том, что вызов "./script.sh build run" сначала оценивает команду сборки "cd ./build/debug/ && make". Я думал, что такие команды будут порождать новую вложенную оболочку, где затем оцениваются команды cd и make, а затем оболочка продолжит работу в исходном рабочем каталоге. Судя по всему этого не происходит и рабочий каталог исполняемого скрипта меняется на "./build/debug". Следующая команда «run» пытается выполнить «./build/debug/program», но, поскольку текущий рабочий каталог изменен, она по существу ищет «./build/debug/build/debug/program», которого не существует. я добавил строку
cd ../../
к коду команды сборки. Теперь это выглядит так
...
elif [[ $OS == 'Linux' ]]; then
cd ./build/debug/ && make
cd ../../
else
...
Я не знаю точно, почему, но в Linux это работает именно так.
cd
не порождает подоболочку, а &&
не порождает подоболочку. Если вы хотите создать подоболочку, вы можете использовать ()
. Итак, если вы напишете (cd ./build/debug && make)
, вы получите желаемое поведение. В качестве альтернативы, если вы знаете, что используете GNU make, вы можете использовать make -C build/debug
и вообще избегать cd
.
Вставить фактическое сообщение об ошибке? Кстати, это нет настоящий скрипт, я почти уверен, что
call cmake here, this creates a .sln or a make file
не работает ;)