SDK Multiplataforma en C logo

SDK Multiplataforma en C

Compilación remota

❮ Anterior

Ya hemos visto en Compiladores e IDEs como compilar nuestras aplicaciones en diferentes sistemas operativos, así como configurar ciertas opciones en función de cada uno. No obstante, es posible que todo el desarrollo se realice sobre una misma plataforma (o incluso en una misma máquina por una misma persona) pero queramos generar binarios en otras con el fin de probar los avances. Un caso típico puede ser trabajar en Windows y comprobar, al final del día, que los cambios se han integrado bien en macOS y Linux. Recompilar todo el proyecto en varios ordenadores es una tarea aburrida, repetitiva y lenta que nos obliga, sistemáticamente, a movernos de nuestro puesto, actualizar repositorios, re-generar soluciones, esperar a que todo compile sin errores y empaquetar los resultados.

La compilación remota nos ofrece la posibilidad de utilizar los compiladores de otras máquinas de la red desde nuestro propio ordenador, a través de la red local o Internet. Es el paso previo a la Integración Continua donde un programa externo trabajará ininterrumpidamente, en segundo plano y de forma autónoma cada vez que se modifique el contenido del repositorio (Figura 1).

Esquema básico de un sistema de integración contínua.
Figura 1: Sistema de Integración Continua trabajará de forma autónoma en segundo plano.

1. Build grid

Lo primero que tenemos que hacer es configurar una red de computadores heterogénea donde coexistan diferentes máquinas con los compiladores apropiados (Figura 2) y que puedan comunicarse entre ellas como veremos en Habilitar SSH. Los actores principales de esta red son:

  • Build Grid: Red formada por todas las máquinas que van a cooperar en tareas de compilación. Pueden estar distribuidas por Internet.
  • Build Master: Ordenador dentro de la red que ejecuta la utilidad de Integración Continua, coordina al resto de máquinas, almacena los resultados y notifica errores.
  • Build Host/Slave: Máquina destinada a tareas de compilación y test, que será manejada remotamente por el Build Master.
  • Build Agent: Configuración que identifica una versión de compilador y CPU. Por ejemplo, el agente v142_x64 representa a Visual Studio 2019 (VC++) de 64bits. Un agente puede ser ejecutado por cualquier Host que tenga instalado el compilador apropiado. El Build Master se encargará de balancear la carga.
  • Build Profile: Perfil que indica todos los targets (librerías y/o ejecutables) a generar dentro de una solución y que agentes deben intervenir. El Build Master puede manejar varios perfiles al mismo tiempo.
  • Build Config: Indica el nivel de optimización y opciones de depuración de la compilación: Debug, Release, ReleaseWithAssert. Configuraciones.
  • Esquema de una red de compiladores, gobernados por un Build Master.
    Figura 2: Ejemplo de Build Grid.

2. Habilitar SSH

La base de la compilación remota es la comunicación en red o, más concretamente, la posibilidad de ejecutar comandos desde una máquina a otra. A día de hoy el estándar es SSH (Secure Shell), un protocolo y aplicación que permite ejecutar comandos a través de una red, añadiendo una capa de cifrado entre emisor y receptor (Listado 1) (Figura 3). Deberemos asegurar que SSH está presente y funcionando en todas las máquinas del Build Grid.

Listado 1: Obtener la lista de archivos de una máquina remota mediante SSH.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
C:\Users>ssh fran@192.168.1.24 ls
fran@192.168.1.24's password:
Desktop
Documents
Downloads
examples.desktop
Music
Pictures
Public
Templates
Videos
Comunicación de dos ordenadores mediante SSH indicando la encriptación de la información.
Figura 3: El protocolo SSH encripta la información que intercambian dos nodos.

2.1. SSH en Windows

Windows 10 incluye soporte para SSH, pero no está activo por defecto. Debes activarlo en Settings->Apps->Manage Optional Features->Add a Feature->OpenSSH Client/Server (Figura 4). Para asegurar que servicio está funcionando ejecuta services.msc y arranca OpenSSH SSH Server si no está corriendo ya.

Captura de las opciones SSH en Windows 10.
Figura 4: Activación de SSH en Windows.

