El relajo del MSBuild en GeneXus GX18: cómo le bajamos la calentura al Build de ZelvaERP/ZelvaPOS
Read Time:14 Minute, 1 Second

El relajo del MSBuild en GeneXus GX18: cómo le bajamos la calentura al Build de ZelvaERP/ZelvaPOS

0 0

1. La historia corta, para el alero que viene con prisa

Mirá pues: la KB de ZelvaERP/ZelvaPOS andaba pesadísima. Cada cambio en GeneXus GX18 se sentía como ir en buseta en hora pico: abrir, guardar, especificar, generar y compilar era un sufrimiento.

Al inicio sospechamos de todo:

  • El tamaño de la KB.
  • El historial acumulado de 9 años.
  • SQL Server.
  • La máquina local.
  • Visual Studio.
  • IIS.
  • K2BTools.
  • GAM.
  • El universo mismo conspirando contra el build.

Pero el rollo principal que logramos mejorar estaba en la etapa de compilación .NET Framework.

GeneXus estaba generando proyectos .csproj así:

<Project ToolsVersion="14.0">

pero al momento de compilar estaba usando este MSBuild:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe

Ese MSBuild no tenía claro qué hacer con ToolsVersion="14.0", entonces tiraba el clásico drama:

Project file contains ToolsVersion="14.0".
This toolset may be unknown or missing...
Treating the project as if it had ToolsVersion="4.0".

Y eso se repetía para un montón de proyectos. Resultado: más ruido, más tiempo, más desesperación.

La solución que quedó funcionando fue configurar MSBuild options así:

/v:minimal /m:6 /ToolsVersion:4.0 /p:GxExternalReference=GeneXus.Security.API.Common.dll

Con eso le dijimos a MSBuild:

“Dejá de hacerte el interesante con el 14.0. Usá 4.0 de una vez y compilemos esta vaina.”

Y sí: mejoró.


2. El ambiente donde pasó el relajo

La KB afectada fue ZelvaERP/ZelvaPOS, una KB grande y con varios años de historia.

Stack involucrado

  • GeneXus GX18.
  • Generador: .NET Framework.
  • Build Mode: MSBuild.
  • Seguridad integrada / GAM.
  • K2BTools / K2B Patterns.
  • IIS local.
  • GeneXus Server.
  • SQL Server como base interna de la KB.

Tamaño observado de la KB local

Los archivos SQL internos de la KB andaban más o menos así:

GX_KB_ZelvaERP.mdf      ≈ 5.7 GB
GX_KB_ZelvaERP_log.ldf  ≈ 1.0 GB

Eso no significa automáticamente que la KB esté dañada, pero sí nos dice que estamos hablando de una KB grandecita, con historia, con bastante carga y con suficiente peso como para no tratarla como una KB de ejemplo de capacitación.


3. Los síntomas: cuando el Build se puso en modo tortuga

Los síntomas eran bien claros:

  1. Guardar cambios tardaba más de lo normal.
  2. Especificar y generar se sentía pesado.
  3. La compilación .NET Framework se quedaba pegada bastante tiempo.
  4. En el Output de GeneXus aparecía una línea como esta:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" /nologo /p:Configuration=Release /p:FrameworkPath="C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319" /v:q /m /p:GxExternalReference=GeneXus.Security.API.Common.dll "D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\build\LastBuild.sln"

Cuando GeneXus muestra eso, ya no estamos hablando de especificación como tal. Ahí GeneXus ya generó y le está diciendo a MSBuild:

“Tomá esta solución LastBuild.sln y compilámela.”

El clavo estaba bastante metido en esa fase.


4. Primera pista: /v:q nos tenía viendo una película sin subtítulos

La configuración inicial usaba algo como:

/v:q

Ese parámetro hace que MSBuild sea súper callado. Muy elegante, sí, pero para diagnosticar es como revisar un carro con los ojos vendados.

Entonces cambiamos temporalmente a:

