Compilación remota
Ya hemos visto en Generadores, 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).
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.
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.
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 |
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.
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
. - Editamos el archivo
/private/etc/ssh/sshd_config
o/etc/ssh/sshd_config
, habilitando la variablePermitUserEnvironment PATH,LANG
. - Paramos y re-lanzamos el servicio mediante el check Remote Login de Sharing.
PATH
en /.ssh/environment
1 |
PATH=$PATH:/bin:/usr/bin:/usr/local:/usr/local/bin:/Applications/CMake.app/Contents/bin |
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. - Copia el archivo
id_rsa.pub
en el directorio/USER/.ssh
de cada Build Host. - Abre un terminal en el Host remoto y teclea:
- 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.
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]-----+ |
1 2 |
cd .ssh scp id_rsa.pub fran@192.168.1.24:/Users/fran/.ssh |
1 2 3 4 5 |
cd .ssh type id_rsa.pub >> authorized_keys (Windows) ... cd .ssh cat id_rsa.pub >> authorized_keys (macOS/Linux) |
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 |
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.
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.
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.
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.