MSBuild 4.5 está ignorando las dependencias del proyecto
.net-4.5 (6)
Si aún no resolvió este problema, intente algunos intentos a ciegas:
Msbuild ha confirmado un error cuando a veces genera un orden de compilación incorrecto basado en dependencias seguidas. Intente crear una solución no completa sino el proyecto exacto que desea construir, como
msbuild.exe YourWebsiteProject.csproj /t:Clean;Build /p:configuration=MyConfig
. ¿El problema aún persiste?Asegúrese de que YourWebsiteProject y sus libs (B y C) tengan las referencias adecuadas: en el proyecto, no en dll en otra carpeta de proyectos (la forma más sencilla de corregir eso), elimine de la referencia B a C y vuelva a agregarlo, solo asegúrese de estar agregar referencia de proyecto y no explorar bin / Debug para muy C.dll). ¿El problema sigue ahí?
Si pudiera proporcionar un registro de msbuild detallado o incluso de diagnóstico (agregue a su línea de comandos msbuild después de switches / ds / v: diag y luego comparta el log de compilación completo de teamcity en alguna parte o registre el registro de línea de comando en un archivo) o algunos proyectos de muestra configurados donde puedo reproducir este comportamiento - podría ayudar mucho con la resolución de problemas.
Tengo un archivo de la solución VS2010 con más de 20 proyectos en él, y algunos de los proyectos tienen dependencias de otros proyectos desde la solución.
También tengo varias configuraciones de compilación configuradas para diferentes propósitos, pero reduje los proyectos que se crearán para incluir solo el número mínimo de proyectos.
Por ejemplo, tengo tres bibliotecas (A, B y C), un proyecto de sitio web y un proyecto de implementación de sitio web (VS2010). El sitio web tiene referencias a las bibliotecas A y B, y B a su vez tiene una referencia a C. Mi configuración de compilación solo ha revisado el sitio web y el proyecto de implementación. Cuando compruebo las dependencias del proyecto de las propiedades de la solución, el sitio web enumera correctamente las bibliotecas, y B muestra C, como se esperaba.
Cuando ejecuto la compilación contra mi configuración de compilación desde VS2010, funciona completamente bien, pero cuando ejecuto MSBuild en la solución que especifica mi configuración (de la siguiente manera), simplemente da como resultado un montón de errores.
msbuild.exe mysolution.sln /t:Build /p:configuration=MyConfig
Aquí hay un ejemplo de los errores que recibo:
Services/IService.cs(11,63): error CS0246: The type or namespace name ''Priority'' could not be found (are you missing a using directive or an assembly reference?)
Noté que esto sucedía en mi servidor de compilación (TeamCity v7.1.2), pero puedo reproducirlo en varias máquinas, y lo reduje a un problema con MSBuild.
Solo comenzó a suceder después de instalar .NET 4.5 (y 2 parches de seguridad), así que lo desinstalé, reinstalé .NET 4.0 (con parches) ya que también fue eliminado, luego intenté con el mismo comando y funcionó bien.
Esto me lleva a creer que algo cambió o se rompió en MSBuild con .NET 4.5, pero nada en su documentación parece hablar sobre este tipo de cambio.
Documentación de MSBuild 4.5: http://msdn.microsoft.com/en-us/library/hh162058.aspx
Incluso he intentado pasar BuildProjectDependencies=true
a MSBuild, y aparece diciendo que omitió los otros proyectos porque no se seleccionaron en el administrador de configuración, que es correcto e intencional.
La única forma de hacerlo funcionar con MSBuild 4.5 fue volver atrás y seleccionar los proyectos que se estaban omitiendo, pero como la solución real es un poco más compleja con la cadena de dependencia, no quiero tener que tratar de administrar las configuraciones de forma manual cada vez que actualizamos la solución con nuevos proyectos o dependencias. DEBERÍA ser automático.
¿Alguna idea de lo que estoy haciendo?
Me he encontrado exactamente el mismo problema. Las dos soluciones que he logrado encontrar son inaceptables a largo plazo, pero superan la cuestión inicial de hacer viejo nuestros procesos de compilación con la nueva pila 4.5.
- Cambie las referencias del proyecto por referencias de archivos
- Crear configuraciones compuestas de compilación
Opté por el n. ° 2, ya que las referencias de archivos significan que los desarrolladores perderían intelisense en tiempo real, etc.
Las configuraciones compuestas son simplemente esto:
- Servidor de lanzamiento -> Todos los proyectos de servidor
- Release Consumer -> "Release Server" + Proyectos de clientes
El problema parece ser que si un proyecto no está incluido en la configuración de compilación actual / activa, no lo incluirá como una dependencia referenciada. Entonces, al agregar las dependencias en la configuración, los proyectos al menos compilarán.
Ambos feos, pero al menos me sale de un aprieto.
Mate
Pensé que actualizaría mi respuesta anterior, ya que dediqué mucho tiempo y esfuerzo a crear mi propia solución a este problema. El trabajo en general es un poco más completo que simplemente vivir con el problema, pero he intentado eliminar el problema y aislarnos de shocks futuros como este.
MSBuild ha sido degradado de trabajar con soluciones, configuraciones u otros. Se le pide a MSBuild que compile proyectos en forma aislada. El orden en que esto sucede se calcula mediante un script de Powershell que analiza nuestras soluciones y proyectos para elaborar el mejor plan de ejecución de compilación Just-In-Time.
La clave para esto (y creo que puede ser útil) son los siguientes fragmentos:
Identificando mis soluciones
Tengo una lista de todas las soluciones en mi plataforma, y básicamente repito cada una de ellas.
$buildPlan = (
@{
solutions = (
@{
name = "DataStorage"
namespace = "Platform.Databases"
},
@{
name = "CoreFramework"
},
@{
namespace = "Platform.Server"
name = "Application1"
},
@{
namespace = "Platform.Server"
name = "Application2"
},
@{
namespace = "Platform.Client"
name = "Application1"
}
)
})
Tengo cierta lógica que ayuda a traducir esto en caminos físicos reales, pero es muy a medida de nuestras necesidades, por lo que no lo voy a enumerar aquí. Suficiente para decir, de esta lista, puedo encontrar el archivo .sln que necesito analizar.
Analizando el archivo de solución para proyectos
Con cada solución, leo el archivo .sln e intento extraer todos los proyectos contenidos que necesitaré construir más adelante.
Entonces, primero, identifique todos los proyectos en mi
$solutionContent = Get-Content $solutionFile
$buildConfigurations += Get-Content $solutionFile | Select-String "{([a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})}/.(Release.*)/|Any CPU/.Build" | % {
New-Object PSObject -Property @{
Name = $_.matches[0].groups[3].value.replace("Release ","");
Guid = $_.matches[0].groups[1].value
}
} | Sort-Object Name,Guid -unique
Y luego traduzca esto a una buena lista de proyectos que pueda repetir más adelante.
$projectDefinitions = $solutionContent |
Select-String ''Project/('' |
ForEach-Object {
$projectParts = $_ -Split ''[,=]'' | ForEach-Object { $_.Trim(''[ "{}]'') };
$configs = ($buildConfigurations | where {$_.Guid -eq $projectParts[3]} | Select-Object Name)
foreach ($config in $configs)
{
$santisiedConfig = if ([string]::IsNullOrEmpty($config.Name)){"Release"}else{$config.Name}
if ($projectParts[1] -match "OurCompanyPrefix.")
{
New-Object PSObject -Property @{
Name = $projectParts[1];
File = $projectParts[2];
Guid = $projectParts[3];
Config = $santisiedConfig
}
}
}
}
Cargue el proyecto de Visual Studio
A partir de mi análisis sintáctico del archivo de solución, ahora tengo una lista de proyectos por solución, que contiene de forma crucial la ruta de archivo relativa desde la raíz de la solución para encontrar el proyecto.
$projectDefinition = [xml](Get-Content $csProjectFileName)
$ns = @{ e = "http://schemas.microsoft.com/developer/msbuild/2003" }
$references = @();
1) Identificación de referencias de proyectos externos
$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:ItemGroup/e:Reference" -Namespace $ns | % {$_.Node} | where {$_.Include -match "OurCompanyPrefix" -and $_.HintPath -notmatch "packages"} | % {$_.Include}
2) Identificación de referencias internas del proyecto
$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:ItemGroup/e:ProjectReference" -Namespace $ns | % { $_.Node.Name }
3) Después de eventos "Post-Build" como referencias externas
$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup/e:PostBuildEvent" -Namespace $ns | where {(!([String]::IsNullOrEmpty($_.Node.InnerText)))} | % {
$postBuildEvents = $_.Node.InnerText.Split("`n")
$projectsReferencedInPostBuildEvents = $postBuildEvents | Select-String "/(SolutionDir/)((/w|/.)*)" | % {$_.Matches[0].Groups[1].Value}
if ($projectsReferencedInPostBuildEvents -ne $null)
{
Write-Output $projectsReferencedInPostBuildEvents | % { $matchedProject = $_; ($releaseConfiguation | ? {$_.File -match $matchedProject}).Name }
}
}
Y, dado que estamos en ello, obtenemos también información de salida básica
Esto es útil cuando se trata de iterar mi lista de proyectos para construir, como saber dónde insertar la salida o dónde encontrar la salida de un dependiente.
$assemblyName = (Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup/e:AssemblyName" -Namespace $ns).Node.InnerText
$outputPath = (Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup[contains(@Condition,''Release|'')]/e:OutputPath" -Namespace $ns).Node.InnerText
Y al final de todo
Solo debemos asegurarnos de que no tengamos ningún duplicado, así que solo grabo las distintas dependencias de este proyecto de código en particular:
$dependendents = @();
if ($references -ne $null)
{
$buildAction.project.dependencies += $references | where {(!([string]::IsNullOrEmpty($_))) -and ($_ -match "OurCompanyPrefix/.(.*)")} | % { $_.ToLower()} | Select -unique
}
Espero que esto te brinde suficiente información para analizar tus archivos SLN y PROJ. Cómo elegiría capturar y almacenar esta información, creo que dependería completamente de usted.
Estoy a punto de escribir un blog bastante completo sobre esto, que contendrá todos los detalles y el marco que he eludido anteriormente. La publicación aún no está lista, pero la vincularé a ella desde una publicación anterior: http://automagik.piximo.me/2013/02/just-in-time-compilation.html . Desde que Microsoft modificó esta publicación, descarriló este trabajo!
Aclamaciones.
En .NET 4.5, el valor predeterminado de la propiedad OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration en C: / Windows / Microsoft.NET / Framework / v4.0.30319 / Microsoft.Common.targets se cambió de false
a true
. Como su nombre lo indica, esta propiedad hace que MSBuild ignore las referencias a proyectos que están excluidos de la configuración de compilación.
(Es posible que Microsoft haya realizado este cambio en respuesta a un error de Connect que archivé contra MSBuild 4.0 , aunque les advertí que el cambio rompe la compilación).
La solución alternativa es simple: vuelva a establecer la propiedad en false
en la primera sección <PropertyGroup>
de cada uno de sus proyectos:
<PropertyGroup>
...
<OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration>false</OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration>
</PropertyGroup>
Entiendo que este problema tiene múltiples causas. Intenté la mayoría de las soluciones aquí. No puedo cambiar nuestro servidor de compilación para usar una secuencia de comandos de PS para que la solución no esté disponible. Nada de lo que pude probar funcionó.
Finalmente, borré mi solución y comencé una nueva. La nueva solución funcionó. Después de diferir la solución rota con la solución de trabajo, encontré que la solución original era líneas faltantes. Cada dependencia que no compilaría faltaba esta línea:
{A93FB559-F0DB-4F4D-9569-E676F59D6168}.Release|Any CPU.Build.0 = Release|Any CPU
Nota 1: El GUID cambiará de dependencia a dependencia.
Nota 2: puede encontrar líneas como esta en la sección "GlobalSection (ProjectConfigurationPlatforms) = postSolution" del archivo de solución.
Mi archivo build.proj dice construir "Release" usando la plataforma "Any CPU". Debido a que MSBuild no pudo encontrar esta línea, no creó esta dependencia. Esto da como resultado el mensaje " error CS0246: no se pudo encontrar el tipo o el espacio de nombres ".
Si tiene curiosidad, alguien ha establecido esta solución en la plataforma "x86" (lo cual es incorrecto para nosotros). Lo cambié a "Cualquier CPU" (junto con varios otros cambios). Visual Studio no agregó las líneas correspondientes al archivo de solución. Todo está bien en el IDE, pero MSBuild comenzó a lanzar errores.
Descubrí que MSBuild está creando proyectos a partir de una solución para que se declaren en el archivo .sln. Entonces, si los reordena con el editor de texto, puede arreglar el pedido de MSBuild.