/v:minimal

Y ahí apareció el mensaje que nos abrió los ojos:

Project file contains ToolsVersion="14.0".
This toolset may be unknown or missing, in which case you may be able to resolve this by installing the appropriate version of MSBuild, or the build may have been forced to a particular ToolsVersion for policy reasons. Treating the project as if it had ToolsVersion="4.0".

Ese warning se repetía varias veces. Demasiadas. Y en una KB grande, warning repetido por cada proyecto es como gotera en invierno: al rato ya tenés inundada la sala.


5. Revisando si había MSBuild moderno instalado

Se probó en PowerShell/CMD:

where msbuild

Resultado:

No devolvió nada.

También se buscaron rutas típicas:

C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe
C:\Program Files\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\MSBuild.exe

En ese momento no existían.

GeneXus estaba usando el viejo confiable:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe

Viejo confiable, sí. Pero viejo al fin.


6. El archivo .csproj cantó como canario

Abrimos un proyecto generado por GeneXus, por ejemplo:

D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\build\erp_proveedores.wpcreardocumentocompra\erp_proveedores.wpcreardocumentocompra.csproj

Y encontramos esto:

<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

Ahí estaba el meollo:

  • GeneXus genera .csproj con ToolsVersion="14.0".
  • Pero GeneXus compila con MSBuild de v4.0.30319.
  • Ese MSBuild no resuelve bien el toolset 14.0.
  • Entonces cae a 4.0, pero después de quejarse por cada proyecto.

O sea, ya estaba usando 4.0 en la práctica, pero haciendo show antes.


7. ¿Qué rayos es ToolsVersion?

Aquí viene la parte importante para que no nos confundamos.

ToolsVersion no es la versión de .NET Framework de la aplicación.

ToolsVersion le dice a MSBuild qué conjunto de herramientas usar para compilar: archivos .targets, tareas de build, propiedades y rutas relacionadas con compiladores.

Ejemplo:

<Project ToolsVersion="14.0">

Eso significa:

“Este proyecto fue generado pensando en el toolset MSBuild 14.0.”

Históricamente:

ToolsVersionAsociado a
4.0Visual Studio 2010 / 2012
12.0Visual Studio 2013
14.0Visual Studio 2015
15.0Visual Studio 2017

Pero ojo: una cosa es el toolset y otra cosa es el framework objetivo.


8. ToolsVersion no es TargetFrameworkVersion

Este punto es clave, porque si no, uno se asusta pensando que está degradando toda la aplicación.

ConceptoQué controla
ToolsVersionQué toolset de MSBuild se usa para compilar
TargetFrameworkVersionContra qué versión de .NET Framework compila la aplicación
Compiler PathRuta del csc.exe configurado en GeneXus
Build Mode = MSBuildGeneXus compila usando MSBuild en vez de CSC directo

Entonces, poner esto:

/ToolsVersion:4.0

no significa automáticamente:

“La aplicación ahora es .NET Framework 4.0 y nos fuimos para atrás como Windows XP.”

No. Significa que MSBuild va a procesar los proyectos usando el toolset 4.0.

Y en nuestro caso eso ya estaba pasando de todas formas, solo que con advertencias repetidas.


9. El intento con MSBuild moderno: buena idea, pero se metió otro duende

Se instaló Visual Studio/Build Tools y se probó ejecutar MSBuild moderno manualmente.

En PowerShell se intentó primero así:

"C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" /nologo /p:Configuration=Release /v:minimal /m /p:GxExternalReference=GeneXus.Security.API.Common.dll "D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\build\LastBuild.sln"

PowerShell se puso especial, porque cuando la ruta va entre comillas hay que usar &.

Forma correcta:

& "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" /nologo /p:Configuration=Release /v:minimal /m /p:GxExternalReference=GeneXus.Security.API.Common.dll "D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\build\LastBuild.sln"

Pero luego salió este error:

