Могу ли я вызвать программу .cpp в Bash?

Могу ли я вызвать программу .cpp в Bash?

Я новичок в программировании на Bash. Я хочу вызвать свою программу на C++ в файле Bash.

Моя программа myProg.cpp:

#include<iostream>
using namespace std;
int main()
{
   cout<<"Salam! World"<<endl;
return 0;
}

И мой bash-файл myBash.sh. Как мне вызвать мою вышеуказанную .cpp-программу в myBash.shфайле?

решение1

Сначала вам нужно скомпилировать его: сначала измените текущий рабочий каталог Терминала на путь к вашему исходному файлу:

cd <path_to_cpp_file>/

Затем скомпилируйте исходный файл:

g++ myProg.cpp -o myProg

Затем вы можете вызвать скомпилированный исполняемый файл из вашего bashскрипта следующим образом:

#!/bin/bash

# ...
<path_to_compiled_executable>/myProg
# ...

решение2

Так как вашнастоящая цельКажется, для автоматизации всего, что необходимо сделать для запуска вашей программы, я предлагаю другой подход.Вместо написания скрипта оболочки вы можете использоватьmakefile.Если хотите, вы можете написать правило в вашем makefile для запуска вашего исполняемого файла после его сборки. Тогда у вас будет два файла — ваш исходный код C++ и ваш makefile — и вы сможете запустить одну команду, которая эффективно:

  1. Создает или перестраивает вашу программу на C++,если и только если необходимо.
  2. Запускает вашу программу.

Последующие разделы этого поста объясняют, почему вы не можете вызвать .cppфайл напрямую (а должны сначала создать исполняемый файл из него); как установить make, как его использовать и что он делает за кулисами; и как избежать распространенных ловушек. Но в случае, если вы хотите получить представление о том, как выглядит этот подход, прежде чем углубляться в него, вы запустите make runпосле размещения этого0в Makefile:

all: myProg

run: all
    ./myProg

Мне это нравится больше, чем скрипт оболочки, и я думаю, что вам тоже может понравиться.

Фон

