Veja nesse artigo como utilizar a biblioteca cpptask junto com Ant / Maven para compilar programas e bibliotecas feitas em C/C++.

Java e C++

Figura 1: Java e C++

Introdução

As linguagens Java e C/C++ são amplamente utilizadas na área de TI, e com certeza, muitos desenvolvedores gostariam de integrar suas aplicações C/C++ com o Ant / Maven, a fim de incorporá-los ao processo de build e/ou integração contínua.

Veremos nesse artigo como efetuar esse processo, através da biblioteca cpptask.

Cpptask

Para integrar a compilação do código C/C++ com o Ant/Maven, usaremos a lib cpptask. Para isso, devemos efetuar o download em:

Nota: A versão utilizada é a cpptasks-1.0b5.Esse artigo utilizará a plataforma Solaris como ambiente de desenvolvimento.

Passos:

  • Depois de baixar o arquivo (cpptasks-1.0b5.zip), descompacte-o. O diretório cpptasks-1.0b5 será criado.
  • Se você procurar, não irá encontrar nenhum arquivo jar. Teremos que gerá-la.
  • Note que dentro do diretório cpptasks-1.0b5 existem os seguintes arquivos:
  1. build.xml
  2. LICENSE
  3. NOTICE
  4. pom.xml
  5. site
  6. src
  7. sun_checks.xml

Ou seja, podemos usar tanto o ant (build.xml), como o maven (pom.xml) para construir a lib.

Usando o ANT

  • Verificar se o jar ant.jar está no CLASSPATH (cpptask depende desse jar)
  • Entrar no diretório onde o cpptask foi descompactado
  • Digitar: ant
  • Será criado o diretório target. Dentro de target existe um diretório lib que contém o jar cpptasks.jar
  • Adicionar o jar cpptasks.jar no CLASSPATH

Usando o Maven

  • Entrar no diretório onde o cpptask foi descompactado
  • Digitar: mvn compile
  • Digitar: mvn install
  • Será criado o diretório target. Dentro desse diretório estará a lib cpptasks-1.0b5.jar.
  • Adicionar o jar no CLASSPATH

Nota: Caso haja problemas, incluir o jar no diretório lib dos pacotes do ant.

Primeiro Exemplo

Crie o seguinte build.xml:

Listagem 1: build.xml para compilar programa C


<project name="hello" default="compile">
    <taskdef resource="cpptasks.tasks"/>
    <target name="compile">
        <mkdir dir="target/main/obj"/>
        <cc outtype="executable" subsystem="console" outfile="target/hello" objdir="target/main/obj">
           <fileset dir="src/" includes="*.c"/>
        </cc>
    </target>
</project>

No mesmo diretório do build.xml, crie a basta src. Dentro de src, crie o seguinte arquivo c:

Listagem 2: Hello world em C


#include <stdio.h>

int main() {
        printf ("\nHello World");
        return 1;
}

Agora execute o comando ant no mesmo diretório onde se encontra o arquivo build.xml. Será criada a pasta target, com o binário hello. Ao executá-lo, temos:

Listagem 3: Saída de hello


  ./hello
  HelloWorld

Analisaremos agora os pontos importantes de build.xml:

Listagem 4: taskdef


    <taskdef resource="cpptasks.tasks"/>

Adiciona a task CCTask (definida no arquivo de resource cpptasks.tasks), para que possamos utilizar a tag cc.

Listagem 5: task cc


<cc outtype="executable" subsystem="console" outfile="target/hello" objdir="target/main/obj">
<fileset dir="src/" includes="*.c"/>
</cc>

Estamos definindo a compilação dos fontes em C:

  • outtype – Define o tipo arquivo de saída. No caso um arquivo executável
  • subsystem – Define a natureza do sistema onde será executado. No caso, via console
  • outfile – Nome do arquivo de saída
  • objdir – Diretório de destino dos arquivos object.

A definição completa encontra-se em: http://ant-contrib.sourceforge.net/cpptasks/antdocs/CCTask.html.

Vejamos agora, outros recursos de cc.

Listagem 6: Exemplo mais complexo de build.xml


<project name="parteC" default="compile">
    <taskdef resource="cpptasks.tasks"/>
    <target name="compile">
        <mkdir dir="utilUnitTest/lib"/>
        <cc outtype="shared" subsystem="console" outfile="lib/UtilUnitTest" objdir="utilUnitTest/src" debug="on">
                <fileset dir="utilUnitTest/src" includes="*.c"/>
                <includepath path="utilUnitTest/include"/>
        </cc>
    </target>