error MSB3644: The reference assemblies for .NETFramework,Version=v4.0 were not found.
To resolve this, install the Developer Pack (SDK/Targeting Pack) for this framework version or retarget your application.

Eso nos dijo:

  • El MSBuild moderno sí arrancó.
  • Pero no encontró las Reference Assemblies / Targeting Pack necesarias para el framework objetivo de esos proyectos.
  • Por tanto, migrar a MSBuild moderno no era solo cambiar una ruta y listo.

Ese camino requiere revisar:

  • Target Framework.
  • Developer Packs.
  • IIS.
  • GAM.
  • K2BTools.
  • DLLs externas.
  • Compatibilidad general de la KB.

Como estábamos apagando un incendio de rendimiento, no nos fuimos por esa avenida todavía.


10. El Compiler Path no era el villano

En GeneXus vimos algo como:

Build Mode = MSBuild
Compiler Path = C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe

A primera vista uno puede pensar:

“Ajá, aquí está el clavo. Dice MSBuild pero apunta a csc.exe.”

Pero no. Eso no es necesariamente problema.

Cuando Build Mode = MSBuild, GeneXus compila usando MSBuild. La propiedad Compiler Path puede seguir apuntando al csc.exe de .NET Framework.

Para .NET Framework 4.x, esta ruta es normal:

C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe

Aunque se instale .NET Framework 4.7.2 o 4.8, normalmente no aparece una carpeta nueva como:

C:\Windows\Microsoft.NET\Framework\v4.8

La rama 4.x vive normalmente bajo:

v4.0.30319

Los Developer Packs / Targeting Packs suelen aparecer más bien en:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8

Así que no tocamos Compiler Path.


11. La solución aplicada: menos drama, más build

Se cambió la propiedad MSBuild options del generador .NET Framework.

Antes

En algún momento andaba así:

/v:q /m /p:GxExternalReference=GeneXus.Security.API.Common.dll

Luego para diagnosticar:

/v:minimal /m /p:GxExternalReference=GeneXus.Security.API.Common.dll

Después

Configuración final recomendada:

/v:minimal /m:6 /ToolsVersion:4.0 /p:GxExternalReference=GeneXus.Security.API.Common.dll

Qué hace cada cosa

ParámetroQué hace
/v:minimalMuestra información útil sin convertir el Output en una novela.
/m:6Permite compilar en paralelo usando hasta 6 procesos/proyectos.
/ToolsVersion:4.0Fuerza a MSBuild a usar toolset 4.0 desde el inicio.
/p:GxExternalReference=GeneXus.Security.API.Common.dllReferencia usada por GeneXus/GAM/seguridad. Ya venía en la configuración.

La joya de la corona fue:

/ToolsVersion:4.0

Ese parámetro eliminó el warning repetitivo del ToolsVersion="14.0".


12. Resultados de las pruebas

Pruebas con /m:4

Configuración:

/v:minimal /m:4 /ToolsVersion:4.0 /p:GxExternalReference=GeneXus.Security.API.Common.dll
PruebaTiempo
Build With This Only de PPOSfac004Ferre53 segundos
Build With This Only de objeto K2B / WorkWith POScot00193 segundos
Build All sin cambios relevantes83 segundos

Pruebas con /m:6

Configuración:

/v:minimal /m:6 /ToolsVersion:4.0 /p:GxExternalReference=GeneXus.Security.API.Common.dll
PruebaTiempo
Build With This Only de PPOSfac004Ferre57 segundos
Build With This Only de objeto K2B / WorkWith POScot00165 segundos
Build All sin cambios relevantes74 segundos

Lectura catracha de los resultados

  • Para un Procedure pequeño, /m:4 fue un poquito mejor.
  • Para K2B / WorkWith, /m:6 le metió turbo.
  • Para Build All sin cambios, /m:6 también ganó.

Conclusión: para el trabajo real de esta KB, queda mejor:

/m:6

