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


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

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

No estoy usando intencionalmente ningún tipo de especial marcas de tiempo en cualquier lugar, pero ¿el compilador (Microsoft, el incluido en. NET 4.0) posiblemente agrega marcas de tiempo en sí?

La razón por la que pregunto es que estoy confirmando la salida a subversion, y debido a la forma en que funciona nuestro servidor de compilación, los cambios registrados desencadenan una reconstrucción, causando que los archivos binarios modificados una vez más sean registrados en un círculo.

Author: Jeffrey Hantin, 2012-01-19

4 answers

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 las entradas idénticas realmente produzcan salidas idénticas. Vea la etiqueta "Concepto-determinismo" en el github de Roslyn 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. Lo contrario es cierto. Cada vez que ejecute el compilador debería obtener una salida diferente. De lo contrario, ¿cómo podrías saber que habías recompilado?

El compilador de C# incrusta 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 absoluto que dos compilaciones "idénticas" produzcan los mismos resultados.

En particular, el orden en el que se rellenan 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 el que se le dan los archivos, y eso puede cambiarse sutilmente por una variedad de factores.

Debido a la forma en que funciona nuestro servidor de compilación, los cambios registrados desencadena una reconstrucción, haciendo que los archivos binarios modificados una vez más se comprueben en un círculo.

Yo lo arreglaría si fuera tú.
 33
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-20 16:09:33

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 ensamblado. No he visto ninguna garantía en ningún lugar que el resultado binario está destinado a ser idéntico.

(Tenga en cuenta que si la fuente ya está en Subversion, generalmente evitaría agregar también los archivos binarios allí. Normalmente solo incluiría versiones de bibliotecas de terceros. Depende exactamente de lo que estés haciendo.)

 13
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-19 14:16:27

Como han mencionado otros, el compilador genera una compilación distinta de ahí el resultado diferente. Lo que está buscando es la capacidad de crear compilaciones deterministas y ahora esto se incluye como parte del compilador de roslyn.

Opciones de la línea de comandos de Roslyn

/ deterministic Producir un conjunto determinista (incluyendo módulo GUID de la versión y marca de tiempo)

Leer más sobre esto función https://github.com/dotnet/roslyn/blob/master/docs/compilers/Deterministic%20Inputs.md

 8
Author: Alex Nolasco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-23 23:10:07

Hasta donde yo sé, solo los binarios de MS son diferentes en cada compilación. hace unos 20 años, no era así. Los binarios de MS eran los mismos después de cada compilación (asumiendo que el código fuente era el mismo).

 2
Author: gregg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-17 03:13:32