Posso chamar um programa .cpp no ​​Bash?

Posso chamar um programa .cpp no ​​Bash?

Eu sou novo em programação Bash. Quero chamar meu programa C++ no arquivo Bash.

Meu programa é myProg.cpp:

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

E meu arquivo bash é myBash.sh. Como posso chamar meu programa .cpp acima em myBash.sharquivo?

Responder1

Você precisa compilá-lo primeiro: primeiro altere o diretório de trabalho atual do Terminal para o caminho do seu arquivo fonte:

cd <path_to_cpp_file>/

Em seguida, compile o arquivo fonte:

g++ myProg.cpp -o myProg

Então você pode chamar o executável compilado do seu bashscript assim:

#!/bin/bash

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

Responder2

Desde o seuobjetivo realparece ser automatizar tudo o que precisa ser feito para executar seu programa, sugiro uma abordagem diferente.Em vez de escrever um script de shell, você pode usar umarquivo make.Se desejar, você pode escrever uma regra em seu makefile para executar seu executável depois de compilado. Você terá então dois arquivos - seu arquivo de código-fonte C++ e seu makefile - e poderá executar um único comando com eficiência:

  1. Constrói ou reconstrói seu programa C++,se e somente se necessário.
  2. Executa seu programa.

As seções subsequentes desta postagem explicam por que você não pode chamar um .cpparquivo diretamente (mas deve primeiro criar um executável a partir dele); como instalar make, como usá-lo e o que ele faz nos bastidores; e como evitar armadilhas comuns. Mas caso você queira ter uma ideia de como é essa abordagem antes de se aprofundar, você correrá make rundepois de colocar isso0em Makefile:

all: myProg

run: all
    ./myProg

Eu gosto mais disso para esse propósito do que de um script de shell, e acho que você também pode gostar.

Fundo

Ao contrário de algunslinguagens interpretadascomo Python e Bash, C++ é umlinguagem compilada.1Os programas escritos em C++ devem serconstruídoantes de serem executados. (Edifício também é às vezes chamadocompilando, no entantocompilandomais apropriadamente refere-se a uma das etapas de construção.) Você não pode executar um C++Código fontearquivo; em vez disso, deve ser compilado emcódigo objeto2, nesse casolinguagem de máquina. Os arquivos objeto devem então ser vinculados entre si e, mesmo que haja apenas um, ele ainda deve ser vinculado a qualquerbibliotecas compartilhadasele usa. A vinculação produz umexecutávelque pode ser executado.

Resumindo, você precisa construir seu programa antes de executá-lo,a primeira vez. Antes das execuções subsequentes não é necessárioconstruído, a menos que você tenha alterado seu código-fonte; nesse caso, você deverá compilá-lo novamente se quiser que suas alterações sejam refletidas no programa que é executado.A makeutilidadefoi projetado especificamente para esse tipo de situação, onde se deseja realizar açõescondicionalmentedependendo se já foram feitas ou não e quando.

Recebendomake

Talvez você já tenha o makecomando instalado; tente executá-lo para descobrir. Se estiver instalado, você verá algo como:

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

Para obter o make você pode instalar ofazer Instalar fazerpacote, mas sugiro instalaressencial para construção Instalar build essencialque fornece uma série de outras ferramentas úteis. (Você pode ter instaladoessencial para construção Instalar build essencialpara obter g++, que é uma maneira que você já deve ter make.) Você pode usar o Centro de Software para instalá-lo ou executar o comando:

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

makeSem Makefile

Para ver como makefunciona, sugiro executá-lo primeiro sem um makefile, passando a ele o nome base do seu arquivo de código-fonte:

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

Nas execuções subsequentes, makecompara os carimbos de data/hora da modificação (mtimes) nos arquivos de entrada e saída e não reconstruirá seu programa desnecessariamente:

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

Quando você altera myProg.cpp, isso atualiza seu carimbo de data/hora de modificação, então makesaberá como reconstruí-lo. (Você também pode atualizar o carimbo de data/hora de um arquivo com otouchcomando, se você precisar ou quiser forçar a reconstrução de qualquer arquivo de saída dependendo dele. E, claro, excluir os arquivos de saída também garantirá que eles sejam reconstruídos quando você executar make- apenas não exclua o arquivo errado!)

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