13. ¿Por qué un Procedure simple todavía tarda 50 y pico segundos?

Porque aunque el Procedure sea chiquito, GeneXus hace su ritual completo:

Integrated Security Initialization
GAM Applications Registration
Copy Module 'GeneXus'
Copy Module 'GeneXusSecurityCommon'
Copy Module 'GeneXusSecurity'
Copy Module 'GeneXusReporting'
Copy Module 'GeneXusUnanimo'
Target Environment update
Building changed objects list
Compressing static files
DeveloperMenu Compilation

Ese es el costo fijo del ecosistema.

No todo ese tiempo es el Procedure. Es GeneXus preparando el ambiente, verificando seguridad, copiando módulos, generando archivos base y compilando.


14. ¿Por qué un objeto K2B tarda más?

Porque K2B no llega solo. Llega con la familia entera.

En una prueba de POScot001, GeneXus terminó especificando/generando cosas como:

ReportWWPOScot001
POScot001General
EntityManagerPOScot001
WWPOScot001
ExportWWPOScot001

Además se generaron .cs, .js, permisos GAM y varias DLLs.

Entonces, cuando alguien dice:

“Solo cambié una cosita en el WorkWith.”

GeneXus responde:

“Sí, pero esa cosita mueve medio barrio.”


15. Build All sin objetos para especificar igual hace trabajo

En una prueba apareció:

No objects to Specify

Pero eso no significa “no hago nada”.

GeneXus igual puede hacer:

Pattern generation
Integrated Security Initialization
GAM Applications Registration
Copy Modules
Target Environment update
Generating Resources
Generation de archivos base
Compressing static files
DeveloperMenu Compilation

Y en una KB grande puede compilar muchísimas DLLs aunque no haya objetos nuevos para especificar.

Por eso un Build All de 74 segundos, en esta KB, ya no se ve tan loco.


16. Riesgos de usar /ToolsVersion:4.0

El riesgo teórico es este:

Que algún .csproj realmente necesite características específicas del toolset 14.0.

Pero en esta KB el riesgo se considera bajo porque antes de forzar /ToolsVersion:4.0, MSBuild ya estaba cayendo automáticamente a 4.0 y compilaba bien.

O sea, antes el flujo era:

.csproj pide 14.0
MSBuild viejo no encuentra 14.0
MSBuild se queja
MSBuild usa 4.0
Compila

Ahora es:

MSBuild usa 4.0 desde el inicio
Compila

Menos teatro, mismo resultado.


17. Qué no cambia esta solución

Esta solución no cambia:

  • Objetos GeneXus.
  • Código fuente de la KB.
  • Target Framework de la aplicación.
  • Base de datos de la aplicación.
  • Base SQL interna de la KB.
  • IIS.
  • GAM.
  • K2BTools.
  • DLLs externas.

Tampoco edita manualmente archivos generados.

Eso es importante: no estamos metiendo mano quirúrgica en archivos que GeneXus después va a regenerar.


18. Qué NO hacer, por amor al build

No se recomienda:

  1. Editar manualmente los .csproj generados por GeneXus.
  2. Editar este archivo:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe.config
  1. Cambiar el Compiler Path sin una prueba controlada.
  2. Cambiar Target Framework a lo loco.
  3. Borrar tablas internas de la KB en SQL Server.
  4. Hacer shrink agresivo del MDF/LDF como si fuera mantenimiento mágico.
  5. Desinstalar Visual Studio o IIS en modo desesperación sin revisar primero.

19. Cómo aplicar la solución en otra máquina del equipo

  1. Abrir GeneXus.
  2. Abrir la KB correspondiente.
  3. Ir a las propiedades del Environment / Generator .NET Framework.
  4. Confirmar:
Build Mode = MSBuild
  1. Buscar la propiedad:
MSBuild options
  1. Configurar:
