c# compiler-construction .net-4.0 binaryfiles binary-reproducibility

c# - ¿Por qué la salida binaria no es igual cuando se compila de nuevo?



compiler-construction .net-4.0 (4)

Como se mencionó por otros, el compilador genera una construcción distinta, por lo tanto, el resultado diferente. Lo que está buscando es la capacidad de crear construcciones deterministas y ahora esto se incluye como parte del compilador de roslyn.

Opciones de línea de comando de Roslyn

/ deterministic Produce un ensamblado determinista (incluida la versión del módulo GUID y la marca de tiempo)

Lea más sobre esta característica https://github.com/dotnet/roslyn/blob/master/docs/compilers/Deterministic%20Inputs.md

Estoy usando un script de compilación para compilar varios proyectos de C #. La salida binaria se copia en una carpeta de resultados, sobrescribe la versión anterior de los archivos y luego se agrega / confirma a subversión.

Noté que la salida binaria de la compilación es diferente incluso cuando no hubo ningún cambio en la fuente o el entorno. ¿Cómo es esto posible? ¿No se supone que el resultado binario es exactamente igual para la misma entrada?

No estoy utilizando intencionalmente ningún tipo de marcas de tiempo especiales en ninguna parte, pero ¿el compilador (Microsoft, el incluido en .NET 4.0) posiblemente agrega marcas de tiempo por sí mismo?

La razón por la que estoy preguntando es que estoy comprometiendo la salida a la subversión, y debido a la forma en que funciona nuestro servidor de compilación, los cambios registrados activan una reconstrucción, lo que hace que los archivos binarios modificados nuevamente se registren en un círculo.


OTRA ACTUALIZACIÓN:

Desde 2015, el equipo del compilador ha estado haciendo un esfuerzo para obtener fuentes de no determinismo de la cadena de herramientas del compilador, de modo que entradas idénticas realmente produzcan resultados idénticos. Vea la etiqueta "Concepto-determinismo" en el Roslyn Github para más detalles.

ACTUALIZACIÓN: esta pregunta fue el tema de mi blog en mayo de 2012 . Gracias por la gran pregunta!

¿Cómo es esto posible?

Muy facilmente.

¿No se supone que el resultado binario es exactamente igual para la misma entrada?

Absolutamente no. El opuesto es verdad. Cada vez que ejecutas el compilador, debes obtener un resultado diferente. De lo contrario, ¿cómo podrías saber que recompilarías?

El compilador de C # integra un GUID recién generado en un ensamblado en cada compilación, garantizando así que no hay dos compilaciones que produzcan exactamente el mismo resultado.

Además, incluso sin el GUID, el compilador no garantiza en modo alguno que dos compilaciones "idénticas" producirán los mismos resultados.

En particular, el orden en que se llenan las tablas de metadatos depende en gran medida de los detalles del sistema de archivos; el compilador de C # comienza a generar metadatos en el orden en que se le dan los archivos, y eso puede modificarse sutilmente por una variedad de factores.

debido a la forma en que funciona nuestro servidor de compilación, los cambios registrados activan una reconstrucción, lo que provoca que los archivos binarios modificados nuevamente se registren en un círculo.

Lo arreglaría si fuera tú.


Por lo que yo sé, solo los binarios de MS son diferentes en cada compilación. Hace unos 20 años, no fue así. Los binarios de MS eran los mismos después de cada compilación (suponiendo que el código fuente fuera el mismo).


Sí, el compilador incluye una marca de tiempo. Además, en algunos casos, el compilador incrementará automáticamente el número de versión del ensamblaje. No he visto ninguna garantía de que el resultado binario sea idéntico.

(Tenga en cuenta que si la fuente ya está en Subversion, generalmente evitaría agregar los archivos binarios allí. Normalmente solo incluiría lanzamientos de bibliotecas de terceros. Sin embargo, eso depende de lo que esté haciendo exactamente. )