2.2. SSH en macOS

SSH también está incluido en los sistemas operativos de Apple. Para activarlo:

  • Abre System Preferences desde el menú Apple y haz clic en el panel Sharing.
  • Activa la opción Remote Login (Figura 5).
  • Esto arrancará instantáneamente varios servicios, incluidos SFTP y SSH.

Por razones de seguridad, SSH no accede a todas las variables de entorno del shell bash en macOS. Esto puede provocar que un comando remoto falle, pero que tecleado desde un terminal en la propia máquina sí que funcione. Por ejemplo, esto ocurre al intentar ejecutar cmake o svn de forma remota. Para subsanarlo:

  • Añadimos las rutas necesarias a la variable PATH en /.ssh/environment.
  • Modificación de PATH en /.ssh/environment
    1
    
    PATH=$PATH:/bin:/usr/bin:/usr/local:/usr/local/bin:/Applications/CMake.app/Contents/bin
    
  • Editamos el archivo /private/etc/ssh/sshd_config o /etc/ssh/sshd_config, habilitando la variable PermitUserEnvironment PATH,LANG.
  • Paramos y re-lanzamos el servicio mediante el check Remote Login de Sharing.
  • Captura de las opciones SSH en macOS.
    Figura 5: Activación de SSH en macOS.

2.3. SSH en Linux

Por defecto, SSH no está incluido en Ubuntu. Para esta distribución y otras basadas en Debian, el servicio se instala y activa con este comando.

1
sudo apt-get install openssh-server -y

2.4. SSH sin password

Una vez activado el SSH en todas las máquinas de la red, ya podemos ejecutar comandos remotos desde el Build Master como hemos visto en (Listado 1). El problema es que SSH nos pedirá continuamente la contraseña del usuario remoto, algo molesto y que puede entorpecer la automatización. Para evitar esto, tenemos que instalar el certificado rsa del Build Master en todas las máquinas remotas (los Build Host) para que reconozcan al emisor del comando y no le pidan contraseña.

  • Desde el Build Master, abre un terminal y teclea ssh-keygen. Esto generará dos certificados rsa en .ssh uno privado, que se quedará en el master y otro público que irá al host.
  • Generando el certificado rsa en el Master.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    fran~>ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/fran/.ssh/id_rsa): 
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/fran/.ssh/id_rsa.
    Your public key has been saved in /home/fran/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:Up6KjbnEV4Hgfo75YM393QdQsK3Z0aTNBz0DoirrW+c fran@192.168.1.24
    The key's randomart image is:
    +---[RSA 2048]----+
    |    .      ..oo..|
    |   . . .  . .o.X.|
    |    . . o.  ..+ B|
    |   .   o.o  .+ ..|
    |    ..o.S   o..  |
    |   . %o=      .  |
    |    @.B...     . |
    |   o.=. o. . .  .|
    |    .oo  E. . .. |
    +----[SHA256]-----+
    
  • Copia el archivo id_rsa.pub en el directorio /USER/.ssh de cada Build Host.
  • Paso del certificado rsa del Master al Host
    1
    2
    
    cd .ssh
    scp id_rsa.pub fran@192.168.1.24:/Users/fran/.ssh
    
  • Abre un terminal en el Host remoto y teclea:
  • Instalando el certificado rsa
    1
    2
    3
    4
    5
    
    cd .ssh
    type id_rsa.pub >> authorized_keys   (Windows)
    ...
    cd .ssh
    cat id_rsa.pub >> authorized_keys    (macOS/Linux)
    
  • Si todo ha ido bien, ya podemos ejecutar un comando remoto sin que nos pida contraseña (Figura 6), ya que el servidor SSH que corre en el Build Host, reconoce al computador Build Master, gracias al certificado que acabamos de instalar.
  • SSH sin contraseña.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    C:\Users>ssh fran@192.168.1.24 ls
    Desktop
    Documents
    Downloads
    examples.desktop
    Music
    Pictures
    Public
    Templates
    Videos
    
    Comando ssh en máquina remota sin password.
    Figura 6: Ejecución de un comando en una máquina remota sin necesidad de utilizar password.

