Jika saya mengkompilasi suatu program menjadi satu biner, membuat sebuah checksum, dan kemudian mengkompilasinya pada mesin yang sama dengan pengaturan kompiler dan kompiler yang sama dan checksum pada program yang dikompilasi ulang, akankah checksum gagal?
Jika demikian, mengapa ini? Jika tidak, akankah CPU yang berbeda menghasilkan biner yang tidak identik?
Jawaban:
Kompilasi program yang sama dengan pengaturan yang sama pada mesin yang sama:
Meskipun jawaban pasti adalah "itu tergantung", masuk akal untuk berharap bahwa sebagian besar kompiler akan menjadi deterministik sebagian besar waktu, dan bahwa biner yang dihasilkan harus identik. Memang, beberapa sistem kontrol versi tergantung pada ini. Namun, selalu ada pengecualian; sangat mungkin bahwa beberapa kompiler di suatu tempat akan memutuskan untuk memasukkan timestamp atau semacamnya (iirc, Delphi, misalnya). Atau proses build itu sendiri mungkin melakukan itu; Saya telah melihat makefiles untuk program C yang mengatur makro preprocessor ke timestamp saat ini. (Saya kira itu akan dihitung sebagai pengaturan kompiler yang berbeda.)
Perlu diketahui juga bahwa jika Anda menautkan biner secara statis, maka Anda secara efektif memasukkan keadaan semua pustaka yang relevan pada mesin Anda, dan setiap perubahan pada salah satu dari itu juga akan memengaruhi biner Anda. Jadi bukan hanya pengaturan kompiler yang relevan.
Kompilasi program yang sama pada mesin yang berbeda dengan CPU yang berbeda.
Di sini, semua taruhan dibatalkan. Sebagian besar kompiler modern mampu melakukan optimasi target-spesifik; jika opsi ini diaktifkan, maka binari cenderung berbeda kecuali CPU serupa (dan bahkan kemudian, itu mungkin). Juga, lihat catatan di atas tentang penautan statis: lingkungan konfigurasi jauh melampaui pengaturan kompiler. Kecuali Anda memiliki kontrol konfigurasi yang sangat ketat, sangat mungkin ada sesuatu yang berbeda antara kedua mesin.
sumber
gcc -c
mungkin identik, tetapi versi tertaut berbeda. Juga, bukan hanya-march
; ada juga-mtune/-mcpu
dan-mfpmatch
(dan mungkin yang lain). Beberapa di antaranya mungkin memiliki standar yang berbeda pada instalasi yang berbeda, jadi Anda mungkin perlu memaksakan kasus terburuk yang mungkin untuk mesin Anda secara eksplisit; melakukan hal itu dapat secara signifikan mengurangi kinerja, terutama jika Anda kembali ke i386 tanpa sse. Dan, tentu saja, jika salah satu CPU Anda adalah ARM dan yang lainnya i686 ...Yang Anda tanyakan adalah "adalah output deterministik ." Jika Anda mengkompilasi program sekali, segera mengkompilasinya lagi Anda mungkin akan berakhir dengan file output yang sama. Namun, jika ada yang berubah - bahkan perubahan kecil - terutama dalam komponen yang digunakan oleh program yang dikompilasi, maka output dari kompiler juga dapat berubah.
sumber
-frandom-seed=string
.Untuk semua kompiler? Tidak. Kompilator C #, setidaknya, tidak diizinkan.
Eric Lippert memiliki rincian yang sangat menyeluruh tentang mengapa output dari kompiler tidak deterministik .
Meskipun spesifik untuk versi kompiler C #, banyak poin dalam artikel dapat diterapkan ke kompiler mana pun .
sumber
-frandom-seed=123
mengontrol beberapa keacakan internal GCC.man gcc
mengatakan:__FILE__
: letakkan sumber dalam folder tetap (mis./tmp/build
)__DATE__
,__TIME__
,__TIMESTAMP__
:-D
-Wdate-time
atau-Werror=date-time
: memperingatkan atau gagal jika salah satu__TIME__
,__DATE__
atau__TIMESTAMP__
digunakan. Kernel Linux 4.4 menggunakannya secara default.D
bendera denganar
, atau gunakan https://github.com/nh2/ar-timestamp-wiper/tree/master untuk menghapus prangko-fno-guess-branch-probability
: versi manual yang lebih lama mengatakan itu adalah sumber non-determinisme, tetapi sekarang tidak lagi . Tidak yakin apakah ini dilindungi-frandom-seed
atau tidak.Debian Reproducible membangun upaya proyek untuk membakukan paket Debian byte-by-byte, dan baru-baru ini mendapatkan hibah Linux Foundation . Itu termasuk lebih dari sekedar kompilasi, tetapi harus menarik.
Buildroot memiliki
BR2_REPRODUCIBLE
opsi yang dapat memberikan beberapa gagasan pada tingkat paket, tetapi masih jauh dari selesai pada saat ini.Utas terkait:
sumber
Proyek https://reproducible-builds.org/ adalah semua tentang ini, dan berusaha keras untuk membuat jawaban atas pertanyaan Anda "tidak, mereka tidak akan berbeda" di banyak tempat sebanyak mungkin. NixOS dan Debian kini memiliki reproduksibilitas lebih dari 90% untuk paket mereka.
Jika Anda mengkompilasi biner, dan saya mengkompilasi biner, dan mereka sedikit-untuk-bit identik, maka saya dapat diyakinkan bahwa kode sumber dan alat-alat adalah apa yang menentukan output, dan bahwa Anda tidak menyelinap di beberapa kode trojan di sepanjang jalan.
Jika kita menggabungkan reproduktifitas dengan bootstrappability dari sumber yang dapat dibaca manusia, seperti yang dilakukan oleh http://bootstrappable.org/ , kita mendapatkan sistem yang ditentukan dari bawah ke atas oleh sumber yang dapat dibaca oleh manusia, dan hanya pada saat itulah kita berada pada titik di mana kita bisa percaya bahwa kita tahu apa yang dilakukan sistem.
sumber
Saya akan mengatakan TIDAK, itu tidak 100% deterministik. Saya sebelumnya bekerja dengan versi GCC yang menghasilkan binari target untuk prosesor Hitachi H8.
Itu tidak masalah dengan cap waktu. Bahkan jika masalah cap waktu diabaikan, arsitektur prosesor tertentu dapat memungkinkan instruksi yang sama untuk dikodekan dalam 2 cara yang sedikit berbeda di mana beberapa bit bisa 1 atau 0. Pengalaman saya sebelumnya menunjukkan bahwa biner yang dihasilkan adalah PALING sama dengan waktu. tetapi kadang-kadang gcc akan menghasilkan binari dengan ukuran yang identik tetapi beberapa byte berbeda hanya dengan 1 bit misalnya 0XE0 menjadi 0XE1.
sumber
Secara umum, tidak. Kebanyakan kompiler yang cukup canggih akan menyertakan waktu kompilasi dalam modul objek. Bahkan jika Anda mengatur ulang jam Anda harus sangat akurat sehubungan dengan ketika Anda memulai kompilasi (dan kemudian berharap bahwa akses disk, dll, adalah kecepatan yang sama seperti sebelumnya).
sumber