Abreviando comando de compilação

3

Existe alguma maneira de encurtar este comando de compilação openCV?

g++ file.cpp -o newFileName 'pkg-config --cflags --libs opencv'

Eu tentei adicionar:

-o newFileName 'pkg-config --cflags --libs opencv'

para um alias, mas ele continua retornando o comando não encontrado, existe alguma outra maneira de encurtar este comando?

EDITAR:

De acordo com as sugestões abaixo, criei um makefile com o seguinte conteúdo:

OPENCV='pkg-config --cflags --libs opencv'
%: %.cpp
    $(CXX) -o $* $*.cpp $(OPENCV)

mas quando executo make surfPoints , estou obtendo a seguinte saída (o arquivo é compilado corretamente quando o comando é executado manualmente):

$ make surfPoints
g++ -o surfPoints surfPoints.cpp 
/tmp/ccxxAU92.o: In function 'main':
surfPoints.cpp:(.text+0x81): undefined reference to 'cv::imread(std::string const&, int)'
surfPoints.cpp:(.text+0xf3): undefined reference to 'cv::imread(std::string const&, int)'
surfPoints.cpp:(.text+0x17f): undefined reference to 'cv::SURF::SURF(double, int, int, bool, bool)'
surfPoints.cpp:(.text+0x1d0): undefined reference to 'cv::FeatureDetector::detect(cv::Mat const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >&, cv::Mat const&) const'
surfPoints.cpp:(.text+0x212): undefined reference to 'cv::FeatureDetector::detect(cv::Mat const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> >&, cv::Mat const&) const'
surfPoints.cpp:(.text+0x280): undefined reference to 'cv::drawKeypoints(cv::Mat const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> > const&, cv::Mat&, cv::Scalar_<double> const&, int)'
surfPoints.cpp:(.text+0x2c1): undefined reference to 'cv::drawKeypoints(cv::Mat const&, std::vector<cv::KeyPoint, std::allocator<cv::KeyPoint> > const&, cv::Mat&, cv::Scalar_<double> const&, int)'
surfPoints.cpp:(.text+0x2d7): undefined reference to 'cv::_InputArray::_InputArray(cv::Mat const&)'
surfPoints.cpp:(.text+0x30b): undefined reference to 'cv::imshow(std::string const&, cv::_InputArray const&)'
surfPoints.cpp:(.text+0x339): undefined reference to 'cv::_InputArray::_InputArray(cv::Mat const&)'
surfPoints.cpp:(.text+0x36d): undefined reference to 'cv::imshow(std::string const&, cv::_InputArray const&)'
surfPoints.cpp:(.text+0x38f): undefined reference to 'cv::waitKey(int)'
/tmp/ccxxAU92.o: In function 'cv::Mat::~Mat()':
surfPoints.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x39): undefined reference to 'cv::fastFree(void*)'
/tmp/ccxxAU92.o: In function 'cv::Mat::release()':
surfPoints.cpp:(.text._ZN2cv3Mat7releaseEv[_ZN2cv3Mat7releaseEv]+0x47): undefined reference to 'cv::Mat::deallocate()'
/tmp/ccxxAU92.o: In function 'cv::Feature2D::~Feature2D()':
surfPoints.cpp:(.text._ZN2cv9Feature2DD2Ev[_ZN2cv9Feature2DD2Ev]+0x69): undefined reference to 'cv::DescriptorExtractor::~DescriptorExtractor()'
surfPoints.cpp:(.text._ZN2cv9Feature2DD2Ev[_ZN2cv9Feature2DD2Ev]+0x80): undefined reference to 'cv::FeatureDetector::~FeatureDetector()'
surfPoints.cpp:(.text._ZN2cv9Feature2DD2Ev[_ZN2cv9Feature2DD2Ev]+0x98): undefined reference to 'cv::Algorithm::~Algorithm()'
surfPoints.cpp:(.text._ZN2cv9Feature2DD2Ev[_ZN2cv9Feature2DD2Ev]+0xcc): undefined reference to 'cv::FeatureDetector::~FeatureDetector()'
surfPoints.cpp:(.text._ZN2cv9Feature2DD2Ev[_ZN2cv9Feature2DD2Ev]+0xe9): undefined reference to 'cv::Algorithm::~Algorithm()'
/tmp/ccxxAU92.o: In function 'cv::SURF::~SURF()':
surfPoints.cpp:(.text._ZN2cv4SURFD1Ev[_ZN2cv4SURFD1Ev]+0xe): undefined reference to 'vtable for cv::SURF'
surfPoints.cpp:(.text._ZN2cv4SURFD1Ev[_ZN2cv4SURFD1Ev]+0x26): undefined reference to 'vtable for cv::SURF'
surfPoints.cpp:(.text._ZN2cv4SURFD1Ev[_ZN2cv4SURFD1Ev]+0x2e): undefined reference to 'vtable for cv::SURF'
surfPoints.cpp:(.text._ZN2cv4SURFD1Ev[_ZN2cv4SURFD1Ev]+0x3b): undefined reference to 'VTT for cv::SURF'
surfPoints.cpp:(.text._ZN2cv4SURFD1Ev[_ZN2cv4SURFD1Ev]+0x62): undefined reference to 'cv::Algorithm::~Algorithm()'
surfPoints.cpp:(.text._ZN2cv4SURFD1Ev[_ZN2cv4SURFD1Ev]+0x97): undefined reference to 'cv::Algorithm::~Algorithm()'
collect2: error: ld returned 1 exit status
make: *** [surfPoints] Error 1
    