2.5. SSH desde C

En el caso que vayamos a escribir un programa gestione la compilación, este debe ser capaz de lanzar comandos SSH desde su propio código en vez del terminal. En (Listado 2) vemos como hacerlo desde el lenguaje C. En Lanzando procesos tienes más información sobre el API de multi-procesamiento de NAppGUI.

Listado 2: Ejecución de un comando SSH desde un procedimiento en C.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Proc *proc = bproc_exec("ssh fran@192.168.1.24 ls", NULL, NULL);
if (proc != NULL)
{
    byte_t buffer[512];
    uint32_t rsize;
    Stream *stm = stm_memory(1024);
    while (bproc_read(proc, buffer, sizeof(buffer), &rsize, NULL) == TRUE)
        stm_write(stm, buffer, rsize);

    bproc_wait(proc);
    bproc_close(&proc);
    return stm;
}

2.6. SSH para copiar archivos

Para copiar archivos entre máquinas remotas, SSH incluye la utilidad scp que también garantiza la encriptación.

Copiar una librería compilada desde una máquina remota a un directorio local.
1
scp fran@192.168.1.24:/build/Debug/core/libcore.a C:/pkg

3. Ejemplo paso a paso

Vamos a realizar todo el proceso de compilación remota desde una máquina Windows a otra macOS, cuya IP es 192.168.1.41 y usuario fran. Como viene siendo habitual en este tutorial, en cada máquina hay dos directorios principales: nappgui_sdk con el código fuente de los proyectos y nappgui_build donde se escriben las salidas generadas por CMake y los compiladores.

Compilación remota desde Windows a macOS
1
2
3
4
ssh fran@192.168.1.41 "cd /Users/fran/nappgui_sdk ; git pull"
ssh fran@192.168.1.41 "cd /Users/fran/nappgui_build ; cmake -G\"Xcode\" -DCMAKE_DEPLOYMENT_TARGET:STRING="11.0" -DCMAKE_ARCHITECTURE:STRING=x86_64 -DCMAKE_PACKAGE:Bool=ON -DCMAKE_PACKAGE_GEN:String="TGZ" -DCMAKE_PACKAGE_PATH:String="/Users/fran/nappgui_bin" ../nappgui_sdk/src" > "C:\result\cmake.txt"
ssh fran@192.168.1.41 "cd /Users/fran/nappgui_build ; xcodebuild -project NAppGUI.xcodeproj -alltargets -configuration Debug" > "C:\result\compile.txt" 
scp "fran@192.168.1.41:/Users/fran/nappgui_bin/Die*" "C:\result"
  • La primera línea actualiza el repositorio Git con los nuevos posibles cambios.
  • A continuación se ejecuta CMake con los siguientes parámetros:
    • -G "Xcode": Generador
    • -DCMAKE_DEPLOYMENT_TARGET:STRING="11.0": Big Sur SDK
    • -DCMAKE_ARCHITECTURE:STRING=x86_64: Arquitectura Intel 64 bits.
    • -DCMAKE_PACKAGE:Bool=ON: Activamos el empaquetado de las aplicaciones generadas.
    • -DCMAKE_PACKAGE_GEN:String="TGZ": El formato de empaquetado será .TGZ.
    • -DCMAKE_PACKAGE_PATH:String="/Users/fran/nappgui_bin": Directorio donde se guardarán los paquetes finales.
    • > "C:\result\cmake.txt" La salida del CMake se guarda en la máquina local. Nos será útil para comprobar posibles errores.
  • La tercera línea ejecuta xcodebuild para que compile todos los proyectos de la solución, que acaba de ser creada por CMake.
    • -configuration Debug: Configuración elegida.
    • > "C:\result\compile.txt" La salida del compilador se guarda en la máquina local.
  • Por último se copia el empaquetado de la aplicación Die en la máquina local.
No te dejes amedrentar por el tamaño de los comandos de consola. El objetivo no es teclearlos a mano una y otra vez, sino incluirlos en algún script o aplicación.
En NAppBuild tienes más información sobre la herramienta de integración continua que utilizamos en NAppGUI.
❮ Anterior