</project>

Nesse caso, estamos:

  • Ativando o modo debug (debug=”on”). Assim erros do gcc serão impressos.
  • Definindo a saída como shared, ou seja, biblioteca dinâmica. Ao definir esse tipo de saída, o arquivo gerado terá o nome: libUtilUnitTest.so (note que o prefixo lib e o sufixo .so são adicionados automaticamente)
  • usamos <includepath> para informar onde estão os .h usados pelos arquivos .c.

Nota: Ao não definir um compilador default, o gcc será utilizado.

Compilando no Windows ou no Linux

O build.xml a seguir, demonstra como utilizar compilação condicional multiplataforma:

Listagem 7: build multi-plataforma


<?xml version="1.0"?>
<project name="Hello" default="hello" basedir=".">
 <taskdef resource="cpptasks.tasks"/>
 <typedef resource="cpptasks.types"/>
 <target name="init">
  <condition property="cc" value="msvc">
   <os family="windows"/>
  </condition>
  <condition property="cc" value="gcc">
   <os family="unix"/>
  </condition>
 </target>
 <target name="hello" depends="init">
  <cc name="${cc}" outfile="hello">
   <fileset dir="." includes="hello.c"/>
  </cc>
 </target>
</project>

Observe que, nesse exemplo, o compilador a ser executado (gcc no Unix ou msvc no Windows), é definido através da task condition do Ant, onde definimos o compilador padrão a partir do sistema onde ele será executado. (build.xml extraído de http://www.drdobbs.com/cpp/ant-cpptasks-multiplatform-cc-projects/184405433)

Integrando Ant Com Maven

Podemos também utilizar o Maven para gerar o build dos programas C/C++. Para isso, basta utilizar o plugin maven-antrun. Por exemplo:

Listagem 8: Hello World com Maven: pom.xml


<project>
        <modelVersion>4.0.0</modelVersion>
        <artifactId>my-test-app</artifactId>
        <groupId>my-test-group</groupId>
        <version>1.0-SNAPSHOT</version>
        <build>
        <plugins>
           <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-antrun-plugin</artifactId>
              <version>1.7</version>
              <dependencies>
               <dependency>
                 <groupId>cpptasks-1.0b5</groupId>
                 <artifactId>cpptasks</artifactId>
                 <version>1.0b5</version>
                 <scope>system</scope>
                 <systemPath>/export/home/ms27817/dev/cpptasks-1.0b5/target/cpptasks-1.0b5.jar</systemPath>
                 </dependency>
                </dependencies>
                <executions>
                 <execution>
                   <id>cpp source</id>
                     <phase>compile</phase>
                       <configuration>
                         <target>
                           <ant antfile="${basedir}/build.xml">
                             <target name="compile"/>
                           </ant>
                         </target>
                        </configuration>
                        <goals>
                          <goal>run</goal>
                        </goals>
                      </execution>
                   </executions>
                </plugin>
        </plugins>
        </build>
</project>

O arquivo pom.xml utiliza o plugin maven-antrun-plugin, que permite executar comandos Ant dentro do Maven.

As partes mais importantes são:

Listagem 9: Dependência de CppTask


<dependency>
   <groupId>cpptasks-1.0b5</groupId>
   <artifactId>cpptasks</artifactId>
   <version>1.0b5</version>
   <scope>system</scope>
   <systemPath>/export/home/ms27817/dev/cpptasks-1.0b5/target/cpptasks-1.0b5.jar</systemPath>
</dependency>

Onde informamos ao Maven que o jar cpptasks-1.0b5.jar é uma dependência.

Listagem 10: Invocando o ANT


<target>
	<ant antfile="${basedir}/build.xml">
          <target name="compile"/>
	</ant>
</target>

Aqui, o arquivo build.xml definido na Listagem 1 é utilizado. Portanto, a task ant irá executar a target compile do build.xml para gerar o binário de hello world.

Conclusão

A biblioteca cpptask é realmente muito útil, ao permitir que código C/C++ seja integrado as ferramentas Ant/Maven, substituindo o make, e com isso favorecendo o build integrado do sistema.

Obrigado e até a próxima!

Referências