por Colin747 24.01.2014 / 17:14

3 respostas

3

make é a ferramenta de que você precisa. Você só precisa digitar make com o Makefile no lugar e seu arquivo será criado.

Aqui está um Makefile simples que geraria o arquivo newFileName de acordo com a linha que você postou na pergunta:

MYFLAGS=$(shell pkg-config --cflags --libs opencv)

newFileName: file.cpp
    $(CXX) $< -o $@ $(MYFLAGS)

Se você colocar isso em seu diretório de código, simplesmente digite make e seu código será compilado.

Breve explicação:

  • make procurará o Makefile no diretório;
  • Como o arquivo está lá, make executará a primeira regra: newFileName e a executará;
  • Esta sintaxe de regra é a seguinte:
    • newFileName: define o nome da regra, ou destino, preferencialmente o nome do arquivo que a regra vai rodar;
    • Tudo após o : são pré-requisitos, ou seja, arquivos que serão necessários para a execução da receita desta regra ou regras que devem ser executadas antes;
    • A (s) linha (s) abaixo é a receita (observe os 4 espaços no início da linha), eles dizem como fazer o arquivo newFileName .
  • $(CXX) será expandido para o compilador C ++ padrão e MYFLAGS será expandido para a saída de pkg-config --cflags --libs opencv .

Bônus: o Make executará a receita de uma regra somente se os pré-requisitos tiverem sido alterados após o carimbo de data e hora da criação do destino, portanto, se você digitar make e já tiver um date newFileName, você não perderá tempo recompilando algo que você já possui. Isso é especialmente bom quando você tem muitos arquivos.

    
por 24.01.2014 / 18:07
3

Quanto mais cedo você aprender a usar make , melhor. Crie um makefile no mesmo diretório que file.cpp - beware make requer o uso de uma aba real para recuar. Se você usar espaços, obterá um Erro "separador ausente":

OPENCV='pkg-config --cflags --libs opencv'

newFileName: file.cpp
    $(CXX) -o newFileName file.cpp $(OPENCV)

Para criar, basta executar make nesse diretório. Isso verificará a regra para o primeiro alvo no makefile. Nesse caso, há apenas um, a meta newFileName . Como file.cpp é um pré-requisito , se um arquivo com o nome de destino não existir ou existir, mas a hora da modificação do pré-requisito for mais recente (ou seja, você modificou file.cpp desde newFileName foi criado pela última vez), a receita será executada.

Para garantir que $(CXX) esteja definido em seu sistema, execute make -p | grep CXX em um diretório com NO makefile . A saída deve incluir CXX = g++ .

Se você adicionar outro destino, por exemplo:

otherFile: file2.cpp
    $(CXX) -o otherFile file2.cpp $(OPENCV)

Você pode executar essa regra usando o nome de destino, make otherFile . Novamente, se nenhum alvo for dado, o primeiro no makefile é usado.

Como esses dois destinos seguem um padrão idêntico, se você usou nomes executáveis que correspondem a nomes de arquivos de origem, você pode fazer isso:

%: %.cpp
    $(CXX) -o $* $*.cpp $(OPENCV)

Agora, make whatever será executado

g++ -o whatever whatever.cpp 'pkg-config --cflags --libs opencv'

Veja Como os padrões correspondem e Automatic Variables para uma explicação de como isso funciona.

Make se torna especialmente útil à medida que você começa a fazer coisas mais complexas - compilando arquivos de objeto ( .o ) e combinando-os em executáveis, etc. Eventualmente, você terá que aprender para usar algum tipo do sistema de compilação, e make é o mais comum no mundo * nix.

    
por 24.01.2014 / 18:08
2

Você tem 3 opções para encurtar coisas em um shell típico, como Bash.

  1. Crie um script de shell
  2. Crie um alias
  3. Faça uma função

Eu mostrarei para você 2 & 3.

alias

Você poderia fazer algo assim como um alias.

$ alias mygcc='g++ file.cpp -o newFileName $(pkg-config --cflags --libs opencv)'

A maior limitação com um alias é que você não pode realmente passar uma lista de argumentos. Pense em um alias como uma macro que explodirá em uma string mais longa, mas essa string foi efetivamente corrigida. Não é possível substituir valores em pontos diferentes na string.

Você pode conseguir um pouco posicionando estrategicamente um nome de arquivo ou outros argumentos para que eles ocorram no final do alias.

$ alias myalias='ls -l'

$ myalias -d
drwxrwxr-x. 2 saml saml 4096 Jan 24 11:19 .

$ myalias file1
-rw-rw-r--. 1 saml saml 0 Jan 24 11:19 file1

Então, quando executamos myalias , podemos fornecer nomes de arquivo ou outros switches e isso funciona.

função

As funções podem fazer muito mais. Você pode colocar as coisas aqui como verificação de erro ou executar algum outro comando e armazenar seus resultados em uma variável. Então, fazer disso uma função permitiria manipular argumentos dentro da string.

$ mygcc () { g++ file.cpp -o newFileName $(pkg-config --cflags --libs opencv); }

Indo além?

Se você precisa de mais do que apenas um simples one-liner, então eu recomendo que você procure usar uma ferramenta adequada como o Make, o CMake ou qualquer uma das inúmeras ferramentas de criação de dependência.

A seleção de uma ferramenta de construção deve ser uma discussão que você e sua equipe tenham, não apenas escolha algo. A escolha deve ser feita para que uma ferramenta apropriada para sua equipe & tecnologias que você está usando para construir seu (s) aplicativo (s).

    
por 24.01.2014 / 17:23