/v:minimal /m:6 /ToolsVersion:4.0 /p:GxExternalReference=GeneXus.Security.API.Common.dll
  1. Guardar.
  2. Probar con un Procedure simple.
  3. Probar con un objeto K2B / WorkWith.
  4. Probar Build All sin cambios.
  5. Comparar tiempos.

20. Rollback: cómo volver atrás si algo se pone raro

Si en una máquina algo falla, volver al valor anterior de MSBuild options.

Ejemplo:

/v:minimal /m /p:GxExternalReference=GeneXus.Security.API.Common.dll

o si estaba bien silencioso:

/v:q /m /p:GxExternalReference=GeneXus.Security.API.Common.dll

Luego ejecutar Build With This Only y validar que compile.


21. Recomendaciones pendientes para seguir afinando la nave

21.1. Crear KB nueva desde GeneXus Server

Como la KB tiene varios años y un MDF grande, se recomienda crear una KB nueva desde GeneXus Server trayendo solo:

Trunk Version

La idea es comparar:

  • Tamaño del MDF/LDF nuevo.
  • Tiempo de apertura.
  • Tiempo al guardar objetos.
  • Build With This Only.
  • Build All.

Pruebas sugeridas:

1. Build With This Only de PPOSfac004Ferre
2. Build With This Only de POScot001
3. Build All sin cambios

Si la KB nueva baja fuerte los tiempos, parte del problema restante está en la historia acumulada de la KB local vieja.

21.2. Revisar SQL Server de la KB

Pendientes recomendados:

  • Revisar tamaño MDF.
  • Revisar tamaño LDF.
  • Revisar fragmentación de índices.
  • Revisar memoria asignada a SQL Server.
  • Confirmar si se usa SQL Server Express.
  • Verificar que la KB esté en SSD local.

Nada de borrar tablas internas de GeneXus. Eso es jugar ruleta rusa con la KB.

21.3. Revisar antivirus

Evaluar exclusiones controladas para:

D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\
D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\build\
D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\web\
D:\Informacion\Proyectos\Zelva_ERP_GX18\Local\web\bin\

Solo hacerlo si las políticas internas de seguridad lo permiten.

21.4. Evitar carpetas sincronizadas

No poner KBs grandes en:

OneDrive
Dropbox
Google Drive
Carpetas de red lentas

Para este tipo de KB: SSD local, ruta decente y sin sincronizadores metiendo mano.


22. Referencias útiles


23. Conclusión: le quitamos el freno de mano al build

El problema principal no era que GeneXus no pudiera compilar. Compilaba. El problema era que estaba compilando con un MSBuild viejo, leyendo proyectos generados con ToolsVersion="14.0", cayendo a ToolsVersion="4.0" y dejando un montón de warnings en el camino.

La solución fue decirle de frente:

/ToolsVersion:4.0

Y ya que estábamos afinando, dejamos:

/v:minimal /m:6 /ToolsVersion:4.0 /p:GxExternalReference=GeneXus.Security.API.Common.dll

Resultado:

  • Menos warnings.
  • Menos ruido.
  • Menor tiempo de compilación.
  • Builds incrementales más decentes.
  • KB más soportable para el trabajo diario.

No resolvimos todos los males del universo GeneXus, pero sí le bajamos bastante al relajo del build. Y

Avatar for Carlos Zelaya Irías

About Post Author

Carlos Zelaya Irías

Carlos Alberto Zelaya Irías es un profesional hondureño especializado en tecnología, desarrollo de software y consultoría empresarial. Como CEO de ZelvaIT, educador universitario y divulgador en plataformas digitales, promueve la innovación tecnológica y la educación inclusiva. Apasionado por la ciberseguridad, metodologías ágiles y transformación digital, comparte conocimientos prácticos para empoderar a su comunidad
Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %

Average Rating

5 Star
0%
4 Star
0%
3 Star
0%
2 Star
0%
1 Star
0%

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Entrada anterior ¿Tus ventas están a medio palo? ZelvaLeads viene al rescate con IA y automatización