В отличие от некоторыхинтерпретируемые языкикак и Python и Bash, C++ являетсяскомпилированный язык.1Программы, написанные на языке C++, должны бытьпостроенныйдо того, как они будут запущены. (Строительство также иногда называюткомпиляция, хотякомпиляция(точнее, относится к одному из этапов построения.) Вы не можете запустить C++исходный кодфайл; вместо этого его необходимо скомпилировать вобъектный код2, в этом случаемашинный язык. Затем объектные файлы должны быть связаны друг с другом, и даже если есть только один, он все равно должен быть связан с любымобщие библиотекион использует. Связывание производитисполняемыйкоторый может быть запущен.

Короче говоря, вам нужно построить свою программу, прежде чем запустить ее.первый раз. Перед последующими запусками это не обязательноповторнособран, если только вы не изменили его исходный код; в этом случае вам придется собрать его заново, если вы хотите, чтобы ваши изменения отразились в работающей программе.Утилитаmakeразработан специально для такого рода ситуаций, когда требуется выполнить действияусловнов зависимости от того, были ли они уже выполнены и когда именно.

Получающийmake

Возможно, у вас уже makeустановлена ​​команда; попробуйте запустить ее, чтобы узнать. Если она установлена, вы увидите что-то вроде:

$ make
make: *** No targets specified and no makefile found.  Stop.

Чтобы получить make, вы можете установитьделать Установить сделатьпакет, но я предлагаю установитьстроить-необходимо Установить сборку-essentialкоторый предоставляет ряд других удобных инструментов. (Вы могли установитьстроить-необходимо Установить сборку-essentialg++(что является одним из способов, который у вас, возможно, уже есть . make) Вы можете использовать Центр программного обеспечения для его установки или выполнить команду:

sudo apt-get update && sudo apt-get install build-essential

makeБез Makefile

Чтобы увидеть, как makeэто работает, я предлагаю сначала запустить его без make-файла, передав ему базовое имя вашего файла с исходным кодом:

$ make myProg
g++     myProg.cpp   -o myProg
$ ./myProg
Salam! World

При последующих запусках makeсравнивает временные метки модификации (mtimes) для входных и выходных файлов, и не будет перестраивать вашу программу без необходимости:

$ make myProg
make: 'myProg' is up to date.

При изменении myProg.cppобновляется временная метка его модификации, поэтому makeбудет известно, что его нужно перестроить. (Вы также можете обновить временную метку файла с помощьюtouch(команда, если вам нужно или вы хотите принудительно перестроить какие-либо выходные файлы, зависящие от нее. И, конечно, удаление выходных файлов также гарантирует, что они будут перестроены при запуске make-- только не удаляйте не тот файл!)

$ touch myProg.cpp
$ make myProg
g++     myProg.cpp   -o myProg

Как makeузнать, что делать, когда бежишь make myProg?

  • Аргумент myProgназываетсяmakeцель.
  • Цели часто, но не всегда, являются именами файлов, которые будут созданы. Цели могут быть определены явно в makefile.
  • Если цель не определена в make-файле или (как в этом случае) make-файл отсутствует, makeищет входные файлы (т. е. исходный код), названные таким образом, чтобы было понятно, что они предназначены для сборки цели.
  • makeопределяет, какую утилиту и синтаксис использовать при создании файла, исходя из его суффикса (в данном случае .cpp).

Все это можно настроить, но в таких простых случаях, как этот, в этом часто нет необходимости.

Создание Makefile для автоматизации сборки и запуска вашей программы

Чтобы автоматизировать более сложные задачи, чем создание программы из одного файла исходного кода, например, если имеется несколько входных файлов или (что более применимо к вашим непосредственным потребностям) действий, которые вы хотите выполнить помимо запуска компилятора, вы можете создать make-файл для определения целей makeи указания того, как они зависят от других целей.

Первая цель, определенная в make-файле, является целью по умолчанию: это то, что makeпытается собрать при запуске без аргументов командной строки (т. е. когда вы запускаете просто make, а не что-то вроде make myProg).

Обычный способ использования makefiles — создание каталога, содержащего все файлы исходного кода (и любые другие файлы), используемые для сборки вашей программы, а также makefile, который обычно называется Makefile. По этому имени makeон будет автоматически найден.

Чтобы создать makefile, который вы можете использовать для запуска myProg, и который автоматически построит его первым, когда это необходимо, поместите его myProg.cppв новый, иначе пустой каталог. Создайте еще один текстовый файл в этом каталоге с именем Makefile.

Для этого можно использовать любой текстовый редактор, но рецепт правила — перечисленные под ним команды, которые будут выполнены для достижения его цели — должен иметь отступвкладкискорее, чемпространства.3Поэтому, если ваш текстовый редактор в настоящее время настроен на добавление пробелов при нажатии Tab, вам следует изменить это.

Например, в Gedit или Pluma вы должны зайти вРедактировать > Настройки, нажмитередакторвкладку и убедитесь, чтоВставляйте пробелы вместо табуляциине отмечено:

Снимок экрана, показывающий диалоговое окно «Настройки» в Pluma, интерфейс которого по сути такой же, как в Gedit, с указанием расположения флажка «Вставлять пробелы вместо табуляции» в верхней части вкладки «Редактор»

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

После того, как вы откроете редактор и (при необходимости) настроите отступы с помощью табуляции, введите следующее:

all: myProg

run: all
    ./myProg

Если вы скопируете и вставите это, это будет неправильно.поскольку пробелы будут вставлены, даже если ваш текстовый редактор не создает их при нажатии Tab. (Это связано со способом, которым Ask Ubuntu отображает код.) Но вы можете просто удалить четыре предшествующих пробела ./myProgи нажать Tab, чтобы создать на их месте табуляцию.

Некоторые текстовые редакторы по умолчанию отображают табуляцию как 8 пробелов или какое-то другое число. Это нормально.

Что делает этот Makefile и как его использовать

Используйте команду:

  • make, для сборки программы, если она еще не собрана и исполняемый файл не соответствует исходному коду.Или,
  • make run, чтобы запустить программу,постройте его сначала, если необходимо(т.е. если нет текущего исполняемого файла).

Этот make-файл определяет две цели: allи run.

  • У allцели нет собственного рецепта, но она зависит от myProgцели. Эта цель явно не определена, поэтому она неявно указывает makeна попытку сборки myProgиз любых файлов исходного кода, доступных для нее в текущем каталоге. (См.makeБез Makefileраздел выше для получения подробной информации.)

    Поскольку allэто первая цель, явно определенная в Makefile, она будет построена при makeзапуске из каталога, в котором Makefileнаходится. Таким образом, мы настроили все так, что запуск makeсам по себе эквивалентен запуску make all.

  • Цель runзапускает программу. Ее рецепт состоит из команды, которая это делает, ./myProg. runобъявляет allцель как зависимость. Это делает так, что когда вы запускаете make run, myProgперестраивается, если текущий myProgисполняемый файл не является текущим (или еще не существует).

    Мы могли бы точно так же сделать rundepend on myProgвместо on all, но нам все равно понадобилась бы явная allцель (или эквивалентная цель с другим именем), чтобы не runбыть целью по умолчанию. Конечно, если вы хотите, чтобы ваша программа была построенаи бегидаже если вы работаете makeсами по себе, вы можете это сделать.

    Еще одно преимущество зависимости от allцели заключается в том, что в случае, если позже потребуется выполнить больше действий, прежде чем ваша программа должна быть запущена, вы можете добавить рецепт к правилу для all.

Использование makefile для запуска программы выглядит следующим образом, если ее необходимо собрать:

$ cd myProg/
$ make run
g++     myProg.cpp   -o myProg
./myProg
Salam! World

Или это, если его не нужно строить:

$ make run
./myProg
Salam! World

А если вы просто хотите убедиться, что программа собрана (поскольку файл исходного кода был последний раз изменен)без запуска программы, просто запустите makeбез аргументов:

$ make      # Here, I run make and myProg isn't current.
g++     myProg.cpp   -o myProg
$ make      # Running "make" again after "make" or "make run" does nothing.
make: Nothing to be done for 'all'.

( make myProgтоже будет работать.)

Усовершенствование: пользовательские флаги компилятора

makeчрезвычайно мощный инструмент, удобный для простых целей, как эта, но также хорошо подходящий для больших, сложных проектов. Попытка подробно описать все, что вы можете сделать с помощью этого, makeзаняла бы целую книгу (в частности,Вот этот).

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

При использовании GCC (как и с g++командой) я рекомендую передать хотя бы -Wallкомпилятору. Это на самом деле не включаетвсепредупреждения, но вы можете включить большую часть остальных с помощью -Wextra. Иногда вы также можете захотеть -pedantic. (См.man gccи3.8Параметры запроса или подавления предупрежденийвСправочное руководство GCC.)

Чтобы вызвать g++вручную с этими флагами, выполните:

g++ -Wall -Wextra -pedantic -o myProg myProg.cpp

Чтобы вызвать makeкомпилятор C++ ( g++) с флагами -Wall, -Wextra, и -pedantic, добавьте CXXFLAGS=строку с ними в начало Makefile.

CXXFLAGS=-Wall -Wextra -pedantic

all: myProg

run: all
    ./myProg

Даже если myProgвсе еще существует и новее, чем myProg.cpp, запуск makeили make runпосле редактирования Makefileвсе равно снова соберет программу, поскольку Makefileтеперь новее, чем myProg. Это хорошо, потому что:

  • В этом случае пересборка исполняемого файла приведет к появлению предупреждений, если таковые имеются (для данной конкретной программы их быть не должно).
  • В более общем смысле, иногда при редактировании make-файла вы хотите, чтобы создавались разные файлы или чтобы они создавались с разным содержимым. (Например, если бы вы добавили флаг -O3для интенсивной оптимизации или -gчтобы заставить компилятор генерировать отладочные символы, результирующий myProgисполняемый файл был бы другим.)

Дальнейшее чтение

Примечания

0: Я рекомендую вам почитать дальше, чтобы увидеть, как это работает. Но если вы хотите попробовать сделать это самостоятельно: вы должны делать отступы строк с помощью табуляции, а не пробелов.

1: Строго говоря, практически любой язык программирования может быть либо интерпретирован, либо скомпилирован в зависимости от того,реализациидля него были написаны. Для некоторых языков существуют как интерпретаторы, так и компиляторы. Однако интерпретируемый C++ встречается редко, хотяне неслыханно.

2: Разделение здания накомпиляцияисвязываниеи вызов трансляции файла исходного кода C++ (.cc/.cpp/.cxx/.C) в объектный кодкомпиляция, это еще не все. Программы на C и C++ (и некоторых других языках) являются первымипредварительно обработанный. В вашей программепрепроцессор Cзаменяет #include<iostream>содержимым заголовочного <iostream>файла до начала фактической компиляции. И в самом узком смысле компиляция преобразует исходный код вязык ассемблераа не объектный код. Многие компиляторы (например, GCC/ g++) могут объединять компиляцию и сборку в один шаг и не создают ассемблерный код, если вас об этом не попросят.

В то время как предварительная обработка является отдельным шагом, GCC и другие компиляторы автоматически запускают препроцессор. Аналогично, они могут автоматически запускать компоновщик, поэтому вся последовательностьпредварительная обработка,компиляция,сборка, исвязьиногда называется «компиляцией», а не «сборкой». (Обратите внимание, что сборка может включать в себя больше шагов, чем эти, например, она может включать в себя генерацию файлов ресурсов, запускскрипт для настройки того, как все будет построено, и т. д.)

3: Вам нужно только сделать отступ с помощью табуляции в самом makefile. Использование makefile не накладывает никаких требований на то, как вы пишете сами файлы исходного кода C++. Не стесняйтесь переключать отступы обратно с табуляции на пробелы, когда вы работаете с другими файлами. (И если выДействительноне нравится отступ с помощью табуляции в makefile, вы можете установить.RECIPEPREFIX специальная переменная.)

решение3

Вот пример: из myBash.sh

#!/bin/sh
g++ myProg.cpp -o myProg
./myProg

Связанный контент