Como você makesabe o que fazer quando corre make myProg?

  • O myProgargumento para makeé chamado dealvo.
  • Os alvos são frequentemente, mas nem sempre, os nomes dos arquivos a serem criados. Os alvos podem ser definidos explicitamente em um makefile.
  • Quando um alvo não está definido no makefile ou (como neste caso) não há makefile, makeprocura por arquivos de entrada (ou seja, código fonte) nomeados de forma a sugerir que eles se destinam à construção do alvo.
  • makeinfere qual utilidade e sintaxe usar na construção de um arquivo a partir de seu sufixo (neste caso, .cpp).

Tudo isso pode ser customizado, mas em casos simples como esse muitas vezes não é necessário.

Criando um Makefile para automatizar a construção e execução do seu programa

Para automatizar tarefas mais complexas do que construir um programa a partir de um único arquivo de código-fonte, como se houver vários arquivos de entrada ou (mais aplicável às suas necessidades imediatas) ações que você deseja realizar além de executar o compilador, você pode criar um makefile para definir alvos para makee especificar como eles dependem de outros alvos.

O primeiro alvo definido em um makefile é o alvo padrão: é o que maketenta construir quando executado sem argumentos de linha de comando (ou seja, quando você executa apenas make, e não algo como make myProg).

A maneira usual de usar makefiles é criar um diretório contendo todos os arquivos de código-fonte (e quaisquer outros arquivos) usados ​​para construir seu programa, bem como o makefile, que geralmente é chamado de Makefile. Por esse nome, makevocê o encontrará automaticamente.

Para criar um makefile que você pode usar para executar myProge que irá construí-lo automaticamente primeiro quando necessário, coloque myProg.cppem um novo diretório, caso contrário, vazio. Crie outro arquivo de texto nesse diretório chamado Makefile.

Você pode usar qualquer editor de texto para isso, mas a receita para uma regra - os comandos listados abaixo dela que serão executados para definir seu destino - deve ser indentada comguiasem vez deespaços.3Portanto, se o seu editor de texto estiver configurado para recuar espaços quando você pressionar Tab, você deverá alterar isso.

Por exemplo, no Gedit ou Pluma, você entrariaEditar > Preferências, Clique noeditorguia e certifique-seInsira espaços em vez de tabulaçõesestá desmarcado:

Captura de tela mostrando a caixa de diálogo Preferências no Pluma - cuja interface é essencialmente a mesma do Gedit - indicando a localização da caixa de seleção Inserir espaços em vez de guias perto do topo da guia Editor

Muitos editores usam como padrão o recuo com tabulações e não espaços, portanto, se você não alterou essa configuração antes, ela já pode estar definida corretamente para makefiles.

Quando estiver em seu editor e (se necessário) configurado para recuar com tabulações, coloque isto em:

all: myProg

run: all
    ./myProg

Se você copiar e colar isso, estará erradoporque os espaços serão eliminados mesmo que o seu editor de texto não os crie quando você pressionar Tab. (Isso tem a ver com a maneira como o Ask Ubuntu exibe o código.) Mas você pode simplesmente remover os quatro espaços anteriores ./myProge pressionar Tabpara criar uma guia em seu lugar.

Alguns editores de texto mostram uma tabulação com 8 espaços ou algum outro número. Isso é bom.

O que esse Makefile faz e como usá-lo

Use o comando:

  • make, para compilar o programa, a menos que ele já esteja compilado e o executável seja atual para o código-fonte.Ou,
  • make run, para executar o programa,construí-lo primeiro, se necessário(ou seja, se não houver nenhum executável atual).

Este makefile define dois alvos: alle run.

  • O allalvo não tem receita própria, mas depende do myProgalvo. Este destino não é definido explicitamente, portanto, diz implicitamente makepara tentar construir myProga partir de quaisquer arquivos de código-fonte disponíveis para ele no diretório atual. (Veja omakeSem Makefileseção acima para obter detalhes.)

    Como allé o primeiro destino definido explicitamente em Makefile, ele será construído quando makefor executado a partir do diretório em que Makefilereside. Assim, configuramos as coisas para que correr makepor si só seja equivalente a correr make all.

  • O runalvo executa o programa. Sua receita consiste no comando que faz isso, ./myProg. rundeclara o allalvo como uma dependência. Isso faz com que, quando você executa make run, myProgseja reconstruído se o executável atual myPrognão for atual (ou ainda não existir).

    Poderíamos muito bem ter feito rundepend on myProgem vez de on all, mas ainda precisaríamos do allalvo explícito (ou um alvo equivalente com um nome diferente) para evitar runque fosse o alvo padrão. Claro, se você quiser que seu programa seja construídoe corramesmo quando você corre makesozinho, você pode fazer isso.

    Outro benefício de depender do allalvo é caso mais tarde haja mais ações que devem ser tomadas antes que seu programa seja executado. Você poderia então adicionar uma receita à regra para all.

