Compilación de programas C++ en entornos Linux

Compilación de un único archivo fuente

Considere el siguiente programa C++ almacenado en saludo.cpp:

/* saludo.cpp */
#include <iostream>
int main() {
    std::cout << "Hola, mundo" << std::endl;
    return 0;
}

Este código utiliza std::cout del encabezado <iostream> para imprimir en la salida estándar. Se compila con:

g++ saludo.cpp

El compilador g++ identifica automáticamente archivos C++ por su extensión. Por defecto, genera un ejecutable llamado a.out, que se ejecuta así:

./a.out

Para especificar un nombre personalizado, use la opción -o:

g++ saludo.cpp -o saludo

También es posible usar gcc directamente si se enlaza explícitamente con la biblioteca estándar de C++:

gcc saludo.cpp -lstdc++ -o saludo

En sistemas donde está disponible, el comando c++ es un alias funcional de g++.

Manejo de múltiples archivos fuente

Dado un proyecto con varios archivos, como los siguientes:

/* hablar.h */
#include <iostream>
class Hablar {
public:
    void saludar(const char* mensaje);
};
/* hablar.cpp */
#include "hablar.h"
void Hablar::saludar(const char* msg) {
    std::cout << "Saludo: " << msg << "\n";
}
/* principal.cpp */
#include "hablar.h"
int main() {
    Hablar h;
    h.saludar("mundo");
    return 0;
}

Se pueden compilar y enlazar juntos en un solo paso:

g++ principal.cpp hablar.cpp -o aplicacion

Los archivos de cabecera (.h) no se especifican en la línea de comandos porque ya están incluidos mediante directivas #include en los archivos fuente.

Generación de archivos objeto

La opción -c compila sin enlazar, produciendo archivos con extensión .o:

g++ -c principal.cpp
g++ -c hablar.cpp

Luego, los objetos se enlazan por separado:

g++ principal.o hablar.o -o aplicacion

Es posible renombrar los archivos objeto con -o:

g++ -c principal.cpp -o mod1.o
g++ -c hablar.cpp -o mod2.o
g++ mod1.o mod2.o -o aplicacion

Preprocesamiento y ensamblado

Para ver el resultado del preprocesador (expansión de macros, inclusión de encabezados, etc.):

g++ -E saludo.cpp

Esto muestra en pantalla el código expandido, que puede superar las 1200 líneas debido a las inclusiones anidadas de <iostream>. Para guardar la salida en un archivo:

g++ -E saludo.cpp -o saludo.ii

Para generar código ensamblador específico de la arquitectura:

g++ -S saludo.cpp

Esto produce saludo.s, legible pero dependiente de la plataforma.

Creación de bibliotecas estáticas

Una biblioteca estática es un archivo de tipo archivo (archive) que contiene múltiples objetos. Considere estos componentes:

/* util.h */
#include <iostream>
void imprimir_mensaje();
class Util {
    char* texto;
public:
    Util(char* s) : texto(s) {}
    void mostrar(const char* prefijo);
    void imprimir_texto();
};
/* util.cpp */
#include "util.h"
void Util::imprimir_texto() {
    std::cout << texto << "\n";
}
void Util::mostrar(const char* p) {
    std::cout << p << " desde biblioteca\n";
}
Util instancia_global("Instancia global");
/* mensaje.cpp */
#include "util.h"
void imprimir_mensaje() {
    std::cout << "Mensaje desde biblioteca estática\n";
}

Primero, compile los archivos a objetos:

g++ -c util.cpp mensaje.cpp

Luego, cree la biblioteca estática usando ar:

ar -r libutil.a util.o mensaje.o

Finalmente, enlace con un programa principal:

/* main.cpp */
#include "util.h"
extern Util instancia_global;
int main() {
    Util local("Instancia local");
    imprimir_mensaje();
    instancia_global.mostrar("Hola");
    instancia_global.imprimir_texto();
    local.imprimir_texto();
    return 0;
}

Compilación final:

g++ main.cpp libutil.a -o programa

Ejecutar ./programa produce:

Hola desde biblioteca
Instancia global
Instancia local

Etiquetas: g++ GCC C++ compilación linux

Publicado el 8-19 00:42