Soy nuevo en la programación Bash. Quiero llamar a mi programa C++ en un archivo Bash.
Mi programa es myProg.cpp
:
#include<iostream>
using namespace std;
int main()
{
cout<<"Salam! World"<<endl;
return 0;
}
Y mi archivo bash es myBash.sh
. ¿Cómo puedo llamar a mi programa .cpp anterior en myBash.sh
el archivo?
Respuesta1
Primero debe compilarlo: primero cambie el directorio de trabajo actual de Terminal a la ruta de su archivo fuente:
cd <path_to_cpp_file>/
Luego compila el archivo fuente:
g++ myProg.cpp -o myProg
Luego puedes llamar al ejecutable compilado desde tu bash
script de esta manera:
#!/bin/bash
# ...
<path_to_compiled_executable>/myProg
# ...
Respuesta2
desde tuverdadero objetivoparece ser automatizar todo lo que sea necesario hacer para ejecutar su programa, sugiero un enfoque diferente.En lugar de escribir un script de shell, puede utilizar unarchivo make.Si lo desea, puede escribir una regla en su archivo MAKE para ejecutar su ejecutable una vez que esté compilado. Luego tendrá dos archivos (su archivo de código fuente C++ y su archivo MAKE) y podrá ejecutar un solo comando de manera eficiente:
- Construye o reconstruye su programa C++,si y solo si es necesario.
- Ejecuta su programa.
Las secciones siguientes de esta publicación explican por qué no puedes llamar a un .cpp
archivo directamente (sino que primero debes crear un ejecutable a partir de él); cómo instalarlo make
, cómo usarlo y qué hace detrás de escena; y cómo evitar errores comunes. Pero en caso de que quieras tener una idea de cómo luce este enfoque antes de profundizar, ejecutarás make run
después de poner esto.0en Makefile
:
all: myProg
run: all
./myProg
Para este propósito, me gusta más que un script de shell, y creo que a usted también le podría gustar.
Fondo
A diferencia de algunosidiomas interpretadosAl igual que Python y Bash, C++ es unlenguaje compilado.1Los programas escritos en C++ deben serconstruidoantes de que se ejecuten. (El edificio a veces también se llamacompilando, aunquecompilandose refiere más apropiadamente a uno de los pasos de la construcción). No se puede ejecutar un programa C++.código fuentearchivo; en su lugar, debe compilarse encódigo de objeto2, en este casoLenguaje de máquina. Los archivos objeto deben entonces estar vinculados entre sí, e incluso si solo hay uno, debe estar vinculado a cualquierbibliotecas compartidasusa. La vinculación produce unaejecutableque se puede ejecutar.
En resumen, debes crear tu programa antes de ejecutarlo.la primera vez. Antes de ejecuciones posteriores no es necesariorecompilado, a menos que haya cambiado su código fuente, en cuyo caso deberá compilarlo nuevamente si desea que sus cambios se reflejen en el programa que se ejecuta.La make
utilidadestá diseñado específicamente para este tipo de situaciones, donde uno desea realizar accionescondicionalmentedependiendo de si ya se han hecho o no y cuándo.
Conseguirmake
Es posible que ya tengas el make
comando instalado; intenta ejecutarlo para averiguarlo. Si está instalado, verá algo como:
$ make
make: *** No targets specified and no makefile found. Stop.
Para conseguir make puedes instalar elhacer paquete, pero sugiero instalaresencial para la construcción que proporciona una serie de otras herramientas útiles. (Es posible que haya instaladoesencial para la construcción para obtenerlo g++
, que es una forma que quizás ya tenga make
). Puede usar el Centro de software para instalarlo o ejecutar el comando:
sudo apt-get update && sudo apt-get install build-essential
make
Sin un archivo Make
Para ver cómo make
funciona, sugiero ejecutarlo primero sin un archivo MAKE, pasándole el nombre base de su archivo de código fuente:
$ make myProg
g++ myProg.cpp -o myProg
$ ./myProg
Salam! World
En ejecuciones posteriores, make
compara las marcas de tiempo de modificación (tiempos) en los archivos de entrada y salida, y no reconstruirá su programa innecesariamente:
$ make myProg
make: 'myProg' is up to date.
Cuando cambia myProg.cpp
, actualiza su marca de tiempo de modificación, por lo que make
sabrá reconstruirla. (También puede actualizar la marca de tiempo de un archivo con eltouch
comando, si necesita o desea forzar la reconstrucción de cualquier archivo de salida que dependa de él. Y, por supuesto, eliminar los archivos de salida también garantizará que se reconstruyan cuando los ejecute make
, ¡pero no elimine el archivo incorrecto!)
$ touch myProg.cpp
$ make myProg
g++ myProg.cpp -o myProg
¿Cómo make
sabe qué hacer cuando corre make myProg
?
- El
myProg
argumento demake
se llamaobjetivo. - Los objetivos suelen ser, aunque no siempre, los nombres de los archivos que se crearán. Los objetivos se pueden definir explícitamente en un archivo MAKE.
- Cuando un objetivo no está definido en el archivo MAKE o (como en este caso) no hay un archivo MAKE,
make
busca archivos de entrada (es decir, código fuente) nombrados de tal manera que sugiera que están destinados a construir el objetivo. make
infiere qué utilidad y sintaxis usar al crear un archivo a partir de su sufijo (en este caso,.cpp
).
Todo esto se puede personalizar, pero en casos simples como este a menudo no es necesario.
Crear un Makefile para automatizar la creación y ejecución de su programa
Para automatizar tareas más complejas que crear un programa a partir de un único archivo de código fuente, como si hay varios archivos de entrada o (más aplicable a sus necesidades inmediatas) acciones que desea realizar además de ejecutar el compilador, puede crear un archivo MAKE para definir objetivos. y make
especificar cómo dependen de otros objetivos.
El primer objetivo definido en un archivo MAKE es el objetivo predeterminado: es lo que make
se intenta compilar cuando se ejecuta sin argumentos de línea de comandos (es decir, cuando ejecuta solo make
y no algo como make myProg
).
La forma habitual de utilizar archivos MAKE es crear un directorio que contenga todos los archivos de código fuente (y cualquier otro archivo) utilizado para construir su programa, así como el archivo MAKE, que generalmente se llama Makefile
. Por ese nombre, make
lo encontrará automáticamente.
Para crear un archivo MAKE, puede usarlo para ejecutarlo myProg
y eso lo compilará automáticamente primero cuando sea necesario, colóquelo myProg.cpp
en un directorio nuevo, que de lo contrario estaría vacío. Cree otro archivo de texto en ese directorio llamado Makefile
.
Puede utilizar cualquier editor de texto para esto, pero la receta de una regla (los comandos enumerados debajo que se ejecutarán para crear su objetivo) debe tener una sangría conpestañasen vez deespacios.3Entonces, si su editor de texto está configurado actualmente para sangrar con espacios cuando presiona Tab, debe cambiar esto.
Por ejemplo, en Gedit o Pluma, entrarías enEditar > Preferencias, haga clic en elEditorpestaña y asegúrese deInsertar espacios en lugar de pestañasno está marcado:
Muchos editores utilizan de forma predeterminada la sangría con tabulaciones y no con espacios, por lo que si no ha cambiado esta configuración antes, es posible que ya esté configurada correctamente para los archivos MAKE.
Una vez que esté en su editor y (si es necesario) lo haya configurado para sangrar con pestañas, coloque esto en:
all: myProg
run: all
./myProg
Si copias y pegas esto, estará mal.porque los espacios se copiarán aunque su editor de texto no los cree cuando presione Tab. (Esto tiene que ver con la forma en que Ask Ubuntu muestra el código). Pero puedes simplemente eliminar los cuatro espacios anteriores ./myProg
y presionar Tabpara crear una pestaña en su lugar.
Algunos editores de texto muestran de forma predeterminada una pestaña con 8 espacios o algún otro número. Está bien.
Qué hace ese Makefile y cómo usarlo
Utilice el comando:
make
, para compilar el programa a menos que ya esté compilado y el ejecutable esté actualizado con el código fuente.O,make run
, para ejecutar el programa,construirlo primero si es necesario(es decir, si no hay ningún ejecutable actual).
Este archivo MAKE define dos objetivos: all
y run
.
El
all
objetivo no tiene una receta propia, sino que depende delmyProg
objetivo. Este objetivo no está definido explícitamente, por lo que implícitamente indicamake
que se intente compilarmyProg
a partir de cualquier archivo de código fuente que esté disponible en el directorio actual. (Ver elmake
Sin un archivo Makesección anterior para más detalles.)Debido
all
a que el primer objetivo se define explícitamente enMakefile
, se creará cuandomake
se ejecute desde el directorio en el queMakefile
reside. Por lo tanto, hemos configurado las cosas para que ejecutarmake
por sí solo sea equivalente a ejecutarmake all
.El
run
objetivo ejecuta el programa. Su receta consta del comando que lo hace,./myProg
.run
declara elall
objetivo como una dependencia. Esto hace que cuando ejecutemake run
,myProg
se reconstruya si elmyProg
ejecutable actual no es actual (o aún no existe).También podríamos haber
run
dependido demyProg
en lugar deall
, pero aún así habríamos necesitado elall
objetivo explícito (o un objetivo equivalente con un nombre diferente) para evitarrun
ser el objetivo predeterminado. Por supuesto, si desea que su programa esté construidoy correrIncluso cuando lo ejecutasmake
solo, puedes hacer esto.Otro beneficio de depender del
all
objetivo es en caso de que más adelante deban realizarse más acciones antes de ejecutar el programa. Luego podrías agregar una receta a la regla paraall
.
El uso del archivo MAKE para ejecutar el programa se ve así, si es necesario compilarlo:
$ cd myProg/
$ make run
g++ myProg.cpp -o myProg
./myProg
Salam! World
O esto, si no es necesario construirlo:
$ make run
./myProg
Salam! World
Y si solo desea asegurarse de que el programa esté compilado (desde la última modificación del archivo de código fuente)sin ejecutar el programa, simplemente ejecuta make
sin argumentos:
$ 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
seguirá funcionando también).
Un refinamiento: indicadores del compilador personalizados
make
es una herramienta extremadamente poderosa, útil para propósitos simples como este pero también adecuada para proyectos grandes y complejos. Intentar detallar todas las cosas que puedes hacer con él make
sería un libro completo (específicamente,Éste).
Pero se me ocurrió que tal vez quieras ver advertencias del compilador, cuando algo no impide que se complete la compilación pero aún así es un error potencial. Estos no detectarán todos los errores de los programas que escriba, pero pueden detectar muchos.
Cuando use GCC (como con el g++
comando), recomiendo pasar al menos -Wall
al compilador. Esto en realidad no permitetodoadvertencias, pero puedes habilitar la mayoría del resto con -Wextra
. Es posible que a veces también quieras -pedantic
. (Verman gcc
y3.8Opciones para solicitar o suprimir advertenciasen elmanual de referencia del CCG.)
Para invocar g++
manualmente con estas banderas, ejecutarías:
g++ -Wall -Wextra -pedantic -o myProg myProg.cpp
Para make
invocar el compilador de C++ ( g++
) con las banderas -Wall
, -Wextra
y -pedantic
, agregue una CXXFLAGS=
línea con ellas en la parte superior de Makefile
.
CXXFLAGS=-Wall -Wextra -pedantic
all: myProg
run: all
./myProg
Aunque myProg
todavía existe y es más nuevo que myProg.cpp
, al ejecutarlo make
o make run
después de editarlo Makefile
se compilará el programa nuevamente, porque Makefile
ahora es más nuevo que myProg
. Esto es bueno porque:
- En este caso, reconstruir el ejecutable hace que vea advertencias, si las hay (no debería haberlas, para ese programa en particular).
- De manera más general, a veces cuando editas un archivo MAKE es porque quieres que se produzcan archivos diferentes o que se produzcan con contenidos diferentes. (Por ejemplo, si hubiera agregado la
-O3
marca para optimizaciones intensas o-g
para hacer que el compilador genere símbolos de depuración, elmyProg
ejecutable resultante sería diferente).
Otras lecturas
- Ejercicio 2: Crea tu Python ahoraenAprenda C de la manera difícilporZed Shaw.
- ElManual de creación de GNU, especialmente2.1Cómo se ve una regla.
- Un sencillo tutorial de MakefileporBruce A.Maxwell, para obtener información sobre otras formas de uso
make
. - "Uso de Makefiles" (p. 15) y "Makefiles frente a scripts de Shell" (p. 62) enSiglo XXI CporBen Klemens. Los números de página corresponden a la primera edición. (La segunda edición probablemente sea mejor, pero sólo tengo la primera edición).
Notas
0: Recomiendo seguir leyendo para ver cómo hacer que esto funcione. Pero en caso de que quieras intentarlo tú mismo primero: debes sangrar las líneas con tabulaciones en lugar de espacios.
1: Estrictamente hablando, prácticamente cualquier lenguaje de programación podría interpretarse o compilarse dependiendo de quéimplementacionesporque ha sido escrito. Para algunos lenguajes, existen tanto intérpretes como compiladores. Sin embargo, C++ interpretado es poco común, aunqueno es inaudito.
2: Dividir el edificio encompilandoyenlacey llamar a la traducción de un archivo de código fuente C++ (.cc/.cpp/.cxx/.C) a código objetocompilando, no es toda la historia. Los programas en C y C++ (y algunos otros lenguajes) son los primerospreprocesado. En su programa, elpreprocesador Cse reemplaza #include<iostream>
con el contenido del <iostream>
archivo de encabezado antes de que comience la compilación real. Y en el sentido más estricto, la compilación convierte el código fuente enlenguaje ensambladoren lugar de código objeto. Muchos compiladores (como GCC/ g++
) pueden combinar compilación y ensamblaje en un solo paso y no producen código ensamblador a menos que se les solicite.
Si bien el preprocesamiento es un paso independiente, GCC y otros compiladores ejecutan automáticamente el preprocesador. De manera similar, pueden ejecutar automáticamente el vinculador, razón por la cual toda la secuencia depreprocesamiento,Compilacion,asamblea, yenlaceA veces se le llama "compilar" en lugar de "construir". (Tenga en cuenta también que la construcción puede contener más que esos pasos; por ejemplo, puede implicar generar archivos de recursos, ejecutarun script para configurar cómo se construirán las cosas, etc.)
3: Sólo tienes que sangrar con pestañas en el propio archivo MAKE. El uso de un archivo MAKE no impone ningún requisito sobre la forma en que escribe los archivos de código fuente de C++. Siéntete libre de cambiar la sangría de tabulaciones a espacios cuando estés trabajando en otros archivos. (Y si tuen realidadSi no te gusta sangrar con pestañas en un archivo MAKE, puedes configurar el.RECIPEPREFIX
variable especial.)
Respuesta3
Aquí hay un ejemplo: de myBash.sh
#!/bin/sh
g++ myProg.cpp -o myProg
./myProg