Usar o makefile para executar o programa fica assim, se precisar ser compilado:

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

Ou isto, se não precisar ser construído:

$ make run
./myProg
Salam! World

E se você quiser apenas ter certeza de que o programa foi compilado (desde que o arquivo do código-fonte foi modificado pela última vez)sem executar o programa, simplesmente execute makesem 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 myProgainda funcionará também.)

Um refinamento: sinalizadores de compilador personalizados

makeé uma ferramenta extremamente poderosa, útil para propósitos simples como este, mas também adequada para projetos grandes e complexos. Tentar detalhar todas as coisas que você pode fazer makedaria um livro inteiro (especificamente,Este).

Mas me ocorreu que você pode querer ver avisos do compilador, quando algo não impede a conclusão da compilação, mas ainda é um erro em potencial. Eles não detectarão todos os bugs dos programas que você escreve, mas poderão detectar muitos.

Ao usar o GCC (como acontece com o g++comando), recomendo passar pelo menos -Wallpara o compilador. Na verdade, isso não permitetodosavisos, mas você pode ativar a maior parte do restante com -Wextra. Às vezes você também pode querer -pedantic. (Verman gcce3.8Opções para solicitar ou suprimir avisosnoManual de referência do GCC.)

Para invocar g++manualmente com esses sinalizadores, você executaria:

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

Para makeinvocar o compilador C++ ( g++) com os sinalizadores -Wall, -Wextrae -pedantic, adicione uma CXXFLAGS=linha com eles no topo de Makefile.

CXXFLAGS=-Wall -Wextra -pedantic

all: myProg

run: all
    ./myProg

Mesmo que myProgainda exista e seja mais recente que o myProg.cpp, a execução makeou make runapós a edição Makefileainda criará o programa novamente, porque Makefileagora é mais recente que o myProg. Isso é bom porque:

  • Nesse caso, reconstruir o executável faz com que você veja avisos, se houver algum (não deveria haver, para aquele programa específico).
  • De forma mais geral, às vezes quando você edita um makefile é porque você deseja que arquivos diferentes sejam produzidos ou que sejam produzidos com conteúdos diferentes. (Por exemplo, se você tivesse adicionado o -O3sinalizador para otimizações pesadas ou -gpara fazer o compilador gerar símbolos de depuração, o myProgexecutável resultante seria diferente.)

Leitura adicional

Notas

0: Recomendo ler mais para ver como fazer isso funcionar. Mas caso você queira tentar primeiro: você deve recuar as linhas com tabulações em vez de espaços.

1: Estritamente falando, praticamente qualquer linguagem de programação poderia ser interpretada ou compilada dependendo do queimplementaçõespois está escrito. Para algumas linguagens, existem intérpretes e compiladores. No entanto, C++ interpretado é incomum - emboranão é inédito.

2: Dividindo o edifício emcompilandoevinculandoe chamando a tradução de um arquivo de código-fonte C++ (.cc/.cpp/.cxx/.C) em código objetocompilando, não é toda a história. Programas em C e C++ (e algumas outras linguagens) são os primeirospré-processado. No seu programa, oPré-processador Csubstitui #include<iostream>pelo conteúdo do <iostream>arquivo de cabeçalho antes do início da compilação real. E no sentido mais restrito, a compilação converte o código-fonte emlinguagem assemblyem vez de código objeto. Muitos compiladores (como GCC/ g++) podem combinar compilação e montagem em uma única etapa e não produzem código assembly a menos que solicitado.

Embora o pré-processamento seja uma etapa separada, o GCC e outros compiladores executam automaticamente o pré-processador. Da mesma forma, eles podem executar automaticamente o vinculador, e é por isso que toda a sequência depré-processando,compilação,conjunto, eligaçãoàs vezes é chamado de "compilar" em vez de "construir". (Observe também que a construção pode conter mais do que essas etapas - por exemplo, pode envolver a geração de arquivos de recursos, a execução deum script para configurar como as coisas serão construídas, etc.)

3: Você só precisa recuar com tabulações no próprio makefile. Usar um makefile não impõe nenhum requisito à maneira como você escreve seus próprios arquivos de código-fonte C++. Sinta-se à vontade para mudar o recuo de tabulações para espaços quando estiver trabalhando em outros arquivos. (E se vocêrealmentenão gosta de recuar tabulações em um makefile, você pode definir o.RECIPEPREFIX variável especial.)

Responder3

Aqui está um exemplo: de myBash.sh

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

informação relacionada