Si je devais compiler un programme en un seul binaire, faire une somme de contrôle, puis le recompiler sur la même machine avec le même compilateur et les mêmes paramètres de compilation et la somme de contrôle du programme recompilé, la somme de contrôle échouerait-elle?
Si oui, pourquoi? Sinon, le fait d'avoir un processeur différent entraînerait-il un binaire non identique?
Réponses:
Compilez le même programme avec les mêmes paramètres sur la même machine:
Bien que la réponse définitive soit «cela dépend», il est raisonnable de s'attendre à ce que la plupart des compilateurs soient déterministes la plupart du temps et que les binaires produits soient identiques. En effet, certains systèmes de contrôle de version en dépendent. Pourtant, il y a toujours des exceptions; il est tout à fait possible que certains quelque part du compilateur décide d'insérer un horodatage ou d' un tel (IIRC, Delphi fait, par exemple). Ou le processus de construction lui-même pourrait le faire; J'ai vu des makefiles pour les programmes C qui définissaient une macro de préprocesseur sur l'horodatage actuel. (Je suppose que cela compterait comme étant un paramètre de compilateur différent, cependant.)
Sachez également que si vous liez statiquement le binaire, vous incorporez effectivement l'état de toutes les bibliothèques pertinentes sur votre machine, et tout changement dans l'une d'entre elles affectera également votre binaire. Ce ne sont donc pas seulement les paramètres du compilateur qui sont pertinents.
Compilez le même programme sur une machine différente avec un processeur différent.
Ici, tous les paris sont désactivés. La plupart des compilateurs modernes sont capables de faire des optimisations spécifiques à la cible; si cette option est activée, les binaires sont susceptibles de différer, sauf si les CPU sont similaires (et même alors, c'est possible). Voir également la note ci-dessus sur la liaison statique: l'environnement de configuration va bien au-delà des paramètres du compilateur. Sauf si vous avez un contrôle de configuration très strict, il est extrêmement probable que quelque chose diffère entre les deux machines.
la source
gcc -c
peut donc être identique, mais les versions liées diffèrent. De plus, ce n'est pas seulement-march
; il y en a aussi-mtune/-mcpu
et-mfpmatch
(et peut-être d'autres). Certains d'entre eux peuvent avoir des valeurs par défaut différentes sur différentes installations, vous devrez donc forcer explicitement le pire des cas pour vos machines; cela pourrait réduire considérablement les performances, en particulier si vous revenez à i386 sans sse. Et, bien sûr, si l'un de vos processeurs est un ARM et l'autre un i686 ...Ce que vous demandez, c'est "est la sortie déterministe ". Si vous avez compilé le programme une fois, le compilé à nouveau immédiatement, vous vous retrouverez probablement avec le même fichier de sortie. Cependant, si quelque chose a changé - même un petit changement - en particulier dans un composant utilisé par le programme compilé, la sortie du compilateur peut également changer.
la source
-frandom-seed=string
.Pour tous les compilateurs? Non. Le compilateur C #, au moins, n'est pas autorisé à le faire.
Eric Lippert a une ventilation très approfondie des raisons pour lesquelles la sortie du compilateur n'est pas déterministe .
Bien qu'il soit spécifique à une version du compilateur C #, de nombreux points de l'article peuvent être appliqués à n'importe quel compilateur.
la source
-frandom-seed=123
contrôle certains aléas internes du GCC.man gcc
dit:__FILE__
: mettre la source dans un dossier fixe (par exemple/tmp/build
)__DATE__
,__TIME__
,__TIMESTAMP__
:-D
-Wdate-time
ou-Werror=date-time
: avertir ou échouer si l'__TIME__
,__DATE__
ou__TIMESTAMP__
sont est utilisé. Le noyau Linux 4.4 l'utilise par défaut.D
drapeau avecar
ou utilisez https://github.com/nh2/ar-timestamp-wiper/tree/master pour essuyer les tampons-fno-guess-branch-probability
: les anciennes versions manuelles disent que c'est une source de non-déterminisme, mais plus maintenant . Je ne sais pas si cela est couvert-frandom-seed
ou non.Le projet de construction Debian Reproductible tente de standardiser les paquets Debian octet par octet et a récemment obtenu une subvention de la Fondation Linux . Cela comprend plus qu'une simple compilation, mais cela devrait être intéressant.
Buildroot a une
BR2_REPRODUCIBLE
option qui peut donner quelques idées au niveau du paquet, mais elle est loin d'être complète à ce stade.Sujets associés:
la source
Le projet https://reproducible-builds.org/ est tout cela, et s'efforce de répondre à votre question "non, ils ne différeront pas" dans autant d'endroits que possible. NixOS et Debian ont désormais plus de 90% de reproductibilité pour leurs packages.
Si vous compilez un binaire, et je compile un binaire, et ils sont identiques bit à bit, alors je peux être rassuré que le code source et les outils sont ce qui détermine la sortie, et que vous n'avez pas faufilé certains code de Troie en cours de route.
Si nous combinons la reproductibilité avec la bootstrappabilité à partir d'une source lisible par l'homme, comme le fait http://bootstrappable.org/ , nous obtenons un système déterminé à partir de zéro par une source lisible par l'homme, et alors seulement nous en sommes à un point où nous pouvons avoir confiance que nous savons ce que fait le système.
la source
Je dirais NON, ce n'est pas 100% déterministe. J'ai précédemment travaillé avec une version de GCC qui génère des binaires cibles pour le processeur Hitachi H8.
Ce n'est pas un problème d'horodatage. Même si le problème d'horodatage est ignoré, l'architecture de processeur spécifique peut permettre à la même instruction d'être codée de 2 façons légèrement différentes où certains bits peuvent être 1 ou 0. Mon expérience précédente montre que les binaires générés étaient les mêmes la plupart du temps mais de temps en temps le gcc produirait des binaires de taille identique mais certains des octets différents par seulement 1 bit par exemple 0XE0 deviennent 0XE1.
la source
En général, non. Les compilateurs les plus sophistiqués incluent le temps de compilation dans le module objet. Même si vous deviez réinitialiser l'horloge, vous devriez être très précis en ce qui concerne le moment où vous avez lancé la compilation (et ensuite espérer que les accès au disque, etc., étaient à la même vitesse qu'auparavant).
la source