Compare commits
931 Commits
Author | SHA1 | Date |
---|---|---|
Eelco Dolstra | 5038e1bec4 | |
Eelco Dolstra | 02b4632e77 | |
Eelco Dolstra | 3a022d4599 | |
Eelco Dolstra | bd79c1f6f6 | |
zimbatm | e63c9e73e3 | |
Benjamin Hipple | c6a542f22a | |
Eelco Dolstra | 7f9a0033c7 | |
zimbatm | 619cc4af85 | |
Eelco Dolstra | c6a0f4c393 | |
Alexandre Esteves | 9533d85ce0 | |
Eelco Dolstra | 6b83174fff | |
Eelco Dolstra | cf4c31c872 | |
Julien Tanguy | ae244af242 | |
Julien Tanguy | 92ede15dd9 | |
Eelco Dolstra | a56b51a0ba | |
Eelco Dolstra | b9d6c6f000 | |
Eelco Dolstra | 5dafde28db | |
Eelco Dolstra | d20f814cde | |
Eelco Dolstra | 252c78b288 | |
Eelco Dolstra | b774845af7 | |
Eelco Dolstra | 5fad9d01c2 | |
Eelco Dolstra | 08ee364950 | |
Eelco Dolstra | e07ec8d27e | |
Eelco Dolstra | cec50290bf | |
Eelco Dolstra | f186000367 | |
Eelco Dolstra | 7348653ff4 | |
Eelco Dolstra | 8c4ea7a451 | |
Eelco Dolstra | 918717f3b5 | |
Matthew Bauer | 87c604c1f0 | |
Eelco Dolstra | 84de821004 | |
Eelco Dolstra | 8478c99d09 | |
Eelco Dolstra | a2c4fcd5e9 | |
toonn | 5bdac86be2 | |
Eelco Dolstra | 31f5ecfaa5 | |
Eelco Dolstra | ecb0a23d51 | |
Eelco Dolstra | f27e53f77e | |
Eelco Dolstra | b6120d26a8 | |
Eelco Dolstra | c128031492 | |
Eelco Dolstra | 7ef2645f45 | |
Matthew Bauer | 693e68e09c | |
Eelco Dolstra | 7298a38a07 | |
Eelco Dolstra | ad03159e25 | |
Eelco Dolstra | bd285849ed | |
Eelco Dolstra | 5fa8b3f965 | |
Eelco Dolstra | ceefddafe8 | |
Eelco Dolstra | 787015fec0 | |
Eelco Dolstra | fdff96501f | |
Eelco Dolstra | e5b397b2c7 | |
Eelco Dolstra | 177e5742fa | |
Eelco Dolstra | 73728874ab | |
Eelco Dolstra | 45b3dc325a | |
Matthew Bauer | 800fba1037 | |
Graham Christensen | 171d784404 | |
Eelco Dolstra | ee07ce7554 | |
Piotr Szubiakowski | d459224724 | |
Graham Christensen | 15ee2bc2fe | |
Graham Christensen | 057af1dbd8 | |
Venkateswara Rao Mandela | 6dab42a551 | |
Matthew Bauer | 5c06a8d328 | |
Graham Christensen | 92ddce4f46 | |
Matthew Bauer | 0463d5e36f | |
Toon Nolten | 1dbaf11948 | |
Eelco Dolstra | f435634a29 | |
zimbatm | b226b5cd97 | |
zimbatm | 91b00b145f | |
Eelco Dolstra | b7ea98bf34 | |
Eelco Dolstra | 477f82e5a7 | |
Daniel Diaz | 653c407784 | |
Graham Christensen | ee9c988a1b | |
Eelco Dolstra | 35ebae198f | |
Graham Christensen | a02457db71 | |
Eelco Dolstra | 05a10dd835 | |
Eelco Dolstra | 2053ac7747 | |
Eelco Dolstra | f9021c4c6c | |
Graham Christensen | 1eeaf99cf8 | |
Eelco Dolstra | 56df30cd3f | |
Will Dietz | c3fefd1a6e | |
Graham Christensen | 363a2f6826 | |
Eelco Dolstra | 399b6f3c46 | |
Eelco Dolstra | a2597d5f27 | |
Eelco Dolstra | e349f2c0a3 | |
Eelco Dolstra | ec415d7166 | |
regnat | 7c5596734f | |
Eelco Dolstra | 320126aeeb | |
Matthew Bauer | 9a0855bbb6 | |
Eelco Dolstra | 41d010fff6 | |
Eelco Dolstra | 219d645987 | |
Eelco Dolstra | 7680357ccc | |
Bas van Dijk | ee1e3132ca | |
Bas van Dijk | 89865144c3 | |
Tom McLaughlin | cd933b22d2 | |
Matthew Bauer | 11d8534629 | |
Matthew Bauer | d171090530 | |
Eelco Dolstra | 41a5246685 | |
Eelco Dolstra | 1fb8e2605a | |
Matthew Bauer | 03addc3b0a | |
Matthew Bauer | c82a856b36 | |
Domen Kožar | b640f69a4d | |
zimbatm | 9031a6838c | |
Eelco Dolstra | 1bace4022f | |
Graham Christensen | cf6172f05e | |
Domen Kožar | 5e0a64229b | |
Eelco Dolstra | 2f853b20df | |
Eelco Dolstra | 53247d6b11 | |
Eelco Dolstra | 00f6fafad6 | |
Eelco Dolstra | f76b2a7fdd | |
Eelco Dolstra | 03f09e1d18 | |
Eelco Dolstra | aa739e7839 | |
Eelco Dolstra | b5ae85f088 | |
Graham Christensen | 648bdf153d | |
Eelco Dolstra | e486d8d40e | |
Eelco Dolstra | 7d6ba1dc90 | |
Niklas Hambüchen | 82b7f0e840 | |
Niklas Hambüchen | cd8bc06e87 | |
Niklas Hambüchen | c3db9e6f8f | |
Niklas Hambüchen | a96006d97f | |
Niklas Hambüchen | d203c554fa | |
Niklas Hambüchen | b49c3a9db5 | |
Niklas Hambüchen | 717e821b99 | |
Niklas Hambüchen | 20129bd83d | |
Sergei Trofimovich | fe068eca00 | |
Niklas Hambüchen | 57daa860e8 | |
Niklas Hambüchen | 1f97b16b1d | |
Niklas Hambüchen | 00a450026f | |
Niklas Hambüchen | 96cd3d6073 | |
Eelco Dolstra | 7e1c85c5fb | |
Graham Christensen | 68bdd83dc8 | |
Eelco Dolstra | db700f730e | |
Eelco Dolstra | 7c0b0dbec8 | |
Eelco Dolstra | 33db1d35ae | |
Daiderd Jordan | a3c77c1536 | |
Graham Christensen | c8205a3413 | |
Graham Christensen | 17d3ec3405 | |
Daiderd Jordan | a52c331edb | |
Daiderd Jordan | 1ac399dd11 | |
Daiderd Jordan | 99ee3755dd | |
Daiderd Jordan | cbf84bcce7 | |
Daiderd Jordan | 97baf32fbc | |
Eelco Dolstra | 5c8f477283 | |
Aniket Deshpande | ec58ba38c5 | |
Eelco Dolstra | 6847c92788 | |
Matthew Bauer | ec0087df0a | |
Eelco Dolstra | 324a5dc92f | |
Eelco Dolstra | 88571219d9 | |
Eelco Dolstra | 09dde33c19 | |
Eelco Dolstra | 5600b070a7 | |
Eelco Dolstra | 64ec087f58 | |
Eelco Dolstra | f8b30338ac | |
Eelco Dolstra | 7b9c68766d | |
Eelco Dolstra | 78fa47a7f0 | |
Eelco Dolstra | 2fef4dd296 | |
Eelco Dolstra | b43e1e186e | |
Eelco Dolstra | dc29e9fb47 | |
Eelco Dolstra | 94f11d0a61 | |
Eelco Dolstra | 99cec651c9 | |
Eelco Dolstra | 8884c364ca | |
Bruno Bieth | 74a65d313f | |
Eelco Dolstra | 4b214e6e45 | |
Eelco Dolstra | 38a4d38bc3 | |
Eelco Dolstra | 3cc1125595 | |
Eelco Dolstra | 2743bf0bb1 | |
Eelco Dolstra | 82ca6ef390 | |
Eelco Dolstra | e84c265645 | |
Eelco Dolstra | b693029ca0 | |
Eelco Dolstra | 26bc876ae6 | |
Eelco Dolstra | 5064971ded | |
Eelco Dolstra | 34fa8ce917 | |
Graham Christensen | 7ce60a81ba | |
Félix Baylac-Jacqué | 9e0f5f803f | |
Matthew Bauer | 5011a52cf3 | |
Matthew Bauer | 4a3e96281d | |
Eelco Dolstra | fb0ad898ed | |
JorisE | 4b0d613383 | |
Eelco Dolstra | aec545c20b | |
Eelco Dolstra | 5450af5d0d | |
worldofpeace | 2d34028b1e | |
Eelco Dolstra | 2b62928905 | |
ln-nl | 3b1cc8b0cb | |
Eelco Dolstra | d8abee9bc6 | |
Johannes Climacus | a8251ba2ed | |
Eelco Dolstra | 17ef3e6f41 | |
Eelco Dolstra | cfd74aef1e | |
Ding Xiang Fei | abdedcdb38 | |
Eelco Dolstra | 22f2744afd | |
Eelco Dolstra | 9eaebbf575 | |
Eelco Dolstra | bfc6bdf222 | |
Maximilian Bosch | b502b6682b | |
Eelco Dolstra | 4d829916e7 | |
Eelco Dolstra | cdcdf3e798 | |
Eelco Dolstra | 14c877b4ab | |
Vladimír Čunát | c0559a1d60 | |
Matthew Bauer | 92f461e4f4 | |
Matthew Bauer | 7c20ee448f | |
Eelco Dolstra | 8f6c72faee | |
Eelco Dolstra | 66b8a62101 | |
Eelco Dolstra | b6eb8a2d7e | |
Eelco Dolstra | 3fd5425f94 | |
Eelco Dolstra | 5f6840fbb4 | |
Eelco Dolstra | d5c95e2b14 | |
Graham Christensen | f1b8e9efe7 | |
Daiderd Jordan | ce02fc74b2 | |
Graham Christensen | 73b797c207 | |
Graham Christensen | a5efe61786 | |
Graham Christensen | b4a05edbfe | |
Graham Christensen | dde8eeb39a | |
Graham Christensen | 6df61db060 | |
Graham Christensen | c78686e411 | |
Daiderd Jordan | d75bdb5793 | |
Daiderd Jordan | ff6867ab94 | |
Florian Klink | 6ade7ec022 | |
Eelco Dolstra | 7c6391ddc7 | |
Graham Christensen | 5713772568 | |
Eelco Dolstra | 71eb76a0d4 | |
Eelco Dolstra | 92caa60c49 | |
Eelco Dolstra | 3e940bbf2d | |
Will Dietz | a834861876 | |
Eelco Dolstra | 7becb1bf1c | |
Daniel Schaefer | 3f192ac80c | |
Eelco Dolstra | f9a2ea4486 | |
Eelco Dolstra | 989cb37777 | |
Samuel Dionne-Riel | cbc7d9a412 | |
Domen Kožar | 83f2b110ce | |
Eelco Dolstra | f22540464f | |
Daiderd Jordan | b614e0e53d | |
Eelco Dolstra | 5112a33fb1 | |
Niklas Hambüchen | 288f93cec0 | |
Eelco Dolstra | bb6e6923f2 | |
Eelco Dolstra | 41ba5135e0 | |
Eelco Dolstra | 2bc6304793 | |
Eelco Dolstra | 2f59b30251 | |
Niklas Hambüchen | caa76c369a | |
Eelco Dolstra | f32fbf952d | |
Eelco Dolstra | e489f5cabf | |
Bjørn Forsman | 07d9981f34 | |
Bjørn Forsman | dbe4c043d7 | |
Samuel Dionne-Riel | d854e7dfd6 | |
Graham Christensen | 6e9e34ea1f | |
Dmitry Kalinkin | 75ec68f93a | |
Eelco Dolstra | 5c05c238e6 | |
Will Dietz | 63e7fc5096 | |
Will Dietz | 1f9c8cd68b | |
Will Dietz | 42e2d5e7b7 | |
Will Dietz | 0bebca402a | |
Domen Kožar | 6f0359012c | |
zimbatm | 514b3c7f83 | |
xbreak | fcd7660976 | |
Eelco Dolstra | 56f1ed5579 | |
Linus Heckemann | 2aa89daab3 | |
Eelco Dolstra | 6a3dfcb623 | |
Linus Heckemann | 6f093073b6 | |
Eelco Dolstra | ffeabf8390 | |
Joachim Breitner | 684c7fff80 | |
Eelco Dolstra | 806291d18c | |
Chaker Benhamed | 81a23fa7e2 | |
Graham Christensen | caf297a9d3 | |
Andreas Rammhold | 34fade478a | |
Eelco Dolstra | 1f64f4c7c8 | |
Eelco Dolstra | ef52ccf035 | |
Eelco Dolstra | 86f3b94c8c | |
Eelco Dolstra | 578ed7a259 | |
Eelco Dolstra | 53522cb6ac | |
Eelco Dolstra | a3f37d87ea | |
Guillaume Maudoux | 115e2c8c67 | |
Guillaume Maudoux | 4f4391193c | |
Guillaume Maudoux | 38ee16ae9c | |
Guillaume Maudoux | 9d7221183a | |
Guillaume Maudoux | 9d87e3fbd2 | |
Guillaume Maudoux | 5c56570726 | |
Guillaume Maudoux | fc02b1b3ee | |
Guillaume Maudoux | 8574b70342 | |
Guillaume Maudoux | ebc86550f9 | |
Guillaume Maudoux | a17f86ce3a | |
Guillaume Maudoux | 43331d6344 | |
Eelco Dolstra | 5886bc5996 | |
volth | fff8db205c | |
Eelco Dolstra | b71e1fb342 | |
Vladimír Čunát | 4cfc131ec4 | |
Will Dietz | 0963479741 | |
Eelco Dolstra | ad6dbecc1d | |
Eelco Dolstra | ebd4d50e6e | |
Dzmitry Zaitsau | 06d6335987 | |
Dzmitry Zaitsau | ac200c3678 | |
Dzmitry Zaitsau | 56c18c67d9 | |
Dzmitry Zaitsau | 07f992a74b | |
Austin Seipp | d7a7a029ff | |
Eelco Dolstra | 6bfb082ea2 | |
zimbatm | b402148d8f | |
Bjørn Forsman | b9567aa8b6 | |
Shea Levy | e58a71442a | |
Eelco Dolstra | d8fe447139 | |
Eelco Dolstra | 25722bd39a | |
Matthew Bauer | 7ce1fae59f | |
Eelco Dolstra | 7a7ec22298 | |
Daiderd Jordan | 8ac1130cc2 | |
Eelco Dolstra | 01d07b1e92 | |
Shea Levy | b30be6b450 | |
Spencer Baugh | 5f1891b795 | |
Domen Kožar | 92d08c02c8 | |
Dmitry Kalinkin | 15efd54373 | |
Eelco Dolstra | 7cc1a2593e | |
Eelco Dolstra | df03430586 | |
Samuel Evans-Powell | 2ae5624b2f | |
Shea Levy | 1d757292d0 | |
Shea Levy | 087be7281a | |
Eelco Dolstra | 4ae6e84901 | |
Eelco Dolstra | 8ce1986611 | |
Eelco Dolstra | bbaf865655 | |
Eelco Dolstra | 44a8b17556 | |
Eelco Dolstra | 7af5f70139 | |
Eelco Dolstra | c7bf1cdb4e | |
Eelco Dolstra | 30906122e2 | |
Eelco Dolstra | 9a7432672b | |
Mateusz Piotrowski | 80f464d9d7 | |
Eelco Dolstra | 013dd28b15 | |
Eelco Dolstra | 2fadd30ba4 | |
Eelco Dolstra | 85488a93ec | |
John Ericson | 2733287046 | |
John Ericson | fef9f5653b | |
John Ericson | e10d6ed2a7 | |
John Ericson | 318153f4c2 | |
Will Dietz | 21ea00d3ec | |
Mateusz Piotrowski | e8b0efdcc9 | |
Dmitry Kalinkin | 93c9ba3e78 | |
Will Dietz | 3f8b78a84d | |
Will Dietz | e78511743e | |
Daiderd Jordan | 82f054d7d5 | |
Shea Levy | ff342fc0c2 | |
Shea Levy | e653df3153 | |
Will Dietz | c1112ae9a2 | |
Will Dietz | aa7e52abff | |
Daiderd Jordan | 7e35e914c1 | |
Eelco Dolstra | 7b0b349085 | |
Patrick Hilhorst | 567941fb59 | |
Eelco Dolstra | 6024dc1d97 | |
Eelco Dolstra | c37e6d77ea | |
Eelco Dolstra | 378e89360d | |
Eelco Dolstra | 522cebdef4 | |
Dmitry Kalinkin | 0cc4728f71 | |
volth | 21d494da83 | |
Daiderd Jordan | 0e6c84a771 | |
Eelco Dolstra | 800cd55ab7 | |
zimbatm | 5e6fa9092f | |
Eelco Dolstra | f7425d55df | |
Eelco Dolstra | 03ce0c3a9e | |
Daiderd Jordan | 6f89053108 | |
Dmitry Kalinkin | 419949bf61 | |
Eelco Dolstra | 18ecd087ae | |
Daiderd Jordan | 77cc632186 | |
Daiderd Jordan | 898823b67d | |
Eelco Dolstra | 05f0543a17 | |
CHEIKH Chawki | fa5143c722 | |
Eelco Dolstra | 4aee93d5ce | |
Eelco Dolstra | 3f4de91d80 | |
Eelco Dolstra | ebeea068d5 | |
Eelco Dolstra | 5e64470b19 | |
Eelco Dolstra | 338fcec779 | |
Kai Harries | de5997332d | |
Kai Harries | b289d86cd1 | |
Eelco Dolstra | 2f8255cba1 | |
Linus Heckemann | 40e0c9e925 | |
Eelco Dolstra | a32ff2573b | |
Eelco Dolstra | 32a0a223d5 | |
Eelco Dolstra | 9dc9b64aad | |
Eelco Dolstra | 6c6bbeb439 | |
Eelco Dolstra | a0ef21262f | |
Eelco Dolstra | 56f6e382be | |
Felix C. Stegerman | fb2c21f71c | |
Eelco Dolstra | ee88babffa | |
Felix C. Stegerman | 18215be59d | |
Eelco Dolstra | b05d6dac7b | |
Eelco Dolstra | 7751616645 | |
Eelco Dolstra | 220c79ec22 | |
Eelco Dolstra | 4ea4d0b1a3 | |
Eelco Dolstra | fdd19fa2d7 | |
Eelco Dolstra | 5eddc24fab | |
Linus Heckemann | 34d2948f21 | |
Eelco Dolstra | 750400e0fa | |
Domen Kožar | 0bea4a50e0 | |
Eelco Dolstra | 812e39313c | |
Eelco Dolstra | 5a3f140856 | |
Eelco Dolstra | 1109193ea3 | |
Eelco Dolstra | 5a1a870849 | |
Eelco Dolstra | 6323b0729a | |
Eelco Dolstra | fc59fe029b | |
Jan Path | d1b049c4ea | |
Eelco Dolstra | fb35aaa422 | |
Linus Heckemann | f3b8173a93 | |
Eelco Dolstra | 38d76d6d78 | |
Eelco Dolstra | 9f99d62480 | |
Eelco Dolstra | 0163e8928c | |
Eelco Dolstra | 056c3fbbfc | |
Falco Peijnenburg | 49e272f647 | |
Will Dietz | 2a8bdfd31a | |
Will Dietz | 9f998096d2 | |
Will Dietz | 3d974d31fa | |
Eelco Dolstra | f90a67e24d | |
Daiderd Jordan | 8e6bf49297 | |
Eelco Dolstra | 18b4c53f71 | |
Eelco Dolstra | 1427958b3c | |
Eelco Dolstra | 0c61515be1 | |
Eelco Dolstra | 63575ffa38 | |
Eelco Dolstra | 2cf98218c8 | |
Eelco Dolstra | cb073f5218 | |
Guillaume Maudoux | 6a5bf9b143 | |
Will Dietz | 9d24b5d56e | |
Will Dietz | 3283c0dc45 | |
Will Dietz | 27c2fcd4c0 | |
Eelco Dolstra | f6a3dfe4e0 | |
Eelco Dolstra | c47e14ee45 | |
Linus Heckemann | a25abe823f | |
Eelco Dolstra | 1a08ad75ea | |
Eelco Dolstra | 3cd15c5b1f | |
Antoine Eiche | d506342aa2 | |
Antoine Eiche | 73c2ae43f0 | |
Eelco Dolstra | 7a9ac91a43 | |
Eelco Dolstra | bd78544f66 | |
Eelco Dolstra | 79e358ce6d | |
Eelco Dolstra | ba51100d64 | |
Graham Christensen (Target) | ea41838ae0 | |
Eelco Dolstra | 9617a04354 | |
Eelco Dolstra | 01bd66bf83 | |
Eelco Dolstra | 0fda9b22c7 | |
Eelco Dolstra | 38b960136d | |
Benjamin Hipple | 65453e2d77 | |
Eelco Dolstra | d93db0ace0 | |
Profpatsch | 05cfc71cab | |
Eelco Dolstra | aa5e47b2f4 | |
Graham Christensen | 47ed3b282f | |
Matthew Bauer | 9cc876fb11 | |
Eelco Dolstra | 5b7cfa487e | |
Eelco Dolstra | 1e7b8deea7 | |
Eelco Dolstra | 7ae7a38c9a | |
Eelco Dolstra | 99d4bb2d4c | |
Eelco Dolstra | c9ba33870e | |
Graham Christensen | 51cbeec49a | |
Eelco Dolstra | 63786cbd3b | |
Eelco Dolstra | f74e0b4786 | |
Graham Christensen | f11acbaf17 | |
Eelco Dolstra | 7cba4214a8 | |
Daiderd Jordan | ed25753501 | |
Will Dietz | d4f78a6b64 | |
Eelco Dolstra | 9750430003 | |
Eelco Dolstra | 98b2cc2e6e | |
Eelco Dolstra | ed78582847 | |
Eelco Dolstra | 44e86304b6 | |
Will Fancher | b7091ce41e | |
Will Fancher | 0ae8d4033d | |
Eelco Dolstra | 7ccdcc7fed | |
Will Dietz | 8df367a92d | |
Eelco Dolstra | 42e4ea2b6d | |
Luke Clifton | fb72104b80 | |
Eelco Dolstra | a48c2e3411 | |
Anders Riutta | 1915862767 | |
Eelco Dolstra | 43b7eebfab | |
Graham Christensen | be9e356e61 | |
Graham Christensen | 10a7f19937 | |
Luke Clifton | 1241a58975 | |
Eelco Dolstra | 2ca6ef0fec | |
Graham Christensen | 0cd863197b | |
Eelco Dolstra | 52f6d541b9 | |
Eelco Dolstra | 901dfc7978 | |
Eelco Dolstra | 8327a7a8fa | |
Graham Christensen | 0aca1ffb6e | |
Eelco Dolstra | 5b2fdfdca2 | |
Ding Xiang Fei | d6ac762bf7 | |
Eelco Dolstra | bba3f0a308 | |
Eelco Dolstra | 33c3f91885 | |
Eelco Dolstra | 91405986f4 | |
Eelco Dolstra | 0a2545f95c | |
Eelco Dolstra | c4ba5f4be9 | |
Eelco Dolstra | 2d91012754 | |
Eelco Dolstra | e0ddabb0d6 | |
Matthew Bauer | 74f6d8767d | |
Eelco Dolstra | 5e0a7206f5 | |
Will Dietz | 28418af920 | |
Vladimír Čunát | 5f3b72cfc2 | |
Michael Bishop | 4b034f390c | |
Eelco Dolstra | 54996b51fb | |
Eelco Dolstra | 4dd09210d7 | |
Daiderd Jordan | 80a4b44d3d | |
Daiderd Jordan | bfdca55868 | |
Daiderd Jordan | 0f18dc5479 | |
Daiderd Jordan | 246acf93f2 | |
Daiderd Jordan | 7314dc7f07 | |
Daiderd Jordan | 070823baa4 | |
Daiderd Jordan | c9a08540c3 | |
Michael Bishop | 2fd1008c70 | |
Eelco Dolstra | 1f49926601 | |
Michael Bishop | c29e5fbb13 | |
Graham Christensen | c42eaaf684 | |
Eelco Dolstra | c5ab07ec2b | |
Eelco Dolstra | 51003f892d | |
Eelco Dolstra | 291f67aecf | |
Graham Christensen | 4be7652dd3 | |
Graham Christensen | 51f9682a8b | |
Graham Christensen | c3e508d924 | |
Graham Christensen | f66fa7cd20 | |
Eelco Dolstra | 6ed4a6bd0e | |
Eelco Dolstra | 254ed7f9f3 | |
Graham Christensen | 87702532d2 | |
Graham Christensen | b7bb627f67 | |
Graham Christensen | 0b7568fb73 | |
Eelco Dolstra | 475a0a54a9 | |
Eelco Dolstra | b7409c5754 | |
Eelco Dolstra | 4095cd6438 | |
Eelco Dolstra | d1f36e8787 | |
Eelco Dolstra | ef09da58f2 | |
Eelco Dolstra | e3731a1a1f | |
Graham Christensen | 149d10c308 | |
Graham Christensen | 2df21b78b9 | |
Eelco Dolstra | c0c31b58a4 | |
Eelco Dolstra | adab8b916a | |
Michael Bishop | 0767e402f1 | |
Eelco Dolstra | 39f1722f36 | |
Eelco Dolstra | f08b14c9d0 | |
Eelco Dolstra | ddeda0b62e | |
Eelco Dolstra | 264e66f696 | |
Eelco Dolstra | 308689f94b | |
Eelco Dolstra | 99828245f8 | |
Benjamin Hipple | c908df881f | |
Benjamin Hipple | 3407a5d936 | |
Eelco Dolstra | 5e83b0227f | |
Eelco Dolstra | 145db703e5 | |
Eelco Dolstra | 64d7d1a884 | |
Eelco Dolstra | 245d01701d | |
Eelco Dolstra | 1286d86b95 | |
Domen Kožar | d16ff76c69 | |
Eelco Dolstra | 20d74a3257 | |
Domen Kožar | 54df4bb0b5 | |
aszlig | 0ad643ed5c | |
Daiderd Jordan | d85bb4814f | |
Daiderd Jordan | 414397759a | |
Eelco Dolstra | c651b7bdc9 | |
Eelco Dolstra | 1b01954a3d | |
Erik Arvstedt | 8ad2defdf0 | |
Eelco Dolstra | 954d1f4d0a | |
Eelco Dolstra | ebe3d2d370 | |
Eelco Dolstra | 6317c65937 | |
Eelco Dolstra | 17a92dfb7d | |
Tuomas Tynkkynen | 2894197de7 | |
Tuomas Tynkkynen | 458282be59 | |
Eelco Dolstra | cc7b4386b1 | |
Eelco Dolstra | 9b1bdf2db8 | |
Graham Christensen | 02098d2073 | |
Eelco Dolstra | d277442df5 | |
Eelco Dolstra | 19265ed26c | |
Eelco Dolstra | 746cf2d27e | |
volth | bad27dc475 | |
Symphorien Gibol | 5b19a6663b | |
Linus Heckemann | d7402c9cd5 | |
Eelco Dolstra | f72c907ad8 | |
Eelco Dolstra | ada4e90267 | |
Eelco Dolstra | c87f4b9324 | |
Eelco Dolstra | a0b971dd9c | |
Ivan Kozik | ec49ea28dc | |
Eelco Dolstra | 103ad1598c | |
Eelco Dolstra | ed6c646f44 | |
Eelco Dolstra | 7de3e00ad9 | |
Eelco Dolstra | d3761f5f8b | |
Eelco Dolstra | fa4def3d46 | |
Eelco Dolstra | 4361a4331f | |
Eelco Dolstra | 2825e05d21 | |
Eelco Dolstra | 34c17fdae5 | |
Eelco Dolstra | eeebe4cdc5 | |
Eelco Dolstra | 848a9375c3 | |
Eelco Dolstra | 4e7d5f660c | |
Eelco Dolstra | e268bbc054 | |
Eelco Dolstra | 25da1c64f9 | |
Graham Christensen | 06080e4abc | |
Eelco Dolstra | 87356cc8a4 | |
Eelco Dolstra | bc65e02d96 | |
Eelco Dolstra | 122e1a61f8 | |
aszlig | 43e28a1b75 | |
Samuel Dionne-Riel | 438e02529d | |
Graham Christensen | 49a53c1d3f | |
Eelco Dolstra | 3193f5ff3e | |
Samuel Dionne-Riel | fb6907e3d6 | |
Graham Christensen | b27431b7cb | |
Eelco Dolstra | 45bcf5416a | |
Eelco Dolstra | 94b2e4e1be | |
Eelco Dolstra | 4b4adbc93d | |
Eelco Dolstra | d9e8ab0ff2 | |
Eelco Dolstra | 607e75083a | |
Eelco Dolstra | bd19959d90 | |
Will Dietz | 0d72f4e0ca | |
Symphorien Gibol | 81d1385437 | |
Eelco Dolstra | f602ff264b | |
Linus Heckemann | 9ac1a79882 | |
Eelco Dolstra | a7fb7d3cde | |
volth | deaa6e9a34 | |
Eelco Dolstra | 925053e974 | |
volth | 85fe4a819c | |
volth | e2b114cfe1 | |
Will Dietz | 4495560d6d | |
Eelco Dolstra | 1b34b69b45 | |
Eelco Dolstra | c2de2ff385 | |
Eelco Dolstra | efd04888ca | |
Eelco Dolstra | 875cd9da2b | |
volth | c03d73c1cf | |
volth | 627e28ba33 | |
Eelco Dolstra | aa64e95bc8 | |
Eelco Dolstra | f1f4c257f4 | |
volth | 1515c65616 | |
volth | e6bf1a79d7 | |
Eelco Dolstra | ddc9b87df1 | |
volth | 841747b0e6 | |
volth | ee218f99ca | |
volth | 403a76a18f | |
Eelco Dolstra | 3defdccf4b | |
Will Dietz | cb9ef85852 | |
Eelco Dolstra | e388739098 | |
Eelco Dolstra | ea3c9dab5f | |
Eelco Dolstra | 3b1f54cf06 | |
Eelco Dolstra | a92ed973e5 | |
Eelco Dolstra | 91f49ca108 | |
Maximilian Bosch | 8a98ffc276 | |
Eelco Dolstra | dd98683e65 | |
Maximilian Bosch | 6b74fdac27 | |
Will Dietz | 6a24e49ba8 | |
Eelco Dolstra | 6924bdf2bf | |
Peter Simons | 81261ca538 | |
Eelco Dolstra | 629398d05c | |
Shea Levy | 1fb475e7fc | |
Will Dietz | 44de71a396 | |
Will Dietz | f601bc0492 | |
Will Dietz | 25cb1a6343 | |
Eelco Dolstra | b920b90857 | |
Eelco Dolstra | 2e244fb68f | |
Niklas Hambüchen | 10ebcf8670 | |
Symphorien Gibol | ef8122064b | |
Eelco Dolstra | d73e881c81 | |
Matthew Justin Bauer | 6d09e4400c | |
Eelco Dolstra | 85530bcc0b | |
Eelco Dolstra | 7902fccf6f | |
Eelco Dolstra | 3c5d9f478d | |
Eelco Dolstra | 0629601da1 | |
Eelco Dolstra | c905d8b0a8 | |
Eelco Dolstra | 455d1f01d0 | |
Eelco Dolstra | 30964103dc | |
Eelco Dolstra | 24c6806994 | |
Eelco Dolstra | 6ad0a2f749 | |
Daniel Peebles | 169e1478d8 | |
Yorick van Pelt | 72a78beb34 | |
Eelco Dolstra | 27d1c052ae | |
Symphorien Gibol | 8c567afe35 | |
Eelco Dolstra | de71335e4d | |
Shea Levy | 9c2283cc4a | |
Michael Raskin | 17bc757980 | |
Will Dietz | 6bf7dc1baf | |
Aleksandr Pashkov | a717ad7484 | |
Eelco Dolstra | 74144ae845 | |
AmineChikhaoui | 170165ee5a | |
Aleksandr Pashkov | b333e6d6fe | |
Eelco Dolstra | a76498e466 | |
Lorenzo Manacorda | b600d46412 | |
Aleksandr Pashkov | 5ee4472b8b | |
Eelco Dolstra | 4ac4f675df | |
Eelco Dolstra | 691b7582c7 | |
Eelco Dolstra | ca06a9cea7 | |
Eelco Dolstra | a2ec7a3bfd | |
Eelco Dolstra | a936a19da3 | |
Will Dietz | 54b1c59643 | |
Eelco Dolstra | 73357500ac | |
Eelco Dolstra | f0d9909f10 | |
Peter Simons | 93aa3bea2e | |
Shea Levy | bbbfc180d9 | |
Eelco Dolstra | 5d4a9d5677 | |
Eelco Dolstra | 7c3c635d4f | |
Eelco Dolstra | 4caaa4c5fe | |
Eelco Dolstra | 3be58fe1bc | |
Graham Christensen | 6ba1726eeb | |
Graham Christensen | d459d3307c | |
Graham Christensen | f9940f47b3 | |
Michael Mercier | 8dd2e28374 | |
Eelco Dolstra | 3c2de9830d | |
Eelco Dolstra | a4c1618876 | |
Eelco Dolstra | 7d21863bb3 | |
Eelco Dolstra | 5a654fd7dd | |
Eelco Dolstra | e87e4a60d6 | |
Eelco Dolstra | 08ec757726 | |
Eelco Dolstra | 81ea8bd5ce | |
Eelco Dolstra | 1672bcd230 | |
Eelco Dolstra | c1d445ecec | |
Eelco Dolstra | 737ed88f35 | |
Eelco Dolstra | e606cd412f | |
Eelco Dolstra | 6185d25e52 | |
Eelco Dolstra | 23d6bb583a | |
Eelco Dolstra | 3cab639e21 | |
Eelco Dolstra | bd56b5fe3f | |
Eelco Dolstra | d820717bc6 | |
Ben Gamari | 7f560b81ea | |
Will Dietz | 93ae90de0f | |
Will Dietz | 14c464b6c8 | |
Eelco Dolstra | 0a830ef12d | |
Will Dietz | ca9c6cb95d | |
Graham Christensen | e6466c20b3 | |
Graham Christensen | cad903b634 | |
Graham Christensen | c4b9486f9b | |
Eelco Dolstra | 1df32c7d7c | |
Eelco Dolstra | 743359bc8a | |
volth | 88c1ea30e4 | |
Eelco Dolstra | e87242e0de | |
Alexandre Esteves | 579f3895b4 | |
Eelco Dolstra | 4bb8741b98 | |
Eelco Dolstra | 9fd7cf98db | |
Eelco Dolstra | 9064dd2f4d | |
Will Dietz | b08923b4a0 | |
Graham Christensen | 33712fed38 | |
volth | 6cc28c0589 | |
volth | f3c090f91c | |
volth | 49b7cf1813 | |
Eelco Dolstra | 966407bcf1 | |
volth | 8a6a14e1f5 | |
Eelco Dolstra | 1ad19232c4 | |
Eelco Dolstra | f3c85f9eb3 | |
Eelco Dolstra | 2b3c1b3a88 | |
Eelco Dolstra | 38def17627 | |
Eelco Dolstra | 39c4d7f5b0 | |
Eelco Dolstra | 5ba2b566a4 | |
Adrien Devresse | d1f8822a43 | |
Yorick van Pelt | b9289e4855 | |
Eelco Dolstra | a91c4ca01f | |
Domen Kožar | 2228891260 | |
Domen Kožar | 85f9650322 | |
Domen Kožar | 257c3c763a | |
Domen Kožar | 1e20ed5a0c | |
AmineChikhaoui | 854c0860f4 | |
AmineChikhaoui | 591e75cd01 | |
AmineChikhaoui | 129394fb95 | |
Eelco Dolstra | a1adcdf087 | |
Peter Simons | f02eadfda5 | |
Eelco Dolstra | c717d8e3bd | |
Eelco Dolstra | 80a7b16593 | |
Gleb Peregud | 5ba6395378 | |
Eelco Dolstra | 53ec5ac69f | |
Eelco Dolstra | 548ad391d9 | |
Eelco Dolstra | 4a2c948943 | |
Félix Baylac-Jacqué | b2f3a7411a | |
Eelco Dolstra | 3560654e6a | |
Danylo Hlynskyi | ac22d77fd1 | |
Tim Sears | 9a714f75af | |
Will Dietz | 8e7d77d494 | |
Shea Levy | 8e6108ff71 | |
Shea Levy | e2b028353b | |
Shea Levy | 0aae411eaa | |
Shea Levy | 25f580ee75 | |
Shea Levy | 58f9ae0dcd | |
Peter Simons | 655058b8a1 | |
Andrew Dunham | 3a918014b2 | |
Peter Simons | 040acdcee2 | |
Samuel Dionne-Riel | 4b3a7f93a5 | |
Daiderd Jordan | 13d4d1c0a2 | |
Eelco Dolstra | 9296186c75 | |
Will Dietz | 6d9129014d | |
Eelco Dolstra | a8c61cef26 | |
Graham Christensen | 51cbe99104 | |
Graham Christensen | 17b158af85 | |
Eelco Dolstra | a99027d587 | |
Eelco Dolstra | 6f907b7571 | |
Daniel Poelzleithner | f6e8ceafa6 | |
Daniel Poelzleithner | b712d4674b | |
Félix Baylac-Jacqué | 00584bb091 | |
Shea Levy | b37f5ae31d | |
Eelco Dolstra | a4aac7f88c | |
Eelco Dolstra | c74f838620 | |
Eelco Dolstra | 20cd1e39d5 | |
Félix Baylac-Jacqué | 10d33452e2 | |
Eelco Dolstra | d5c9315d84 | |
Félix Baylac-Jacqué | a91fb422fe | |
Eelco Dolstra | d34fa2bcc3 | |
Eelco Dolstra | 4fd28bee89 | |
Shea Levy | 3d748d3323 | |
Sean Seefried | 2ef8f0608c | |
Shea Levy | dc0a542c9f | |
Eelco Dolstra | e3cdcf89b0 | |
Eelco Dolstra | 1839a5542a | |
Daiderd Jordan | f524bcb43d | |
Eelco Dolstra | d6aaa35478 | |
John Arnold | a405d25fa3 | |
Shea Levy | a38fe5c1a8 | |
Shea Levy | 7459388448 | |
Shea Levy | fd98fca7bb | |
Samuel Dionne-Riel | a4c9b2595e | |
Shea Levy | 377cf43ff6 | |
Eelco Dolstra | 3ec1b3da45 | |
Shea Levy | 346c0ac361 | |
Eelco Dolstra | d8b752ff49 | |
Eelco Dolstra | 9387163d53 | |
Andrew Dunham | f8ab9cef6c | |
Samuel Dionne-Riel | 9478f88681 | |
Samuel Dionne-Riel | 399f43c3d5 | |
Nicolas Dudebout | d8a1c27806 | |
Bogdan Seniuc | b828051659 | |
Doug Beardsley | 72902ec399 | |
Eelco Dolstra | e10a7ec7eb | |
AmineChikhaoui | e01b01c579 | |
AmineChikhaoui | 62d75ad3e1 | |
AmineChikhaoui | 33b08899d5 | |
AmineChikhaoui | 86930ed414 | |
AmineChikhaoui | 2855c3d965 | |
Eelco Dolstra | 27e9ce0eb2 | |
Andrew Dunham | 0081a1eac2 | |
Eelco Dolstra | 1d9742b95f | |
Eelco Dolstra | 5c904e10eb | |
Matthew Justin Bauer | d7a84d330c | |
Justin Humm | 045eb84409 | |
Tuomas Tynkkynen | af86132e1a | |
Graham Christensen | 3fbaa230a2 | |
Ryan Trinkle | f2273b11f5 | |
Graham Christensen | 4eb40c72ed | |
Graham Christensen | f06f8102bd | |
Graham Christensen | 4ba91f5bae | |
Eelco Dolstra | 4ee4fda521 | |
zimbatm | 865ca2402f | |
Graham Christensen | 2921165a9d | |
Eelco Dolstra | 446bb88f13 | |
Eelco Dolstra | 2b61c74922 | |
Eelco Dolstra | 9d1220a01d | |
Eelco Dolstra | e01c01f72c | |
Eelco Dolstra | 7ec13eda9b | |
Tuomas Tynkkynen | cc6712ae90 | |
Shea Levy | 6856fe62b0 | |
Eelco Dolstra | 0cb1e52052 | |
Dmitry Kalinkin | e2f56c1333 | |
Will Dietz | 74da813912 | |
Will Dietz | 59b32403f2 | |
Eelco Dolstra | 2bc6cfe1ad | |
Eelco Dolstra | 28eb9621cc | |
Eelco Dolstra | ed87fd17dd | |
Eelco Dolstra | dce8af59a6 | |
Eelco Dolstra | f87e286e82 | |
Eelco Dolstra | 92aee1b7d6 | |
Shea Levy | c24e0439b2 | |
Eelco Dolstra | ec91840e70 | |
Eelco Dolstra | 97002b684c | |
Will Dietz | f66ae22288 | |
Eelco Dolstra | 11898d6a37 | |
Eelco Dolstra | 47f7e5585b | |
Shea Levy | 92dfc22327 | |
Eelco Dolstra | 8615cfb130 | |
Corey O'Connor | 22b144fea6 | |
Will Dietz | 02d36fdab7 | |
Eelco Dolstra | bed22114bf | |
Eelco Dolstra | 03d8136b02 | |
Eelco Dolstra | e0c1597910 | |
Will Dietz | dc99ea4483 | |
Eelco Dolstra | 668ac3ea2c | |
Eelco Dolstra | 9d40787938 | |
Eelco Dolstra | 5df427f35b | |
Eelco Dolstra | 21ebf6a160 | |
Eelco Dolstra | 1aca195e52 | |
Eelco Dolstra | 78d0c72b52 | |
Will Dietz | f5a2136a40 | |
Shea Levy | d53970d31b | |
Will Dietz | 9b33201e72 | |
Shea Levy | ae299ab47a | |
Eelco Dolstra | 44a1b6c026 | |
Eelco Dolstra | 138af2e554 | |
Ben Challenor | a74288b943 | |
Ben Challenor | ec6a328fe8 | |
Eelco Dolstra | b2074f0892 | |
zimbatm | 43bef1b82c | |
zimbatm | fef8ebf51d | |
Linus Heckemann | 639c166647 | |
Linus Heckemann | 637701b604 | |
Linus Heckemann | 12913ccf45 | |
Eelco Dolstra | 48662d151b | |
Eelco Dolstra | 3e6b194d78 | |
Eelco Dolstra | 64441f0551 | |
Eelco Dolstra | eb75bc5afb | |
Eelco Dolstra | 4868721506 | |
Eelco Dolstra | 7b8914825a | |
Shea Levy | cfdbfa6b2c | |
Shea Levy | d25d9f7cec | |
Shea Levy | e2088febf3 | |
Will Dietz | d98755b0c2 | |
Eelco Dolstra | 55aa622fb1 | |
Eelco Dolstra | c04bca3401 | |
Eelco Dolstra | ca14b14200 | |
Shea Levy | 56f2ed0081 | |
Eelco Dolstra | 7afdc8d4a1 | |
Eelco Dolstra | 6e60141a80 | |
Guillaume Maudoux | 80735c4cc9 | |
Asad Saeeduddin | be54f4a0b6 | |
Eelco Dolstra | 24b739817f | |
Eelco Dolstra | dc83c8eea5 | |
Tim Engler | 383afab9ad | |
Eelco Dolstra | 16551f54c9 | |
Eelco Dolstra | 4452f6e855 | |
Will Dietz | 56253bb08f | |
Will Dietz | e917c05628 | |
Eelco Dolstra | 70dbac7491 | |
Shea Levy | 088ef81759 | |
Will Dietz | e9a5ce9b07 | |
Will Dietz | 6b9a03f5d8 | |
Will Dietz | c89a3d5368 | |
Shea Levy | 3748a0ca1e | |
Shea Levy | aa8bbbf69d | |
Eelco Dolstra | 5c7a6d07de | |
Tuomas Tynkkynen | a0e38c16bc | |
Eelco Dolstra | 939cf4cceb | |
Matthew O'Gorman | 467fdd8ca4 | |
Matthew O'Gorman | 3c16044cb0 | |
Matt O'Gorman | 12fe2249e1 | |
Matthew O'Gorman | 0312d30315 | |
Matthew O'Gorman | 429154b74c | |
Will Dietz | c577186f59 | |
Michael Fiano | ad97d1a786 | |
Shea Levy | 4a000cbb39 | |
Will Dietz | e89d02bf03 | |
Daiderd Jordan | 05cb8e5c5a | |
Shea Levy | 14ca85688c | |
Eelco Dolstra | 8a5da93841 | |
Linus Heckemann | 919c3c20b3 | |
Linus Heckemann | eb03a296c1 | |
Tuomas Tynkkynen | 77e9e1ed91 | |
Eelco Dolstra | 24ec750003 | |
Will Dietz | 009cf9cd23 | |
Will Dietz | 3cac8734ac | |
Will Dietz | 8282c60d74 | |
Graham Christensen | 9432f3fb7d | |
Graham Christensen | ab435463d0 | |
Michael Weiss | bd94e63853 | |
Dmitry Kalinkin | d9d8a84a96 | |
Eelco Dolstra | 64e486ab63 | |
Eelco Dolstra | 39b4177500 | |
Eelco Dolstra | 2691d51a33 | |
Eelco Dolstra | b6dec2f3ca | |
Linus Heckemann | 78ac3eb4eb | |
Maximilian Bosch | 0413aeb35d | |
Will Dietz | 79f5c296c0 |
|
@ -13,9 +13,6 @@ perl/Makefile.config
|
|||
|
||||
/corepkgs/config.nix
|
||||
|
||||
# /corepkgs/buildenv/
|
||||
/corepkgs/buildenv/builder.pl
|
||||
|
||||
# /corepkgs/channels/
|
||||
/corepkgs/channels/unpack.sh
|
||||
|
||||
|
@ -72,9 +69,6 @@ perl/Makefile.config
|
|||
# /src/nix-channel/
|
||||
/src/nix-channel/nix-channel
|
||||
|
||||
# /src/buildenv/
|
||||
/src/buildenv/buildenv
|
||||
|
||||
# /src/nix-build/
|
||||
/src/nix-build/nix-build
|
||||
|
||||
|
@ -87,6 +81,9 @@ perl/Makefile.config
|
|||
/tests/common.sh
|
||||
/tests/dummy
|
||||
/tests/result*
|
||||
/tests/restricted-innocent
|
||||
/tests/shell
|
||||
/tests/shell.drv
|
||||
|
||||
# /tests/lang/
|
||||
/tests/lang/*.out
|
||||
|
|
21
Makefile
21
Makefile
|
@ -1,23 +1,11 @@
|
|||
makefiles = \
|
||||
local.mk \
|
||||
src/boost/format/local.mk \
|
||||
src/libutil/local.mk \
|
||||
src/libstore/local.mk \
|
||||
src/libmain/local.mk \
|
||||
src/libexpr/local.mk \
|
||||
src/nix/local.mk \
|
||||
src/nix-store/local.mk \
|
||||
src/nix-instantiate/local.mk \
|
||||
src/nix-env/local.mk \
|
||||
src/nix-daemon/local.mk \
|
||||
src/nix-collect-garbage/local.mk \
|
||||
src/nix-copy-closure/local.mk \
|
||||
src/nix-prefetch-url/local.mk \
|
||||
src/buildenv/local.mk \
|
||||
src/resolve-system-dependencies/local.mk \
|
||||
src/nix-channel/local.mk \
|
||||
src/nix-build/local.mk \
|
||||
src/build-remote/local.mk \
|
||||
scripts/local.mk \
|
||||
corepkgs/local.mk \
|
||||
misc/systemd/local.mk \
|
||||
|
@ -27,15 +15,8 @@ makefiles = \
|
|||
tests/local.mk \
|
||||
tests/plugins/local.mk
|
||||
|
||||
GLOBAL_CXXFLAGS += -std=c++14 -g -Wall -include config.h
|
||||
GLOBAL_CXXFLAGS += -g -Wall -include config.h
|
||||
|
||||
-include Makefile.config
|
||||
|
||||
OPTIMIZE = 1
|
||||
|
||||
ifeq ($(OPTIMIZE), 1)
|
||||
GLOBAL_CFLAGS += -O3
|
||||
GLOBAL_CXXFLAGS += -O3
|
||||
endif
|
||||
|
||||
include mk/lib.mk
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
AR = @AR@
|
||||
BDW_GC_LIBS = @BDW_GC_LIBS@
|
||||
BUILD_SHARED_LIBS = @BUILD_SHARED_LIBS@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
ENABLE_S3 = @ENABLE_S3@
|
||||
HAVE_SODIUM = @HAVE_SODIUM@
|
||||
HAVE_READLINE = @HAVE_READLINE@
|
||||
HAVE_BROTLI = @HAVE_BROTLI@
|
||||
HAVE_SECCOMP = @HAVE_SECCOMP@
|
||||
BOOST_LDFLAGS = @BOOST_LDFLAGS@
|
||||
LIBCURL_LIBS = @LIBCURL_LIBS@
|
||||
OPENSSL_LIBS = @OPENSSL_LIBS@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
|
@ -16,9 +18,9 @@ SODIUM_LIBS = @SODIUM_LIBS@
|
|||
LIBLZMA_LIBS = @LIBLZMA_LIBS@
|
||||
SQLITE3_LIBS = @SQLITE3_LIBS@
|
||||
LIBBROTLI_LIBS = @LIBBROTLI_LIBS@
|
||||
EDITLINE_LIBS = @EDITLINE_LIBS@
|
||||
bash = @bash@
|
||||
bindir = @bindir@
|
||||
brotli = @brotli@
|
||||
lsof = @lsof@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
[![Open Collective supporters](https://opencollective.com/nixos/tiers/supporter/badge.svg?label=Supporters&color=brightgreen)](https://opencollective.com/nixos)
|
||||
|
||||
Nix, the purely functional package manager
|
||||
------------------------------------------
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
90
configure.ac
90
configure.ac
|
@ -1,4 +1,5 @@
|
|||
AC_INIT(nix, m4_esyscmd([bash -c "echo -n $(cat ./version)$VERSION_SUFFIX"]))
|
||||
AC_INIT(nix, m4_esyscmd([bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX"]))
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
AC_CONFIG_SRCDIR(README.md)
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
|
||||
|
@ -42,13 +43,28 @@ esac
|
|||
|
||||
AC_MSG_RESULT($system)
|
||||
AC_SUBST(system)
|
||||
AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier (`cpu-os')])
|
||||
AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier ('cpu-os')])
|
||||
|
||||
|
||||
# State should be stored in /nix/var, unless the user overrides it explicitly.
|
||||
test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var
|
||||
|
||||
|
||||
# Set default flags for nix (as per AC_PROG_CC/CXX docs),
|
||||
# while still allowing the user to override them from the command line.
|
||||
: ${CFLAGS="-O3"}
|
||||
: ${CXXFLAGS="-O3"}
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CPP
|
||||
AX_CXX_COMPILE_STDCXX_17([noext], [mandatory])
|
||||
|
||||
AC_CHECK_TOOL([AR], [ar])
|
||||
|
||||
# Use 64-bit file system calls so that we can support files > 2 GiB.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
||||
# Solaris-specific stuff.
|
||||
AC_STRUCT_DIRENT_D_TYPE
|
||||
if test "$sys_name" = sunos; then
|
||||
|
@ -57,18 +73,6 @@ if test "$sys_name" = sunos; then
|
|||
fi
|
||||
|
||||
|
||||
CFLAGS=
|
||||
CXXFLAGS=
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CPP
|
||||
AX_CXX_COMPILE_STDCXX_11
|
||||
|
||||
|
||||
# Use 64-bit file system calls so that we can support files > 2 GiB.
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
|
||||
# Check for pubsetbuf.
|
||||
AC_MSG_CHECKING([for pubsetbuf])
|
||||
AC_LANG_PUSH(C++)
|
||||
|
@ -127,8 +131,6 @@ NEED_PROG(bzip2, bzip2)
|
|||
NEED_PROG(gzip, gzip)
|
||||
NEED_PROG(xz, xz)
|
||||
AC_PATH_PROG(dot, dot)
|
||||
AC_PATH_PROG(pv, pv, pv)
|
||||
AC_PATH_PROGS(brotli, brotli bro, bro)
|
||||
AC_PATH_PROG(lsof, lsof, lsof)
|
||||
|
||||
|
||||
|
@ -146,15 +148,25 @@ AC_ARG_WITH(store-dir, AC_HELP_STRING([--with-store-dir=PATH],
|
|||
AC_SUBST(storedir)
|
||||
|
||||
|
||||
# Look for boost, a required dependency.
|
||||
# Note that AX_BOOST_BASE only exports *CPP* BOOST_CPPFLAGS, no CXX flags,
|
||||
# and CPPFLAGS are not passed to the C++ compiler automatically.
|
||||
# Thus we append the returned CPPFLAGS to the CXXFLAGS here.
|
||||
AX_BOOST_BASE([1.66], [CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"], [AC_MSG_ERROR([Nix requires boost.])])
|
||||
# For unknown reasons, setting this directly in the ACTION-IF-FOUND above
|
||||
# ends up with LDFLAGS being empty, so we set it afterwards.
|
||||
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
||||
|
||||
|
||||
# Look for OpenSSL, a required dependency.
|
||||
PKG_CHECK_MODULES([OPENSSL], [libcrypto], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# Look for libbz2, a required dependency.
|
||||
AC_CHECK_LIB([bz2], [BZ2_bzWriteOpen], [true],
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See http://www.bzip.org/.])])
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://web.archive.org/web/20180624184756/http://www.bzip.org/.])])
|
||||
AC_CHECK_HEADERS([bzlib.h], [true],
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See http://www.bzip.org/.])])
|
||||
[AC_MSG_ERROR([Nix requires libbz2, which is part of bzip2. See https://web.archive.org/web/20180624184756/http://www.bzip.org/.])])
|
||||
|
||||
|
||||
# Look for SQLite, a required dependency.
|
||||
|
@ -164,6 +176,17 @@ PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CX
|
|||
# Look for libcurl, a required dependency.
|
||||
PKG_CHECK_MODULES([LIBCURL], [libcurl], [CXXFLAGS="$LIBCURL_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Look for editline, a required dependency.
|
||||
# The the libeditline.pc file was added only in libeditline >= 1.15.2,
|
||||
# see https://github.com/troglobit/editline/commit/0a8f2ef4203c3a4a4726b9dd1336869cd0da8607,
|
||||
# but e.g. Ubuntu 16.04 has an older version, so we fall back to searching for
|
||||
# editline.h when the pkg-config approach fails.
|
||||
PKG_CHECK_MODULES([EDITLINE], [libeditline], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLAGS"], [
|
||||
AC_CHECK_HEADERS([editline.h], [true],
|
||||
[AC_MSG_ERROR([Nix requires libeditline; it was found neither via pkg-config nor its normal header.])])
|
||||
AC_SEARCH_LIBS([readline read_history], [editline], [],
|
||||
[AC_MSG_ERROR([Nix requires libeditline; it was not found via pkg-config, but via its header, but required functions do not work. Maybe it is too old? >= 1.14 is required.])])
|
||||
])
|
||||
|
||||
# Look for libsodium, an optional dependency.
|
||||
PKG_CHECK_MODULES([SODIUM], [libsodium],
|
||||
|
@ -179,12 +202,9 @@ AC_CHECK_LIB([lzma], [lzma_stream_encoder_mt],
|
|||
[AC_DEFINE([HAVE_LZMA_MT], [1], [xz multithreaded compression support])])
|
||||
|
||||
|
||||
# Look for libbrotli{enc,dec}, optional dependencies
|
||||
PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec],
|
||||
[AC_DEFINE([HAVE_BROTLI], [1], [Whether to use libbrotli.])
|
||||
CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]
|
||||
have_brotli=1], [have_brotli=])
|
||||
AC_SUBST(HAVE_BROTLI, [$have_brotli])
|
||||
# Look for libbrotli{enc,dec}.
|
||||
PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"])
|
||||
|
||||
|
||||
# Look for libseccomp, required for Linux sandboxing.
|
||||
if test "$sys_name" = linux; then
|
||||
|
@ -215,7 +235,7 @@ AC_SUBST(ENABLE_S3, [$enable_s3])
|
|||
AC_LANG_POP(C++)
|
||||
|
||||
if test -n "$enable_s3"; then
|
||||
declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
|
||||
declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP $CPPFLAGS - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' '))
|
||||
AC_DEFINE_UNQUOTED([AWS_VERSION_MAJOR], ${aws_version_tokens@<:@0@:>@}, [Major version of aws-sdk-cpp.])
|
||||
AC_DEFINE_UNQUOTED([AWS_VERSION_MINOR], ${aws_version_tokens@<:@1@:>@}, [Minor version of aws-sdk-cpp.])
|
||||
fi
|
||||
|
@ -232,12 +252,6 @@ if test "$gc" = yes; then
|
|||
fi
|
||||
|
||||
|
||||
AC_ARG_ENABLE(init-state, AC_HELP_STRING([--disable-init-state],
|
||||
[do not initialise DB etc. in `make install']),
|
||||
init_state=$enableval, init_state=yes)
|
||||
#AM_CONDITIONAL(INIT_STATE, test "$init_state" = "yes")
|
||||
|
||||
|
||||
# documentation generation switch
|
||||
AC_ARG_ENABLE(doc-gen, AC_HELP_STRING([--disable-doc-gen],
|
||||
[disable documentation generation]),
|
||||
|
@ -260,11 +274,6 @@ if test "$(uname)" = "Darwin"; then
|
|||
fi
|
||||
|
||||
|
||||
# Figure out the extension of dynamic libraries.
|
||||
eval dynlib_suffix=$shrext_cmds
|
||||
AC_SUBST(dynlib_suffix)
|
||||
|
||||
|
||||
# Do we have GNU tar?
|
||||
AC_MSG_CHECKING([if you have a recent GNU tar])
|
||||
if $tar --version 2> /dev/null | grep -q GNU && tar cvf /dev/null --warning=no-timestamp ./config.log > /dev/null; then
|
||||
|
@ -281,6 +290,15 @@ AC_ARG_WITH(sandbox-shell, AC_HELP_STRING([--with-sandbox-shell=PATH],
|
|||
sandbox_shell=$withval)
|
||||
AC_SUBST(sandbox_shell)
|
||||
|
||||
AC_ARG_ENABLE(shared, AC_HELP_STRING([--enable-shared],
|
||||
[Build shared libraries for Nix [default=yes]]),
|
||||
shared=$enableval, shared=yes)
|
||||
if test "$shared" = yes; then
|
||||
AC_SUBST(BUILD_SHARED_LIBS, 1, [Whether to build shared libraries.])
|
||||
else
|
||||
AC_SUBST(BUILD_SHARED_LIBS, 0, [Whether to build shared libraries.])
|
||||
fi
|
||||
|
||||
|
||||
# Expand all variables in config.status.
|
||||
test "$prefix" = NONE && prefix=$ac_default_prefix
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p python3 --pure
|
||||
|
||||
# To be used with `--trace-function-calls` and `flamegraph.pl`.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# nix-instantiate --trace-function-calls '<nixpkgs>' -A hello 2> nix-function-calls.trace
|
||||
# ./contrib/stack-collapse.py nix-function-calls.trace > nix-function-calls.folded
|
||||
# nix-shell -p flamegraph --run "flamegraph.pl nix-function-calls.folded > nix-function-calls.svg"
|
||||
|
||||
import sys
|
||||
from pprint import pprint
|
||||
import fileinput
|
||||
|
||||
stack = []
|
||||
timestack = []
|
||||
|
||||
for line in fileinput.input():
|
||||
components = line.strip().split(" ", 2)
|
||||
if components[0] != "function-trace":
|
||||
continue
|
||||
|
||||
direction = components[1]
|
||||
components = components[2].rsplit(" ", 2)
|
||||
|
||||
loc = components[0]
|
||||
_at = components[1]
|
||||
time = int(components[2])
|
||||
|
||||
if direction == "entered":
|
||||
stack.append(loc)
|
||||
timestack.append(time)
|
||||
elif direction == "exited":
|
||||
dur = time - timestack.pop()
|
||||
vst = ";".join(stack)
|
||||
print(f"{vst} {dur}")
|
||||
stack.pop()
|
|
@ -1,11 +1,9 @@
|
|||
with import <nix/config.nix>;
|
||||
|
||||
{ derivations, manifest }:
|
||||
|
||||
derivation {
|
||||
name = "user-environment";
|
||||
system = builtins.currentSystem;
|
||||
builder = nixLibexecDir + "/nix/buildenv";
|
||||
system = "builtin";
|
||||
builder = "builtin:buildenv";
|
||||
|
||||
inherit manifest;
|
||||
|
||||
|
@ -24,21 +22,4 @@ derivation {
|
|||
|
||||
# Also don't bother substituting.
|
||||
allowSubstitutes = false;
|
||||
|
||||
__sandboxProfile = ''
|
||||
(allow sysctl-read)
|
||||
(allow file-read*
|
||||
(literal "/usr/lib/libSystem.dylib")
|
||||
(literal "/usr/lib/libSystem.B.dylib")
|
||||
(literal "/usr/lib/libobjc.A.dylib")
|
||||
(literal "/usr/lib/libobjc.dylib")
|
||||
(literal "/usr/lib/libauto.dylib")
|
||||
(literal "/usr/lib/libc++abi.dylib")
|
||||
(literal "/usr/lib/libc++.1.dylib")
|
||||
(literal "/usr/lib/libDiagnosticMessagesClient.dylib")
|
||||
(subpath "/usr/lib/system")
|
||||
(subpath "/dev"))
|
||||
'';
|
||||
|
||||
inherit chrootDeps;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
{ system ? "" # obsolete
|
||||
, url
|
||||
, hash ? "" # an SRI ash
|
||||
|
||||
# Legacy hash specification
|
||||
, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? ""
|
||||
, outputHash ?
|
||||
if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
|
||||
if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256
|
||||
, outputHashAlgo ?
|
||||
if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
|
||||
if hash != "" then "" else if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256"
|
||||
|
||||
, executable ? false
|
||||
, unpack ? false
|
||||
, name ? baseNameOf (toString url)
|
||||
|
|
|
@ -18,21 +18,17 @@ let
|
|||
if [ * != $channelName ]; then
|
||||
mv * $out/$channelName
|
||||
fi
|
||||
if [ -n "$binaryCacheURL" ]; then
|
||||
mkdir $out/binary-caches
|
||||
echo -n "$binaryCacheURL" > $out/binary-caches/$channelName
|
||||
fi
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{ name, channelName, src, binaryCacheURL ? "" }:
|
||||
{ name, channelName, src }:
|
||||
|
||||
derivation {
|
||||
system = builtins.currentSystem;
|
||||
builder = shell;
|
||||
args = [ "-e" builder ];
|
||||
inherit name channelName src binaryCacheURL;
|
||||
inherit name channelName src;
|
||||
|
||||
PATH = "${nixBinDir}:${coreutils}";
|
||||
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
<part xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="part-advanced-topics"
|
||||
version="5.0">
|
||||
|
||||
<title>Advanced Topics</title>
|
||||
|
||||
<xi:include href="distributed-builds.xml" />
|
||||
<xi:include href="cores-vs-jobs.xml" />
|
||||
<xi:include href="diff-hook.xml" />
|
||||
<xi:include href="post-build-hook.xml" />
|
||||
|
||||
</part>
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="chap-tuning-cores-and-jobs">
|
||||
|
||||
<title>Tuning Cores and Jobs</title>
|
||||
|
||||
<para>Nix has two relevant settings with regards to how your CPU cores
|
||||
will be utilized: <xref linkend="conf-cores" /> and
|
||||
<xref linkend="conf-max-jobs" />. This chapter will talk about what
|
||||
they are, how they interact, and their configuration trade-offs.</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><xref linkend="conf-max-jobs" /></term>
|
||||
<listitem><para>
|
||||
Dictates how many separate derivations will be built at the same
|
||||
time. If you set this to zero, the local machine will do no
|
||||
builds. Nix will still substitute from binary caches, and build
|
||||
remotely if remote builders are configured.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><xref linkend="conf-cores" /></term>
|
||||
<listitem><para>
|
||||
Suggests how many cores each derivation should use. Similar to
|
||||
<command>make -j</command>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>The <xref linkend="conf-cores" /> setting determines the value of
|
||||
<envar>NIX_BUILD_CORES</envar>. <envar>NIX_BUILD_CORES</envar> is equal
|
||||
to <xref linkend="conf-cores" />, unless <xref linkend="conf-cores" />
|
||||
equals <literal>0</literal>, in which case <envar>NIX_BUILD_CORES</envar>
|
||||
will be the total number of cores in the system.</para>
|
||||
|
||||
<para>The total number of consumed cores is a simple multiplication,
|
||||
<xref linkend="conf-cores" /> * <envar>NIX_BUILD_CORES</envar>.</para>
|
||||
|
||||
<para>The balance on how to set these two independent variables depends
|
||||
upon each builder's workload and hardware. Here are a few example
|
||||
scenarios on a machine with 24 cores:</para>
|
||||
|
||||
<table>
|
||||
<caption>Balancing 24 Build Cores</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><xref linkend="conf-max-jobs" /></th>
|
||||
<th><xref linkend="conf-cores" /></th>
|
||||
<th><envar>NIX_BUILD_CORES</envar></th>
|
||||
<th>Maximum Processes</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>24</td>
|
||||
<td>24</td>
|
||||
<td>24</td>
|
||||
<td>
|
||||
One derivation will be built at a time, each one can use 24
|
||||
cores. Undersold if a job can’t use 24 cores.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>6</td>
|
||||
<td>6</td>
|
||||
<td>24</td>
|
||||
<td>
|
||||
Four derivations will be built at once, each given access to
|
||||
six cores.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>12</td>
|
||||
<td>6</td>
|
||||
<td>6</td>
|
||||
<td>72</td>
|
||||
<td>
|
||||
12 derivations will be built at once, each given access to six
|
||||
cores. This configuration is over-sold. If all 12 derivations
|
||||
being built simultaneously try to use all six cores, the
|
||||
machine's performance will be degraded due to extensive context
|
||||
switching between the 12 builds.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>24</td>
|
||||
<td>1</td>
|
||||
<td>1</td>
|
||||
<td>24</td>
|
||||
<td>
|
||||
24 derivations can build at the same time, each using a single
|
||||
core. Never oversold, but derivations which require many cores
|
||||
will be very slow to compile.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>24</td>
|
||||
<td>0</td>
|
||||
<td>24</td>
|
||||
<td>576</td>
|
||||
<td>
|
||||
24 derivations can build at the same time, each using all the
|
||||
available cores of the machine. Very likely to be oversold,
|
||||
and very likely to suffer context switches.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<para>It is up to the derivations' build script to respect
|
||||
host's requested cores-per-build by following the value of the
|
||||
<envar>NIX_BUILD_CORES</envar> environment variable.</para>
|
||||
|
||||
</chapter>
|
|
@ -0,0 +1,205 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="chap-diff-hook"
|
||||
version="5.0"
|
||||
>
|
||||
|
||||
<title>Verifying Build Reproducibility with <option linkend="conf-diff-hook">diff-hook</option></title>
|
||||
|
||||
<subtitle>Check build reproducibility by running builds multiple times
|
||||
and comparing their results.</subtitle>
|
||||
|
||||
<para>Specify a program with Nix's <xref linkend="conf-diff-hook" /> to
|
||||
compare build results when two builds produce different results. Note:
|
||||
this hook is only executed if the results are not the same, this hook
|
||||
is not used for determining if the results are the same.</para>
|
||||
|
||||
<para>For purposes of demonstration, we'll use the following Nix file,
|
||||
<filename>deterministic.nix</filename> for testing:</para>
|
||||
|
||||
<programlisting>
|
||||
let
|
||||
inherit (import <nixpkgs> {}) runCommand;
|
||||
in {
|
||||
stable = runCommand "stable" {} ''
|
||||
touch $out
|
||||
'';
|
||||
|
||||
unstable = runCommand "unstable" {} ''
|
||||
echo $RANDOM > $out
|
||||
'';
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>Additionally, <filename>nix.conf</filename> contains:
|
||||
|
||||
<programlisting>
|
||||
diff-hook = /etc/nix/my-diff-hook
|
||||
run-diff-hook = true
|
||||
</programlisting>
|
||||
|
||||
where <filename>/etc/nix/my-diff-hook</filename> is an executable
|
||||
file containing:
|
||||
|
||||
<programlisting>
|
||||
#!/bin/sh
|
||||
exec >&2
|
||||
echo "For derivation $3:"
|
||||
/run/current-system/sw/bin/diff -r "$1" "$2"
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The diff hook is executed by the same user and group who ran the
|
||||
build. However, the diff hook does not have write access to the store
|
||||
path just built.</para>
|
||||
|
||||
<section>
|
||||
<title>
|
||||
Spot-Checking Build Determinism
|
||||
</title>
|
||||
|
||||
<para>
|
||||
Verify a path which already exists in the Nix store by passing
|
||||
<option>--check</option> to the build command.
|
||||
</para>
|
||||
|
||||
<para>If the build passes and is deterministic, Nix will exit with a
|
||||
status code of 0:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-build ./deterministic.nix -A stable
|
||||
these derivations will be built:
|
||||
/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv
|
||||
building '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'...
|
||||
/nix/store/yyxlzw3vqaas7wfp04g0b1xg51f2czgq-stable
|
||||
|
||||
$ nix-build ./deterministic.nix -A stable --check
|
||||
checking outputs of '/nix/store/z98fasz2jqy9gs0xbvdj939p27jwda38-stable.drv'...
|
||||
/nix/store/yyxlzw3vqaas7wfp04g0b1xg51f2czgq-stable
|
||||
</screen>
|
||||
|
||||
<para>If the build is not deterministic, Nix will exit with a status
|
||||
code of 1:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-build ./deterministic.nix -A unstable
|
||||
these derivations will be built:
|
||||
/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv
|
||||
building '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'...
|
||||
/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable
|
||||
|
||||
$ nix-build ./deterministic.nix -A unstable --check
|
||||
checking outputs of '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'...
|
||||
error: derivation '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv' may not be deterministic: output '/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable' differs
|
||||
</screen>
|
||||
|
||||
<para>In the Nix daemon's log, we will now see:
|
||||
<screen>
|
||||
For derivation /nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv:
|
||||
1c1
|
||||
< 8108
|
||||
---
|
||||
> 30204
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>Using <option>--check</option> with <option>--keep-failed</option>
|
||||
will cause Nix to keep the second build's output in a special,
|
||||
<literal>.check</literal> path:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-build ./deterministic.nix -A unstable --check --keep-failed
|
||||
checking outputs of '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv'...
|
||||
note: keeping build directory '/tmp/nix-build-unstable.drv-0'
|
||||
error: derivation '/nix/store/cgl13lbj1w368r5z8gywipl1ifli7dhk-unstable.drv' may not be deterministic: output '/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable' differs from '/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable.check'
|
||||
</screen>
|
||||
|
||||
<para>In particular, notice the
|
||||
<literal>/nix/store/krpqk0l9ib0ibi1d2w52z293zw455cap-unstable.check</literal>
|
||||
output. Nix has copied the build results to that directory where you
|
||||
can examine it.</para>
|
||||
|
||||
<note xml:id="check-dirs-are-unregistered">
|
||||
<title><literal>.check</literal> paths are not registered store paths</title>
|
||||
|
||||
<para>Check paths are not protected against garbage collection,
|
||||
and this path will be deleted on the next garbage collection.</para>
|
||||
|
||||
<para>The path is guaranteed to be alive for the duration of
|
||||
<xref linkend="conf-diff-hook" />'s execution, but may be deleted
|
||||
any time after.</para>
|
||||
|
||||
<para>If the comparison is performed as part of automated tooling,
|
||||
please use the diff-hook or author your tooling to handle the case
|
||||
where the build was not deterministic and also a check path does
|
||||
not exist.</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
<option>--check</option> is only usable if the derivation has
|
||||
been built on the system already. If the derivation has not been
|
||||
built Nix will fail with the error:
|
||||
<screen>
|
||||
error: some outputs of '/nix/store/hzi1h60z2qf0nb85iwnpvrai3j2w7rr6-unstable.drv' are not valid, so checking is not possible
|
||||
</screen>
|
||||
|
||||
Run the build without <option>--check</option>, and then try with
|
||||
<option>--check</option> again.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>
|
||||
Automatic and Optionally Enforced Determinism Verification
|
||||
</title>
|
||||
|
||||
<para>
|
||||
Automatically verify every build at build time by executing the
|
||||
build multiple times.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Setting <xref linkend="conf-repeat" /> and
|
||||
<xref linkend="conf-enforce-determinism" /> in your
|
||||
<filename>nix.conf</filename> permits the automated verification
|
||||
of every build Nix performs.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following configuration will run each build three times, and
|
||||
will require the build to be deterministic:
|
||||
|
||||
<programlisting>
|
||||
enforce-determinism = true
|
||||
repeat = 2
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Setting <xref linkend="conf-enforce-determinism" /> to false as in
|
||||
the following configuration will run the build multiple times,
|
||||
execute the build hook, but will allow the build to succeed even
|
||||
if it does not build reproducibly:
|
||||
|
||||
<programlisting>
|
||||
enforce-determinism = false
|
||||
repeat = 1
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
An example output of this configuration:
|
||||
<screen>
|
||||
$ nix-build ./test.nix -A unstable
|
||||
these derivations will be built:
|
||||
/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv
|
||||
building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 1/2)...
|
||||
building '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' (round 2/2)...
|
||||
output '/nix/store/6xg356v9gl03hpbbg8gws77n19qanh02-unstable' of '/nix/store/ch6llwpr2h8c3jmnf3f2ghkhx59aa97f-unstable.drv' differs from '/nix/store/6xg356v9gl03hpbbg8gws77n19qanh02-unstable.check' from previous round
|
||||
/nix/store/6xg356v9gl03hpbbg8gws77n19qanh02-unstable
|
||||
</screen>
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
|
@ -81,6 +81,7 @@ or a newline, e.g.
|
|||
|
||||
<para>Each machine specification consists of the following elements,
|
||||
separated by spaces. Only the first element is required.
|
||||
To leave a field at its default, set it to <literal>-</literal>.
|
||||
|
||||
<orderedlist>
|
||||
|
||||
|
@ -179,4 +180,11 @@ builders = @/etc/nix/machines
|
|||
causes the list of machines in <filename>/etc/nix/machines</filename>
|
||||
to be included. (This is the default.)</para>
|
||||
|
||||
<para>If you want the builders to use caches, you likely want to set
|
||||
the option <link linkend='conf-builders-use-substitutes'><literal>builders-use-substitutes</literal></link>
|
||||
in your local <filename>nix.conf</filename>.</para>
|
||||
|
||||
<para>To build only on remote builders and disable building on the local machine,
|
||||
you can use the option <option>--max-jobs 0</option>.</para>
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="chap-post-build-hook"
|
||||
version="5.0"
|
||||
>
|
||||
|
||||
<title>Using the <xref linkend="conf-post-build-hook" /></title>
|
||||
<subtitle>Uploading to an S3-compatible binary cache after each build</subtitle>
|
||||
|
||||
|
||||
<section xml:id="chap-post-build-hook-caveats">
|
||||
<title>Implementation Caveats</title>
|
||||
<para>Here we use the post-build hook to upload to a binary cache.
|
||||
This is a simple and working example, but it is not suitable for all
|
||||
use cases.</para>
|
||||
|
||||
<para>The post build hook program runs after each executed build,
|
||||
and blocks the build loop. The build loop exits if the hook program
|
||||
fails.</para>
|
||||
|
||||
<para>Concretely, this implementation will make Nix slow or unusable
|
||||
when the internet is slow or unreliable.</para>
|
||||
|
||||
<para>A more advanced implementation might pass the store paths to a
|
||||
user-supplied daemon or queue for processing the store paths outside
|
||||
of the build loop.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Prerequisites</title>
|
||||
|
||||
<para>
|
||||
This tutorial assumes you have configured an S3-compatible binary cache
|
||||
according to the instructions at
|
||||
<xref linkend="ssec-s3-substituter-authenticated-writes" />, and
|
||||
that the <literal>root</literal> user's default AWS profile can
|
||||
upload to the bucket.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Set up a Signing Key</title>
|
||||
<para>Use <command>nix-store --generate-binary-cache-key</command> to
|
||||
create our public and private signing keys. We will sign paths
|
||||
with the private key, and distribute the public key for verifying
|
||||
the authenticity of the paths.</para>
|
||||
|
||||
<screen>
|
||||
# nix-store --generate-binary-cache-key example-nix-cache-1 /etc/nix/key.private /etc/nix/key.public
|
||||
# cat /etc/nix/key.public
|
||||
example-nix-cache-1:1/cKDz3QCCOmwcztD2eV6Coggp6rqc9DGjWv7C0G+rM=
|
||||
</screen>
|
||||
|
||||
<para>Then, add the public key and the cache URL to your
|
||||
<filename>nix.conf</filename>'s <xref linkend="conf-trusted-public-keys" />
|
||||
and <xref linkend="conf-substituters" /> like:</para>
|
||||
|
||||
<programlisting>
|
||||
substituters = https://cache.nixos.org/ s3://example-nix-cache
|
||||
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= example-nix-cache-1:1/cKDz3QCCOmwcztD2eV6Coggp6rqc9DGjWv7C0G+rM=
|
||||
</programlisting>
|
||||
|
||||
<para>we will restart the Nix daemon a later step.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Implementing the build hook</title>
|
||||
<para>Write the following script to
|
||||
<filename>/etc/nix/upload-to-cache.sh</filename>:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
set -f # disable globbing
|
||||
export IFS=' '
|
||||
|
||||
echo "Signing paths" $OUT_PATHS
|
||||
nix sign-paths --key-file /etc/nix/key.private $OUT_PATHS
|
||||
echo "Uploading paths" $OUT_PATHS
|
||||
exec nix copy --to 's3://example-nix-cache' $OUT_PATHS
|
||||
</programlisting>
|
||||
|
||||
<note>
|
||||
<title>Should <literal>$OUT_PATHS</literal> be quoted?</title>
|
||||
<para>
|
||||
The <literal>$OUT_PATHS</literal> variable is a space-separated
|
||||
list of Nix store paths. In this case, we expect and want the
|
||||
shell to perform word splitting to make each output path its
|
||||
own argument to <command>nix sign-paths</command>. Nix guarantees
|
||||
the paths will not contain any spaces, however a store path
|
||||
might contain glob characters. The <command>set -f</command>
|
||||
disables globbing in the shell.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
Then make sure the hook program is executable by the <literal>root</literal> user:
|
||||
<screen>
|
||||
# chmod +x /etc/nix/upload-to-cache.sh
|
||||
</screen></para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Updating Nix Configuration</title>
|
||||
|
||||
<para>Edit <filename>/etc/nix/nix.conf</filename> to run our hook,
|
||||
by adding the following configuration snippet at the end:</para>
|
||||
|
||||
<programlisting>
|
||||
post-build-hook = /etc/nix/upload-to-cache.sh
|
||||
</programlisting>
|
||||
|
||||
<para>Then, restart the <command>nix-daemon</command>.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Testing</title>
|
||||
|
||||
<para>Build any derivation, for example:</para>
|
||||
|
||||
<screen>
|
||||
$ nix-build -E '(import <nixpkgs> {}).writeText "example" (builtins.toString builtins.currentTime)'
|
||||
these derivations will be built:
|
||||
/nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv
|
||||
building '/nix/store/s4pnfbkalzy5qz57qs6yybna8wylkig6-example.drv'...
|
||||
running post-build-hook '/home/grahamc/projects/github.com/NixOS/nix/post-hook.sh'...
|
||||
post-build-hook: Signing paths /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
|
||||
post-build-hook: Uploading paths /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
|
||||
/nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
|
||||
</screen>
|
||||
|
||||
<para>Then delete the path from the store, and try substituting it from the binary cache:</para>
|
||||
<screen>
|
||||
$ rm ./result
|
||||
$ nix-store --delete /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
|
||||
</screen>
|
||||
|
||||
<para>Now, copy the path back from the cache:</para>
|
||||
<screen>
|
||||
$ nix store --realize /nix/store/ibcyipq5gf91838ldx40mjsp0b8w9n18-example
|
||||
copying path '/nix/store/m8bmqwrch6l3h8s0k3d673xpmipcdpsa-example from 's3://example-nix-cache'...
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
/nix/store/m8bmqwrch6l3h8s0k3d673xpmipcdpsa-example
|
||||
</screen>
|
||||
</section>
|
||||
<section>
|
||||
<title>Conclusion</title>
|
||||
<para>
|
||||
We now have a Nix installation configured to automatically sign and
|
||||
upload every local build to a remote binary cache.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Before deploying this to production, be sure to consider the
|
||||
implementation caveats in <xref linkend="chap-post-build-hook-caveats" />.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
|
@ -1,7 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<refentry xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xml:id="sec-conf-file">
|
||||
xml:id="sec-conf-file"
|
||||
version="5">
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>nix.conf</refentrytitle>
|
||||
|
@ -123,7 +125,7 @@ false</literal>.</para>
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>auto-optimise-store</literal></term>
|
||||
<varlistentry xml:id="conf-auto-optimise-store"><term><literal>auto-optimise-store</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, Nix
|
||||
automatically detects files in the store that have identical
|
||||
|
@ -135,7 +137,6 @@ false</literal>.</para>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-builders">
|
||||
<term><literal>builders</literal></term>
|
||||
<listitem>
|
||||
|
@ -146,7 +147,7 @@ false</literal>.</para>
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>builders-use-substitutes</literal></term>
|
||||
<varlistentry xml:id="conf-builders-use-substitutes"><term><literal>builders-use-substitutes</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, Nix will instruct
|
||||
remote build machines to use their own binary substitutes if available. In
|
||||
|
@ -159,7 +160,6 @@ false</literal>.</para>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-build-users-group"><term><literal>build-users-group</literal></term>
|
||||
|
||||
<listitem><para>This options specifies the Unix group containing
|
||||
|
@ -201,7 +201,7 @@ false</literal>.</para>
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>compress-build-log</literal></term>
|
||||
<varlistentry xml:id="conf-compress-build-log"><term><literal>compress-build-log</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (the default),
|
||||
build logs written to <filename>/nix/var/log/nix/drvs</filename>
|
||||
|
@ -210,7 +210,6 @@ false</literal>.</para>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-connect-timeout"><term><literal>connect-timeout</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
@ -239,10 +238,75 @@ false</literal>.</para>
|
|||
linkend='opt-cores'>--cores</option> command line switch and
|
||||
defaults to <literal>1</literal>. The value <literal>0</literal>
|
||||
means that the builder should use all available CPU cores in the
|
||||
system.</para></listitem>
|
||||
system.</para>
|
||||
|
||||
<para>See also <xref linkend="chap-tuning-cores-and-jobs" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-diff-hook"><term><literal>diff-hook</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Absolute path to an executable capable of diffing build results.
|
||||
The hook executes if <xref linkend="conf-run-diff-hook" /> is
|
||||
true, and the output of a build is known to not be the same.
|
||||
This program is not executed to determine if two results are the
|
||||
same.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The diff hook is executed by the same user and group who ran the
|
||||
build. However, the diff hook does not have write access to the
|
||||
store path just built.
|
||||
</para>
|
||||
|
||||
<para>The diff hook program receives three parameters:</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
A path to the previous build's results
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
A path to the current build's results
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The path to the build's derivation
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The path to the build's scratch directory. This directory
|
||||
will exist only if the build was run with
|
||||
<option>--keep-failed</option>.
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>
|
||||
The stderr and stdout output from the diff hook will not be
|
||||
displayed to the user. Instead, it will print to the nix-daemon's
|
||||
log.
|
||||
</para>
|
||||
|
||||
<para>When using the Nix daemon, <literal>diff-hook</literal> must
|
||||
be set in the <filename>nix.conf</filename> configuration file, and
|
||||
cannot be passed at the command line.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-enforce-determinism">
|
||||
<term><literal>enforce-determinism</literal></term>
|
||||
|
||||
<listitem><para>See <xref linkend="conf-repeat" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-extra-sandbox-paths">
|
||||
<term><literal>extra-sandbox-paths</literal></term>
|
||||
|
@ -254,7 +318,26 @@ false</literal>.</para>
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>extra-substituters</literal></term>
|
||||
<varlistentry xml:id="conf-extra-platforms"><term><literal>extra-platforms</literal></term>
|
||||
|
||||
<listitem><para>Platforms other than the native one which
|
||||
this machine is capable of building for. This can be useful for
|
||||
supporting additional architectures on compatible machines:
|
||||
i686-linux can be built on x86_64-linux machines (and the default
|
||||
for this setting reflects this); armv7 is backwards-compatible with
|
||||
armv6 and armv5tel; some aarch64 machines can also natively run
|
||||
32-bit ARM code; and qemu-user may be used to support non-native
|
||||
platforms (though this may be slow and buggy). Most values for this
|
||||
are not enabled by default because build systems will often
|
||||
misdetect the target platform and generate incompatible code, so you
|
||||
may wish to cross-check the results of using this option against
|
||||
proper natively-built versions of your
|
||||
derivations.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-extra-substituters"><term><literal>extra-substituters</literal></term>
|
||||
|
||||
<listitem><para>Additional binary caches appended to those
|
||||
specified in <option>substituters</option>. When used by
|
||||
|
@ -264,8 +347,7 @@ false</literal>.</para>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>fallback</literal></term>
|
||||
<varlistentry xml:id="conf-fallback"><term><literal>fallback</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, Nix will fall
|
||||
back to building from source if a binary substitute fails. This
|
||||
|
@ -274,8 +356,7 @@ false</literal>.</para>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>fsync-metadata</literal></term>
|
||||
<varlistentry xml:id="conf-fsync-metadata"><term><literal>fsync-metadata</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, changes to the
|
||||
Nix store metadata (in <filename>/nix/var/nix/db</filename>) are
|
||||
|
@ -285,7 +366,6 @@ false</literal>.</para>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-hashed-mirrors"><term><literal>hashed-mirrors</literal></term>
|
||||
|
||||
<listitem><para>A list of web servers used by
|
||||
|
@ -314,7 +394,7 @@ builtins.fetchurl {
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>http-connections</literal></term>
|
||||
<varlistentry xml:id="conf-http-connections"><term><literal>http-connections</literal></term>
|
||||
|
||||
<listitem><para>The maximum number of parallel TCP connections
|
||||
used to fetch files from binary caches and by other downloads. It
|
||||
|
@ -323,7 +403,7 @@ builtins.fetchurl {
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>keep-build-log</literal></term>
|
||||
<varlistentry xml:id="conf-keep-build-log"><term><literal>keep-build-log</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (the default),
|
||||
Nix will write the build log of a derivation (i.e. the standard
|
||||
|
@ -348,11 +428,9 @@ builtins.fetchurl {
|
|||
options a store path was built), so by default this option is on.
|
||||
Turn it off to save a bit of disk space (or a lot if
|
||||
<literal>keep-outputs</literal> is also turned on).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>keep-env-derivations</literal></term>
|
||||
<varlistentry xml:id="conf-keep-env-derivations"><term><literal>keep-env-derivations</literal></term>
|
||||
|
||||
<listitem><para>If <literal>false</literal> (default), derivations
|
||||
are not stored in Nix user environments. That is, the derivation
|
||||
|
@ -375,7 +453,6 @@ builtins.fetchurl {
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-keep-outputs"><term><literal>keep-outputs</literal></term>
|
||||
|
||||
<listitem><para>If <literal>true</literal>, the garbage collector
|
||||
|
@ -389,10 +466,8 @@ builtins.fetchurl {
|
|||
only at build time (e.g., the C compiler, or source tarballs
|
||||
downloaded from the network). To prevent it from doing so, set
|
||||
this option to <literal>true</literal>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-max-build-log-size"><term><literal>max-build-log-size</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
@ -406,20 +481,32 @@ builtins.fetchurl {
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-max-free"><term><literal>max-free</literal></term>
|
||||
|
||||
<listitem><para>When a garbage collection is triggered by the
|
||||
<literal>min-free</literal> option, it stops as soon as
|
||||
<literal>max-free</literal> bytes are available. The default is
|
||||
infinity (i.e. delete all garbage).</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-max-jobs"><term><literal>max-jobs</literal></term>
|
||||
|
||||
<listitem><para>This option defines the maximum number of jobs
|
||||
that Nix will try to build in parallel. The default is
|
||||
<literal>1</literal>. The special value <literal>auto</literal>
|
||||
causes Nix to use the number of CPUs in your system. It can be
|
||||
causes Nix to use the number of CPUs in your system. <literal>0</literal>
|
||||
is useful when using remote builders to prevent any local builds (except for
|
||||
<literal>preferLocalBuild</literal> derivation attribute which executes locally
|
||||
regardless). It can be
|
||||
overridden using the <option
|
||||
linkend='opt-max-jobs'>--max-jobs</option> (<option>-j</option>)
|
||||
command line switch.</para></listitem>
|
||||
command line switch.</para>
|
||||
|
||||
<para>See also <xref linkend="chap-tuning-cores-and-jobs" />.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-max-silent-time"><term><literal>max-silent-time</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
@ -440,8 +527,50 @@ builtins.fetchurl {
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-min-free"><term><literal>min-free</literal></term>
|
||||
|
||||
<varlistentry><term><literal>netrc-file</literal></term>
|
||||
<listitem>
|
||||
<para>When free disk space in <filename>/nix/store</filename>
|
||||
drops below <literal>min-free</literal> during a build, Nix
|
||||
performs a garbage-collection until <literal>max-free</literal>
|
||||
bytes are available or there is no more garbage. A value of
|
||||
<literal>0</literal> (the default) disables this feature.</para>
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-narinfo-cache-negative-ttl"><term><literal>narinfo-cache-negative-ttl</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>The TTL in seconds for negative lookups. If a store path is
|
||||
queried from a substituter but was not found, there will be a
|
||||
negative lookup cached in the local disk cache database for the
|
||||
specified duration.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-narinfo-cache-positive-ttl"><term><literal>narinfo-cache-positive-ttl</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>The TTL in seconds for positive lookups. If a store path is
|
||||
queried from a substituter, the result of the query will be cached
|
||||
in the local disk cache database including some of the NAR
|
||||
metadata. The default TTL is a month, setting a shorter TTL for
|
||||
positive lookups can be useful for binary caches that have
|
||||
frequent garbage collection, in which case having a more frequent
|
||||
cache invalidation would prevent trying to pull the path again and
|
||||
failing with a hash mismatch if the build isn't reproducible.
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-netrc-file"><term><literal>netrc-file</literal></term>
|
||||
|
||||
<listitem><para>If set to an absolute path to a <filename>netrc</filename>
|
||||
file, Nix will use the HTTP authentication credentials in this file when
|
||||
|
@ -459,7 +588,12 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
For the exact syntax, see <link
|
||||
xlink:href="https://ec.haxx.se/usingcurl-netrc.html">the
|
||||
<literal>curl</literal> documentation.</link></para></listitem>
|
||||
<literal>curl</literal> documentation.</link></para>
|
||||
|
||||
<note><para>This must be an absolute path, and <literal>~</literal>
|
||||
is not resolved. For example, <filename>~/.netrc</filename> won't
|
||||
resolve to your home directory's <filename>.netrc</filename>.</para></note>
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
@ -495,7 +629,6 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-pre-build-hook"><term><literal>pre-build-hook</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
@ -531,6 +664,61 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-post-build-hook">
|
||||
<term><literal>post-build-hook</literal></term>
|
||||
<listitem>
|
||||
<para>Optional. The path to a program to execute after each build.</para>
|
||||
|
||||
<para>This option is only settable in the global
|
||||
<filename>nix.conf</filename>, or on the command line by trusted
|
||||
users.</para>
|
||||
|
||||
<para>When using the nix-daemon, the daemon executes the hook as
|
||||
<literal>root</literal>. If the nix-daemon is not involved, the
|
||||
hook runs as the user executing the nix-build.</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>The hook executes after an evaluation-time build.</para></listitem>
|
||||
<listitem><para>The hook does not execute on substituted paths.</para></listitem>
|
||||
<listitem><para>The hook's output always goes to the user's terminal.</para></listitem>
|
||||
<listitem><para>If the hook fails, the build succeeds but no further builds execute.</para></listitem>
|
||||
<listitem><para>The hook executes synchronously, and blocks other builds from progressing while it runs.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>The program executes with no arguments. The program's environment
|
||||
contains the following environment variables:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><envar>DRV_PATH</envar></term>
|
||||
<listitem>
|
||||
<para>The derivation for the built paths.</para>
|
||||
<para>Example:
|
||||
<literal>/nix/store/5nihn1a7pa8b25l9zafqaqibznlvvp3f-bash-4.4-p23.drv</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><envar>OUT_PATHS</envar></term>
|
||||
<listitem>
|
||||
<para>Output paths of the built derivation, separated by a space character.</para>
|
||||
<para>Example:
|
||||
<literal>/nix/store/zf5lbh336mnzf1nlswdn11g4n2m8zh3g-bash-4.4-p23-dev
|
||||
/nix/store/rjxwxwv1fpn9wa2x5ssk5phzwlcv4mna-bash-4.4-p23-doc
|
||||
/nix/store/6bqvbzjkcp9695dq0dpl5y43nvy37pq1-bash-4.4-p23-info
|
||||
/nix/store/r7fng3kk3vlpdlh2idnrbn37vh4imlj2-bash-4.4-p23-man
|
||||
/nix/store/xfghy8ixrhz3kyy6p724iv3cxji088dx-bash-4.4-p23</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>See <xref linkend="chap-post-build-hook" /> for an example
|
||||
implementation.</para>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-repeat"><term><literal>repeat</literal></term>
|
||||
|
||||
|
@ -538,13 +726,12 @@ password <replaceable>my-password</replaceable>
|
|||
they are deterministic. The default value is 0. If the value is
|
||||
non-zero, every build is repeated the specified number of
|
||||
times. If the contents of any of the runs differs from the
|
||||
previous ones, the build is rejected and the resulting store paths
|
||||
are not registered as “valid” in Nix’s database.</para></listitem>
|
||||
|
||||
previous ones and <xref linkend="conf-enforce-determinism" /> is
|
||||
true, the build is rejected and the resulting store paths are not
|
||||
registered as “valid” in Nix’s database.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>require-sigs</literal></term>
|
||||
<varlistentry xml:id="conf-require-sigs"><term><literal>require-sigs</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (the default),
|
||||
any non-content-addressed path added or copied to the Nix store
|
||||
|
@ -572,8 +759,21 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-run-diff-hook"><term><literal>run-diff-hook</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If true, enable the execution of <xref linkend="conf-diff-hook" />.
|
||||
</para>
|
||||
|
||||
<varlistentry><term><literal>sandbox</literal></term>
|
||||
<para>
|
||||
When using the Nix daemon, <literal>run-diff-hook</literal> must
|
||||
be set in the <filename>nix.conf</filename> configuration file,
|
||||
and cannot be passed at the command line.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-sandbox"><term><literal>sandbox</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal>, builds will be
|
||||
performed in a <emphasis>sandboxed environment</emphasis>, i.e.,
|
||||
|
@ -601,13 +801,13 @@ password <replaceable>my-password</replaceable>
|
|||
<varname>__noChroot</varname> attribute set to
|
||||
<literal>true</literal> do not run in sandboxes.</para>
|
||||
|
||||
<para>The default is <literal>false</literal>.</para>
|
||||
<para>The default is <literal>true</literal> on Linux and
|
||||
<literal>false</literal> on all other platforms.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-sandbox-dev-shm-size"><term><literal>sandbox-dev-shm-size</literal></term>
|
||||
|
||||
<listitem><para>This option determines the maximum size of the
|
||||
|
@ -644,7 +844,7 @@ password <replaceable>my-password</replaceable>
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>secret-key-files</literal></term>
|
||||
<varlistentry xml:id="conf-secret-key-files"><term><literal>secret-key-files</literal></term>
|
||||
|
||||
<listitem><para>A whitespace-separated list of files containing
|
||||
secret (private) keys. These are used to sign locally-built
|
||||
|
@ -665,7 +865,7 @@ password <replaceable>my-password</replaceable>
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>substitute</literal></term>
|
||||
<varlistentry xml:id="conf-substitute"><term><literal>substitute</literal></term>
|
||||
|
||||
<listitem><para>If set to <literal>true</literal> (default), Nix
|
||||
will use binary substitutes if available. This option can be
|
||||
|
@ -673,8 +873,15 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-stalled-download-timeout"><term><literal>stalled-download-timeout</literal></term>
|
||||
<listitem>
|
||||
<para>The timeout (in seconds) for receiving data from servers
|
||||
during download. Nix cancels idle downloads after this timeout's
|
||||
duration.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>substituters</literal></term>
|
||||
<varlistentry xml:id="conf-substituters"><term><literal>substituters</literal></term>
|
||||
|
||||
<listitem><para>A list of URLs of substituters, separated by
|
||||
whitespace. The default is
|
||||
|
@ -682,8 +889,7 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>system</literal></term>
|
||||
<varlistentry xml:id="conf-system"><term><literal>system</literal></term>
|
||||
|
||||
<listitem><para>This option specifies the canonical Nix system
|
||||
name of the current installation, such as
|
||||
|
@ -704,6 +910,58 @@ password <replaceable>my-password</replaceable>
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-system-features"><term><literal>system-features</literal></term>
|
||||
|
||||
<listitem><para>A set of system “features” supported by this
|
||||
machine, e.g. <literal>kvm</literal>. Derivations can express a
|
||||
dependency on such features through the derivation attribute
|
||||
<varname>requiredSystemFeatures</varname>. For example, the
|
||||
attribute
|
||||
|
||||
<programlisting>
|
||||
requiredSystemFeatures = [ "kvm" ];
|
||||
</programlisting>
|
||||
|
||||
ensures that the derivation can only be built on a machine with
|
||||
the <literal>kvm</literal> feature.</para>
|
||||
|
||||
<para>This setting by default includes <literal>kvm</literal> if
|
||||
<filename>/dev/kvm</filename> is accessible, and the
|
||||
pseudo-features <literal>nixos-test</literal>,
|
||||
<literal>benchmark</literal> and <literal>big-parallel</literal>
|
||||
that are used in Nixpkgs to route builds to specific
|
||||
machines.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-tarball-ttl"><term><literal>tarball-ttl</literal></term>
|
||||
|
||||
<listitem>
|
||||
<para>Default: <literal>3600</literal> seconds.</para>
|
||||
|
||||
<para>The number of seconds a downloaded tarball is considered
|
||||
fresh. If the cached tarball is stale, Nix will check whether
|
||||
it is still up to date using the ETag header. Nix will download
|
||||
a new version if the ETag header is unsupported, or the
|
||||
cached ETag doesn't match.
|
||||
</para>
|
||||
|
||||
<para>Setting the TTL to <literal>0</literal> forces Nix to always
|
||||
check if the tarball is up to date.</para>
|
||||
|
||||
<para>Nix caches tarballs in
|
||||
<filename>$XDG_CACHE_HOME/nix/tarballs</filename>.</para>
|
||||
|
||||
<para>Files fetched via <envar>NIX_PATH</envar>,
|
||||
<function>fetchGit</function>, <function>fetchMercurial</function>,
|
||||
<function>fetchTarball</function>, and <function>fetchurl</function>
|
||||
respect this TTL.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-timeout"><term><literal>timeout</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
@ -723,8 +981,35 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-trace-function-calls"><term><literal>trace-function-calls</literal></term>
|
||||
|
||||
<varlistentry><term><literal>trusted-public-keys</literal></term>
|
||||
<listitem>
|
||||
|
||||
<para>Default: <literal>false</literal>.</para>
|
||||
|
||||
<para>If set to <literal>true</literal>, the Nix evaluator will
|
||||
trace every function call. Nix will print a log message at the
|
||||
"vomit" level for every function entrance and function exit.</para>
|
||||
|
||||
<informalexample><screen>
|
||||
function-trace entered undefined position at 1565795816999559622
|
||||
function-trace exited undefined position at 1565795816999581277
|
||||
function-trace entered /nix/store/.../example.nix:226:41 at 1565795253249935150
|
||||
function-trace exited /nix/store/.../example.nix:226:41 at 1565795253249941684
|
||||
</screen></informalexample>
|
||||
|
||||
<para>The <literal>undefined position</literal> means the function
|
||||
call is a builtin.</para>
|
||||
|
||||
<para>Use the <literal>contrib/stack-collapse.py</literal> script
|
||||
distributed with the Nix source code to convert the trace logs
|
||||
in to a format suitable for <command>flamegraph.pl</command>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-trusted-public-keys"><term><literal>trusted-public-keys</literal></term>
|
||||
|
||||
<listitem><para>A whitespace-separated list of public keys. When
|
||||
paths are copied from another Nix store (such as a binary cache),
|
||||
|
@ -734,8 +1019,7 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><literal>trusted-substituters</literal></term>
|
||||
<varlistentry xml:id="conf-trusted-substituters"><term><literal>trusted-substituters</literal></term>
|
||||
|
||||
<listitem><para>A list of URLs of substituters, separated by
|
||||
whitespace. These are not used by default, but can be enabled by
|
||||
|
@ -747,7 +1031,6 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry xml:id="conf-trusted-users"><term><literal>trusted-users</literal></term>
|
||||
|
||||
<listitem>
|
||||
|
@ -772,11 +1055,179 @@ password <replaceable>my-password</replaceable>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
<refsection>
|
||||
<title>Deprecated Settings</title>
|
||||
|
||||
<para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry xml:id="conf-binary-caches">
|
||||
<term><literal>binary-caches</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>binary-caches</literal> is now an alias to
|
||||
<xref linkend="conf-substituters" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-binary-cache-public-keys">
|
||||
<term><literal>binary-cache-public-keys</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>binary-cache-public-keys</literal> is now an alias to
|
||||
<xref linkend="conf-trusted-public-keys" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-compress-log">
|
||||
<term><literal>build-compress-log</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-compress-log</literal> is now an alias to
|
||||
<xref linkend="conf-compress-build-log" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-cores">
|
||||
<term><literal>build-cores</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-cores</literal> is now an alias to
|
||||
<xref linkend="conf-cores" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-extra-chroot-dirs">
|
||||
<term><literal>build-extra-chroot-dirs</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-extra-chroot-dirs</literal> is now an alias to
|
||||
<xref linkend="conf-extra-sandbox-paths" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-extra-sandbox-paths">
|
||||
<term><literal>build-extra-sandbox-paths</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-extra-sandbox-paths</literal> is now an alias to
|
||||
<xref linkend="conf-extra-sandbox-paths" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-fallback">
|
||||
<term><literal>build-fallback</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-fallback</literal> is now an alias to
|
||||
<xref linkend="conf-fallback" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-max-jobs">
|
||||
<term><literal>build-max-jobs</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-max-jobs</literal> is now an alias to
|
||||
<xref linkend="conf-max-jobs" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-max-log-size">
|
||||
<term><literal>build-max-log-size</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-max-log-size</literal> is now an alias to
|
||||
<xref linkend="conf-max-build-log-size" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-max-silent-time">
|
||||
<term><literal>build-max-silent-time</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-max-silent-time</literal> is now an alias to
|
||||
<xref linkend="conf-max-silent-time" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-repeat">
|
||||
<term><literal>build-repeat</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-repeat</literal> is now an alias to
|
||||
<xref linkend="conf-repeat" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-timeout">
|
||||
<term><literal>build-timeout</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-timeout</literal> is now an alias to
|
||||
<xref linkend="conf-timeout" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-use-chroot">
|
||||
<term><literal>build-use-chroot</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-use-chroot</literal> is now an alias to
|
||||
<xref linkend="conf-sandbox" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-use-sandbox">
|
||||
<term><literal>build-use-sandbox</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-use-sandbox</literal> is now an alias to
|
||||
<xref linkend="conf-sandbox" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-build-use-substitutes">
|
||||
<term><literal>build-use-substitutes</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>build-use-substitutes</literal> is now an alias to
|
||||
<xref linkend="conf-substitute" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-gc-keep-derivations">
|
||||
<term><literal>gc-keep-derivations</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>gc-keep-derivations</literal> is now an alias to
|
||||
<xref linkend="conf-keep-derivations" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-gc-keep-outputs">
|
||||
<term><literal>gc-keep-outputs</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>gc-keep-outputs</literal> is now an alias to
|
||||
<xref linkend="conf-keep-outputs" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-env-keep-derivations">
|
||||
<term><literal>env-keep-derivations</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>env-keep-derivations</literal> is now an alias to
|
||||
<xref linkend="conf-keep-env-derivations" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-extra-binary-caches">
|
||||
<term><literal>extra-binary-caches</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>extra-binary-caches</literal> is now an alias to
|
||||
<xref linkend="conf-extra-substituters" />.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry xml:id="conf-trusted-binary-caches">
|
||||
<term><literal>trusted-binary-caches</literal></term>
|
||||
|
||||
<listitem><para><emphasis>Deprecated:</emphasis>
|
||||
<literal>trusted-binary-caches</literal> is now an alias to
|
||||
<xref linkend="conf-trusted-substituters" />.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refentry>
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
<varlistentry><term><envar>IN_NIX_SHELL</envar></term>
|
||||
|
||||
<listitem><para>Indicator that tells if the current environment was set up by
|
||||
<command>nix-shell</command>.</para></listitem>
|
||||
<command>nix-shell</command>. Since Nix 2.0 the values are
|
||||
<literal>"pure"</literal> and <literal>"impure"</literal></para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
@ -52,10 +53,15 @@ nixpkgs=/home/eelco/Dev/nixpkgs-branch:/etc/nixos</screen>
|
|||
<envar>NIX_PATH</envar> to
|
||||
|
||||
<screen>
|
||||
nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz</screen>
|
||||
nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-15.09.tar.gz</screen>
|
||||
|
||||
tells Nix to download the latest revision in the Nixpkgs/NixOS
|
||||
14.12 channel.</para>
|
||||
15.09 channel.</para>
|
||||
|
||||
<para>A following shorthand can be used to refer to the official channels:
|
||||
|
||||
<screen>nixpkgs=channel:nixos-15.09</screen>
|
||||
</para>
|
||||
|
||||
<para>The search path can be extended using the <option
|
||||
linkend="opt-I">-I</option> option, which takes precedence over
|
||||
|
|
|
@ -31,12 +31,11 @@
|
|||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>A Nix channel is mechanism that allows you to automatically stay
|
||||
up-to-date with a set of pre-built Nix expressions. A Nix channel is
|
||||
just a URL that points to a place containing both a set of Nix
|
||||
expressions and a pointer to a binary cache. <phrase
|
||||
condition="manual">See also <xref linkend="sec-channels"
|
||||
/>.</phrase></para>
|
||||
<para>A Nix channel is a mechanism that allows you to automatically
|
||||
stay up-to-date with a set of pre-built Nix expressions. A Nix
|
||||
channel is just a URL that points to a place containing a set of Nix
|
||||
expressions. <phrase condition="manual">See also <xref
|
||||
linkend="sec-channels" />.</phrase></para>
|
||||
|
||||
<para>This command has the following operations:
|
||||
|
||||
|
@ -165,25 +164,13 @@ following files:</para>
|
|||
<varlistentry><term><filename>nixexprs.tar.xz</filename></term>
|
||||
|
||||
<listitem><para>A tarball containing Nix expressions and files
|
||||
referenced by them (such as build scripts and patches). At
|
||||
top-level, the tarball should contain a single directory. That
|
||||
referenced by them (such as build scripts and patches). At the
|
||||
top level, the tarball should contain a single directory. That
|
||||
directory must contain a file <filename>default.nix</filename>
|
||||
that serves as the channel’s “entry point”.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><filename>binary-cache-url</filename></term>
|
||||
|
||||
<listitem><para>A file containing the URL to a binary cache (such
|
||||
as <uri>https://cache.nixos.org</uri>. Nix will automatically
|
||||
check this cache for pre-built binaries, if the user has
|
||||
sufficient rights to add binary caches. For instance, in a
|
||||
multi-user Nix setup, the binary caches provided by the channels
|
||||
of the root user are used automatically, but caches corresponding
|
||||
to the channels of non-root users are ignored.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
|
|
@ -22,12 +22,6 @@
|
|||
<arg><option>--delete-old</option></arg>
|
||||
<arg><option>-d</option></arg>
|
||||
<arg><option>--delete-older-than</option> <replaceable>period</replaceable></arg>
|
||||
<group choice='opt'>
|
||||
<arg choice='plain'><option>--print-roots</option></arg>
|
||||
<arg choice='plain'><option>--print-live</option></arg>
|
||||
<arg choice='plain'><option>--print-dead</option></arg>
|
||||
<arg choice='plain'><option>--delete</option></arg>
|
||||
</group>
|
||||
<arg><option>--max-freed</option> <replaceable>bytes</replaceable></arg>
|
||||
<arg><option>--dry-run</option></arg>
|
||||
</cmdsynopsis>
|
||||
|
|
|
@ -95,15 +95,6 @@ those paths. If this bothers you, use
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<!--
|
||||
<varlistentry><term><option>- -show-progress</option></term>
|
||||
|
||||
<listitem><para>Show the progress of each path's transfer as it's made.
|
||||
This requires the <command>pv</command> utility to be in <envar>PATH</envar>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
-->
|
||||
|
||||
<varlistentry><term><option>--include-outputs</option></term>
|
||||
|
||||
<listitem><para>Also copy the outputs of store derivations
|
||||
|
|
|
@ -221,31 +221,53 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
|||
|
||||
<varlistentry><term><filename>~/.nix-defexpr</filename></term>
|
||||
|
||||
<listitem><para>A directory that contains the default Nix
|
||||
<listitem><para>The source for the default Nix
|
||||
expressions used by the <option>--install</option>,
|
||||
<option>--upgrade</option>, and <option>--query
|
||||
--available</option> operations to obtain derivations. The
|
||||
--available</option> operations to obtain derivations. The
|
||||
<option>--file</option> option may be used to override this
|
||||
default.</para>
|
||||
|
||||
<para>The Nix expressions in this directory are combined into a
|
||||
single set, with each file as an attribute that has the name of
|
||||
the file. Thus, if <filename>~/.nix-defexpr</filename> contains
|
||||
two files, <filename>foo</filename> and <filename>bar</filename>,
|
||||
<para>If <filename>~/.nix-defexpr</filename> is a file,
|
||||
it is loaded as a Nix expression. If the expression
|
||||
is a set, it is used as the default Nix expression.
|
||||
If the expression is a function, an empty set is passed
|
||||
as argument and the return value is used as
|
||||
the default Nix expression.</para>
|
||||
|
||||
<para>If <filename>~/.nix-defexpr</filename> is a directory
|
||||
containing a <filename>default.nix</filename> file, that file
|
||||
is loaded as in the above paragraph.</para>
|
||||
|
||||
<para>If <filename>~/.nix-defexpr</filename> is a directory without
|
||||
a <filename>default.nix</filename> file, then its contents
|
||||
(both files and subdirectories) are loaded as Nix expressions.
|
||||
The expressions are combined into a single set, each expression
|
||||
under an attribute with the same name as the original file
|
||||
or subdirectory.
|
||||
</para>
|
||||
|
||||
<para>For example, if <filename>~/.nix-defexpr</filename> contains
|
||||
two files, <filename>foo.nix</filename> and <filename>bar.nix</filename>,
|
||||
then the default Nix expression will essentially be
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
foo = import ~/.nix-defexpr/foo;
|
||||
bar = import ~/.nix-defexpr/bar;
|
||||
foo = import ~/.nix-defexpr/foo.nix;
|
||||
bar = import ~/.nix-defexpr/bar.nix;
|
||||
}</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>The file <filename>manifest.nix</filename> is always ignored.
|
||||
Subdirectories without a <filename>default.nix</filename> file
|
||||
are traversed recursively in search of more Nix expressions,
|
||||
but the names of these intermediate directories are not
|
||||
added to the attribute paths of the default Nix expression.</para>
|
||||
|
||||
<para>The command <command>nix-channel</command> places symlinks
|
||||
to the downloaded Nix expressions from each subscribed channel in
|
||||
this directory.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
@ -456,7 +478,7 @@ $ nix-env -f ~/foo.nix -i '.*'</screen>
|
|||
from another profile:
|
||||
|
||||
<screen>
|
||||
$ nix-env -i --from-profile /nix/var/nix/profiles/foo -i gcc</screen>
|
||||
$ nix-env -i --from-profile /nix/var/nix/profiles/foo gcc</screen>
|
||||
|
||||
</para>
|
||||
|
||||
|
@ -1346,11 +1368,15 @@ $ nix-env --list-generations
|
|||
<para>This operation deletes the specified generations of the current
|
||||
profile. The generations can be a list of generation numbers, the
|
||||
special value <literal>old</literal> to delete all non-current
|
||||
generations, or a value such as <literal>30d</literal> to delete all
|
||||
generations, a value such as <literal>30d</literal> to delete all
|
||||
generations older than the specified number of days (except for the
|
||||
generation that was active at that point in time).
|
||||
Periodically deleting old generations is important to make garbage
|
||||
collection effective.</para>
|
||||
generation that was active at that point in time), or a value such as
|
||||
<literal>+5</literal> to keep the last <literal>5</literal> generations
|
||||
ignoring any newer than current, e.g., if <literal>30</literal> is the current
|
||||
generation <literal>+5</literal> will delete generation <literal>25</literal>
|
||||
and all older generations.
|
||||
Periodically deleting old generations is important to make garbage collection
|
||||
effective.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
@ -1359,6 +1385,8 @@ collection effective.</para>
|
|||
<screen>
|
||||
$ nix-env --delete-generations 3 4 8
|
||||
|
||||
$ nix-env --delete-generations +5
|
||||
|
||||
$ nix-env --delete-generations 30d
|
||||
|
||||
$ nix-env -p other_profile --delete-generations old</screen>
|
||||
|
@ -1458,7 +1486,7 @@ error: no generation older than the current (91) exists</screen>
|
|||
<refsection condition="manpage"><title>Environment variables</title>
|
||||
|
||||
<variablelist>
|
||||
|
||||
|
||||
<varlistentry><term><envar>NIX_PROFILE</envar></term>
|
||||
|
||||
<listitem><para>Location of the Nix profile. Defaults to the
|
||||
|
@ -1472,6 +1500,6 @@ error: no generation older than the current (91) exists</screen>
|
|||
</variablelist>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
</refentry>
|
||||
|
|
|
@ -154,7 +154,9 @@ input.</para>
|
|||
<listitem><para>When used with <option>--eval</option>, perform
|
||||
evaluation in read/write mode so nix language features that
|
||||
require it will still work (at the cost of needing to do
|
||||
instantiation of every evaluated derivation).</para>
|
||||
instantiation of every evaluated derivation). If this option is
|
||||
not enabled, there may be uninstantiated store paths in the final
|
||||
output.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<arg><option>--run</option> <replaceable>cmd</replaceable></arg>
|
||||
<arg><option>--exclude</option> <replaceable>regexp</replaceable></arg>
|
||||
<arg><option>--pure</option></arg>
|
||||
<arg><option>--keep</option> <replaceable>name</replaceable></arg>
|
||||
<group choice='req'>
|
||||
<arg choice='plain'>
|
||||
<group choice='req'>
|
||||
|
@ -165,6 +166,13 @@ also <xref linkend="sec-common-options" />.</phrase></para>
|
|||
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><option>--keep</option> <replaceable>name</replaceable></term>
|
||||
|
||||
<listitem><para>When a <option>--pure</option> shell is started,
|
||||
keep the listed environment variables.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>The following common options are supported:</para>
|
||||
|
@ -309,13 +317,28 @@ while (my $token = $p->get_tag("a")) {
|
|||
|
||||
</para>
|
||||
|
||||
<para>Finally, the following Haskell script uses a specific branch of
|
||||
Nixpkgs/NixOS (the 14.12 stable branch):
|
||||
<para>Sometimes you need to pass a simple Nix expression to customize
|
||||
a package like Terraform:
|
||||
|
||||
<programlisting><![CDATA[
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i runghc -p haskellPackages.ghc haskellPackages.HTTP haskellPackages.tagsoup
|
||||
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz
|
||||
#! nix-shell -i bash -p "terraform.withPlugins (plugins: [ plugins.openstack ])"
|
||||
|
||||
terraform apply
|
||||
]]></programlisting>
|
||||
|
||||
<note><para>You must use double quotes (<literal>"</literal>) when
|
||||
passing a simple Nix expression in a nix-shell shebang.</para></note>
|
||||
</para>
|
||||
|
||||
<para>Finally, using the merging of multiple nix-shell shebangs the
|
||||
following Haskell script uses a specific branch of Nixpkgs/NixOS (the
|
||||
18.03 stable branch):
|
||||
|
||||
<programlisting><![CDATA[
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (ps: [ps.HTTP ps.tagsoup])"
|
||||
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-18.03.tar.gz
|
||||
|
||||
import Network.HTTP
|
||||
import Text.HTML.TagSoup
|
||||
|
|
|
@ -204,7 +204,7 @@ printed.)</para>
|
|||
with <option>-K</option>, if an output path is not identical to
|
||||
the corresponding output from the previous build, the new output
|
||||
path is left in
|
||||
<filename>/nix/store/<replaceable>name</replaceable>-check.</filename></para>
|
||||
<filename>/nix/store/<replaceable>name</replaceable>.check.</filename></para>
|
||||
|
||||
<para>See also the <option>build-repeat</option> configuration
|
||||
option, which repeats a derivation a number of times and prevents
|
||||
|
@ -215,6 +215,48 @@ printed.)</para>
|
|||
|
||||
</variablelist>
|
||||
|
||||
<para>Special exit codes:</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><literal>100</literal></term>
|
||||
<listitem><para>Generic build failure, the builder process
|
||||
returned with a non-zero exit code.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>101</literal></term>
|
||||
<listitem><para>Build timeout, the build was aborted because it
|
||||
did not complete within the specified <link
|
||||
linkend='conf-timeout'><literal>timeout</literal></link>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>102</literal></term>
|
||||
<listitem><para>Hash mismatch, the build output was rejected
|
||||
because it does not match the specified <link
|
||||
linkend="fixed-output-drvs"><varname>outputHash</varname></link>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>104</literal></term>
|
||||
<listitem><para>Not deterministic, the build succeeded in check
|
||||
mode but the resulting output is not binary reproducable.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>With the <option>--keep-going</option> flag it's possible for
|
||||
multiple failures to occur, in this case the 1xx status codes are or combined
|
||||
using binary or. <screen>
|
||||
1100100
|
||||
^^^^
|
||||
|||`- timeout
|
||||
||`-- output hash mismatch
|
||||
|`--- build failure
|
||||
`---- not deterministic
|
||||
</screen></para>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
@ -275,7 +317,7 @@ as a means of providing Nix store access to a restricted ssh user.
|
|||
|
||||
<listitem><para>Allow the connected client to request the realization
|
||||
of derivations. In effect, this can be used to make the host act
|
||||
as a build slave.</para></listitem>
|
||||
as a remote builder.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
@ -501,10 +543,11 @@ error: cannot delete path `/nix/store/zq0h41l75vlb4z45kzgjjmsjxvcv1qk7-mesa-6.4'
|
|||
<arg choice='plain'><option>--referrers</option></arg>
|
||||
<arg choice='plain'><option>--referrers-closure</option></arg>
|
||||
<arg choice='plain'><option>--deriver</option></arg>
|
||||
<arg choice='plain'><option>--deriver</option></arg>
|
||||
<arg choice='plain'><option>-d</option></arg>
|
||||
<arg choice='plain'><option>--graph</option></arg>
|
||||
<arg choice='plain'><option>--tree</option></arg>
|
||||
<arg choice='plain'><option>--binding</option> <replaceable>name</replaceable></arg>
|
||||
<arg choice='plain'><option>-b</option> <replaceable>name</replaceable></arg>
|
||||
<arg choice='plain'><option>--hash</option></arg>
|
||||
<arg choice='plain'><option>--size</option></arg>
|
||||
<arg choice='plain'><option>--roots</option></arg>
|
||||
|
@ -642,6 +685,7 @@ query is applied to the target of the symlink.</para>
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--deriver</option></term>
|
||||
<term><option>-d</option></term>
|
||||
|
||||
<listitem><para>Prints the <link
|
||||
linkend="gloss-deriver">deriver</link> of the store paths
|
||||
|
@ -677,7 +721,20 @@ query is applied to the target of the symlink.</para>
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--graphml</option></term>
|
||||
|
||||
<listitem><para>Prints the references graph of the store paths
|
||||
<replaceable>paths</replaceable> in the <link
|
||||
xlink:href="http://graphml.graphdrawing.org/">GraphML</link> file format.
|
||||
This can be used to visualise dependency graphs. To obtain a
|
||||
build-time dependency graph, apply this to a store derivation. To
|
||||
obtain a runtime dependency graph, apply it to an output
|
||||
path.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><option>--binding</option> <replaceable>name</replaceable></term>
|
||||
<term><option>-b</option> <replaceable>name</replaceable></term>
|
||||
|
||||
<listitem><para>Prints the value of the attribute
|
||||
<replaceable>name</replaceable> (i.e., environment variable) of
|
||||
|
@ -868,6 +925,60 @@ $ nix-store --add ./foo.c
|
|||
|
||||
</refsection>
|
||||
|
||||
<!--######################################################################-->
|
||||
|
||||
<refsection><title>Operation <option>--add-fixed</option></title>
|
||||
|
||||
<refsection><title>Synopsis</title>
|
||||
|
||||
<cmdsynopsis>
|
||||
<command>nix-store</command>
|
||||
<arg><option>--recursive</option></arg>
|
||||
<arg choice='plain'><option>--add-fixed</option></arg>
|
||||
<arg choice='plain'><replaceable>algorithm</replaceable></arg>
|
||||
<arg choice='plain' rep='repeat'><replaceable>paths</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Description</title>
|
||||
|
||||
<para>The operation <option>--add-fixed</option> adds the specified paths to
|
||||
the Nix store. Unlike <option>--add</option> paths are registered using the
|
||||
specified hashing algorithm, resulting in the same output path as a fixed output
|
||||
derivation. This can be used for sources that are not available from a public
|
||||
url or broke since the download expression was written.
|
||||
</para>
|
||||
|
||||
<para>This operation has the following options:
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry><term><option>--recursive</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Use recursive instead of flat hashing mode, used when adding directories
|
||||
to the store.
|
||||
</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
<refsection><title>Example</title>
|
||||
|
||||
<screen>
|
||||
$ nix-store --add-fixed sha256 ./hello-2.10.tar.gz
|
||||
/nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz</screen>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
|
||||
|
||||
|
||||
<!--######################################################################-->
|
||||
|
@ -1267,6 +1378,7 @@ ktorrent-2.2.1/NEWS
|
|||
<cmdsynopsis>
|
||||
<command>nix-store</command>
|
||||
<arg choice='plain'><option>--dump-db</option></arg>
|
||||
<arg rep='repeat'><replaceable>paths</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsection>
|
||||
|
||||
|
@ -1277,6 +1389,13 @@ Nix database to standard output. It can be loaded into an empty Nix
|
|||
store using <option>--load-db</option>. This is useful for making
|
||||
backups and when migrating to different database schemas.</para>
|
||||
|
||||
<para>By default, <option>--dump-db</option> will dump the entire Nix
|
||||
database. When one or more store paths is passed, only the subset of
|
||||
the Nix database for those store paths is dumped. As with
|
||||
<option>--export</option>, the user is responsible for passing all the
|
||||
store paths for a closure. See <option>--export</option> for an
|
||||
example.</para>
|
||||
|
||||
</refsection>
|
||||
|
||||
</refsection>
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
<arg choice='plain'><option>-v</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
<arg>
|
||||
<arg choice='plain'><option>--quiet</option></arg>
|
||||
</arg>
|
||||
<arg>
|
||||
<group choice='plain'>
|
||||
<arg choice='plain'><option>--no-build-output</option></arg>
|
||||
|
|
|
@ -75,6 +75,23 @@
|
|||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--quiet</option></term>
|
||||
|
||||
<listitem>
|
||||
|
||||
<para>Decreases the level of verbosity of diagnostic messages
|
||||
printed on standard error. This is the inverse option to
|
||||
<option>-v</option> / <option>--verbose</option>.
|
||||
</para>
|
||||
|
||||
<para>This option may be specified repeatedly. See the previous
|
||||
verbosity levels list.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><option>--no-build-output</option> / <option>-Q</option></term>
|
||||
|
||||
<listitem><para>By default, output written by builders to standard
|
||||
|
@ -90,14 +107,22 @@
|
|||
<varlistentry xml:id="opt-max-jobs"><term><option>--max-jobs</option> / <option>-j</option>
|
||||
<replaceable>number</replaceable></term>
|
||||
|
||||
<listitem><para>Sets the maximum number of build jobs that Nix will
|
||||
<listitem>
|
||||
|
||||
<para>Sets the maximum number of build jobs that Nix will
|
||||
perform in parallel to the specified number. Specify
|
||||
<literal>auto</literal> to use the number of CPUs in the system.
|
||||
The default is specified by the <link
|
||||
linkend='conf-max-jobs'><literal>max-jobs</literal></link>
|
||||
configuration setting, which itself defaults to
|
||||
<literal>1</literal>. A higher value is useful on SMP systems or to
|
||||
exploit I/O latency.</para></listitem>
|
||||
exploit I/O latency.</para>
|
||||
|
||||
<para> Setting it to <literal>0</literal> disallows building on the local
|
||||
machine, which is useful when you want builds to happen only on remote
|
||||
builders.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
|
|
@ -50,6 +50,40 @@ allowedRequisites = [ foobar ];
|
|||
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><varname>disallowedReferences</varname></term>
|
||||
|
||||
<listitem><para>The optional attribute
|
||||
<varname>disallowedReferences</varname> specifies a list of illegal
|
||||
references (dependencies) of the output of the builder. For
|
||||
example,
|
||||
|
||||
<programlisting>
|
||||
disallowedReferences = [ foo ];
|
||||
</programlisting>
|
||||
|
||||
enforces that the output of a derivation cannot have a direct runtime
|
||||
dependencies on the derivation <varname>foo</varname>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><varname>disallowedRequisites</varname></term>
|
||||
|
||||
<listitem><para>This attribute is similar to
|
||||
<varname>disallowedReferences</varname>, but it specifies illegal
|
||||
requisites for the whole closure, so all the dependencies
|
||||
recursively. For example,
|
||||
|
||||
<programlisting>
|
||||
disallowedRequisites = [ foobar ];
|
||||
</programlisting>
|
||||
|
||||
enforces that the output of a derivation cannot have any
|
||||
runtime dependency on <varname>foobar</varname> or any other derivation
|
||||
depending recursively on <varname>foobar</varname>.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><varname>exportReferencesGraph</varname></term>
|
||||
|
||||
|
@ -112,7 +146,13 @@ impureEnvVars = [ "http_proxy" "https_proxy" <replaceable>...</replaceable> ];
|
|||
linkend="fixed-output-drvs">fixed-output derivations</link>, where
|
||||
impurities such as these are okay since (the hash of) the output
|
||||
is known in advance. It is ignored for all other
|
||||
derivations.</para></listitem>
|
||||
derivations.</para>
|
||||
|
||||
<warning><para><varname>impureEnvVars</varname> implementation takes
|
||||
environment variables from the current builder process. When a daemon is
|
||||
building its environmental variables are used. Without the daemon, the
|
||||
environmental variables come from the environment of the
|
||||
<command>nix-build</command>.</para></warning></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
@ -176,7 +216,7 @@ fetchurl {
|
|||
<programlisting>
|
||||
{ stdenv, curl }: # The <command>curl</command> program is used for downloading.
|
||||
|
||||
{ url, md5 }:
|
||||
{ url, sha256 }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = baseNameOf (toString url);
|
||||
|
@ -184,10 +224,10 @@ stdenv.mkDerivation {
|
|||
buildInputs = [ curl ];
|
||||
|
||||
# This is a fixed-output derivation; the output must be a regular
|
||||
# file with MD5 hash <varname>md5</varname>.
|
||||
# file with SHA256 hash <varname>sha256</varname>.
|
||||
outputHashMode = "flat";
|
||||
outputHashAlgo = "md5";
|
||||
outputHash = md5;
|
||||
outputHashAlgo = "sha256";
|
||||
outputHash = sha256;
|
||||
|
||||
inherit url;
|
||||
}
|
||||
|
@ -197,8 +237,8 @@ stdenv.mkDerivation {
|
|||
|
||||
<para>The <varname>outputHashAlgo</varname> attribute specifies
|
||||
the hash algorithm used to compute the hash. It can currently be
|
||||
<literal>"md5"</literal>, <literal>"sha1"</literal> or
|
||||
<literal>"sha256"</literal>.</para>
|
||||
<literal>"sha1"</literal>, <literal>"sha256"</literal> or
|
||||
<literal>"sha512"</literal>.</para>
|
||||
|
||||
<para>The <varname>outputHashMode</varname> attribute determines
|
||||
how the hash is computed. It must be one of the following two
|
||||
|
@ -211,7 +251,7 @@ stdenv.mkDerivation {
|
|||
<listitem><para>The output must be a non-executable regular
|
||||
file. If it isn’t, the build fails. The hash is simply
|
||||
computed over the contents of that file (so it’s equal to what
|
||||
Unix commands like <command>md5sum</command> or
|
||||
Unix commands like <command>sha256sum</command> or
|
||||
<command>sha1sum</command> produce).</para>
|
||||
|
||||
<para>This is the default.</para></listitem>
|
||||
|
@ -272,9 +312,7 @@ big = "a very long string";
|
|||
<varlistentry><term><varname>preferLocalBuild</varname></term>
|
||||
|
||||
<listitem><para>If this attribute is set to
|
||||
<literal>true</literal>, it has two effects. First, the
|
||||
derivation will always be built, not substituted, even if a
|
||||
substitute is available. Second, if <link
|
||||
<literal>true</literal> and <link
|
||||
linkend="chap-distributed-builds">distributed building is
|
||||
enabled</link>, then, if possible, the derivaton will be built
|
||||
locally instead of forwarded to a remote machine. This is
|
||||
|
@ -284,6 +322,19 @@ big = "a very long string";
|
|||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry><term><varname>allowSubstitutes</varname></term>
|
||||
|
||||
<listitem><para>If this attribute is set to
|
||||
<literal>false</literal>, then Nix will always build this
|
||||
derivation; it will not try to substitute its outputs. This is
|
||||
useful for very trivial derivations (such as
|
||||
<function>writeText</function> in Nixpkgs) that are cheaper to
|
||||
build than to substitute from a binary cache.</para></listitem>
|
||||
|
||||
</varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -41,9 +41,9 @@ encountered</quote>).</para></footnote>.</para>
|
|||
</simplesect>
|
||||
|
||||
|
||||
<simplesect><title>Let-expressions</title>
|
||||
<simplesect xml:id="sect-let-expressions"><title>Let-expressions</title>
|
||||
|
||||
<para>A let-expression allows you define local variables for an
|
||||
<para>A let-expression allows you to define local variables for an
|
||||
expression. For instance,
|
||||
|
||||
<programlisting>
|
||||
|
@ -217,7 +217,25 @@ but can also be written as:
|
|||
ellipsis(<literal>...</literal>) as you can access attribute names as
|
||||
<literal>a</literal>, using <literal>args.a</literal>, which was given as an
|
||||
additional attribute to the function.
|
||||
</para></listitem>
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<para>
|
||||
The <literal>args@</literal> expression is bound to the argument passed to the function which
|
||||
means that attributes with defaults that aren't explicitly specified in the function call
|
||||
won't cause an evaluation error, but won't exist in <literal>args</literal>.
|
||||
</para>
|
||||
<para>
|
||||
For instance
|
||||
<programlisting>
|
||||
let
|
||||
function = args@{ a ? 23, ... }: args;
|
||||
in
|
||||
function {}
|
||||
</programlisting>
|
||||
will evaluate to an empty attribute set.
|
||||
</para>
|
||||
</warning></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
|
|
|
@ -15,13 +15,16 @@ weakest binding).</para>
|
|||
<tgroup cols='3'>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Name</entry>
|
||||
<entry>Syntax</entry>
|
||||
<entry>Associativity</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Precedence</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Select</entry>
|
||||
<entry><replaceable>e</replaceable> <literal>.</literal>
|
||||
<replaceable>attrpath</replaceable>
|
||||
[ <literal>or</literal> <replaceable>def</replaceable> ]
|
||||
|
@ -33,19 +36,25 @@ weakest binding).</para>
|
|||
dot-separated list of attribute names.) If the attribute
|
||||
doesn’t exist, return <replaceable>def</replaceable> if
|
||||
provided, otherwise abort evaluation.</entry>
|
||||
<entry>1</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Application</entry>
|
||||
<entry><replaceable>e1</replaceable> <replaceable>e2</replaceable></entry>
|
||||
<entry>left</entry>
|
||||
<entry>Call function <replaceable>e1</replaceable> with
|
||||
argument <replaceable>e2</replaceable>.</entry>
|
||||
<entry>2</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Arithmetic Negation</entry>
|
||||
<entry><literal>-</literal> <replaceable>e</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
<entry>Arithmetic negation.</entry>
|
||||
<entry>3</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Has Attribute</entry>
|
||||
<entry><replaceable>e</replaceable> <literal>?</literal>
|
||||
<replaceable>attrpath</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
|
@ -53,34 +62,69 @@ weakest binding).</para>
|
|||
the attribute denoted by <replaceable>attrpath</replaceable>;
|
||||
return <literal>true</literal> or
|
||||
<literal>false</literal>.</entry>
|
||||
<entry>4</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>List Concatenation</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>++</literal> <replaceable>e2</replaceable></entry>
|
||||
<entry>right</entry>
|
||||
<entry>List concatenation.</entry>
|
||||
<entry>5</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Multiplication</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>*</literal> <replaceable>e2</replaceable>,
|
||||
</entry>
|
||||
<entry>left</entry>
|
||||
<entry>Arithmetic multiplication.</entry>
|
||||
<entry>6</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Division</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>/</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>left</entry>
|
||||
<entry>Arithmetic multiplication and division.</entry>
|
||||
<entry>Arithmetic division.</entry>
|
||||
<entry>6</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Addition</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>+</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>left</entry>
|
||||
<entry>Arithmetic addition.</entry>
|
||||
<entry>7</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Subtraction</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>+</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>-</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>left</entry>
|
||||
<entry>Arithmetic addition and subtraction. String or path concatenation (only by <literal>+</literal>).</entry>
|
||||
<entry>Arithmetic subtraction.</entry>
|
||||
<entry>7</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>String Concatenation</entry>
|
||||
<entry>
|
||||
<replaceable>string1</replaceable> <literal>+</literal> <replaceable>string2</replaceable>
|
||||
</entry>
|
||||
<entry>left</entry>
|
||||
<entry>String concatenation.</entry>
|
||||
<entry>7</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Not</entry>
|
||||
<entry><literal>!</literal> <replaceable>e</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
<entry>Boolean negation.</entry>
|
||||
<entry>8</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Update</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>//</literal>
|
||||
<replaceable>e2</replaceable></entry>
|
||||
<entry>right</entry>
|
||||
|
@ -89,47 +133,90 @@ weakest binding).</para>
|
|||
<replaceable>e2</replaceable> (with the latter taking
|
||||
precedence over the former in case of equally named
|
||||
attributes).</entry>
|
||||
<entry>9</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Less Than</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal><</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>></literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal><=</literal> <replaceable>e2</replaceable>,
|
||||
</entry>
|
||||
<entry>none</entry>
|
||||
<entry>Arithmetic comparison.</entry>
|
||||
<entry>10</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Less Than or Equal To</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal><=</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>none</entry>
|
||||
<entry>Arithmetic comparison.</entry>
|
||||
<entry>10</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Greater Than</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>></literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>none</entry>
|
||||
<entry>Arithmetic comparison.</entry>
|
||||
<entry>10</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Greater Than or Equal To</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>>=</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>none</entry>
|
||||
<entry>Arithmetic comparison.</entry>
|
||||
<entry>10</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Equality</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>==</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>none</entry>
|
||||
<entry>Equality.</entry>
|
||||
<entry>11</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Inequality</entry>
|
||||
<entry>
|
||||
<replaceable>e1</replaceable> <literal>==</literal> <replaceable>e2</replaceable>,
|
||||
<replaceable>e1</replaceable> <literal>!=</literal> <replaceable>e2</replaceable>
|
||||
</entry>
|
||||
<entry>none</entry>
|
||||
<entry>Equality and inequality.</entry>
|
||||
<entry>Inequality.</entry>
|
||||
<entry>11</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Logical AND</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>&&</literal>
|
||||
<replaceable>e2</replaceable></entry>
|
||||
<entry>left</entry>
|
||||
<entry>Logical AND.</entry>
|
||||
<entry>12</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Logical OR</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>||</literal>
|
||||
<replaceable>e2</replaceable></entry>
|
||||
<entry>left</entry>
|
||||
<entry>Logical OR.</entry>
|
||||
<entry>13</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Logical Implication</entry>
|
||||
<entry><replaceable>e1</replaceable> <literal>-></literal>
|
||||
<replaceable>e2</replaceable></entry>
|
||||
<entry>none</entry>
|
||||
<entry>Logical implication (equivalent to
|
||||
<literal>!<replaceable>e1</replaceable> ||
|
||||
<replaceable>e2</replaceable></literal>).</entry>
|
||||
<entry>14</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<appendix xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:id="part-glossary">
|
||||
|
||||
<title>Glossary</title>
|
||||
|
||||
|
@ -85,29 +86,48 @@
|
|||
|
||||
<glossentry xml:id="gloss-reference"><glossterm>reference</glossterm>
|
||||
|
||||
<glossdef><para>A store path <varname>P</varname> is said to have a
|
||||
reference to a store path <varname>Q</varname> if the store object
|
||||
at <varname>P</varname> contains the path <varname>Q</varname>
|
||||
somewhere. This implies than an execution involving
|
||||
<varname>P</varname> potentially needs <varname>Q</varname> to be
|
||||
present. The <emphasis>references</emphasis> of a store path are
|
||||
the set of store paths to which it has a reference.</para></glossdef>
|
||||
<glossdef>
|
||||
<para>A store path <varname>P</varname> is said to have a
|
||||
reference to a store path <varname>Q</varname> if the store object
|
||||
at <varname>P</varname> contains the path <varname>Q</varname>
|
||||
somewhere. The <emphasis>references</emphasis> of a store path are
|
||||
the set of store paths to which it has a reference.
|
||||
</para>
|
||||
<para>A derivation can reference other derivations and sources
|
||||
(but not output paths), whereas an output path only references other
|
||||
output paths.
|
||||
</para>
|
||||
</glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
<glossentry xml:id="gloss-reachable"><glossterm>reachable</glossterm>
|
||||
|
||||
<glossdef><para>A store path <varname>Q</varname> is reachable from
|
||||
another store path <varname>P</varname> if <varname>Q</varname> is in the
|
||||
<link linkend="gloss-closure">closure</link> of the
|
||||
<link linkend="gloss-reference">references</link> relation.
|
||||
</para></glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry xml:id="gloss-closure"><glossterm>closure</glossterm>
|
||||
|
||||
<glossdef><para>The closure of a store path is the set of store
|
||||
paths that are directly or indirectly “reachable” from that store
|
||||
path; that is, it’s the closure of the path under the <link
|
||||
linkend="gloss-reference">references</link> relation. For instance,
|
||||
if the store object at path <varname>P</varname> contains a
|
||||
reference to path <varname>Q</varname>, then <varname>Q</varname> is
|
||||
in the closure of <varname>P</varname>. For correct deployment it
|
||||
is necessary to deploy whole closures, since otherwise at runtime
|
||||
files could be missing. The command <command>nix-store
|
||||
-qR</command> prints out closures of store paths.</para></glossdef>
|
||||
linkend="gloss-reference">references</link> relation. For a package, the
|
||||
closure of its derivation is equivalent to the build-time
|
||||
dependencies, while the closure of its output path is equivalent to its
|
||||
runtime dependencies. For correct deployment it is necessary to deploy whole
|
||||
closures, since otherwise at runtime files could be missing. The command
|
||||
<command>nix-store -qR</command> prints out closures of store paths.
|
||||
</para>
|
||||
<para>As an example, if the store object at path <varname>P</varname> contains
|
||||
a reference to path <varname>Q</varname>, then <varname>Q</varname> is
|
||||
in the closure of <varname>P</varname>. Further, if <varname>Q</varname>
|
||||
references <varname>R</varname> then <varname>R</varname> is also in
|
||||
the closure of <varname>P</varname>.
|
||||
</para></glossdef>
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
@ -147,7 +167,7 @@
|
|||
linkend="sec-profiles" />.</para>
|
||||
|
||||
</glossdef>
|
||||
|
||||
|
||||
</glossentry>
|
||||
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ To build Nix itself in this shell:
|
|||
[nix-shell]$ configurePhase
|
||||
[nix-shell]$ make
|
||||
</screen>
|
||||
To install it in <literal>$(pwd)/nix</literal> and test it:
|
||||
To install it in <literal>$(pwd)/inst</literal> and test it:
|
||||
<screen>
|
||||
[nix-shell]$ make install
|
||||
[nix-shell]$ make installcheck
|
||||
|
|
|
@ -21,4 +21,69 @@ in your <filename>~/.profile</filename> (or similar), like this:</para>
|
|||
<screen>
|
||||
source <replaceable>prefix</replaceable>/etc/profile.d/nix.sh</screen>
|
||||
|
||||
</chapter>
|
||||
<section xml:id="sec-nix-ssl-cert-file">
|
||||
|
||||
<title><envar>NIX_SSL_CERT_FILE</envar></title>
|
||||
|
||||
<para>If you need to specify a custom certificate bundle to account
|
||||
for an HTTPS-intercepting man in the middle proxy, you must specify
|
||||
the path to the certificate bundle in the environment variable
|
||||
<envar>NIX_SSL_CERT_FILE</envar>.</para>
|
||||
|
||||
|
||||
<para>If you don't specify a <envar>NIX_SSL_CERT_FILE</envar>
|
||||
manually, Nix will install and use its own certificate
|
||||
bundle.</para>
|
||||
|
||||
<procedure>
|
||||
<step><para>Set the environment variable and install Nix</para>
|
||||
<screen>
|
||||
$ export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
|
||||
$ sh <(curl https://nixos.org/nix/install)
|
||||
</screen></step>
|
||||
|
||||
<step><para>In the shell profile and rc files (for example,
|
||||
<filename>/etc/bashrc</filename>, <filename>/etc/zshrc</filename>),
|
||||
add the following line:</para>
|
||||
<programlisting>
|
||||
export NIX_SSL_CERT_FILE=/etc/ssl/my-certificate-bundle.crt
|
||||
</programlisting>
|
||||
</step>
|
||||
</procedure>
|
||||
|
||||
<note><para>You must not add the export and then do the install, as
|
||||
the Nix installer will detect the presense of Nix configuration, and
|
||||
abort.</para></note>
|
||||
|
||||
<section xml:id="sec-nix-ssl-cert-file-with-nix-daemon-and-macos">
|
||||
<title><envar>NIX_SSL_CERT_FILE</envar> with macOS and the Nix daemon</title>
|
||||
|
||||
<para>On macOS you must specify the environment variable for the Nix
|
||||
daemon service, then restart it:</para>
|
||||
|
||||
<screen>
|
||||
$ sudo launchctl setenv NIX_SSL_CERT_FILE /etc/ssl/my-certificate-bundle.crt
|
||||
$ sudo launchctl kickstart -k system/org.nixos.nix-daemon
|
||||
</screen>
|
||||
</section>
|
||||
|
||||
<section xml:id="sec-installer-proxy-settings">
|
||||
|
||||
<title>Proxy Environment Variables</title>
|
||||
|
||||
<para>The Nix installer has special handling for these proxy-related
|
||||
environment variables:
|
||||
<varname>http_proxy</varname>, <varname>https_proxy</varname>,
|
||||
<varname>ftp_proxy</varname>, <varname>no_proxy</varname>,
|
||||
<varname>HTTP_PROXY</varname>, <varname>HTTPS_PROXY</varname>,
|
||||
<varname>FTP_PROXY</varname>, <varname>NO_PROXY</varname>.
|
||||
</para>
|
||||
<para>If any of these variables are set when running the Nix installer,
|
||||
then the installer will create an override file at
|
||||
<filename>/etc/systemd/system/nix-daemon.service.d/override.conf</filename>
|
||||
so <command>nix-daemon</command> will use them.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -6,13 +6,30 @@
|
|||
|
||||
<title>Installing a Binary Distribution</title>
|
||||
|
||||
<para>If you are using Linux or macOS, the easiest way to install
|
||||
Nix is to run the following command:
|
||||
<para>If you are using Linux or macOS, the easiest way to install Nix
|
||||
is to run the following command:
|
||||
|
||||
<screen>
|
||||
$ bash <(curl https://nixos.org/nix/install)
|
||||
$ sh <(curl https://nixos.org/nix/install)
|
||||
</screen>
|
||||
|
||||
As of Nix 2.1.0, the Nix installer will always default to creating a
|
||||
single-user installation, however opting in to the multi-user
|
||||
installation is highly recommended.
|
||||
</para>
|
||||
|
||||
<section xml:id="sect-single-user-installation">
|
||||
<title>Single User Installation</title>
|
||||
|
||||
<para>
|
||||
To explicitly select a single-user installation on your system:
|
||||
|
||||
<screen>
|
||||
sh <(curl https://nixos.org/nix/install) --no-daemon
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This will perform a single-user installation of Nix, meaning that
|
||||
<filename>/nix</filename> is owned by the invoking user. You should
|
||||
run this under your usual user account, <emphasis>not</emphasis> as
|
||||
|
@ -33,51 +50,8 @@ and <filename>.profile</filename> to source
|
|||
the <command>NIX_INSTALLER_NO_MODIFY_PROFILE</command> environment
|
||||
variable before executing the install script to disable this
|
||||
behaviour.
|
||||
|
||||
</para>
|
||||
|
||||
<!--
|
||||
<para>You can also manually download and install a binary package.
|
||||
Binary packages of the latest stable release are available for Fedora,
|
||||
Debian, Ubuntu, macOS and various other systems from the <link
|
||||
xlink:href="http://nixos.org/nix/download.html">Nix homepage</link>.
|
||||
You can also get builds of the latest development release from our
|
||||
<link
|
||||
xlink:href="http://hydra.nixos.org/job/nix/master/release/latest-finished#tabs-constituents">continuous
|
||||
build system</link>.</para>
|
||||
|
||||
<para>For Fedora, RPM packages are available. These can be installed
|
||||
or upgraded using <command>rpm -U</command>. For example,
|
||||
|
||||
<screen>
|
||||
$ rpm -U nix-1.8-1.i386.rpm</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>For Debian and Ubuntu, you can download a Deb package and
|
||||
install it like this:
|
||||
|
||||
<screen>
|
||||
$ dpkg -i nix_1.8-1_amd64.deb</screen>
|
||||
|
||||
</para>
|
||||
-->
|
||||
|
||||
<para>You can also download a binary tarball that contains Nix and all
|
||||
its dependencies. (This is what the install script at
|
||||
<uri>https://nixos.org/nix/install</uri> does automatically.) You
|
||||
should unpack it somewhere (e.g. in <filename>/tmp</filename>), and
|
||||
then run the script named <command>install</command> inside the binary
|
||||
tarball:
|
||||
|
||||
<screen>
|
||||
alice$ cd /tmp
|
||||
alice$ tar xfj nix-1.8-x86_64-darwin.tar.bz2
|
||||
alice$ cd nix-1.8-x86_64-darwin
|
||||
alice$ ./install
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
|
||||
<para>You can uninstall Nix simply by running:
|
||||
|
||||
|
@ -86,5 +60,131 @@ $ rm -rf /nix
|
|||
</screen>
|
||||
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="sect-multi-user-installation">
|
||||
<title>Multi User Installation</title>
|
||||
<para>
|
||||
The multi-user Nix installation creates system users, and a system
|
||||
service for the Nix daemon.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<title>Supported Systems</title>
|
||||
|
||||
<listitem>
|
||||
<para>Linux running systemd, with SELinux disabled</para>
|
||||
</listitem>
|
||||
<listitem><para>macOS</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
You can instruct the installer to perform a multi-user
|
||||
installation on your system:
|
||||
|
||||
<screen>
|
||||
sh <(curl https://nixos.org/nix/install) --daemon
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The multi-user installation of Nix will create build users between
|
||||
the user IDs 30001 and 30032, and a group with the group ID 30000.
|
||||
|
||||
You should run this under your usual user account,
|
||||
<emphasis>not</emphasis> as root. The script will invoke
|
||||
<command>sudo</command> as needed.
|
||||
</para>
|
||||
|
||||
<note><para>
|
||||
If you need Nix to use a different group ID or user ID set, you
|
||||
will have to download the tarball manually and <link
|
||||
linkend="sect-nix-install-binary-tarball">edit the install
|
||||
script</link>.
|
||||
</para></note>
|
||||
|
||||
<para>
|
||||
The installer will modify <filename>/etc/bashrc</filename>, and
|
||||
<filename>/etc/zshrc</filename> if they exist. The installer will
|
||||
first back up these files with a
|
||||
<literal>.backup-before-nix</literal> extension. The installer
|
||||
will also create <filename>/etc/profile.d/nix.sh</filename>.
|
||||
</para>
|
||||
|
||||
<para>You can uninstall Nix with the following commands:
|
||||
|
||||
<screen>
|
||||
sudo rm -rf /etc/profile/nix.sh /etc/nix /nix ~root/.nix-profile ~root/.nix-defexpr ~root/.nix-channels ~/.nix-profile ~/.nix-defexpr ~/.nix-channels
|
||||
|
||||
# If you are on Linux with systemd, you will need to run:
|
||||
sudo systemctl stop nix-daemon.socket
|
||||
sudo systemctl stop nix-daemon.service
|
||||
sudo systemctl disable nix-daemon.socket
|
||||
sudo systemctl disable nix-daemon.service
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
# If you are on macOS, you will need to run:
|
||||
sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
sudo rm /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
</screen>
|
||||
|
||||
There may also be references to Nix in
|
||||
<filename>/etc/profile</filename>,
|
||||
<filename>/etc/bashrc</filename>, and
|
||||
<filename>/etc/zshrc</filename> which you may remove.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="sect-nix-install-pinned-version-url">
|
||||
<title>Installing a pinned Nix version from a URL</title>
|
||||
|
||||
<para>
|
||||
NixOS.org hosts version-specific installation URLs for all Nix
|
||||
versions since 1.11.16, at
|
||||
<literal>https://nixos.org/releases/nix/nix-VERSION/install</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
These install scripts can be used the same as the main
|
||||
NixOS.org installation script:
|
||||
|
||||
<screen>
|
||||
sh <(curl https://nixos.org/nix/install)
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the same directory of the install script are sha256 sums, and
|
||||
gpg signature files.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="sect-nix-install-binary-tarball">
|
||||
<title>Installing from a binary tarball</title>
|
||||
|
||||
<para>
|
||||
You can also download a binary tarball that contains Nix and all
|
||||
its dependencies. (This is what the install script at
|
||||
<uri>https://nixos.org/nix/install</uri> does automatically.) You
|
||||
should unpack it somewhere (e.g. in <filename>/tmp</filename>),
|
||||
and then run the script named <command>install</command> inside
|
||||
the binary tarball:
|
||||
|
||||
|
||||
<screen>
|
||||
alice$ cd /tmp
|
||||
alice$ tar xfj nix-1.8-x86_64-darwin.tar.bz2
|
||||
alice$ cd nix-1.8-x86_64-darwin
|
||||
alice$ ./install
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you need to edit the multi-user installation script to use
|
||||
different group ID or a different user ID range, modify the
|
||||
variables set in the file named
|
||||
<filename>install-multi-user</filename>.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
@ -9,8 +9,11 @@
|
|||
<itemizedlist>
|
||||
|
||||
<listitem><para>GNU Make.</para></listitem>
|
||||
|
||||
<listitem><para>Bash Shell. The <literal>./configure</literal> script
|
||||
relies on bashisms, so Bash is required.</para></listitem>
|
||||
|
||||
<listitem><para>A version of GCC or Clang that supports C++14.</para></listitem>
|
||||
<listitem><para>A version of GCC or Clang that supports C++17.</para></listitem>
|
||||
|
||||
<listitem><para><command>pkg-config</command> to locate
|
||||
dependencies. If your distribution does not provide it, you can get
|
||||
|
@ -22,12 +25,27 @@
|
|||
If your distribution does not provide it, you can get it from <link
|
||||
xlink:href="https://www.openssl.org"/>.</para></listitem>
|
||||
|
||||
<listitem><para>The <literal>libbrotlienc</literal> and
|
||||
<literal>libbrotlidec</literal> libraries to provide implementation
|
||||
of the Brotli compression algorithm. They are available for download
|
||||
from the official repository <link
|
||||
xlink:href="https://github.com/google/brotli" />.</para></listitem>
|
||||
|
||||
<listitem><para>The bzip2 compressor program and the
|
||||
<literal>libbz2</literal> library. Thus you must have bzip2
|
||||
installed, including development headers and libraries. If your
|
||||
distribution does not provide these, you can obtain bzip2 from <link
|
||||
xlink:href="http://www.bzip.org/"/>.</para></listitem>
|
||||
xlink:href="https://web.archive.org/web/20180624184756/http://www.bzip.org/"
|
||||
/>.</para></listitem>
|
||||
|
||||
<listitem><para><literal>liblzma</literal>, which is provided by
|
||||
XZ Utils. If your distribution does not provide this, you can
|
||||
get it from <link xlink:href="https://tukaani.org/xz/"/>.</para></listitem>
|
||||
|
||||
<listitem><para>cURL and its library. If your distribution does not
|
||||
provide it, you can get it from <link
|
||||
xlink:href="https://curl.haxx.se/"/>.</para></listitem>
|
||||
|
||||
<listitem><para>The SQLite embedded database library, version 3.6.19
|
||||
or higher. If your distribution does not provide it, please install
|
||||
it from <link xlink:href="http://www.sqlite.org/" />.</para></listitem>
|
||||
|
@ -40,6 +58,14 @@
|
|||
pass the flag <option>--enable-gc</option> to
|
||||
<command>configure</command>.</para></listitem>
|
||||
|
||||
<listitem><para>The <literal>boost</literal> library of version
|
||||
1.66.0 or higher. It can be obtained from the official web site
|
||||
<link xlink:href="https://www.boost.org/" />.</para></listitem>
|
||||
|
||||
<listitem><para>The <literal>editline</literal> library of version
|
||||
1.14.0 or higher. It can be obtained from the its repository
|
||||
<link xlink:href="https://github.com/troglobit/editline" />.</para></listitem>
|
||||
|
||||
<listitem><para>The <command>xmllint</command> and
|
||||
<command>xsltproc</command> programs to build this manual and the
|
||||
man-pages. These are part of the <literal>libxml2</literal> and
|
||||
|
@ -65,6 +91,15 @@
|
|||
modify the parser or when you are building from the Git
|
||||
repository.</para></listitem>
|
||||
|
||||
<listitem><para>The <literal>libseccomp</literal> is used to provide
|
||||
syscall filtering on Linux. This is an optional dependency and can
|
||||
be disabled passing a <option>--disable-seccomp-sandboxing</option>
|
||||
option to the <command>configure</command> script (Not recommended
|
||||
unless your system doesn't support
|
||||
<literal>libseccomp</literal>). To get the library, visit <link
|
||||
xlink:href="https://github.com/seccomp/libseccomp"
|
||||
/>.</para></listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem><para>Linux (i686, x86_64).</para></listitem>
|
||||
<listitem><para>Linux (i686, x86_64, aarch64).</para></listitem>
|
||||
|
||||
<listitem><para>macOS (x86_64).</para></listitem>
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ch-upgrading-nix">
|
||||
|
||||
<title>Upgrading Nix</title>
|
||||
|
||||
<para>
|
||||
Multi-user Nix users on macOS can upgrade Nix by running:
|
||||
<command>sudo -i sh -c 'nix-channel --update &&
|
||||
nix-env -iA nixpkgs.nix &&
|
||||
launchctl remove org.nixos.nix-daemon &&
|
||||
launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist'</command>
|
||||
</para>
|
||||
|
||||
|
||||
<para>
|
||||
Single-user installations of Nix should run this:
|
||||
<command>nix-channel --update; nix-env -iA nixpkgs.nix</command>
|
||||
</para>
|
||||
</chapter>
|
|
@ -60,7 +60,8 @@ This is because tools such as compilers don’t search in per-packages
|
|||
directories such as
|
||||
<filename>/nix/store/5lbfaxb722zp…-openssl-0.9.8d/include</filename>,
|
||||
so if a package builds correctly on your system, this is because you
|
||||
specified the dependency explicitly.</para>
|
||||
specified the dependency explicitly. This takes care of the build-time
|
||||
dependencies.</para>
|
||||
|
||||
<para>Once a package is built, runtime dependencies are found by
|
||||
scanning binaries for the hash parts of Nix store paths (such as
|
||||
|
@ -261,12 +262,6 @@ xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
|
|||
xlink:href="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">GNU
|
||||
LGPLv2.1 or (at your option) any later version</link>.</para>
|
||||
|
||||
<para>Nix uses the <link
|
||||
xlink:href="https://github.com/arangodb/linenoise-ng">linenoise-ng
|
||||
library</link>, which has the following license:</para>
|
||||
|
||||
<programlisting><xi:include href="../../../src/linenoise/LICENSE" parse="text" /></programlisting>
|
||||
|
||||
</simplesect>
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
<xi:include href="introduction/introduction.xml" />
|
||||
<xi:include href="installation/installation.xml" />
|
||||
<xi:include href="installation/upgrading.xml" />
|
||||
<xi:include href="packages/package-management.xml" />
|
||||
<xi:include href="expressions/writing-nix-expressions.xml" />
|
||||
<xi:include href="advanced-topics/advanced-topics.xml" />
|
||||
|
|
|
@ -24,11 +24,11 @@ symlinks to the files of the active applications. </para>
|
|||
<para>Components are installed from a set of <emphasis>Nix
|
||||
expressions</emphasis> that tell Nix how to build those packages,
|
||||
including, if necessary, their dependencies. There is a collection of
|
||||
Nix expressions called the Nix Package collection that contains
|
||||
Nix expressions called the Nixpkgs package collection that contains
|
||||
packages ranging from basic development stuff such as GCC and Glibc,
|
||||
to end-user applications like Mozilla Firefox. (Nix is however not
|
||||
tied to the Nix Package collection; you could write your own Nix
|
||||
expressions based on it, or completely new ones.)</para>
|
||||
tied to the Nixpkgs package collection; you could write your own Nix
|
||||
expressions based on Nixpkgs, or completely new ones.)</para>
|
||||
|
||||
<para>You can manually download the latest version of Nixpkgs from
|
||||
<link xlink:href='http://nixos.org/nixpkgs/download.html'/>. However,
|
||||
|
|
|
@ -52,6 +52,14 @@ garbage collector as follows:
|
|||
<screen>
|
||||
$ nix-store --gc</screen>
|
||||
|
||||
The behaviour of the gargage collector is affected by the <literal>keep-
|
||||
derivations</literal> (default: true) and <literal>keep-outputs</literal>
|
||||
(default: false) options in the Nix configuration file. The defaults will ensure
|
||||
that all derivations that are not build-time dependencies of garbage collector roots
|
||||
will be collected but that all output paths that are not runtime dependencies
|
||||
will be collected. (This is usually what you want, but while you are developing
|
||||
it may make sense to keep outputs to ensure that rebuild times are quick.)
|
||||
|
||||
If you are feeling uncertain, you can also first view what files would
|
||||
be deleted:
|
||||
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ssec-s3-substituter">
|
||||
|
||||
<title>Serving a Nix store via AWS S3 or S3-compatible Service</title>
|
||||
|
||||
<para>Nix has built-in support for storing and fetching store paths
|
||||
from Amazon S3 and S3 compatible services. This uses the same
|
||||
<emphasis>binary</emphasis> cache mechanism that Nix usually uses to
|
||||
fetch prebuilt binaries from <uri>cache.nixos.org</uri>.</para>
|
||||
|
||||
<para>The following options can be specified as URL parameters to
|
||||
the S3 URL:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry><term><literal>profile</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name of the AWS configuration profile to use. By default
|
||||
Nix will use the <literal>default</literal> profile.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>region</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The region of the S3 bucket. <literal>us–east-1</literal> by
|
||||
default.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If your bucket is not in <literal>us–east-1</literal>, you
|
||||
should always explicitly specify the region parameter.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>endpoint</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The URL to your S3-compatible service, for when not using
|
||||
Amazon S3. Do not specify this value if you're using Amazon
|
||||
S3.
|
||||
</para>
|
||||
<note><para>This endpoint must support HTTPS and will use
|
||||
path-based addressing instead of virtual host based
|
||||
addressing.</para></note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry><term><literal>scheme</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The scheme used for S3 requests, <literal>https</literal>
|
||||
(default) or <literal>http</literal>. This option allows you to
|
||||
disable HTTPS for binary caches which don't support it.
|
||||
</para>
|
||||
<note><para>HTTPS should be used if the cache might contain
|
||||
sensitive information.</para></note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>In this example we will use the bucket named
|
||||
<literal>example-nix-cache</literal>.</para>
|
||||
|
||||
<section xml:id="ssec-s3-substituter-anonymous-reads">
|
||||
<title>Anonymous Reads to your S3-compatible binary cache</title>
|
||||
|
||||
<para>If your binary cache is publicly accessible and does not
|
||||
require authentication, the simplest and easiest way to use Nix with
|
||||
your S3 compatible binary cache is to use the HTTP URL for that
|
||||
cache.</para>
|
||||
|
||||
<para>For AWS S3 the binary cache URL for example bucket will be
|
||||
exactly <uri>https://example-nix-cache.s3.amazonaws.com</uri> or
|
||||
<uri>s3://example-nix-cache</uri>. For S3 compatible binary caches,
|
||||
consult that cache's documentation.</para>
|
||||
|
||||
<para>Your bucket will need the following bucket policy:</para>
|
||||
|
||||
<programlisting><![CDATA[
|
||||
{
|
||||
"Id": "DirectReads",
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "AllowDirectReads",
|
||||
"Action": [
|
||||
"s3:GetObject",
|
||||
"s3:GetBucketLocation"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::example-nix-cache",
|
||||
"arn:aws:s3:::example-nix-cache/*"
|
||||
],
|
||||
"Principal": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]]></programlisting>
|
||||
</section>
|
||||
|
||||
<section xml:id="ssec-s3-substituter-authenticated-reads">
|
||||
<title>Authenticated Reads to your S3 binary cache</title>
|
||||
|
||||
<para>For AWS S3 the binary cache URL for example bucket will be
|
||||
exactly <uri>s3://example-nix-cache</uri>.</para>
|
||||
|
||||
<para>Nix will use the <link
|
||||
xlink:href="https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html">default
|
||||
credential provider chain</link> for authenticating requests to
|
||||
Amazon S3.</para>
|
||||
|
||||
<para>Nix supports authenticated reads from Amazon S3 and S3
|
||||
compatible binary caches.</para>
|
||||
|
||||
<para>Your bucket will need a bucket policy allowing the desired
|
||||
users to perform the <literal>s3:GetObject</literal> and
|
||||
<literal>s3:GetBucketLocation</literal> action on all objects in the
|
||||
bucket. The anonymous policy in <xref
|
||||
linkend="ssec-s3-substituter-anonymous-reads" /> can be updated to
|
||||
have a restricted <literal>Principal</literal> to support
|
||||
this.</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section xml:id="ssec-s3-substituter-authenticated-writes">
|
||||
<title>Authenticated Writes to your S3-compatible binary cache</title>
|
||||
|
||||
<para>Nix support fully supports writing to Amazon S3 and S3
|
||||
compatible buckets. The binary cache URL for our example bucket will
|
||||
be <uri>s3://example-nix-cache</uri>.</para>
|
||||
|
||||
<para>Nix will use the <link
|
||||
xlink:href="https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html">default
|
||||
credential provider chain</link> for authenticating requests to
|
||||
Amazon S3.</para>
|
||||
|
||||
<para>Your account will need the following IAM policy to
|
||||
upload to the cache:</para>
|
||||
|
||||
<programlisting><![CDATA[
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "UploadToCache",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:AbortMultipartUpload",
|
||||
"s3:GetBucketLocation",
|
||||
"s3:GetObject",
|
||||
"s3:ListBucket",
|
||||
"s3:ListBucketMultipartUploads",
|
||||
"s3:ListMultipartUploadParts",
|
||||
"s3:ListObjects",
|
||||
"s3:PutObject"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::example-nix-cache",
|
||||
"arn:aws:s3:::example-nix-cache/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]]></programlisting>
|
||||
|
||||
|
||||
<example><title>Uploading with a specific credential profile for Amazon S3</title>
|
||||
<para><command>nix copy --to 's3://example-nix-cache?profile=cache-upload&region=eu-west-2' nixpkgs.hello</command></para>
|
||||
</example>
|
||||
|
||||
<example><title>Uploading to an S3-Compatible Binary Cache</title>
|
||||
<para><command>nix copy --to 's3://example-nix-cache?profile=cache-upload&scheme=https&endpoint=minio.example.com' nixpkgs.hello</command></para>
|
||||
</example>
|
||||
</section>
|
||||
</section>
|
|
@ -15,5 +15,6 @@ packages between machines.</para>
|
|||
<xi:include href="binary-cache-substituter.xml" />
|
||||
<xi:include href="copy-closure.xml" />
|
||||
<xi:include href="ssh-substituter.xml" />
|
||||
<xi:include href="s3-substituter.xml" />
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -12,7 +12,7 @@ automatically fetching any store paths in Firefox’s closure if they
|
|||
are available on the server <literal>avalon</literal>:
|
||||
|
||||
<screen>
|
||||
$ nix-env -i firefox --option ssh-substituter-hosts alice@avalon
|
||||
$ nix-env -i firefox --substituters ssh://alice@avalon
|
||||
</screen>
|
||||
|
||||
This works similar to the binary cache substituter that Nix usually
|
||||
|
@ -31,7 +31,7 @@ an SSH passphrase interactively. Therefore, you should use
|
|||
installing it into your profile, e.g.
|
||||
|
||||
<screen>
|
||||
$ nix-store -r /nix/store/m85bxg…-firefox-34.0.5 --option ssh-substituter-hosts alice@avalon
|
||||
$ nix-store -r /nix/store/m85bxg…-firefox-34.0.5 --substituters ssh://alice@avalon
|
||||
</screen>
|
||||
|
||||
This is essentially equivalent to doing
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
</partintro>
|
||||
-->
|
||||
|
||||
<xi:include href="rl-2.3.xml" />
|
||||
<xi:include href="rl-2.2.xml" />
|
||||
<xi:include href="rl-2.1.xml" />
|
||||
<xi:include href="rl-2.0.xml" />
|
||||
<xi:include href="rl-1.11.10.xml" />
|
||||
<xi:include href="rl-1.11.xml" />
|
||||
|
|
|
@ -35,14 +35,14 @@
|
|||
available paths from the installation medium. The replacement is
|
||||
to use a chroot store as a substituter
|
||||
(e.g. <literal>--substituters /mnt</literal>), or to build into a
|
||||
chroot store (e.g. <literal>--store /mnt --substituter /</literal>).</para>
|
||||
chroot store (e.g. <literal>--store /mnt --substituters /</literal>).</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The command <command>nix-push</command> has been removed as
|
||||
part of the effort to eliminate Nix's dependency on Perl. You can
|
||||
use <command>nix copy</command> instead, e.g. <literal>nix copy
|
||||
--to /tmp/my-binary-cache <replaceable>paths…</replaceable></literal></para>
|
||||
--to file:///tmp/my-binary-cache <replaceable>paths…</replaceable></literal></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
@ -323,13 +323,12 @@
|
|||
|
||||
<listitem>
|
||||
<para><command>nix sign-paths</command> signs store
|
||||
paths. (TODO: add examples)</para>
|
||||
paths.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>nix copy-sigs</command> copies signatures from
|
||||
one store to another. (TODO: add examples and
|
||||
tests)</para>
|
||||
one store to another.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
@ -460,7 +459,7 @@
|
|||
secret keys specified by the <option>secret-key-files</option>
|
||||
store option. Secret/public key pairs can be generated using
|
||||
<command>nix-store
|
||||
--generate-binary-cache-key</command>. (TODO: rename)</para>
|
||||
--generate-binary-cache-key</command>.</para>
|
||||
|
||||
<para>In addition, locally-built store paths are marked as
|
||||
“ultimately trusted”, but this bit is not propagated when
|
||||
|
@ -537,7 +536,7 @@
|
|||
xlink:href="https://github.com/NixOS/nix/commit/8bdf83f936adae6f2c907a6d2541e80d4120f051">no
|
||||
longer</link> a fatal error if build rounds produce different
|
||||
output. Also, a hook named <option>diff-hook</option> is <link
|
||||
xlink:href="https://github.com/NixOS/nix/commit/9a313469a4bdea2d1e8df24d16289dc2a172a169w">provided</link>
|
||||
xlink:href="https://github.com/NixOS/nix/commit/9a313469a4bdea2d1e8df24d16289dc2a172a169">provided</link>
|
||||
to allow you to run tools such as <command>diffoscope</command>
|
||||
when build rounds produce different output.</para>
|
||||
</listitem>
|
||||
|
@ -723,8 +722,7 @@ configureFlags = "--prefix=${placeholder "out"} --includedir=${placeholder "dev"
|
|||
|
||||
will cause the <envar>configureFlags</envar> environment variable
|
||||
to contain the actual store paths corresponding to the
|
||||
<literal>out</literal> and <literal>dev</literal> outputs. TODO:
|
||||
add docs.</para>
|
||||
<literal>out</literal> and <literal>dev</literal> outputs.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-2.1">
|
||||
|
||||
<title>Release 2.1 (2018-09-02)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. It also reduces memory
|
||||
consumption in certain situations. In addition, it has the following
|
||||
new features:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>The Nix installer will no longer default to the Multi-User
|
||||
installation for macOS. You can still <link
|
||||
linkend="sect-multi-user-installation">instruct the installer to
|
||||
run in multi-user mode</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The Nix installer now supports performing a Multi-User
|
||||
installation for Linux computers which are running systemd. You
|
||||
can <link
|
||||
linkend="sect-multi-user-installation">select a Multi-User installation</link> by passing the
|
||||
<option>--daemon</option> flag to the installer: <command>sh <(curl
|
||||
https://nixos.org/nix/install) --daemon</command>.
|
||||
</para>
|
||||
|
||||
<para>The multi-user installer cannot handle systems with SELinux.
|
||||
If your system has SELinux enabled, you can <link
|
||||
linkend="sect-single-user-installation">force the installer to run
|
||||
in single-user mode</link>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>New builtin functions:
|
||||
<literal>builtins.bitAnd</literal>,
|
||||
<literal>builtins.bitOr</literal>,
|
||||
<literal>builtins.bitXor</literal>,
|
||||
<literal>builtins.fromTOML</literal>,
|
||||
<literal>builtins.concatMap</literal>,
|
||||
<literal>builtins.mapAttrs</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The S3 binary cache store now supports uploading NARs larger
|
||||
than 5 GiB.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The S3 binary cache store now supports uploading to
|
||||
S3-compatible services with the <literal>endpoint</literal>
|
||||
option.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The flag <option>--fallback</option> is no longer required
|
||||
to recover from disappeared NARs in binary caches.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>nix-daemon</command> now respects
|
||||
<option>--store</option>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>nix run</command> now respects
|
||||
<varname>nix-support/propagated-user-env-packages</varname>.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>This release has contributions from
|
||||
|
||||
Adrien Devresse,
|
||||
Aleksandr Pashkov,
|
||||
Alexandre Esteves,
|
||||
Amine Chikhaoui,
|
||||
Andrew Dunham,
|
||||
Asad Saeeduddin,
|
||||
aszlig,
|
||||
Ben Challenor,
|
||||
Ben Gamari,
|
||||
Benjamin Hipple,
|
||||
Bogdan Seniuc,
|
||||
Corey O'Connor,
|
||||
Daiderd Jordan,
|
||||
Daniel Peebles,
|
||||
Daniel Poelzleithner,
|
||||
Danylo Hlynskyi,
|
||||
Dmitry Kalinkin,
|
||||
Domen Kožar,
|
||||
Doug Beardsley,
|
||||
Eelco Dolstra,
|
||||
Erik Arvstedt,
|
||||
Félix Baylac-Jacqué,
|
||||
Gleb Peregud,
|
||||
Graham Christensen,
|
||||
Guillaume Maudoux,
|
||||
Ivan Kozik,
|
||||
John Arnold,
|
||||
Justin Humm,
|
||||
Linus Heckemann,
|
||||
Lorenzo Manacorda,
|
||||
Matthew Justin Bauer,
|
||||
Matthew O'Gorman,
|
||||
Maximilian Bosch,
|
||||
Michael Bishop,
|
||||
Michael Fiano,
|
||||
Michael Mercier,
|
||||
Michael Raskin,
|
||||
Michael Weiss,
|
||||
Nicolas Dudebout,
|
||||
Peter Simons,
|
||||
Ryan Trinkle,
|
||||
Samuel Dionne-Riel,
|
||||
Sean Seefried,
|
||||
Shea Levy,
|
||||
Symphorien Gibol,
|
||||
Tim Engler,
|
||||
Tim Sears,
|
||||
Tuomas Tynkkynen,
|
||||
volth,
|
||||
Will Dietz,
|
||||
Yorick van Pelt and
|
||||
zimbatm.
|
||||
</para>
|
||||
|
||||
</section>
|
|
@ -0,0 +1,143 @@
|
|||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-2.2">
|
||||
|
||||
<title>Release 2.2 (2019-01-11)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. It also has the following
|
||||
changes:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>In derivations that use structured attributes (i.e. that
|
||||
specify set the <varname>__structuredAttrs</varname> attribute to
|
||||
<literal>true</literal> to cause all attributes to be passed to
|
||||
the builder in JSON format), you can now specify closure checks
|
||||
per output, e.g.:
|
||||
|
||||
<programlisting>
|
||||
outputChecks."out" = {
|
||||
# The closure of 'out' must not be larger than 256 MiB.
|
||||
maxClosureSize = 256 * 1024 * 1024;
|
||||
|
||||
# It must not refer to C compiler or to the 'dev' output.
|
||||
disallowedRequisites = [ stdenv.cc "dev" ];
|
||||
};
|
||||
|
||||
outputChecks."dev" = {
|
||||
# The 'dev' output must not be larger than 128 KiB.
|
||||
maxSize = 128 * 1024;
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem>
|
||||
<para>The derivation attribute
|
||||
<varname>requiredSystemFeatures</varname> is now enforced for
|
||||
local builds, and not just to route builds to remote builders.
|
||||
The supported features of a machine can be specified through the
|
||||
configuration setting <varname>system-features</varname>.</para>
|
||||
|
||||
<para>By default, <varname>system-features</varname> includes
|
||||
<literal>kvm</literal> if <filename>/dev/kvm</filename>
|
||||
exists. For compatibility, it also includes the pseudo-features
|
||||
<literal>nixos-test</literal>, <literal>benchmark</literal> and
|
||||
<literal>big-parallel</literal> which are used by Nixpkgs to route
|
||||
builds to particular Hydra build machines.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Sandbox builds are now enabled by default on Linux.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The new command <command>nix doctor</command> shows
|
||||
potential issues with your Nix installation.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The <literal>fetchGit</literal> builtin function now uses a
|
||||
caching scheme that puts different remote repositories in distinct
|
||||
local repositories, rather than a single shared repository. This
|
||||
may require more disk space but is faster.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The <literal>dirOf</literal> builtin function now works on
|
||||
relative paths.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Nix now supports <link
|
||||
xlink:href="https://www.w3.org/TR/SRI/">SRI hashes</link>,
|
||||
allowing the hash algorithm and hash to be specified in a single
|
||||
string. For example, you can write:
|
||||
|
||||
<programlisting>
|
||||
import <nix/fetchurl.nix> {
|
||||
url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz;
|
||||
hash = "sha256-XSLa0FjVyADWWhFfkZ2iKTjFDda6mMXjoYMXLRSYQKQ=";
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
instead of
|
||||
|
||||
<programlisting>
|
||||
import <nix/fetchurl.nix> {
|
||||
url = https://nixos.org/releases/nix/nix-2.1.3/nix-2.1.3.tar.xz;
|
||||
sha256 = "5d22dad058d5c800d65a115f919da22938c50dd6ba98c5e3a183172d149840a4";
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
<para>In fixed-output derivations, the
|
||||
<varname>outputHashAlgo</varname> attribute is no longer mandatory
|
||||
if <varname>outputHash</varname> specifies the hash.</para>
|
||||
|
||||
<para><command>nix hash-file</command> and <command>nix
|
||||
hash-path</command> now print hashes in SRI format by
|
||||
default. They also use SHA-256 by default instead of SHA-512
|
||||
because that's what we use most of the time in Nixpkgs.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Integers are now 64 bits on all platforms.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The evaluator now prints profiling statistics (enabled via
|
||||
the <envar>NIX_SHOW_STATS</envar> and
|
||||
<envar>NIX_COUNT_CALLS</envar> environment variables) in JSON
|
||||
format.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The option <option>--xml</option> in <command>nix-store
|
||||
--query</command> has been removed. Instead, there now is an
|
||||
option <option>--graphml</option> to output the dependency graph
|
||||
in GraphML format.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>All <filename>nix-*</filename> commands are now symlinks to
|
||||
<filename>nix</filename>. This saves a bit of disk space.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><command>nix repl</command> now uses
|
||||
<literal>libeditline</literal> or
|
||||
<literal>libreadline</literal>.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
<section xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
version="5.0"
|
||||
xml:id="ssec-relnotes-2.3">
|
||||
|
||||
<title>Release 2.3 (2019-09-04)</title>
|
||||
|
||||
<para>This is primarily a bug fix release. However, it makes some
|
||||
incompatible changes:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Nix now uses BSD file locks instead of POSIX file
|
||||
locks. Because of this, you should not use Nix 2.3 and previous
|
||||
releases at the same time on a Nix store.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>It also has the following changes:</para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para><function>builtins.fetchGit</function>'s <varname>ref</varname>
|
||||
argument now allows specifying an absolute remote ref.
|
||||
Nix will automatically prefix <varname>ref</varname> with
|
||||
<literal>refs/heads</literal> only if <varname>ref</varname> doesn't
|
||||
already begin with <literal>refs/</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The installer now enables sandboxing by default on
|
||||
Linux. The <literal>max-jobs</literal> setting now defaults to
|
||||
1.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>New builtin functions:
|
||||
<literal>builtins.isPath</literal>,
|
||||
<literal>builtins.hashFile</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The <command>nix</command> command has a new
|
||||
<option>--print-build-logs</option> (<option>-L</option>) flag to
|
||||
print build log output to stderr, rather than showing the last log
|
||||
line in the progress bar. To distinguish between concurrent
|
||||
builds, log lines are prefixed by the name of the package.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Builds are now executed in a pseudo-terminal, and the
|
||||
<envar>TERM</envar> environment variable is set to
|
||||
<literal>xterm-256color</literal>. This allows many programs
|
||||
(e.g. <command>gcc</command>, <command>clang</command>,
|
||||
<command>cmake</command>) to print colorized log output.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Add <option>--no-net</option> convenience flag. This flag
|
||||
disables substituters; sets the <literal>tarball-ttl</literal>
|
||||
setting to infinity (ensuring that any previously downloaded files
|
||||
are considered current); and disables retrying downloads and sets
|
||||
the connection timeout to the minimum. This flag is enabled
|
||||
automatically if there are no configured non-loopback network
|
||||
interfaces.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Add a <literal>post-build-hook</literal> setting to run a
|
||||
program after a build has succeeded.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Add a <literal>trace-function-calls</literal> setting to log
|
||||
the duration of Nix function calls to stderr.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>On Linux, sandboxing is now disabled by default on systems
|
||||
that don’t have the necessary kernel support.</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
4
local.mk
4
local.mk
|
@ -6,9 +6,7 @@ dist-files += configure config.h.in nix.spec perl/configure
|
|||
|
||||
clean-files += Makefile.config
|
||||
|
||||
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr
|
||||
GLOBAL_CXXFLAGS += -I . -I src -I src/libutil -I src/libstore -I src/libmain -I src/libexpr -I src/nix
|
||||
|
||||
$(foreach i, config.h $(call rwildcard, src/lib*, *.hh), \
|
||||
$(eval $(call install-file-in, $(i), $(includedir)/nix, 0644)))
|
||||
|
||||
$(foreach i, $(call rwildcard, src/boost, *.hpp), $(eval $(call install-file-in, $(i), $(includedir)/nix/$(patsubst src/%/,%,$(dir $(i))), 0644)))
|
||||
|
|
|
@ -0,0 +1,951 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check for baseline language coverage in the compiler for the specified
|
||||
# version of the C++ standard. If necessary, add switches to CXX and
|
||||
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||
# or '14' (for the C++14 standard).
|
||||
#
|
||||
# The second argument, if specified, indicates whether you insist on an
|
||||
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||
# -std=c++11). If neither is specified, you get whatever works, with
|
||||
# preference for an extended mode.
|
||||
#
|
||||
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||
# indicates that baseline support for the specified C++ standard is
|
||||
# required and that the macro should error out if no mode with that
|
||||
# support is found. If specified 'optional', then configuration proceeds
|
||||
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||
# supporting mode is found.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
|
||||
# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 11
|
||||
|
||||
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||
dnl (serial version number 13).
|
||||
|
||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||
m4_if([$2], [], [],
|
||||
[$2], [ext], [],
|
||||
[$2], [noext], [],
|
||||
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||
AC_LANG_PUSH([C++])dnl
|
||||
ac_success=no
|
||||
|
||||
m4_if([$2], [noext], [], [dnl
|
||||
if test x$ac_success = xno; then
|
||||
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||
switch="-std=gnu++${alternative}"
|
||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||
$cachevar,
|
||||
[ac_save_CXX="$CXX"
|
||||
CXX="$CXX $switch"
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||
[eval $cachevar=yes],
|
||||
[eval $cachevar=no])
|
||||
CXX="$ac_save_CXX"])
|
||||
if eval test x\$$cachevar = xyes; then
|
||||
CXX="$CXX $switch"
|
||||
if test -n "$CXXCPP" ; then
|
||||
CXXCPP="$CXXCPP $switch"
|
||||
fi
|
||||
ac_success=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi])
|
||||
|
||||
m4_if([$2], [ext], [], [dnl
|
||||
if test x$ac_success = xno; then
|
||||
dnl HP's aCC needs +std=c++11 according to:
|
||||
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||
dnl Cray's crayCC needs "-h std=c++11"
|
||||
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||
$cachevar,
|
||||
[ac_save_CXX="$CXX"
|
||||
CXX="$CXX $switch"
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||
[eval $cachevar=yes],
|
||||
[eval $cachevar=no])
|
||||
CXX="$ac_save_CXX"])
|
||||
if eval test x\$$cachevar = xyes; then
|
||||
CXX="$CXX $switch"
|
||||
if test -n "$CXXCPP" ; then
|
||||
CXXCPP="$CXXCPP $switch"
|
||||
fi
|
||||
ac_success=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test x$ac_success = xyes; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi])
|
||||
AC_LANG_POP([C++])
|
||||
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||
if test x$ac_success = xno; then
|
||||
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||
fi
|
||||
fi
|
||||
if test x$ac_success = xno; then
|
||||
HAVE_CXX$1=0
|
||||
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||
else
|
||||
HAVE_CXX$1=1
|
||||
AC_DEFINE(HAVE_CXX$1,1,
|
||||
[define if the compiler supports basic C++$1 syntax])
|
||||
fi
|
||||
AC_SUBST(HAVE_CXX$1)
|
||||
])
|
||||
|
||||
|
||||
dnl Test body for checking C++11 support
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
)
|
||||
|
||||
|
||||
dnl Test body for checking C++14 support
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||
)
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||
)
|
||||
|
||||
dnl Tests for new features in C++11
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||
|
||||
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||
// Hopefully, this will speed up the test.
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#error "This is not a C++ compiler"
|
||||
|
||||
#elif __cplusplus < 201103L
|
||||
|
||||
#error "This is not a C++11 compiler"
|
||||
|
||||
#else
|
||||
|
||||
namespace cxx11
|
||||
{
|
||||
|
||||
namespace test_static_assert
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct check
|
||||
{
|
||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_final_override
|
||||
{
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual ~Base() {}
|
||||
virtual void f() {}
|
||||
};
|
||||
|
||||
struct Derived : public Base
|
||||
{
|
||||
virtual ~Derived() override {}
|
||||
virtual void f() override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_double_right_angle_brackets
|
||||
{
|
||||
|
||||
template < typename T >
|
||||
struct check {};
|
||||
|
||||
typedef check<void> single_type;
|
||||
typedef check<check<void>> double_type;
|
||||
typedef check<check<check<void>>> triple_type;
|
||||
typedef check<check<check<check<void>>>> quadruple_type;
|
||||
|
||||
}
|
||||
|
||||
namespace test_decltype
|
||||
{
|
||||
|
||||
int
|
||||
f()
|
||||
{
|
||||
int a = 1;
|
||||
decltype(a) b = 2;
|
||||
return a + b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_type_deduction
|
||||
{
|
||||
|
||||
template < typename T1, typename T2 >
|
||||
struct is_same
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct is_same<T, T>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template < typename T1, typename T2 >
|
||||
auto
|
||||
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||
{
|
||||
return a1 + a2;
|
||||
}
|
||||
|
||||
int
|
||||
test(const int c, volatile int v)
|
||||
{
|
||||
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||
auto ac = c;
|
||||
auto av = v;
|
||||
auto sumi = ac + av + 'x';
|
||||
auto sumf = ac + av + 1.0;
|
||||
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||
return (sumf > 0.0) ? sumi : add(c, v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_noexcept
|
||||
{
|
||||
|
||||
int f() { return 0; }
|
||||
int g() noexcept { return 0; }
|
||||
|
||||
static_assert(noexcept(f()) == false, "");
|
||||
static_assert(noexcept(g()) == true, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_constexpr
|
||||
{
|
||||
|
||||
template < typename CharT >
|
||||
unsigned long constexpr
|
||||
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||
{
|
||||
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||
}
|
||||
|
||||
template < typename CharT >
|
||||
unsigned long constexpr
|
||||
strlen_c(const CharT *const s) noexcept
|
||||
{
|
||||
return strlen_c_r(s, 0UL);
|
||||
}
|
||||
|
||||
static_assert(strlen_c("") == 0UL, "");
|
||||
static_assert(strlen_c("1") == 1UL, "");
|
||||
static_assert(strlen_c("example") == 7UL, "");
|
||||
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_rvalue_references
|
||||
{
|
||||
|
||||
template < int N >
|
||||
struct answer
|
||||
{
|
||||
static constexpr int value = N;
|
||||
};
|
||||
|
||||
answer<1> f(int&) { return answer<1>(); }
|
||||
answer<2> f(const int&) { return answer<2>(); }
|
||||
answer<3> f(int&&) { return answer<3>(); }
|
||||
|
||||
void
|
||||
test()
|
||||
{
|
||||
int i = 0;
|
||||
const int c = 0;
|
||||
static_assert(decltype(f(i))::value == 1, "");
|
||||
static_assert(decltype(f(c))::value == 2, "");
|
||||
static_assert(decltype(f(0))::value == 3, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_uniform_initialization
|
||||
{
|
||||
|
||||
struct test
|
||||
{
|
||||
static const int zero {};
|
||||
static const int one {1};
|
||||
};
|
||||
|
||||
static_assert(test::zero == 0, "");
|
||||
static_assert(test::one == 1, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_lambdas
|
||||
{
|
||||
|
||||
void
|
||||
test1()
|
||||
{
|
||||
auto lambda1 = [](){};
|
||||
auto lambda2 = lambda1;
|
||||
lambda1();
|
||||
lambda2();
|
||||
}
|
||||
|
||||
int
|
||||
test2()
|
||||
{
|
||||
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||
auto b = []() -> int { return '0'; }();
|
||||
auto c = [=](){ return a + b; }();
|
||||
auto d = [&](){ return c; }();
|
||||
auto e = [a, &b](int x) mutable {
|
||||
const auto identity = [](int y){ return y; };
|
||||
for (auto i = 0; i < a; ++i)
|
||||
a += b--;
|
||||
return x + identity(a + b);
|
||||
}(0);
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
|
||||
int
|
||||
test3()
|
||||
{
|
||||
const auto nullary = [](){ return 0; };
|
||||
const auto unary = [](int x){ return x; };
|
||||
using nullary_t = decltype(nullary);
|
||||
using unary_t = decltype(unary);
|
||||
const auto higher1st = [](nullary_t f){ return f(); };
|
||||
const auto higher2nd = [unary](nullary_t f1){
|
||||
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||
};
|
||||
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_variadic_templates
|
||||
{
|
||||
|
||||
template <int...>
|
||||
struct sum;
|
||||
|
||||
template <int N0, int... N1toN>
|
||||
struct sum<N0, N1toN...>
|
||||
{
|
||||
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct sum<>
|
||||
{
|
||||
static constexpr auto value = 0;
|
||||
};
|
||||
|
||||
static_assert(sum<>::value == 0, "");
|
||||
static_assert(sum<1>::value == 1, "");
|
||||
static_assert(sum<23>::value == 23, "");
|
||||
static_assert(sum<1, 2>::value == 3, "");
|
||||
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||
// because of this.
|
||||
namespace test_template_alias_sfinae
|
||||
{
|
||||
|
||||
struct foo {};
|
||||
|
||||
template<typename T>
|
||||
using member = typename T::member_type;
|
||||
|
||||
template<typename T>
|
||||
void func(...) {}
|
||||
|
||||
template<typename T>
|
||||
void func(member<T>*) {}
|
||||
|
||||
void test();
|
||||
|
||||
void test() { func<foo>(0); }
|
||||
|
||||
}
|
||||
|
||||
} // namespace cxx11
|
||||
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
]])
|
||||
|
||||
|
||||
dnl Tests for new features in C++14
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||
|
||||
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||
// Hopefully, this will speed up the test.
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#error "This is not a C++ compiler"
|
||||
|
||||
#elif __cplusplus < 201402L
|
||||
|
||||
#error "This is not a C++14 compiler"
|
||||
|
||||
#else
|
||||
|
||||
namespace cxx14
|
||||
{
|
||||
|
||||
namespace test_polymorphic_lambdas
|
||||
{
|
||||
|
||||
int
|
||||
test()
|
||||
{
|
||||
const auto lambda = [](auto&&... args){
|
||||
const auto istiny = [](auto x){
|
||||
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||
};
|
||||
const int aretiny[] = { istiny(args)... };
|
||||
return aretiny[0];
|
||||
};
|
||||
return lambda(1, 1L, 1.0f, '1');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_binary_literals
|
||||
{
|
||||
|
||||
constexpr auto ivii = 0b0000000000101010;
|
||||
static_assert(ivii == 42, "wrong value");
|
||||
|
||||
}
|
||||
|
||||
namespace test_generalized_constexpr
|
||||
{
|
||||
|
||||
template < typename CharT >
|
||||
constexpr unsigned long
|
||||
strlen_c(const CharT *const s) noexcept
|
||||
{
|
||||
auto length = 0UL;
|
||||
for (auto p = s; *p; ++p)
|
||||
++length;
|
||||
return length;
|
||||
}
|
||||
|
||||
static_assert(strlen_c("") == 0UL, "");
|
||||
static_assert(strlen_c("x") == 1UL, "");
|
||||
static_assert(strlen_c("test") == 4UL, "");
|
||||
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_lambda_init_capture
|
||||
{
|
||||
|
||||
int
|
||||
test()
|
||||
{
|
||||
auto x = 0;
|
||||
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||
return lambda2();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_digit_separators
|
||||
{
|
||||
|
||||
constexpr auto ten_million = 100'000'000;
|
||||
static_assert(ten_million == 100000000, "");
|
||||
|
||||
}
|
||||
|
||||
namespace test_return_type_deduction
|
||||
{
|
||||
|
||||
auto f(int& x) { return x; }
|
||||
decltype(auto) g(int& x) { return x; }
|
||||
|
||||
template < typename T1, typename T2 >
|
||||
struct is_same
|
||||
{
|
||||
static constexpr auto value = false;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct is_same<T, T>
|
||||
{
|
||||
static constexpr auto value = true;
|
||||
};
|
||||
|
||||
int
|
||||
test()
|
||||
{
|
||||
auto x = 0;
|
||||
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||
return x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace cxx14
|
||||
|
||||
#endif // __cplusplus >= 201402L
|
||||
|
||||
]])
|
||||
|
||||
|
||||
dnl Tests for new features in C++17
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
||||
|
||||
// If the compiler admits that it is not ready for C++17, why torture it?
|
||||
// Hopefully, this will speed up the test.
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#error "This is not a C++ compiler"
|
||||
|
||||
#elif __cplusplus < 201703L
|
||||
|
||||
#error "This is not a C++17 compiler"
|
||||
|
||||
#else
|
||||
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
namespace cxx17
|
||||
{
|
||||
|
||||
namespace test_constexpr_lambdas
|
||||
{
|
||||
|
||||
constexpr int foo = [](){return 42;}();
|
||||
|
||||
}
|
||||
|
||||
namespace test::nested_namespace::definitions
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace test_fold_expression
|
||||
{
|
||||
|
||||
template<typename... Args>
|
||||
int multiply(Args... args)
|
||||
{
|
||||
return (args * ... * 1);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
bool all(Args... args)
|
||||
{
|
||||
return (args && ...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_extended_static_assert
|
||||
{
|
||||
|
||||
static_assert (true);
|
||||
|
||||
}
|
||||
|
||||
namespace test_auto_brace_init_list
|
||||
{
|
||||
|
||||
auto foo = {5};
|
||||
auto bar {5};
|
||||
|
||||
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
|
||||
static_assert(std::is_same<int, decltype(bar)>::value);
|
||||
}
|
||||
|
||||
namespace test_typename_in_template_template_parameter
|
||||
{
|
||||
|
||||
template<template<typename> typename X> struct D;
|
||||
|
||||
}
|
||||
|
||||
namespace test_fallthrough_nodiscard_maybe_unused_attributes
|
||||
{
|
||||
|
||||
int f1()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
[[nodiscard]] int f2()
|
||||
{
|
||||
[[maybe_unused]] auto unused = f1();
|
||||
|
||||
switch (f1())
|
||||
{
|
||||
case 17:
|
||||
f1();
|
||||
[[fallthrough]];
|
||||
case 42:
|
||||
f1();
|
||||
}
|
||||
return f1();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_extended_aggregate_initialization
|
||||
{
|
||||
|
||||
struct base1
|
||||
{
|
||||
int b1, b2 = 42;
|
||||
};
|
||||
|
||||
struct base2
|
||||
{
|
||||
base2() {
|
||||
b3 = 42;
|
||||
}
|
||||
int b3;
|
||||
};
|
||||
|
||||
struct derived : base1, base2
|
||||
{
|
||||
int d;
|
||||
};
|
||||
|
||||
derived d1 {{1, 2}, {}, 4}; // full initialization
|
||||
derived d2 {{}, {}, 4}; // value-initialized bases
|
||||
|
||||
}
|
||||
|
||||
namespace test_general_range_based_for_loop
|
||||
{
|
||||
|
||||
struct iter
|
||||
{
|
||||
int i;
|
||||
|
||||
int& operator* ()
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
const int& operator* () const
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
iter& operator++()
|
||||
{
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct sentinel
|
||||
{
|
||||
int i;
|
||||
};
|
||||
|
||||
bool operator== (const iter& i, const sentinel& s)
|
||||
{
|
||||
return i.i == s.i;
|
||||
}
|
||||
|
||||
bool operator!= (const iter& i, const sentinel& s)
|
||||
{
|
||||
return !(i == s);
|
||||
}
|
||||
|
||||
struct range
|
||||
{
|
||||
iter begin() const
|
||||
{
|
||||
return {0};
|
||||
}
|
||||
|
||||
sentinel end() const
|
||||
{
|
||||
return {5};
|
||||
}
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
range r {};
|
||||
|
||||
for (auto i : r)
|
||||
{
|
||||
[[maybe_unused]] auto v = i;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_lambda_capture_asterisk_this_by_value
|
||||
{
|
||||
|
||||
struct t
|
||||
{
|
||||
int i;
|
||||
int foo()
|
||||
{
|
||||
return [*this]()
|
||||
{
|
||||
return i;
|
||||
}();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace test_enum_class_construction
|
||||
{
|
||||
|
||||
enum class byte : unsigned char
|
||||
{};
|
||||
|
||||
byte foo {42};
|
||||
|
||||
}
|
||||
|
||||
namespace test_constexpr_if
|
||||
{
|
||||
|
||||
template <bool cond>
|
||||
int f ()
|
||||
{
|
||||
if constexpr(cond)
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_selection_statement_with_initializer
|
||||
{
|
||||
|
||||
int f()
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
|
||||
int f2()
|
||||
{
|
||||
if (auto i = f(); i > 0)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
switch (auto i = f(); i + 4)
|
||||
{
|
||||
case 17:
|
||||
return 2;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_template_argument_deduction_for_class_templates
|
||||
{
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct pair
|
||||
{
|
||||
pair (T1 p1, T2 p2)
|
||||
: m1 {p1},
|
||||
m2 {p2}
|
||||
{}
|
||||
|
||||
T1 m1;
|
||||
T2 m2;
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
[[maybe_unused]] auto p = pair{13, 42u};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test_non_type_auto_template_parameters
|
||||
{
|
||||
|
||||
template <auto n>
|
||||
struct B
|
||||
{};
|
||||
|
||||
B<5> b1;
|
||||
B<'a'> b2;
|
||||
|
||||
}
|
||||
|
||||
namespace test_structured_bindings
|
||||
{
|
||||
|
||||
int arr[2] = { 1, 2 };
|
||||
std::pair<int, int> pr = { 1, 2 };
|
||||
|
||||
auto f1() -> int(&)[2]
|
||||
{
|
||||
return arr;
|
||||
}
|
||||
|
||||
auto f2() -> std::pair<int, int>&
|
||||
{
|
||||
return pr;
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
int x1 : 2;
|
||||
volatile double y1;
|
||||
};
|
||||
|
||||
S f3()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto [ x1, y1 ] = f1();
|
||||
auto& [ xr1, yr1 ] = f1();
|
||||
auto [ x2, y2 ] = f2();
|
||||
auto& [ xr2, yr2 ] = f2();
|
||||
const auto [ x3, y3 ] = f3();
|
||||
|
||||
}
|
||||
|
||||
namespace test_exception_spec_type_system
|
||||
{
|
||||
|
||||
struct Good {};
|
||||
struct Bad {};
|
||||
|
||||
void g1() noexcept;
|
||||
void g2();
|
||||
|
||||
template<typename T>
|
||||
Bad
|
||||
f(T*, T*);
|
||||
|
||||
template<typename T1, typename T2>
|
||||
Good
|
||||
f(T1*, T2*);
|
||||
|
||||
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
|
||||
|
||||
}
|
||||
|
||||
namespace test_inline_variables
|
||||
{
|
||||
|
||||
template<class T> void f(T)
|
||||
{}
|
||||
|
||||
template<class T> inline T g(T)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
|
||||
template<> inline void f<>(int)
|
||||
{}
|
||||
|
||||
template<> int g<>(int)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace cxx17
|
||||
|
||||
#endif // __cplusplus < 201703L
|
||||
|
||||
]])
|
|
@ -0,0 +1,35 @@
|
|||
# =============================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html
|
||||
# =============================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check for baseline language coverage in the compiler for the C++17
|
||||
# standard; if necessary, add switches to CXX and CXXCPP to enable
|
||||
# support.
|
||||
#
|
||||
# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
|
||||
# macro with the version set to C++17. The two optional arguments are
|
||||
# forwarded literally as the second and third argument respectively.
|
||||
# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
|
||||
# more information. If you want to use this macro, you also need to
|
||||
# download the ax_cxx_compile_stdcxx.m4 file.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||
# Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 2
|
||||
|
||||
AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
|
||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])])
|
|
@ -6,6 +6,7 @@ use Data::Dumper;
|
|||
use File::Basename;
|
||||
use File::Path;
|
||||
use File::Slurp;
|
||||
use File::Copy;
|
||||
use JSON::PP;
|
||||
use LWP::UserAgent;
|
||||
|
||||
|
@ -43,7 +44,7 @@ print STDERR "Nix revision is $nixRev, version is $version\n";
|
|||
|
||||
File::Path::make_path($releasesDir);
|
||||
if (system("mountpoint -q $releasesDir") != 0) {
|
||||
system("sshfs hydra-mirror:/releases $releasesDir") == 0 or die;
|
||||
system("sshfs hydra-mirror\@nixos.org:/releases $releasesDir") == 0 or die;
|
||||
}
|
||||
|
||||
my $releaseDir = "$releasesDir/nix/$releaseName";
|
||||
|
@ -54,7 +55,7 @@ sub downloadFile {
|
|||
|
||||
my $buildInfo = decode_json(fetch("$evalUrl/job/$jobName", 'application/json'));
|
||||
|
||||
my $srcFile = $buildInfo->{buildproducts}->{$productNr}->{path} or die;
|
||||
my $srcFile = $buildInfo->{buildproducts}->{$productNr}->{path} or die "job '$jobName' lacks product $productNr\n";
|
||||
$dstName //= basename($srcFile);
|
||||
my $dstFile = "$releaseDir/" . $dstName;
|
||||
|
||||
|
@ -66,25 +67,31 @@ sub downloadFile {
|
|||
}
|
||||
|
||||
my $sha256_expected = $buildInfo->{buildproducts}->{$productNr}->{sha256hash} or die;
|
||||
my $sha256_actual = `nix hash-file --type sha256 '$dstFile'`;
|
||||
my $sha256_actual = `nix hash-file --base16 --type sha256 '$dstFile'`;
|
||||
chomp $sha256_actual;
|
||||
if ($sha256_expected ne $sha256_actual) {
|
||||
print STDERR "file $dstFile is corrupt\n";
|
||||
print STDERR "file $dstFile is corrupt, got $sha256_actual, expected $sha256_expected\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
write_file("$dstFile.sha256", $sha256_expected);
|
||||
|
||||
if (! -e "$dstFile.asc") {
|
||||
system("gpg2 --detach-sign --armor $dstFile") == 0 or die "unable to sign $dstFile\n";
|
||||
}
|
||||
|
||||
return ($dstFile, $sha256_expected);
|
||||
}
|
||||
|
||||
downloadFile("tarball", "2"); # PDF
|
||||
downloadFile("tarball", "3"); # .tar.bz2
|
||||
my ($tarball, $tarballHash) = downloadFile("tarball", "4"); # .tar.xz
|
||||
my ($tarball_i686_linux, $tarball_i686_linux_hash) = downloadFile("binaryTarball.i686-linux", "1");
|
||||
my ($tarball_x86_64_linux, $tarball_x86_64_linux_hash) = downloadFile("binaryTarball.x86_64-linux", "1");
|
||||
my ($tarball_aarch64_linux, $tarball_aarch64_linux_hash) = downloadFile("binaryTarball.aarch64-linux", "1");
|
||||
my ($tarball_x86_64_darwin, $tarball_x86_64_darwin_hash) = downloadFile("binaryTarball.x86_64-darwin", "1");
|
||||
downloadFile("tarball", "2"); # .tar.bz2
|
||||
my ($tarball, $tarballHash) = downloadFile("tarball", "3"); # .tar.xz
|
||||
downloadFile("binaryTarball.i686-linux", "1");
|
||||
downloadFile("binaryTarball.x86_64-linux", "1");
|
||||
downloadFile("binaryTarball.aarch64-linux", "1");
|
||||
downloadFile("binaryTarball.x86_64-darwin", "1");
|
||||
downloadFile("installerScript", "1");
|
||||
|
||||
exit if $version =~ /pre/;
|
||||
|
||||
# Update Nixpkgs in a very hacky way.
|
||||
system("cd $nixpkgsDir && git pull") == 0 or die;
|
||||
|
@ -144,12 +151,6 @@ system("cd $siteDir && git pull") == 0 or die;
|
|||
write_file("$siteDir/nix-release.tt",
|
||||
"[%-\n" .
|
||||
"latestNixVersion = \"$version\"\n" .
|
||||
"nix_hash_i686_linux = \"$tarball_i686_linux_hash\"\n" .
|
||||
"nix_hash_x86_64_linux = \"$tarball_x86_64_linux_hash\"\n" .
|
||||
"nix_hash_aarch64_linux = \"$tarball_aarch64_linux_hash\"\n" .
|
||||
"nix_hash_x86_64_darwin = \"$tarball_x86_64_darwin_hash\"\n" .
|
||||
"-%]\n");
|
||||
|
||||
system("cd $siteDir && nix-shell --run 'make nix/install nix/install.sig'") == 0 or die;
|
||||
|
||||
system("cd $siteDir && git commit -a -m 'Nix $version released'") == 0 or die;
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
FROM alpine
|
||||
|
||||
# Enable HTTPS support in wget.
|
||||
RUN apk add --update openssl
|
||||
|
||||
# Download Nix and install it into the system.
|
||||
RUN wget -O- https://nixos.org/releases/nix/nix-1.11.14/nix-1.11.14-x86_64-linux.tar.bz2 | bzcat - | tar xf - \
|
||||
&& addgroup -g 30000 -S nixbld \
|
||||
&& for i in $(seq 1 30); do adduser -S -D -h /var/empty -g "Nix build user $i" -u $((30000 + i)) -G nixbld nixbld$i ; done \
|
||||
&& mkdir -m 0755 /nix && USER=root sh nix-*-x86_64-linux/install \
|
||||
&& ln -s /nix/var/nix/profiles/default/etc/profile.d/nix.sh /etc/profile.d/ \
|
||||
&& rm -r /nix-*-x86_64-linux \
|
||||
&& rm -r /var/cache/apk/*
|
||||
|
||||
ONBUILD ENV \
|
||||
ENV=/etc/profile \
|
||||
PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
|
||||
|
||||
ENV \
|
||||
ENV=/etc/profile \
|
||||
PATH=/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:/bin:/sbin:/usr/bin:/usr/sbin \
|
||||
GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt \
|
||||
NIX_PATH=/nix/var/nix/profiles/per-user/root/channels
|
|
@ -2,12 +2,23 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>OBJC_DISABLE_INITIALIZE_FORK_SAFETY</key>
|
||||
<string>YES</string>
|
||||
</dict>
|
||||
<key>Label</key>
|
||||
<string>org.nixos.nix-daemon</string>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>Program</key>
|
||||
<string>@bindir@/nix-daemon</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>/bin/wait4path @bindir@/nix-daemon && @bindir@/nix-daemon</string>
|
||||
</array>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/var/log/nix-daemon.log</string>
|
||||
<key>StandardOutPath</key>
|
||||
|
|
|
@ -7,3 +7,6 @@ ConditionPathIsReadWrite=@localstatedir@/nix/daemon-socket
|
|||
[Service]
|
||||
ExecStart=@@bindir@/nix-daemon nix-daemon --daemon
|
||||
KillMode=process
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
@ -91,7 +91,7 @@ define build-library
|
|||
$(1)_PATH := $$(_d)/$$($(1)_NAME).$(SO_EXT)
|
||||
|
||||
$$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/
|
||||
$$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED)
|
||||
$$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED)
|
||||
|
||||
ifneq ($(OS), Darwin)
|
||||
$(1)_LDFLAGS_USE += -Wl,-rpath,$$(abspath $$(_d))
|
||||
|
@ -105,7 +105,7 @@ define build-library
|
|||
$$(eval $$(call create-dir, $$($(1)_INSTALL_DIR)))
|
||||
|
||||
$$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/
|
||||
$$(trace-ld) $(CXX) -o $$@ -shared $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED))
|
||||
$$(trace-ld) $(CXX) -o $$@ -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED))
|
||||
|
||||
$(1)_LDFLAGS_USE_INSTALLED += -L$$(DESTDIR)$$($(1)_INSTALL_DIR) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME)))
|
||||
ifneq ($(OS), Darwin)
|
||||
|
@ -125,7 +125,7 @@ define build-library
|
|||
$(1)_PATH := $$(_d)/$$($(1)_NAME).a
|
||||
|
||||
$$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/
|
||||
$(trace-ar) ar crs $$@ $$?
|
||||
$(trace-ar) $(AR) crs $$@ $$?
|
||||
|
||||
$(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS)
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ define build-program
|
|||
$$(eval $$(call create-dir, $$(_d)))
|
||||
|
||||
$$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/
|
||||
$$(trace-ld) $(CXX) -o $$@ $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE))
|
||||
$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE))
|
||||
|
||||
$(1)_INSTALL_DIR ?= $$(bindir)
|
||||
$(1)_INSTALL_PATH := $$($(1)_INSTALL_DIR)/$(1)
|
||||
|
@ -46,12 +46,12 @@ define build-program
|
|||
_libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH))
|
||||
|
||||
$(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/
|
||||
$$(trace-ld) $(CXX) -o $$@ $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED))
|
||||
$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED))
|
||||
|
||||
else
|
||||
|
||||
$(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_PATH) | $(DESTDIR)$$($(1)_INSTALL_DIR)/
|
||||
install -t $$($(1)_INSTALL_DIR) $$<
|
||||
install -t $(DESTDIR)$$($(1)_INSTALL_DIR) $$<
|
||||
|
||||
endif
|
||||
|
||||
|
|
71
nix.spec.in
71
nix.spec.in
|
@ -3,31 +3,47 @@
|
|||
%global nixbld_user "nix-builder-"
|
||||
%global nixbld_group "nixbld"
|
||||
|
||||
# NOTE: BUILD on EL7 requires
|
||||
# - Centos / RHEL7 software collection repository
|
||||
# yum install centos-release-scl
|
||||
#
|
||||
# - Recent boost backport
|
||||
# curl https://copr.fedorainfracloud.org/coprs/whosthere/boost/repo/epel-7/whosthere-boost-epel-7.repo -o /etc/yum.repos.d/whosthere-boost-epel-7.repo
|
||||
#
|
||||
|
||||
# Disable documentation generation
|
||||
# necessary on some platforms
|
||||
%bcond_without docgen
|
||||
|
||||
Summary: The Nix software deployment system
|
||||
Name: nix
|
||||
Version: @PACKAGE_VERSION@
|
||||
Release: 2%{?dist}
|
||||
License: LGPLv2+
|
||||
%if 0%{?rhel} && 0%{?rhel} < 7
|
||||
Group: Applications/System
|
||||
%endif
|
||||
URL: http://nixos.org/
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
%if 0%{?el5}
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
%endif
|
||||
|
||||
Requires: curl
|
||||
Requires: bzip2
|
||||
Requires: gzip
|
||||
Requires: xz
|
||||
Requires: libseccomp
|
||||
BuildRequires: bison
|
||||
BuildRequires: boost-devel >= 1.60
|
||||
BuildRequires: bzip2-devel
|
||||
BuildRequires: sqlite-devel
|
||||
|
||||
# for RHEL <= 7, we need software collections for a C++14 compatible compatible compiler
|
||||
%if 0%{?rhel}
|
||||
BuildRequires: devtoolset-7-gcc
|
||||
BuildRequires: devtoolset-7-gcc-c++
|
||||
%endif
|
||||
|
||||
BuildRequires: flex
|
||||
BuildRequires: libcurl-devel
|
||||
BuildRequires: libseccomp-devel
|
||||
|
||||
# Hack to make that shitty RPM scanning hack shut up.
|
||||
Provides: perl(Nix::SSH)
|
||||
BuildRequires: openssl-devel
|
||||
BuildRequires: sqlite-devel
|
||||
BuildRequires: xz-devel
|
||||
|
||||
%description
|
||||
Nix is a purely functional package manager. It allows multiple
|
||||
|
@ -39,9 +55,6 @@ it can be used equally well under other Unix systems.
|
|||
|
||||
%package devel
|
||||
Summary: Development files for %{name}
|
||||
%if 0%{?rhel} && 0%{?rhel} < 7
|
||||
Group: Development/Libraries
|
||||
%endif
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
|
||||
%description devel
|
||||
|
@ -51,9 +64,6 @@ developing applications that use %{name}.
|
|||
|
||||
%package doc
|
||||
Summary: Documentation files for %{name}
|
||||
%if 0%{?rhel} && 0%{?rhel} < 7
|
||||
Group: Documentation
|
||||
%endif
|
||||
BuildArch: noarch
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
|
@ -65,20 +75,25 @@ The %{name}-doc package contains documentation files for %{name}.
|
|||
|
||||
|
||||
%build
|
||||
%if 0%{?rhel}
|
||||
source /opt/rh/devtoolset-7/enable
|
||||
%endif
|
||||
extraFlags=
|
||||
# - override docdir so large documentation files are owned by the
|
||||
# -doc subpackage
|
||||
# - set localstatedir by hand to the preferred nix value
|
||||
%configure --localstatedir=/nix/var \
|
||||
%{!?without_docgen:--disable-doc-gen} \
|
||||
--docdir=%{_defaultdocdir}/%{name}-doc-%{version} \
|
||||
$extraFlags
|
||||
make -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
|
||||
make V=1 %{?_smp_mflags}
|
||||
|
||||
|
||||
%install
|
||||
%if 0%{?el5}
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
%if 0%{?rhel}
|
||||
source /opt/rh/devtoolset-7/enable
|
||||
%endif
|
||||
|
||||
make DESTDIR=$RPM_BUILD_ROOT install
|
||||
|
||||
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
|
||||
|
@ -128,6 +143,7 @@ systemctl start nix-daemon.socket
|
|||
%endif
|
||||
|
||||
%files
|
||||
%license COPYING
|
||||
%{_bindir}/nix*
|
||||
%{_libdir}/*.so
|
||||
%{_prefix}/libexec/*
|
||||
|
@ -136,9 +152,11 @@ systemctl start nix-daemon.socket
|
|||
%{_prefix}/lib/systemd/system/nix-daemon.service
|
||||
%endif
|
||||
%{_datadir}/nix
|
||||
%{_mandir}/man1/*.1*
|
||||
%{_mandir}/man5/*.5*
|
||||
%{_mandir}/man8/*.8*
|
||||
#%if ! %{without docgen}
|
||||
#%{_mandir}/man1/*.1*
|
||||
#%{_mandir}/man5/*.5*
|
||||
#%{_mandir}/man8/*.8*
|
||||
#%endif
|
||||
%config(noreplace) %{_sysconfdir}/profile.d/nix.sh
|
||||
%config(noreplace) %{_sysconfdir}/profile.d/nix-daemon.sh
|
||||
/nix
|
||||
|
@ -147,6 +165,9 @@ systemctl start nix-daemon.socket
|
|||
%{_includedir}/nix
|
||||
%{_prefix}/lib/pkgconfig/*.pc
|
||||
|
||||
%files doc
|
||||
%docdir %{_defaultdocdir}/%{name}-doc-%{version}
|
||||
%{_defaultdocdir}/%{name}-doc-%{version}
|
||||
|
||||
#%if ! %{without docgen}
|
||||
#%files doc
|
||||
#%docdir %{_defaultdocdir}/%{name}-doc-%{version}
|
||||
#%{_defaultdocdir}/%{name}-doc-%{version}
|
||||
#%endif
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
makefiles = local.mk
|
||||
|
||||
GLOBAL_CXXFLAGS += -std=c++14 -g -Wall
|
||||
GLOBAL_CXXFLAGS += -g -Wall
|
||||
|
||||
-include Makefile.config
|
||||
|
||||
OPTIMIZE = 1
|
||||
|
||||
ifeq ($(OPTIMIZE), 1)
|
||||
GLOBAL_CFLAGS += -O3
|
||||
GLOBAL_CXXFLAGS += -O3
|
||||
endif
|
||||
|
||||
include mk/lib.mk
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
AC_INIT(nix-perl, m4_esyscmd([bash -c "echo -n $(cat ../version)$VERSION_SUFFIX"]))
|
||||
AC_INIT(nix-perl, m4_esyscmd([bash -c "echo -n $(cat ../.version)$VERSION_SUFFIX"]))
|
||||
AC_CONFIG_SRCDIR(MANIFEST)
|
||||
AC_CONFIG_AUX_DIR(../config)
|
||||
|
||||
CFLAGS=
|
||||
CXXFLAGS=
|
||||
# Set default flags for nix (as per AC_PROG_CC/CXX docs),
|
||||
# while still allowing the user to override them from the command line.
|
||||
: ${CFLAGS="-O3"}
|
||||
: ${CXXFLAGS="-O3"}
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AX_CXX_COMPILE_STDCXX_11
|
||||
|
|
|
@ -27,7 +27,7 @@ static ref<Store> store()
|
|||
static std::shared_ptr<Store> _store;
|
||||
if (!_store) {
|
||||
try {
|
||||
settings.loadConfFile();
|
||||
loadConfFile();
|
||||
settings.lockCPU = false;
|
||||
_store = openStore();
|
||||
} catch (Error & e) {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
{ pkgs }:
|
||||
|
||||
with pkgs;
|
||||
|
||||
rec {
|
||||
# Use "busybox-sandbox-shell" if present,
|
||||
# if not (legacy) fallback and hope it's sufficient.
|
||||
sh = pkgs.busybox-sandbox-shell or (pkgs.busybox.override {
|
||||
sh = pkgs.busybox-sandbox-shell or (busybox.override {
|
||||
useMusl = true;
|
||||
enableStatic = true;
|
||||
enableMinimal = true;
|
||||
|
@ -28,9 +30,50 @@ rec {
|
|||
});
|
||||
|
||||
configureFlags =
|
||||
[ "--disable-init-state"
|
||||
[
|
||||
"--enable-gc"
|
||||
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
|
||||
] ++ lib.optionals stdenv.isLinux [
|
||||
"--with-sandbox-shell=${sh}/bin/busybox"
|
||||
];
|
||||
|
||||
tarballDeps =
|
||||
[ bison
|
||||
flex
|
||||
libxml2
|
||||
libxslt
|
||||
docbook5
|
||||
docbook_xsl_ns
|
||||
autoconf-archive
|
||||
autoreconfHook
|
||||
];
|
||||
|
||||
buildDeps =
|
||||
[ curl
|
||||
bzip2 xz brotli editline
|
||||
openssl pkgconfig sqlite boehmgc
|
||||
boost
|
||||
|
||||
# Tests
|
||||
git
|
||||
mercurial
|
||||
]
|
||||
++ lib.optionals stdenv.isLinux [libseccomp utillinuxMinimal]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
|
||||
((aws-sdk-cpp.override {
|
||||
apis = ["s3" "transfer"];
|
||||
customMemoryManagement = false;
|
||||
}).overrideDerivation (args: {
|
||||
/*
|
||||
patches = args.patches or [] ++ [ (fetchpatch {
|
||||
url = https://github.com/edolstra/aws-sdk-cpp/commit/3e07e1f1aae41b4c8b340735ff9e8c735f0c063f.patch;
|
||||
sha256 = "1pij0v449p166f9l29x7ppzk8j7g9k9mp15ilh5qxp29c7fnvxy2";
|
||||
}) ];
|
||||
*/
|
||||
}));
|
||||
|
||||
perlDeps =
|
||||
[ perl
|
||||
perlPackages.DBDSQLite
|
||||
];
|
||||
}
|
||||
|
|
174
release.nix
174
release.nix
|
@ -1,5 +1,5 @@
|
|||
{ nix ? builtins.fetchGit ./.
|
||||
, nixpkgs ? builtins.fetchGit { url = https://github.com/NixOS/nixpkgs.git; ref = "nix-2.0"; }
|
||||
, nixpkgs ? builtins.fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-19.03.tar.gz
|
||||
, officialRelease ? false
|
||||
, systems ? [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ]
|
||||
}:
|
||||
|
@ -14,26 +14,22 @@ let
|
|||
tarball =
|
||||
with pkgs;
|
||||
|
||||
with import ./release-common.nix { inherit pkgs; };
|
||||
|
||||
releaseTools.sourceTarball {
|
||||
name = "nix-tarball";
|
||||
version = builtins.readFile ./version;
|
||||
version = builtins.readFile ./.version;
|
||||
versionSuffix = if officialRelease then "" else "pre${toString nix.revCount}_${nix.shortRev}";
|
||||
src = nix;
|
||||
inherit officialRelease;
|
||||
|
||||
buildInputs =
|
||||
[ curl bison flex libxml2 libxslt
|
||||
bzip2 xz brotli
|
||||
pkgconfig sqlite libsodium boehmgc
|
||||
docbook5 docbook5_xsl
|
||||
autoconf-archive
|
||||
] ++ lib.optional stdenv.isLinux libseccomp;
|
||||
buildInputs = tarballDeps ++ buildDeps;
|
||||
|
||||
configureFlags = "--enable-gc";
|
||||
|
||||
postUnpack = ''
|
||||
(cd source && find . -type f) | cut -c3- > source/.dist-files
|
||||
cat source/.dist-files
|
||||
(cd $sourceRoot && find . -type f) | cut -c3- > $sourceRoot/.dist-files
|
||||
cat $sourceRoot/.dist-files
|
||||
'';
|
||||
|
||||
preConfigure = ''
|
||||
|
@ -59,7 +55,9 @@ let
|
|||
|
||||
build = pkgs.lib.genAttrs systems (system:
|
||||
|
||||
with import nixpkgs { inherit system; };
|
||||
let pkgs = import nixpkgs { inherit system; }; in
|
||||
|
||||
with pkgs;
|
||||
|
||||
with import ./release-common.nix { inherit pkgs; };
|
||||
|
||||
|
@ -67,22 +65,20 @@ let
|
|||
name = "nix";
|
||||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ curl
|
||||
bzip2 xz brotli
|
||||
openssl pkgconfig sqlite boehmgc
|
||||
buildInputs = buildDeps;
|
||||
|
||||
# Tests
|
||||
git
|
||||
mercurial
|
||||
]
|
||||
++ lib.optional stdenv.isLinux libseccomp
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin)
|
||||
(aws-sdk-cpp.override {
|
||||
apis = ["s3"];
|
||||
customMemoryManagement = false;
|
||||
});
|
||||
preConfigure =
|
||||
# Copy libboost_context so we don't get all of Boost in our closure.
|
||||
# https://github.com/NixOS/nixpkgs/issues/45462
|
||||
''
|
||||
mkdir -p $out/lib
|
||||
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
|
||||
rm -f $out/lib/*.a
|
||||
${lib.optionalString stdenv.isLinux ''
|
||||
chmod u+w $out/lib/*.so.*
|
||||
patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
|
||||
''}
|
||||
'';
|
||||
|
||||
configureFlags = configureFlags ++
|
||||
[ "--sysconfdir=/etc" ];
|
||||
|
@ -91,8 +87,6 @@ let
|
|||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d";
|
||||
|
||||
preBuild = "unset NIX_INDENT_MAKE";
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
doInstallCheck = true;
|
||||
|
@ -109,7 +103,7 @@ let
|
|||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ (builtins.getAttr system jobs.build) curl bzip2 xz pkgconfig pkgs.perl ]
|
||||
[ jobs.build.${system} curl bzip2 xz pkgconfig pkgs.perl boost ]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium;
|
||||
|
||||
configureFlags = ''
|
||||
|
@ -120,8 +114,6 @@ let
|
|||
enableParallelBuilding = true;
|
||||
|
||||
postUnpack = "sourceRoot=$sourceRoot/perl";
|
||||
|
||||
preBuild = "unset NIX_INDENT_MAKE";
|
||||
});
|
||||
|
||||
|
||||
|
@ -132,61 +124,79 @@ let
|
|||
let
|
||||
toplevel = builtins.getAttr system jobs.build;
|
||||
version = toplevel.src.version;
|
||||
installerClosureInfo = closureInfo { rootPaths = [ toplevel cacert ]; };
|
||||
in
|
||||
|
||||
runCommand "nix-binary-tarball-${version}"
|
||||
{ exportReferencesGraph = [ "closure1" toplevel "closure2" cacert ];
|
||||
buildInputs = [ perl ] ++ lib.optional (system != "aarch64-linux") shellcheck;
|
||||
{ nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${system}";
|
||||
}
|
||||
''
|
||||
storePaths=$(perl ${pathsFromGraph} ./closure1 ./closure2)
|
||||
printRegistration=1 perl ${pathsFromGraph} ./closure1 ./closure2 > $TMPDIR/reginfo
|
||||
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
||||
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
|
||||
--subst-var-by nix ${toplevel} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user \
|
||||
|
||||
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \
|
||||
--subst-var-by nix ${toplevel} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-systemd-multi-user.sh} $TMPDIR/install-systemd-multi-user.sh \
|
||||
--subst-var-by nix ${toplevel} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-multi-user.sh} $TMPDIR/install-multi-user \
|
||||
--subst-var-by nix ${toplevel} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
|
||||
if type -p shellcheck; then
|
||||
shellcheck -e SC1090 $TMPDIR/install
|
||||
shellcheck -e SC1091,SC2002 $TMPDIR/install-darwin-multi-user
|
||||
# SC1090: Don't worry about not being able to find
|
||||
# $nix/etc/profile.d/nix.sh
|
||||
shellcheck --exclude SC1090 $TMPDIR/install
|
||||
shellcheck $TMPDIR/install-darwin-multi-user.sh
|
||||
shellcheck $TMPDIR/install-systemd-multi-user.sh
|
||||
|
||||
# SC1091: Don't panic about not being able to source
|
||||
# /etc/profile
|
||||
# SC2002: Ignore "useless cat" "error", when loading
|
||||
# .reginfo, as the cat is a much cleaner
|
||||
# implementation, even though it is "useless"
|
||||
# SC2116: Allow ROOT_HOME=$(echo ~root) for resolving
|
||||
# root's home directory
|
||||
shellcheck --external-sources \
|
||||
--exclude SC1091,SC2002,SC2116 $TMPDIR/install-multi-user
|
||||
fi
|
||||
|
||||
chmod +x $TMPDIR/install
|
||||
chmod +x $TMPDIR/install-darwin-multi-user
|
||||
chmod +x $TMPDIR/install-darwin-multi-user.sh
|
||||
chmod +x $TMPDIR/install-systemd-multi-user.sh
|
||||
chmod +x $TMPDIR/install-multi-user
|
||||
dir=nix-${version}-${system}
|
||||
fn=$out/$dir.tar.bz2
|
||||
fn=$out/$dir.tar.xz
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
||||
tar cvfj $fn \
|
||||
tar cvfJ $fn \
|
||||
--owner=0 --group=0 --mode=u+rw,uga+r \
|
||||
--absolute-names \
|
||||
--hard-dereference \
|
||||
--transform "s,$TMPDIR/install,$dir/install," \
|
||||
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
||||
--transform "s,$NIX_STORE,$dir/store,S" \
|
||||
$TMPDIR/install $TMPDIR/install-darwin-multi-user $TMPDIR/reginfo $storePaths
|
||||
$TMPDIR/install $TMPDIR/install-darwin-multi-user.sh \
|
||||
$TMPDIR/install-systemd-multi-user.sh \
|
||||
$TMPDIR/install-multi-user $TMPDIR/reginfo \
|
||||
$(cat ${installerClosureInfo}/store-paths)
|
||||
'');
|
||||
|
||||
|
||||
coverage =
|
||||
with import nixpkgs { system = "x86_64-linux"; };
|
||||
with pkgs;
|
||||
|
||||
with import ./release-common.nix { inherit pkgs; };
|
||||
|
||||
releaseTools.coverageAnalysis {
|
||||
name = "nix-build";
|
||||
src = tarball;
|
||||
|
||||
buildInputs =
|
||||
[ curl bzip2 openssl pkgconfig sqlite xz libsodium libseccomp
|
||||
# These are for "make check" only:
|
||||
graphviz libxml2 libxslt git mercurial
|
||||
];
|
||||
|
||||
configureFlags = ''
|
||||
--disable-init-state
|
||||
'';
|
||||
buildInputs = buildDeps;
|
||||
|
||||
dontInstall = false;
|
||||
|
||||
|
@ -201,17 +211,14 @@ let
|
|||
};
|
||||
|
||||
|
||||
rpm_fedora25i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora25i386) [ "libsodium-devel" ];
|
||||
rpm_fedora25x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora25x86_64) [ "libsodium-devel" ];
|
||||
#rpm_fedora27x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora27x86_64) [ ];
|
||||
|
||||
|
||||
#deb_debian8i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian8i386) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
#deb_debian8x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian8x86_64) [ "libsodium-dev" ] [ "libsodium13" ];
|
||||
|
||||
deb_ubuntu1604i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1604i386) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
deb_ubuntu1604x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1604x86_64) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
deb_ubuntu1610i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1610i386) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
deb_ubuntu1610x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1610x86_64) [ "libsodium-dev" ] [ "libsodium18" ];
|
||||
#deb_ubuntu1710i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.ubuntu1710i386) [ ] [ "libsodium18" ];
|
||||
#deb_ubuntu1710x86_64 = makeDeb_x86_64 (diskImageFuns: diskImageFuns.ubuntu1710x86_64) [ ] [ "libsodium18" "libboost-context1.62.0" ];
|
||||
|
||||
|
||||
# System tests.
|
||||
|
@ -239,6 +246,7 @@ let
|
|||
{ diskImage = vmTools.diskImages.ubuntu1204x86_64;
|
||||
}
|
||||
''
|
||||
set -x
|
||||
useradd -m alice
|
||||
su - alice -c 'tar xf ${binaryTarball.x86_64-linux}/*.tar.*'
|
||||
mkdir /dest-nix
|
||||
|
@ -247,6 +255,17 @@ let
|
|||
su - alice -c '_NIX_INSTALLER_TEST=1 ./nix-*/install'
|
||||
su - alice -c 'nix-store --verify'
|
||||
su - alice -c 'PAGER= nix-store -qR ${build.x86_64-linux}'
|
||||
|
||||
# Check whether 'nix upgrade-nix' works.
|
||||
cat > /tmp/paths.nix <<EOF
|
||||
{
|
||||
x86_64-linux = "${build.x86_64-linux}";
|
||||
}
|
||||
EOF
|
||||
su - alice -c 'nix upgrade-nix -vvv --nix-store-paths-url file:///tmp/paths.nix'
|
||||
(! [ -L /home/alice/.profile-1-link ])
|
||||
su - alice -c 'PAGER= nix-store -qR ${build.x86_64-linux}'
|
||||
|
||||
mkdir -p $out/nix-support
|
||||
touch $out/nix-support/hydra-build-products
|
||||
umount /nix
|
||||
|
@ -264,14 +283,32 @@ let
|
|||
pkgs.runCommand "eval-nixos" { buildInputs = [ build.x86_64-linux ]; }
|
||||
''
|
||||
export NIX_STATE_DIR=$TMPDIR
|
||||
nix-store --init
|
||||
|
||||
nix-instantiate ${nixpkgs}/nixos/release-combined.nix -A tested --dry-run
|
||||
nix-instantiate ${nixpkgs}/nixos/release-combined.nix -A tested --dry-run \
|
||||
--arg nixpkgs '{ outPath = ${nixpkgs}; revCount = 123; shortRev = "abcdefgh"; }'
|
||||
|
||||
touch $out
|
||||
'';
|
||||
|
||||
|
||||
installerScript =
|
||||
pkgs.runCommand "installer-script"
|
||||
{ buildInputs = [ build.x86_64-linux ];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
substitute ${./scripts/install.in} $out/install \
|
||||
${pkgs.lib.concatMapStrings
|
||||
(system: "--replace '@binaryTarball_${system}@' $(nix hash-file --base16 --type sha256 ${binaryTarball.${system}}/*.tar.xz) ")
|
||||
[ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" ]
|
||||
} \
|
||||
--replace '@nixVersion@' ${build.x86_64-linux.src.version}
|
||||
|
||||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
|
||||
# Aggregate job containing the release-critical jobs.
|
||||
release = pkgs.releaseTools.aggregate {
|
||||
name = "nix-${tarball.version}";
|
||||
|
@ -281,20 +318,17 @@ let
|
|||
build.i686-linux
|
||||
build.x86_64-darwin
|
||||
build.x86_64-linux
|
||||
build.aarch64-linux
|
||||
binaryTarball.i686-linux
|
||||
binaryTarball.x86_64-darwin
|
||||
binaryTarball.x86_64-linux
|
||||
#deb_debian8i386
|
||||
#deb_debian8x86_64
|
||||
deb_ubuntu1604i386
|
||||
deb_ubuntu1604x86_64
|
||||
rpm_fedora25i386
|
||||
rpm_fedora25x86_64
|
||||
binaryTarball.aarch64-linux
|
||||
tests.remoteBuilds
|
||||
tests.nix-copy-closure
|
||||
tests.binaryTarball
|
||||
tests.evalNixpkgs
|
||||
tests.evalNixOS
|
||||
installerScript
|
||||
];
|
||||
};
|
||||
|
||||
|
@ -314,7 +348,7 @@ let
|
|||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages =
|
||||
[ "sqlite" "sqlite-devel" "bzip2-devel" "libcurl-devel" "openssl-devel" "xz-devel" "libseccomp-devel" ]
|
||||
[ "sqlite" "sqlite-devel" "bzip2-devel" "libcurl-devel" "openssl-devel" "xz-devel" "libseccomp-devel" "libsodium-devel" "boost-devel" "bison" "flex" ]
|
||||
++ extraPackages; };
|
||||
# At most 2047MB can be simulated in qemu-system-i386
|
||||
memSize = 2047;
|
||||
|
@ -337,9 +371,9 @@ let
|
|||
src = jobs.tarball;
|
||||
diskImage = (diskImageFun vmTools.diskImageFuns)
|
||||
{ extraPackages =
|
||||
[ "libsqlite3-dev" "libbz2-dev" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" "libseccomp-dev" ]
|
||||
[ "libsqlite3-dev" "libbz2-dev" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" "libseccomp-dev" "libsodium-dev" "libboost-all-dev" ]
|
||||
++ extraPackages; };
|
||||
memSize = 1024;
|
||||
memSize = 2047;
|
||||
meta.schedulingPriority = 50;
|
||||
postInstall = "make installcheck";
|
||||
configureFlags = "--sysconfdir=/etc";
|
||||
|
|
|
@ -1,772 +1,43 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# Sourced from:
|
||||
# - https://github.com/LnL7/nix-darwin/blob/8c29d0985d74b4a990238497c47a2542a5616b3c/bootstrap.sh
|
||||
# - https://gist.github.com/expipiplus1/e571ce88c608a1e83547c918591b149f/ac504c6c1b96e65505fbda437a28ce563408ecb0
|
||||
# - https://github.com/NixOS/nixos-org-configurations/blob/a122f418797713d519aadf02e677fce0dc1cb446/delft/scripts/nix-mac-installer.sh
|
||||
# - https://github.com/matthewbauer/macNixOS/blob/f6045394f9153edea417be90c216788e754feaba/install-macNixOS.sh
|
||||
# - https://gist.github.com/LnL7/9717bd6cdcb30b086fd7f2093e5f8494/86b26f852ce563e973acd30f796a9a416248c34a
|
||||
#
|
||||
# however tracking which bits came from which would be impossible.
|
||||
|
||||
readonly ESC='\033[0m'
|
||||
readonly BOLD='\033[38;1m'
|
||||
readonly BLUE='\033[38;34m'
|
||||
readonly BLUE_UL='\033[38;4;34m'
|
||||
readonly GREEN='\033[38;32m'
|
||||
readonly GREEN_UL='\033[38;4;32m'
|
||||
readonly RED='\033[38;31m'
|
||||
readonly RED_UL='\033[38;4;31m'
|
||||
readonly YELLOW='\033[38;33m'
|
||||
readonly YELLOW_UL='\033[38;4;33m'
|
||||
|
||||
readonly CORES=$(sysctl -n hw.ncpu)
|
||||
readonly NIX_USER_COUNT="32"
|
||||
readonly NIX_BUILD_GROUP_ID="30000"
|
||||
readonly NIX_BUILD_GROUP_NAME="nixbld"
|
||||
readonly NIX_FIRST_BUILD_UID="30001"
|
||||
# Please don't change this. We don't support it, because the
|
||||
# default shell profile that comes with Nix doesn't support it.
|
||||
readonly NIX_ROOT="/nix"
|
||||
readonly PLIST_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
|
||||
readonly PROFILE_TARGETS=("/etc/bashrc" "/etc/zshrc")
|
||||
readonly PROFILE_BACKUP_SUFFIX=".backup-before-nix"
|
||||
readonly PROFILE_NIX_FILE="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"
|
||||
|
||||
readonly NIX_INSTALLED_NIX="@nix@"
|
||||
readonly NIX_INSTALLED_CACERT="@cacert@"
|
||||
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
||||
|
||||
readonly ROOT_HOME="/var/root"
|
||||
|
||||
if [ -t 0 ]; then
|
||||
readonly IS_HEADLESS='no'
|
||||
else
|
||||
readonly IS_HEADLESS='yes'
|
||||
fi
|
||||
|
||||
headless() {
|
||||
if [ "$IS_HEADLESS" = "yes" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
contactme() {
|
||||
echo "We'd love to help if you need it."
|
||||
echo ""
|
||||
echo "If you can, open an issue at https://github.com/nixos/nix/issues"
|
||||
echo ""
|
||||
echo "Or feel free to contact the team,"
|
||||
echo " - on IRC #nixos on irc.freenode.net"
|
||||
echo " - on twitter @nixos_org"
|
||||
}
|
||||
|
||||
uninstall_directions() {
|
||||
subheader "Uninstalling nix:"
|
||||
local step=0
|
||||
|
||||
if [ -e "$PLIST_DEST" ]; then
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Delete $PLIST_DEST
|
||||
|
||||
sudo launchctl unload $PLIST_DEST
|
||||
sudo rm $PLIST_DEST
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ] && [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Restore $profile_target$PROFILE_BACKUP_SUFFIX back to $profile_target
|
||||
|
||||
sudo mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
||||
|
||||
(after this one, you may need to re-open any terminals that were
|
||||
opened while it existed.)
|
||||
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Delete the files Nix added to your system:
|
||||
|
||||
sudo rm -rf /etc/nix $NIX_ROOT $ROOT_HOME/.nix-profile $ROOT_HOME/.nix-defexpr $ROOT_HOME/.nix-channels $HOME/.nix-profile $HOME/.nix-defexpr $HOME/.nix-channels
|
||||
|
||||
and that is it.
|
||||
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
nix_user_for_core() {
|
||||
printf "nixbld%d" "$1"
|
||||
}
|
||||
|
||||
nix_uid_for_core() {
|
||||
echo $((NIX_FIRST_BUILD_UID + $1 - 1))
|
||||
}
|
||||
|
||||
dsclattr() {
|
||||
/usr/bin/dscl . -read "$1" \
|
||||
| awk "/$2/ { print \$2 }"
|
||||
}
|
||||
|
||||
_textout() {
|
||||
echo -en "$1"
|
||||
shift
|
||||
if [ "$*" = "" ]; then
|
||||
cat
|
||||
else
|
||||
echo "$@"
|
||||
fi
|
||||
echo -en "$ESC"
|
||||
}
|
||||
|
||||
header() {
|
||||
follow="---------------------------------------------------------"
|
||||
header=$(echo "---- $* $follow$follow$follow" | head -c 80)
|
||||
echo ""
|
||||
_textout "$BLUE" "$header"
|
||||
}
|
||||
|
||||
warningheader() {
|
||||
follow="---------------------------------------------------------"
|
||||
header=$(echo "---- $* $follow$follow$follow" | head -c 80)
|
||||
echo ""
|
||||
_textout "$RED" "$header"
|
||||
}
|
||||
|
||||
subheader() {
|
||||
echo ""
|
||||
_textout "$BLUE_UL" "$*"
|
||||
}
|
||||
|
||||
row() {
|
||||
printf "$BOLD%s$ESC:\\t%s\\n" "$1" "$2"
|
||||
}
|
||||
|
||||
task() {
|
||||
echo ""
|
||||
ok "~~> $1"
|
||||
}
|
||||
|
||||
bold() {
|
||||
echo "$BOLD$*$ESC"
|
||||
}
|
||||
|
||||
ok() {
|
||||
_textout "$GREEN" "$@"
|
||||
}
|
||||
|
||||
warning() {
|
||||
warningheader "warning!"
|
||||
cat
|
||||
echo ""
|
||||
}
|
||||
|
||||
failure() {
|
||||
header "oh no!"
|
||||
_textout "$RED" "$@"
|
||||
echo ""
|
||||
_textout "$RED" "$(contactme)"
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
}
|
||||
|
||||
ui_confirm() {
|
||||
_textout "$GREEN$GREEN_UL" "$1"
|
||||
|
||||
if headless; then
|
||||
echo "No TTY, assuming you would say yes :)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local prompt="[y/n] "
|
||||
echo -n "$prompt"
|
||||
while read -r y; do
|
||||
if [ "$y" = "y" ]; then
|
||||
echo ""
|
||||
return 0
|
||||
elif [ "$y" = "n" ]; then
|
||||
echo ""
|
||||
return 1
|
||||
else
|
||||
_textout "$RED" "Sorry, I didn't understand. I can only understand answers of y or n"
|
||||
echo -n "$prompt"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
return 1
|
||||
}
|
||||
|
||||
__sudo() {
|
||||
local expl="$1"
|
||||
local cmd="$2"
|
||||
shift
|
||||
header "sudo execution"
|
||||
|
||||
echo "I am executing:"
|
||||
echo ""
|
||||
printf " $ sudo %s\\n" "$cmd"
|
||||
echo ""
|
||||
echo "$expl"
|
||||
echo ""
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_sudo() {
|
||||
local expl="$1"
|
||||
shift
|
||||
if ! headless; then
|
||||
__sudo "$expl" "$*"
|
||||
fi
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
|
||||
readonly SCRATCH=$(mktemp -d -t tmp.XXXXXXXXXX)
|
||||
function finish_cleanup {
|
||||
rm -rf "$SCRATCH"
|
||||
}
|
||||
|
||||
function finish_fail {
|
||||
finish_cleanup
|
||||
|
||||
failure <<EOF
|
||||
Jeeze, something went wrong. If you can take all the output and open
|
||||
an issue, we'd love to fix the problem so nobody else has this issue.
|
||||
|
||||
:(
|
||||
EOF
|
||||
}
|
||||
trap finish_fail EXIT
|
||||
|
||||
function finish_success {
|
||||
finish_cleanup
|
||||
|
||||
ok "Alright! We're done!"
|
||||
cat <<EOF
|
||||
|
||||
Before Nix will work in your existing shells, you'll need to close
|
||||
them and open them again. Other than that, you should be ready to go.
|
||||
|
||||
Try it! Open a new terminal, and type:
|
||||
|
||||
$ nix-shell -p nix-info --run "nix-info -m"
|
||||
|
||||
Thank you for using this installer. If you have any feedback, don't
|
||||
hesitate:
|
||||
|
||||
$(contactme)
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
validate_starting_assumptions() {
|
||||
poly_validate_assumptions() {
|
||||
if [ "$(uname -s)" != "Darwin" ]; then
|
||||
failure "This script is for use with macOS!"
|
||||
fi
|
||||
|
||||
if [ $EUID -eq 0 ]; then
|
||||
failure <<EOF
|
||||
Please do not run this script with root privileges. We will call sudo
|
||||
when we need to.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if type nix-env 2> /dev/null >&2; then
|
||||
failure <<EOF
|
||||
Nix already appears to be installed, and this tool assumes it is
|
||||
_not_ yet installed.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "${NIX_REMOTE:-}" != "" ]; then
|
||||
failure <<EOF
|
||||
For some reason, \$NIX_REMOTE is set. It really should not be set
|
||||
before this installer runs, and it hints that Nix is currently
|
||||
installed. Please delete the old Nix installation and start again.
|
||||
|
||||
Note: You might need to close your shell window and open a new shell
|
||||
to clear the variable.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if echo "${SSL_CERT_FILE:-}" | grep -qE "(nix/var/nix|nix-profile)"; then
|
||||
failure <<EOF
|
||||
It looks like \$SSL_CERT_FILE is set to a path that used to be part of
|
||||
the old Nix installation. Please unset that variable and try again:
|
||||
|
||||
$ unset SSL_CERT_FILE
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
for file in ~/.bash_profile ~/.bash_login ~/.profile ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin; do
|
||||
if [ -f "$file" ]; then
|
||||
if grep -l "^[^#].*.nix-profile" "$file"; then
|
||||
failure <<EOF
|
||||
I found a reference to a ".nix-profile" in $file.
|
||||
This has a high chance of breaking a new nix installation. It was most
|
||||
likely put there by a previous Nix installer.
|
||||
|
||||
Please remove this reference and try running this again. You should
|
||||
also look for similar references in:
|
||||
|
||||
- ~/.bash_profile
|
||||
- ~/.bash_login
|
||||
- ~/.profile
|
||||
|
||||
or other shell init files that you may have.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -d /nix ]; then
|
||||
failure <<EOF
|
||||
There are some relics of a previous installation of Nix at /nix, and
|
||||
this scripts assumes Nix is _not_ yet installed. Please delete the old
|
||||
Nix installation and start again.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -d /etc/nix ]; then
|
||||
failure <<EOF
|
||||
There are some relics of a previous installation of Nix at /etc/nix, and
|
||||
this scripts assumes Nix is _not_ yet installed. Please delete the old
|
||||
Nix installation and start again.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
|
||||
failure <<EOF
|
||||
When this script runs, it backs up the current $profile_target to
|
||||
$profile_target$PROFILE_BACKUP_SUFFIX. This backup file already exists, though.
|
||||
|
||||
Please follow these instructions to clean up the old backup file:
|
||||
|
||||
1. Copy $profile_target and $profile_target$PROFILE_BACKUP_SUFFIX to another place, just
|
||||
in case.
|
||||
|
||||
2. Take care to make sure that $profile_target$PROFILE_BACKUP_SUFFIX doesn't look like
|
||||
it has anything nix-related in it. If it does, something is probably
|
||||
quite wrong. Please open an issue or get in touch immediately.
|
||||
|
||||
3. Take care to make sure that $profile_target doesn't look like it has
|
||||
anything nix-related in it. If it does, and $profile_target _did not_,
|
||||
run:
|
||||
|
||||
$ /usr/bin/sudo /bin/mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
||||
|
||||
and try again.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if grep -qi "nix" "$profile_target"; then
|
||||
failure <<EOF
|
||||
It looks like $profile_target already has some Nix configuration in
|
||||
there. There should be no reason to run this again. If you're having
|
||||
trouble, please open an issue.
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
danger_paths=("$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.nix-profile")
|
||||
for danger_path in "${danger_paths[@]}"; do
|
||||
if _sudo "making sure that $danger_path doesn't exist" \
|
||||
test -e "$danger_path"; then
|
||||
failure <<EOF
|
||||
I found a file at $danger_path, which is a relic of a previous
|
||||
installation. You must first delete this file before continuing.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
setup_report() {
|
||||
header "hardware report"
|
||||
row " Cores" "$CORES"
|
||||
|
||||
header "Nix config report"
|
||||
row " Temp Dir" "$SCRATCH"
|
||||
row " Nix Root" "$NIX_ROOT"
|
||||
row " Build Users" "$NIX_USER_COUNT"
|
||||
row " Build Group ID" "$NIX_BUILD_GROUP_ID"
|
||||
row "Build Group Name" "$NIX_BUILD_GROUP_NAME"
|
||||
if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" != "" ]; then
|
||||
row "Preexisting Install" "Allowed"
|
||||
fi
|
||||
|
||||
subheader "build users:"
|
||||
|
||||
row " Username" "UID"
|
||||
for i in $(seq 1 "$NIX_USER_COUNT"); do
|
||||
row " $(nix_user_for_core "$i")" "$(nix_uid_for_core "$i")"
|
||||
done
|
||||
echo ""
|
||||
poly_service_installed_check() {
|
||||
[ -e "$PLIST_DEST" ]
|
||||
}
|
||||
|
||||
create_build_group() {
|
||||
local primary_group_id
|
||||
poly_service_uninstall_directions() {
|
||||
cat <<EOF
|
||||
$1. Delete $PLIST_DEST
|
||||
|
||||
task "Setting up the build group $NIX_BUILD_GROUP_NAME"
|
||||
if ! /usr/bin/dscl . -read "/Groups/$NIX_BUILD_GROUP_NAME" > /dev/null 2>&1; then
|
||||
_sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
|
||||
/usr/sbin/dseditgroup -o create \
|
||||
-r "Nix build group for nix-daemon" \
|
||||
-i "$NIX_BUILD_GROUP_ID" \
|
||||
"$NIX_BUILD_GROUP_NAME" >&2
|
||||
row " Created" "Yes"
|
||||
else
|
||||
primary_group_id=$(dsclattr "/Groups/$NIX_BUILD_GROUP_NAME" "PrimaryGroupID")
|
||||
if [ "$primary_group_id" -ne "$NIX_BUILD_GROUP_ID" ]; then
|
||||
failure <<EOF
|
||||
It seems the build group $NIX_BUILD_GROUP_NAME already exists, but
|
||||
with the UID $primary_group_id. This script can't really handle
|
||||
that right now, so I'm going to give up.
|
||||
sudo launchctl unload $PLIST_DEST
|
||||
sudo rm $PLIST_DEST
|
||||
|
||||
You can fix this by editing this script and changing the
|
||||
NIX_BUILD_GROUP_ID variable near the top to from $NIX_BUILD_GROUP_ID
|
||||
to $primary_group_id and re-run.
|
||||
EOF
|
||||
else
|
||||
row " Exists" "Yes"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
create_build_user_for_core() {
|
||||
local coreid
|
||||
local username
|
||||
local uid
|
||||
|
||||
coreid="$1"
|
||||
username=$(nix_user_for_core "$coreid")
|
||||
uid=$(nix_uid_for_core "$coreid")
|
||||
dsclpath="/Users/$username"
|
||||
|
||||
task "Setting up the build user $username"
|
||||
|
||||
if ! /usr/bin/dscl . -read "$dsclpath" > /dev/null 2>&1; then
|
||||
_sudo "Creating the Nix build user, $username" \
|
||||
/usr/bin/dscl . create "$dsclpath" \
|
||||
UniqueID "${uid}"
|
||||
row " Created" "Yes"
|
||||
else
|
||||
actual_uid=$(dsclattr "$dsclpath" "UniqueID")
|
||||
if [ "$actual_uid" -ne "$uid" ]; then
|
||||
failure <<EOF
|
||||
It seems the build user $username already exists, but with the UID
|
||||
with the UID $actual_uid. This script can't really handle that right
|
||||
now, so I'm going to give up.
|
||||
|
||||
If you already created the users and you know they start from
|
||||
$actual_uid and go up from there, you can edit this script and change
|
||||
NIX_FIRST_BUILD_UID near the top of the file to $actual_uid and try
|
||||
again.
|
||||
EOF
|
||||
else
|
||||
row " Exists" "Yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "IsHidden")" = "1" ]; then
|
||||
row " IsHidden" "Yes"
|
||||
else
|
||||
_sudo "in order to make $username a hidden user" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "IsHidden" "1"
|
||||
row " IsHidden" "Yes"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "NFSHomeDirectory")" = "/var/empty" ]; then
|
||||
row " NFSHomeDirectory" "/var/empty"
|
||||
else
|
||||
_sudo "in order to give $username a safe home directory" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "NFSHomeDirectory" "/var/empty"
|
||||
row " NFSHomeDirectory" "/var/empty"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "RealName")" = "Nix build user $coreid" ]; then
|
||||
row " RealName" "Nix build user $coreid"
|
||||
else
|
||||
_sudo "in order to give $username a useful name" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "RealName" "Nix build user $coreid"
|
||||
row " RealName" "Nix build user $coreid"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "UserShell")" = "/sbin/nologin" ]; then
|
||||
row " Logins Disabled" "Yes"
|
||||
else
|
||||
_sudo "in order to prevent $username from logging in" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "UserShell" "/sbin/nologin"
|
||||
row " Logins Disabled" "Yes"
|
||||
fi
|
||||
|
||||
if dseditgroup -o checkmember -m "$username" "$NIX_BUILD_GROUP_NAME" > /dev/null 2>&1 ; then
|
||||
row " Member of $NIX_BUILD_GROUP_NAME" "Yes"
|
||||
else
|
||||
_sudo "Add $username to the $NIX_BUILD_GROUP_NAME group"\
|
||||
/usr/sbin/dseditgroup -o edit -t user \
|
||||
-a "$username" "$NIX_BUILD_GROUP_NAME"
|
||||
row " Member of $NIX_BUILD_GROUP_NAME" "Yes"
|
||||
fi
|
||||
|
||||
if [ "$(dsclattr "$dsclpath" "PrimaryGroupID")" = "$NIX_BUILD_GROUP_ID" ]; then
|
||||
row " PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
else
|
||||
_sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
|
||||
/usr/bin/dscl . -create "$dsclpath" "PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
row " PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
create_build_users() {
|
||||
for i in $(seq 1 "$NIX_USER_COUNT"); do
|
||||
create_build_user_for_core "$i"
|
||||
done
|
||||
}
|
||||
|
||||
create_directories() {
|
||||
_sudo "to make the basic directory structure of Nix (part 1)" \
|
||||
mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool}
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 2)" \
|
||||
mkdir -pv -m 1777 /nix/var/nix/{gcroots,profiles}/per-user
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 3)" \
|
||||
mkdir -pv -m 1775 /nix/store
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 4)" \
|
||||
chgrp "$NIX_BUILD_GROUP_NAME" /nix/store
|
||||
|
||||
_sudo "to set up the root user's profile (part 1)" \
|
||||
mkdir -pv -m 0755 /nix/var/nix/profiles/per-user/root
|
||||
|
||||
_sudo "to set up the root user's profile (part 2)" \
|
||||
mkdir -pv -m 0700 "$ROOT_HOME/.nix-defexpr"
|
||||
|
||||
_sudo "to place the default nix daemon configuration (part 1)" \
|
||||
mkdir -pv -m 0555 /etc/nix
|
||||
}
|
||||
|
||||
place_channel_configuration() {
|
||||
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels"
|
||||
_sudo "to set up the default system channel (part 1)" \
|
||||
install -m 0664 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
|
||||
}
|
||||
|
||||
welcome_to_nix() {
|
||||
ok "Welcome to the Multi-User Nix Installation"
|
||||
|
||||
poly_service_setup_note() {
|
||||
cat <<EOF
|
||||
|
||||
This installation tool will set up your computer with the Nix package
|
||||
manager. This will happen in a few stages:
|
||||
|
||||
1. Make sure your computer doesn't already have Nix. If it does, I
|
||||
will show you instructions on how to clean up your old one.
|
||||
|
||||
2. Show you what we are going to install and where. Then we will ask
|
||||
if you are ready to continue.
|
||||
|
||||
3. Create the system users and groups that the Nix daemon uses to run
|
||||
builds.
|
||||
|
||||
4. Perform the basic installation of the Nix files daemon.
|
||||
|
||||
5. Configure your shell to import special Nix Profile files, so you
|
||||
can use Nix.
|
||||
|
||||
6. Start the Nix daemon.
|
||||
|
||||
EOF
|
||||
|
||||
if ui_confirm "Would you like to see a more detailed list of what we will do?"; then
|
||||
cat <<EOF
|
||||
|
||||
We will:
|
||||
|
||||
- make sure your computer doesn't already have Nix files
|
||||
(if it does, I will tell you how to clean them up.)
|
||||
- create local users (see the list above for the users we'll make)
|
||||
- create a local group ($NIX_BUILD_GROUP_NAME)
|
||||
- install Nix in to $NIX_ROOT
|
||||
- create a configuration file in /etc/nix
|
||||
- set up the "default profile" by creating some Nix-related files in
|
||||
$ROOT_HOME
|
||||
EOF
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ]; then
|
||||
cat <<EOF
|
||||
- back up $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX
|
||||
- update $profile_target to include some Nix configuration
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
cat <<EOF
|
||||
- load and start a LaunchDaemon (at $PLIST_DEST) for nix-daemon
|
||||
|
||||
EOF
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
failure <<EOF
|
||||
Okay, maybe you would like to talk to the team.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
chat_about_sudo() {
|
||||
header "let's talk about sudo"
|
||||
|
||||
if headless; then
|
||||
cat <<EOF
|
||||
This script is going to call sudo a lot. Normally, it would show you
|
||||
exactly what commands it is running and why. However, the script is
|
||||
run in a headless fashion, like this:
|
||||
|
||||
$ curl https://nixos.org/nix/install | sh
|
||||
|
||||
or maybe in a CI pipeline. Because of that, we're going to skip the
|
||||
verbose output in the interest of brevity.
|
||||
|
||||
If you would like to
|
||||
see the output, try like this:
|
||||
|
||||
$ curl -o install-nix https://nixos.org/nix/install
|
||||
$ sh ./install-nix
|
||||
|
||||
EOF
|
||||
return 0
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
This script is going to call sudo a lot. Every time we do, it'll
|
||||
output exactly what it'll do, and why.
|
||||
|
||||
Just like this:
|
||||
EOF
|
||||
|
||||
__sudo "to demonstrate how our sudo prompts look" \
|
||||
echo "this is a sudo prompt"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
This might look scary, but everything can be undone by running just a
|
||||
few commands. We used to ask you to confirm each time sudo ran, but it
|
||||
was too many times. Instead, I'll just ask you this one time:
|
||||
|
||||
EOF
|
||||
if ui_confirm "Can we use sudo?"; then
|
||||
ok "Yay! Thanks! Let's get going!"
|
||||
else
|
||||
failure <<EOF
|
||||
That is okay, but we can't install.
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
install_from_extracted_nix() {
|
||||
(
|
||||
cd "$EXTRACTED_NIX_PATH"
|
||||
|
||||
_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
|
||||
rsync -rlpt ./store/* "$NIX_ROOT/store/"
|
||||
|
||||
if [ -d "$NIX_INSTALLED_NIX" ]; then
|
||||
echo " Alright! We have our first nix at $NIX_INSTALLED_NIX"
|
||||
else
|
||||
failure <<EOF
|
||||
Something went wrong, and I didn't find Nix installed at
|
||||
$NIX_INSTALLED_NIX.
|
||||
EOF
|
||||
fi
|
||||
|
||||
_sudo "to initialize the Nix Database" \
|
||||
$NIX_INSTALLED_NIX/bin/nix-store --init
|
||||
|
||||
cat ./.reginfo \
|
||||
| _sudo "to load data for the first time in to the Nix Database" \
|
||||
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db
|
||||
|
||||
echo " Just finished getting the nix database ready."
|
||||
)
|
||||
}
|
||||
|
||||
shell_source_lines() {
|
||||
cat <<EOF
|
||||
|
||||
# Nix
|
||||
if [ -e '$PROFILE_NIX_FILE' ]; then
|
||||
. '$PROFILE_NIX_FILE'
|
||||
fi
|
||||
# End Nix
|
||||
|
||||
EOF
|
||||
}
|
||||
configure_shell_profile() {
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ]; then
|
||||
_sudo "to back up your current $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX" \
|
||||
cp "$profile_target" "$profile_target$PROFILE_BACKUP_SUFFIX"
|
||||
|
||||
shell_source_lines \
|
||||
| _sudo "extend your $profile_target with nix-daemon settings" \
|
||||
tee -a "$profile_target"
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
setup_default_profile() {
|
||||
_sudo "to installing a bootstrapping Nix in to the default Profile" \
|
||||
HOME=$ROOT_HOME "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
|
||||
|
||||
_sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \
|
||||
HOME=$ROOT_HOME "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT"
|
||||
|
||||
_sudo "to update the default channel in the default profile" \
|
||||
HOME=$ROOT_HOME NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs
|
||||
}
|
||||
|
||||
|
||||
place_nix_configuration() {
|
||||
cat <<EOF > "$SCRATCH/nix.conf"
|
||||
build-users-group = $NIX_BUILD_GROUP_NAME
|
||||
|
||||
max-jobs = $NIX_USER_COUNT
|
||||
cores = 1
|
||||
sandbox = false
|
||||
EOF
|
||||
_sudo "to place the default nix daemon configuration (part 2)" \
|
||||
install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf
|
||||
}
|
||||
|
||||
configure_nix_daemon_plist() {
|
||||
poly_configure_nix_daemon_service() {
|
||||
_sudo "to set up the nix-daemon as a LaunchDaemon" \
|
||||
ln -sfn "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST"
|
||||
|
||||
|
@ -778,42 +49,96 @@ configure_nix_daemon_plist() {
|
|||
|
||||
}
|
||||
|
||||
|
||||
main() {
|
||||
welcome_to_nix
|
||||
chat_about_sudo
|
||||
|
||||
if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" = "" ]; then
|
||||
validate_starting_assumptions
|
||||
fi
|
||||
|
||||
setup_report
|
||||
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
ok "Alright, no changes have been made :)"
|
||||
contactme
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create_build_group
|
||||
create_build_users
|
||||
create_directories
|
||||
place_channel_configuration
|
||||
install_from_extracted_nix
|
||||
|
||||
configure_shell_profile
|
||||
|
||||
set +eu
|
||||
. /etc/profile
|
||||
set -eu
|
||||
|
||||
setup_default_profile
|
||||
place_nix_configuration
|
||||
configure_nix_daemon_plist
|
||||
|
||||
trap finish_success EXIT
|
||||
poly_group_exists() {
|
||||
/usr/bin/dscl . -read "/Groups/$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_group_id_get() {
|
||||
dsclattr "/Groups/$1" "PrimaryGroupID"
|
||||
}
|
||||
|
||||
main
|
||||
poly_create_build_group() {
|
||||
_sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
|
||||
/usr/sbin/dseditgroup -o create \
|
||||
-r "Nix build group for nix-daemon" \
|
||||
-i "$NIX_BUILD_GROUP_ID" \
|
||||
"$NIX_BUILD_GROUP_NAME" >&2
|
||||
}
|
||||
|
||||
poly_user_exists() {
|
||||
/usr/bin/dscl . -read "/Users/$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_user_id_get() {
|
||||
dsclattr "/Users/$1" "UniqueID"
|
||||
}
|
||||
|
||||
poly_user_hidden_get() {
|
||||
dsclattr "/Users/$1" "IsHidden"
|
||||
}
|
||||
|
||||
poly_user_hidden_set() {
|
||||
_sudo "in order to make $1 a hidden user" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "IsHidden" "1"
|
||||
}
|
||||
|
||||
poly_user_home_get() {
|
||||
dsclattr "/Users/$1" "NFSHomeDirectory"
|
||||
}
|
||||
|
||||
poly_user_home_set() {
|
||||
_sudo "in order to give $1 a safe home directory" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "NFSHomeDirectory" "$2"
|
||||
}
|
||||
|
||||
poly_user_note_get() {
|
||||
dsclattr "/Users/$1" "RealName"
|
||||
}
|
||||
|
||||
poly_user_note_set() {
|
||||
_sudo "in order to give $username a useful note" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "RealName" "$2"
|
||||
}
|
||||
|
||||
poly_user_shell_get() {
|
||||
dsclattr "/Users/$1" "UserShell"
|
||||
}
|
||||
|
||||
poly_user_shell_set() {
|
||||
_sudo "in order to give $1 a safe home directory" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "UserShell" "$2"
|
||||
}
|
||||
|
||||
poly_user_in_group_check() {
|
||||
username=$1
|
||||
group=$2
|
||||
dseditgroup -o checkmember -m "$username" "$group" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_user_in_group_set() {
|
||||
username=$1
|
||||
group=$2
|
||||
|
||||
_sudo "Add $username to the $group group"\
|
||||
/usr/sbin/dseditgroup -o edit -t user \
|
||||
-a "$username" "$group"
|
||||
}
|
||||
|
||||
poly_user_primary_group_get() {
|
||||
dsclattr "/Users/$1" "PrimaryGroupID"
|
||||
}
|
||||
|
||||
poly_user_primary_group_set() {
|
||||
_sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "PrimaryGroupID" "$2"
|
||||
}
|
||||
|
||||
poly_create_build_user() {
|
||||
username=$1
|
||||
uid=$2
|
||||
builder_num=$3
|
||||
|
||||
_sudo "Creating the Nix build user (#$builder_num), $username" \
|
||||
/usr/bin/dscl . create "/Users/$username" \
|
||||
UniqueID "${uid}"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,808 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# Sourced from:
|
||||
# - https://github.com/LnL7/nix-darwin/blob/8c29d0985d74b4a990238497c47a2542a5616b3c/bootstrap.sh
|
||||
# - https://gist.github.com/expipiplus1/e571ce88c608a1e83547c918591b149f/ac504c6c1b96e65505fbda437a28ce563408ecb0
|
||||
# - https://github.com/NixOS/nixos-org-configurations/blob/a122f418797713d519aadf02e677fce0dc1cb446/delft/scripts/nix-mac-installer.sh
|
||||
# - https://github.com/matthewbauer/macNixOS/blob/f6045394f9153edea417be90c216788e754feaba/install-macNixOS.sh
|
||||
# - https://gist.github.com/LnL7/9717bd6cdcb30b086fd7f2093e5f8494/86b26f852ce563e973acd30f796a9a416248c34a
|
||||
#
|
||||
# however tracking which bits came from which would be impossible.
|
||||
|
||||
readonly ESC='\033[0m'
|
||||
readonly BOLD='\033[38;1m'
|
||||
readonly BLUE='\033[38;34m'
|
||||
readonly BLUE_UL='\033[38;4;34m'
|
||||
readonly GREEN='\033[38;32m'
|
||||
readonly GREEN_UL='\033[38;4;32m'
|
||||
readonly RED='\033[38;31m'
|
||||
readonly RED_UL='\033[38;4;31m'
|
||||
readonly YELLOW='\033[38;33m'
|
||||
readonly YELLOW_UL='\033[38;4;33m'
|
||||
|
||||
readonly NIX_USER_COUNT="32"
|
||||
readonly NIX_BUILD_GROUP_ID="30000"
|
||||
readonly NIX_BUILD_GROUP_NAME="nixbld"
|
||||
readonly NIX_FIRST_BUILD_UID="30001"
|
||||
# Please don't change this. We don't support it, because the
|
||||
# default shell profile that comes with Nix doesn't support it.
|
||||
readonly NIX_ROOT="/nix"
|
||||
|
||||
readonly PROFILE_TARGETS=("/etc/bashrc" "/etc/profile.d/nix.sh" "/etc/zshrc")
|
||||
readonly PROFILE_BACKUP_SUFFIX=".backup-before-nix"
|
||||
readonly PROFILE_NIX_FILE="$NIX_ROOT/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"
|
||||
|
||||
readonly NIX_INSTALLED_NIX="@nix@"
|
||||
readonly NIX_INSTALLED_CACERT="@cacert@"
|
||||
readonly EXTRACTED_NIX_PATH="$(dirname "$0")"
|
||||
|
||||
readonly ROOT_HOME=$(echo ~root)
|
||||
|
||||
if [ -t 0 ]; then
|
||||
readonly IS_HEADLESS='no'
|
||||
else
|
||||
readonly IS_HEADLESS='yes'
|
||||
fi
|
||||
|
||||
headless() {
|
||||
if [ "$IS_HEADLESS" = "yes" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
contactme() {
|
||||
echo "We'd love to help if you need it."
|
||||
echo ""
|
||||
echo "If you can, open an issue at https://github.com/nixos/nix/issues"
|
||||
echo ""
|
||||
echo "Or feel free to contact the team,"
|
||||
echo " - on IRC #nixos on irc.freenode.net"
|
||||
echo " - on twitter @nixos_org"
|
||||
}
|
||||
|
||||
uninstall_directions() {
|
||||
subheader "Uninstalling nix:"
|
||||
local step=0
|
||||
|
||||
if poly_service_installed_check; then
|
||||
step=$((step + 1))
|
||||
poly_service_uninstall_directions "$step"
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ] && [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Restore $profile_target$PROFILE_BACKUP_SUFFIX back to $profile_target
|
||||
|
||||
sudo mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
||||
|
||||
(after this one, you may need to re-open any terminals that were
|
||||
opened while it existed.)
|
||||
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
step=$((step + 1))
|
||||
cat <<EOF
|
||||
$step. Delete the files Nix added to your system:
|
||||
|
||||
sudo rm -rf /etc/nix $NIX_ROOT $ROOT_HOME/.nix-profile $ROOT_HOME/.nix-defexpr $ROOT_HOME/.nix-channels $HOME/.nix-profile $HOME/.nix-defexpr $HOME/.nix-channels
|
||||
|
||||
and that is it.
|
||||
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
nix_user_for_core() {
|
||||
printf "nixbld%d" "$1"
|
||||
}
|
||||
|
||||
nix_uid_for_core() {
|
||||
echo $((NIX_FIRST_BUILD_UID + $1 - 1))
|
||||
}
|
||||
|
||||
_textout() {
|
||||
echo -en "$1"
|
||||
shift
|
||||
if [ "$*" = "" ]; then
|
||||
cat
|
||||
else
|
||||
echo "$@"
|
||||
fi
|
||||
echo -en "$ESC"
|
||||
}
|
||||
|
||||
header() {
|
||||
follow="---------------------------------------------------------"
|
||||
header=$(echo "---- $* $follow$follow$follow" | head -c 80)
|
||||
echo ""
|
||||
_textout "$BLUE" "$header"
|
||||
}
|
||||
|
||||
warningheader() {
|
||||
follow="---------------------------------------------------------"
|
||||
header=$(echo "---- $* $follow$follow$follow" | head -c 80)
|
||||
echo ""
|
||||
_textout "$RED" "$header"
|
||||
}
|
||||
|
||||
subheader() {
|
||||
echo ""
|
||||
_textout "$BLUE_UL" "$*"
|
||||
}
|
||||
|
||||
row() {
|
||||
printf "$BOLD%s$ESC:\\t%s\\n" "$1" "$2"
|
||||
}
|
||||
|
||||
task() {
|
||||
echo ""
|
||||
ok "~~> $1"
|
||||
}
|
||||
|
||||
bold() {
|
||||
echo "$BOLD$*$ESC"
|
||||
}
|
||||
|
||||
ok() {
|
||||
_textout "$GREEN" "$@"
|
||||
}
|
||||
|
||||
warning() {
|
||||
warningheader "warning!"
|
||||
cat
|
||||
echo ""
|
||||
}
|
||||
|
||||
failure() {
|
||||
header "oh no!"
|
||||
_textout "$RED" "$@"
|
||||
echo ""
|
||||
_textout "$RED" "$(contactme)"
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
}
|
||||
|
||||
ui_confirm() {
|
||||
_textout "$GREEN$GREEN_UL" "$1"
|
||||
|
||||
if headless; then
|
||||
echo "No TTY, assuming you would say yes :)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local prompt="[y/n] "
|
||||
echo -n "$prompt"
|
||||
while read -r y; do
|
||||
if [ "$y" = "y" ]; then
|
||||
echo ""
|
||||
return 0
|
||||
elif [ "$y" = "n" ]; then
|
||||
echo ""
|
||||
return 1
|
||||
else
|
||||
_textout "$RED" "Sorry, I didn't understand. I can only understand answers of y or n"
|
||||
echo -n "$prompt"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
return 1
|
||||
}
|
||||
|
||||
__sudo() {
|
||||
local expl="$1"
|
||||
local cmd="$2"
|
||||
shift
|
||||
header "sudo execution"
|
||||
|
||||
echo "I am executing:"
|
||||
echo ""
|
||||
printf " $ sudo %s\\n" "$cmd"
|
||||
echo ""
|
||||
echo "$expl"
|
||||
echo ""
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_sudo() {
|
||||
local expl="$1"
|
||||
shift
|
||||
if ! headless; then
|
||||
__sudo "$expl" "$*"
|
||||
fi
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
|
||||
readonly SCRATCH=$(mktemp -d -t tmp.XXXXXXXXXX)
|
||||
function finish_cleanup {
|
||||
rm -rf "$SCRATCH"
|
||||
}
|
||||
|
||||
function finish_fail {
|
||||
finish_cleanup
|
||||
|
||||
failure <<EOF
|
||||
Jeeze, something went wrong. If you can take all the output and open
|
||||
an issue, we'd love to fix the problem so nobody else has this issue.
|
||||
|
||||
:(
|
||||
EOF
|
||||
}
|
||||
trap finish_fail EXIT
|
||||
|
||||
channel_update_failed=0
|
||||
function finish_success {
|
||||
finish_cleanup
|
||||
|
||||
ok "Alright! We're done!"
|
||||
if [ "x$channel_update_failed" = x1 ]; then
|
||||
echo ""
|
||||
echo "But fetching the nixpkgs channel failed. (Are you offline?)"
|
||||
echo "To try again later, run \"sudo -i nix-channel --update nixpkgs\"."
|
||||
fi
|
||||
cat <<EOF
|
||||
|
||||
Before Nix will work in your existing shells, you'll need to close
|
||||
them and open them again. Other than that, you should be ready to go.
|
||||
|
||||
Try it! Open a new terminal, and type:
|
||||
|
||||
$ nix-shell -p nix-info --run "nix-info -m"
|
||||
|
||||
Thank you for using this installer. If you have any feedback, don't
|
||||
hesitate:
|
||||
|
||||
$(contactme)
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
validate_starting_assumptions() {
|
||||
poly_validate_assumptions
|
||||
|
||||
if [ $EUID -eq 0 ]; then
|
||||
failure <<EOF
|
||||
Please do not run this script with root privileges. We will call sudo
|
||||
when we need to.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if type nix-env 2> /dev/null >&2; then
|
||||
failure <<EOF
|
||||
Nix already appears to be installed, and this tool assumes it is
|
||||
_not_ yet installed.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "${NIX_REMOTE:-}" != "" ]; then
|
||||
failure <<EOF
|
||||
For some reason, \$NIX_REMOTE is set. It really should not be set
|
||||
before this installer runs, and it hints that Nix is currently
|
||||
installed. Please delete the old Nix installation and start again.
|
||||
|
||||
Note: You might need to close your shell window and open a new shell
|
||||
to clear the variable.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if echo "${SSL_CERT_FILE:-}" | grep -qE "(nix/var/nix|nix-profile)"; then
|
||||
failure <<EOF
|
||||
It looks like \$SSL_CERT_FILE is set to a path that used to be part of
|
||||
the old Nix installation. Please unset that variable and try again:
|
||||
|
||||
$ unset SSL_CERT_FILE
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
for file in ~/.bash_profile ~/.bash_login ~/.profile ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin; do
|
||||
if [ -f "$file" ]; then
|
||||
if grep -l "^[^#].*.nix-profile" "$file"; then
|
||||
failure <<EOF
|
||||
I found a reference to a ".nix-profile" in $file.
|
||||
This has a high chance of breaking a new nix installation. It was most
|
||||
likely put there by a previous Nix installer.
|
||||
|
||||
Please remove this reference and try running this again. You should
|
||||
also look for similar references in:
|
||||
|
||||
- ~/.bash_profile
|
||||
- ~/.bash_login
|
||||
- ~/.profile
|
||||
|
||||
or other shell init files that you may have.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -d /nix/store ] || [ -d /nix/var ]; then
|
||||
failure <<EOF
|
||||
There are some relics of a previous installation of Nix at /nix, and
|
||||
this scripts assumes Nix is _not_ yet installed. Please delete the old
|
||||
Nix installation and start again.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -d /etc/nix ]; then
|
||||
failure <<EOF
|
||||
There are some relics of a previous installation of Nix at /etc/nix, and
|
||||
this scripts assumes Nix is _not_ yet installed. Please delete the old
|
||||
Nix installation and start again.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target$PROFILE_BACKUP_SUFFIX" ]; then
|
||||
failure <<EOF
|
||||
When this script runs, it backs up the current $profile_target to
|
||||
$profile_target$PROFILE_BACKUP_SUFFIX. This backup file already exists, though.
|
||||
|
||||
Please follow these instructions to clean up the old backup file:
|
||||
|
||||
1. Copy $profile_target and $profile_target$PROFILE_BACKUP_SUFFIX to another place, just
|
||||
in case.
|
||||
|
||||
2. Take care to make sure that $profile_target$PROFILE_BACKUP_SUFFIX doesn't look like
|
||||
it has anything nix-related in it. If it does, something is probably
|
||||
quite wrong. Please open an issue or get in touch immediately.
|
||||
|
||||
3. Take care to make sure that $profile_target doesn't look like it has
|
||||
anything nix-related in it. If it does, and $profile_target _did not_,
|
||||
run:
|
||||
|
||||
$ /usr/bin/sudo /bin/mv $profile_target$PROFILE_BACKUP_SUFFIX $profile_target
|
||||
|
||||
and try again.
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ -e "$profile_target" ] && grep -qi "nix" "$profile_target"; then
|
||||
failure <<EOF
|
||||
It looks like $profile_target already has some Nix configuration in
|
||||
there. There should be no reason to run this again. If you're having
|
||||
trouble, please open an issue.
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
danger_paths=("$ROOT_HOME/.nix-defexpr" "$ROOT_HOME/.nix-channels" "$ROOT_HOME/.nix-profile")
|
||||
for danger_path in "${danger_paths[@]}"; do
|
||||
if _sudo "making sure that $danger_path doesn't exist" \
|
||||
test -e "$danger_path"; then
|
||||
failure <<EOF
|
||||
I found a file at $danger_path, which is a relic of a previous
|
||||
installation. You must first delete this file before continuing.
|
||||
|
||||
$(uninstall_directions)
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
setup_report() {
|
||||
header "Nix config report"
|
||||
row " Temp Dir" "$SCRATCH"
|
||||
row " Nix Root" "$NIX_ROOT"
|
||||
row " Build Users" "$NIX_USER_COUNT"
|
||||
row " Build Group ID" "$NIX_BUILD_GROUP_ID"
|
||||
row "Build Group Name" "$NIX_BUILD_GROUP_NAME"
|
||||
if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" != "" ]; then
|
||||
row "Preexisting Install" "Allowed"
|
||||
fi
|
||||
|
||||
subheader "build users:"
|
||||
|
||||
row " Username" "UID"
|
||||
for i in $(seq 1 "$NIX_USER_COUNT"); do
|
||||
row " $(nix_user_for_core "$i")" "$(nix_uid_for_core "$i")"
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
create_build_group() {
|
||||
local primary_group_id
|
||||
|
||||
task "Setting up the build group $NIX_BUILD_GROUP_NAME"
|
||||
if ! poly_group_exists "$NIX_BUILD_GROUP_NAME"; then
|
||||
poly_create_build_group
|
||||
row " Created" "Yes"
|
||||
else
|
||||
primary_group_id=$(poly_group_id_get "$NIX_BUILD_GROUP_NAME")
|
||||
if [ "$primary_group_id" -ne "$NIX_BUILD_GROUP_ID" ]; then
|
||||
failure <<EOF
|
||||
It seems the build group $NIX_BUILD_GROUP_NAME already exists, but
|
||||
with the UID $primary_group_id. This script can't really handle
|
||||
that right now, so I'm going to give up.
|
||||
|
||||
You can fix this by editing this script and changing the
|
||||
NIX_BUILD_GROUP_ID variable near the top to from $NIX_BUILD_GROUP_ID
|
||||
to $primary_group_id and re-run.
|
||||
EOF
|
||||
else
|
||||
row " Exists" "Yes"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
create_build_user_for_core() {
|
||||
local coreid
|
||||
local username
|
||||
local uid
|
||||
|
||||
coreid="$1"
|
||||
username=$(nix_user_for_core "$coreid")
|
||||
uid=$(nix_uid_for_core "$coreid")
|
||||
|
||||
task "Setting up the build user $username"
|
||||
|
||||
if ! poly_user_exists "$username"; then
|
||||
poly_create_build_user "$username" "$uid" "$coreid"
|
||||
row " Created" "Yes"
|
||||
else
|
||||
actual_uid=$(poly_user_id_get "$username")
|
||||
if [ "$actual_uid" != "$uid" ]; then
|
||||
failure <<EOF
|
||||
It seems the build user $username already exists, but with the UID
|
||||
with the UID '$actual_uid'. This script can't really handle that right
|
||||
now, so I'm going to give up.
|
||||
|
||||
If you already created the users and you know they start from
|
||||
$actual_uid and go up from there, you can edit this script and change
|
||||
NIX_FIRST_BUILD_UID near the top of the file to $actual_uid and try
|
||||
again.
|
||||
EOF
|
||||
else
|
||||
row " Exists" "Yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$(poly_user_hidden_get "$username")" = "1" ]; then
|
||||
row " Hidden" "Yes"
|
||||
else
|
||||
poly_user_hidden_set "$username"
|
||||
row " Hidden" "Yes"
|
||||
fi
|
||||
|
||||
if [ "$(poly_user_home_get "$username")" = "/var/empty" ]; then
|
||||
row " Home Directory" "/var/empty"
|
||||
else
|
||||
poly_user_home_set "$username" "/var/empty"
|
||||
row " Home Directory" "/var/empty"
|
||||
fi
|
||||
|
||||
# We use grep instead of an equality check because it is difficult
|
||||
# to extract _just_ the user's note, instead it is prefixed with
|
||||
# some plist junk. This was causing the user note to always be set,
|
||||
# even if there was no reason for it.
|
||||
if ! poly_user_note_get "$username" | grep -q "Nix build user $coreid"; then
|
||||
row " Note" "Nix build user $coreid"
|
||||
else
|
||||
poly_user_note_set "$username" "Nix build user $coreid"
|
||||
row " Note" "Nix build user $coreid"
|
||||
fi
|
||||
|
||||
if [ "$(poly_user_shell_get "$username")" = "/sbin/nologin" ]; then
|
||||
row " Logins Disabled" "Yes"
|
||||
else
|
||||
poly_user_shell_set "$username" "/sbin/nologin"
|
||||
row " Logins Disabled" "Yes"
|
||||
fi
|
||||
|
||||
if poly_user_in_group_check "$username" "$NIX_BUILD_GROUP_NAME"; then
|
||||
row " Member of $NIX_BUILD_GROUP_NAME" "Yes"
|
||||
else
|
||||
poly_user_in_group_set "$username" "$NIX_BUILD_GROUP_NAME"
|
||||
row " Member of $NIX_BUILD_GROUP_NAME" "Yes"
|
||||
fi
|
||||
|
||||
if [ "$(poly_user_primary_group_get "$username")" = "$NIX_BUILD_GROUP_ID" ]; then
|
||||
row " PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
else
|
||||
poly_user_primary_group_set "$username" "$NIX_BUILD_GROUP_ID"
|
||||
row " PrimaryGroupID" "$NIX_BUILD_GROUP_ID"
|
||||
fi
|
||||
}
|
||||
|
||||
create_build_users() {
|
||||
for i in $(seq 1 "$NIX_USER_COUNT"); do
|
||||
create_build_user_for_core "$i"
|
||||
done
|
||||
}
|
||||
|
||||
create_directories() {
|
||||
_sudo "to make the basic directory structure of Nix (part 1)" \
|
||||
mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool}
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 2)" \
|
||||
mkdir -pv -m 1777 /nix/var/nix/{gcroots,profiles}/per-user
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 3)" \
|
||||
mkdir -pv -m 1775 /nix/store
|
||||
|
||||
_sudo "to make the basic directory structure of Nix (part 4)" \
|
||||
chgrp "$NIX_BUILD_GROUP_NAME" /nix/store
|
||||
|
||||
_sudo "to set up the root user's profile (part 1)" \
|
||||
mkdir -pv -m 0755 /nix/var/nix/profiles/per-user/root
|
||||
|
||||
_sudo "to set up the root user's profile (part 2)" \
|
||||
mkdir -pv -m 0700 "$ROOT_HOME/.nix-defexpr"
|
||||
|
||||
_sudo "to place the default nix daemon configuration (part 1)" \
|
||||
mkdir -pv -m 0555 /etc/nix
|
||||
}
|
||||
|
||||
place_channel_configuration() {
|
||||
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$SCRATCH/.nix-channels"
|
||||
_sudo "to set up the default system channel (part 1)" \
|
||||
install -m 0664 "$SCRATCH/.nix-channels" "$ROOT_HOME/.nix-channels"
|
||||
}
|
||||
|
||||
welcome_to_nix() {
|
||||
ok "Welcome to the Multi-User Nix Installation"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
This installation tool will set up your computer with the Nix package
|
||||
manager. This will happen in a few stages:
|
||||
|
||||
1. Make sure your computer doesn't already have Nix. If it does, I
|
||||
will show you instructions on how to clean up your old one.
|
||||
|
||||
2. Show you what we are going to install and where. Then we will ask
|
||||
if you are ready to continue.
|
||||
|
||||
3. Create the system users and groups that the Nix daemon uses to run
|
||||
builds.
|
||||
|
||||
4. Perform the basic installation of the Nix files daemon.
|
||||
|
||||
5. Configure your shell to import special Nix Profile files, so you
|
||||
can use Nix.
|
||||
|
||||
6. Start the Nix daemon.
|
||||
|
||||
EOF
|
||||
|
||||
if ui_confirm "Would you like to see a more detailed list of what we will do?"; then
|
||||
cat <<EOF
|
||||
|
||||
We will:
|
||||
|
||||
- make sure your computer doesn't already have Nix files
|
||||
(if it does, I will tell you how to clean them up.)
|
||||
- create local users (see the list above for the users we'll make)
|
||||
- create a local group ($NIX_BUILD_GROUP_NAME)
|
||||
- install Nix in to $NIX_ROOT
|
||||
- create a configuration file in /etc/nix
|
||||
- set up the "default profile" by creating some Nix-related files in
|
||||
$ROOT_HOME
|
||||
EOF
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ]; then
|
||||
cat <<EOF
|
||||
- back up $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX
|
||||
- update $profile_target to include some Nix configuration
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
poly_service_setup_note
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
failure <<EOF
|
||||
Okay, maybe you would like to talk to the team.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
chat_about_sudo() {
|
||||
header "let's talk about sudo"
|
||||
|
||||
if headless; then
|
||||
cat <<EOF
|
||||
This script is going to call sudo a lot. Normally, it would show you
|
||||
exactly what commands it is running and why. However, the script is
|
||||
run in a headless fashion, like this:
|
||||
|
||||
$ curl https://nixos.org/nix/install | sh
|
||||
|
||||
or maybe in a CI pipeline. Because of that, we're going to skip the
|
||||
verbose output in the interest of brevity.
|
||||
|
||||
If you would like to
|
||||
see the output, try like this:
|
||||
|
||||
$ curl -o install-nix https://nixos.org/nix/install
|
||||
$ sh ./install-nix
|
||||
|
||||
EOF
|
||||
return 0
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
This script is going to call sudo a lot. Every time we do, it'll
|
||||
output exactly what it'll do, and why.
|
||||
|
||||
Just like this:
|
||||
EOF
|
||||
|
||||
__sudo "to demonstrate how our sudo prompts look" \
|
||||
echo "this is a sudo prompt"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
This might look scary, but everything can be undone by running just a
|
||||
few commands. We used to ask you to confirm each time sudo ran, but it
|
||||
was too many times. Instead, I'll just ask you this one time:
|
||||
|
||||
EOF
|
||||
if ui_confirm "Can we use sudo?"; then
|
||||
ok "Yay! Thanks! Let's get going!"
|
||||
else
|
||||
failure <<EOF
|
||||
That is okay, but we can't install.
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
install_from_extracted_nix() {
|
||||
(
|
||||
cd "$EXTRACTED_NIX_PATH"
|
||||
|
||||
_sudo "to copy the basic Nix files to the new store at $NIX_ROOT/store" \
|
||||
rsync -rlpt ./store/* "$NIX_ROOT/store/"
|
||||
|
||||
if [ -d "$NIX_INSTALLED_NIX" ]; then
|
||||
echo " Alright! We have our first nix at $NIX_INSTALLED_NIX"
|
||||
else
|
||||
failure <<EOF
|
||||
Something went wrong, and I didn't find Nix installed at
|
||||
$NIX_INSTALLED_NIX.
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat ./.reginfo \
|
||||
| _sudo "to load data for the first time in to the Nix Database" \
|
||||
"$NIX_INSTALLED_NIX/bin/nix-store" --load-db
|
||||
|
||||
echo " Just finished getting the nix database ready."
|
||||
)
|
||||
}
|
||||
|
||||
shell_source_lines() {
|
||||
cat <<EOF
|
||||
|
||||
# Nix
|
||||
if [ -e '$PROFILE_NIX_FILE' ]; then
|
||||
. '$PROFILE_NIX_FILE'
|
||||
fi
|
||||
# End Nix
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
configure_shell_profile() {
|
||||
# If there is an /etc/profile.d directory, we want to ensure there
|
||||
# is a nix.sh within it, so we can use the following loop to add
|
||||
# the source lines to it. Note that I'm _not_ adding the source
|
||||
# lines here, because we want to be using the regular machinery.
|
||||
#
|
||||
# If we go around that machinery, it becomes more complicated and
|
||||
# adds complications to the uninstall instruction generator and
|
||||
# old instruction sniffer as well.
|
||||
if [ -d /etc/profile.d ]; then
|
||||
_sudo "create a stub /etc/profile.d/nix.sh which will be updated" \
|
||||
touch /etc/profile.d/nix.sh
|
||||
fi
|
||||
|
||||
for profile_target in "${PROFILE_TARGETS[@]}"; do
|
||||
if [ -e "$profile_target" ]; then
|
||||
_sudo "to back up your current $profile_target to $profile_target$PROFILE_BACKUP_SUFFIX" \
|
||||
cp "$profile_target" "$profile_target$PROFILE_BACKUP_SUFFIX"
|
||||
|
||||
shell_source_lines \
|
||||
| _sudo "extend your $profile_target with nix-daemon settings" \
|
||||
tee -a "$profile_target"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
setup_default_profile() {
|
||||
_sudo "to installing a bootstrapping Nix in to the default Profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_NIX"
|
||||
|
||||
if [ -z "${NIX_SSL_CERT_FILE:-}" ] || ! [ -f "${NIX_SSL_CERT_FILE:-}" ]; then
|
||||
_sudo "to installing a bootstrapping SSL certificate just for Nix in to the default Profile" \
|
||||
HOME="$ROOT_HOME" "$NIX_INSTALLED_NIX/bin/nix-env" -i "$NIX_INSTALLED_CACERT"
|
||||
export NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt
|
||||
fi
|
||||
|
||||
# Have to explicitly pass NIX_SSL_CERT_FILE as part of the sudo call,
|
||||
# otherwise it will be lost in environments where sudo doesn't pass
|
||||
# all the environment variables by default.
|
||||
_sudo "to update the default channel in the default profile" \
|
||||
HOME="$ROOT_HOME" NIX_SSL_CERT_FILE="$NIX_SSL_CERT_FILE" "$NIX_INSTALLED_NIX/bin/nix-channel" --update nixpkgs \
|
||||
|| channel_update_failed=1
|
||||
|
||||
}
|
||||
|
||||
|
||||
place_nix_configuration() {
|
||||
cat <<EOF > "$SCRATCH/nix.conf"
|
||||
build-users-group = $NIX_BUILD_GROUP_NAME
|
||||
EOF
|
||||
_sudo "to place the default nix daemon configuration (part 2)" \
|
||||
install -m 0664 "$SCRATCH/nix.conf" /etc/nix/nix.conf
|
||||
}
|
||||
|
||||
main() {
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
# shellcheck source=./install-darwin-multi-user.sh
|
||||
. "$EXTRACTED_NIX_PATH/install-darwin-multi-user.sh"
|
||||
elif [ "$(uname -s)" = "Linux" ]; then
|
||||
if [ -e /run/systemd/system ]; then
|
||||
# shellcheck source=./install-systemd-multi-user.sh
|
||||
. "$EXTRACTED_NIX_PATH/install-systemd-multi-user.sh"
|
||||
else
|
||||
failure "Sorry, the multi-user installation requires systemd on Linux (detected using /run/systemd/system)"
|
||||
fi
|
||||
else
|
||||
failure "Sorry, I don't know what to do on $(uname)"
|
||||
fi
|
||||
|
||||
welcome_to_nix
|
||||
chat_about_sudo
|
||||
|
||||
if [ "${ALLOW_PREEXISTING_INSTALLATION:-}" = "" ]; then
|
||||
validate_starting_assumptions
|
||||
fi
|
||||
|
||||
setup_report
|
||||
|
||||
if ! ui_confirm "Ready to continue?"; then
|
||||
ok "Alright, no changes have been made :)"
|
||||
contactme
|
||||
trap finish_cleanup EXIT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
create_build_group
|
||||
create_build_users
|
||||
create_directories
|
||||
place_channel_configuration
|
||||
install_from_extracted_nix
|
||||
|
||||
configure_shell_profile
|
||||
|
||||
set +eu
|
||||
. /etc/profile
|
||||
set -eu
|
||||
|
||||
setup_default_profile
|
||||
place_nix_configuration
|
||||
poly_configure_nix_daemon_service
|
||||
|
||||
trap finish_success EXIT
|
||||
}
|
||||
|
||||
|
||||
main
|
|
@ -12,7 +12,7 @@ if ! [ -e "$self/.reginfo" ]; then
|
|||
echo "$0: incomplete installer (.reginfo is missing)" >&2
|
||||
fi
|
||||
|
||||
if [ -z "$USER" ]; then
|
||||
if [ -z "$USER" ] && ! USER=$(id -u -n); then
|
||||
echo "$0: \$USER is not set" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
@ -22,15 +22,52 @@ if [ -z "$HOME" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# macOS support for 10.10 or higher
|
||||
# macOS support for 10.12.6 or higher
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
if [ $(($(sw_vers -productVersion | cut -d '.' -f 2))) -lt 10 ]; then
|
||||
echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.10 or higher"
|
||||
macos_major=$(sw_vers -productVersion | cut -d '.' -f 2)
|
||||
macos_minor=$(sw_vers -productVersion | cut -d '.' -f 3)
|
||||
if [ "$macos_major" -lt 12 ] || { [ "$macos_major" -eq 12 ] && [ "$macos_minor" -lt 6 ]; }; then
|
||||
echo "$0: macOS $(sw_vers -productVersion) is not supported, upgrade to 10.12.6 or higher"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
printf '\e[1;31mSwitching to the Multi-User Darwin Installer\e[0m\n'
|
||||
exec "$self/install-darwin-multi-user"
|
||||
# Determine if we could use the multi-user installer or not
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
|
||||
elif [ "$(uname -s)" = "Linux" ] && [ -e /run/systemd/system ]; then
|
||||
echo "Note: a multi-user installation is possible. See https://nixos.org/nix/manual/#sect-multi-user-installation" >&2
|
||||
fi
|
||||
|
||||
INSTALL_MODE=no-daemon
|
||||
# Trivially handle the --daemon / --no-daemon options
|
||||
if [ "x${1:-}" = "x--no-daemon" ]; then
|
||||
INSTALL_MODE=no-daemon
|
||||
elif [ "x${1:-}" = "x--daemon" ]; then
|
||||
INSTALL_MODE=daemon
|
||||
elif [ "x${1:-}" != "x" ]; then
|
||||
(
|
||||
echo "Nix Installer [--daemon|--no-daemon]"
|
||||
|
||||
echo "Choose installation method."
|
||||
echo ""
|
||||
echo " --daemon: Installs and configures a background daemon that manages the store,"
|
||||
echo " providing multi-user support and better isolation for local builds."
|
||||
echo " Both for security and reproducibility, this method is recommended if"
|
||||
echo " supported on your platform."
|
||||
echo " See https://nixos.org/nix/manual/#sect-multi-user-installation"
|
||||
echo ""
|
||||
echo " --no-daemon: Simple, single-user installation that does not require root and is"
|
||||
echo " trivial to uninstall."
|
||||
echo " (default)"
|
||||
echo ""
|
||||
) >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$INSTALL_MODE" = "daemon" ]; then
|
||||
printf '\e[1;31mSwitching to the Daemon-based Installer\e[0m\n'
|
||||
exec "$self/install-multi-user"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
@ -74,12 +111,6 @@ for i in $(cd "$self/store" >/dev/null && echo ./*); do
|
|||
done
|
||||
echo "" >&2
|
||||
|
||||
echo "initialising Nix database..." >&2
|
||||
if ! $nix/bin/nix-store --init; then
|
||||
echo "$0: failed to initialize the Nix database" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! "$nix/bin/nix-store" --load-db < "$self/.reginfo"; then
|
||||
echo "$0: unable to register valid paths" >&2
|
||||
exit 1
|
||||
|
@ -103,7 +134,10 @@ if ! $nix/bin/nix-channel --list | grep -q "^nixpkgs "; then
|
|||
$nix/bin/nix-channel --add https://nixos.org/channels/nixpkgs-unstable
|
||||
fi
|
||||
if [ -z "$_NIX_INSTALLER_TEST" ]; then
|
||||
$nix/bin/nix-channel --update nixpkgs
|
||||
if ! $nix/bin/nix-channel --update nixpkgs; then
|
||||
echo "Fetching the nixpkgs channel failed. (Are you offline?)"
|
||||
echo "To try again later, run \"nix-channel --update nixpkgs\"."
|
||||
fi
|
||||
fi
|
||||
|
||||
added=
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
readonly SERVICE_SRC=/lib/systemd/system/nix-daemon.service
|
||||
readonly SERVICE_DEST=/etc/systemd/system/nix-daemon.service
|
||||
|
||||
readonly SOCKET_SRC=/lib/systemd/system/nix-daemon.socket
|
||||
readonly SOCKET_DEST=/etc/systemd/system/nix-daemon.socket
|
||||
|
||||
|
||||
# Path for the systemd override unit file to contain the proxy settings
|
||||
readonly SERVICE_OVERRIDE=${SERVICE_DEST}.d/override.conf
|
||||
|
||||
create_systemd_override() {
|
||||
header "Configuring proxy for the nix-daemon service"
|
||||
_sudo "create directory for systemd unit override" mkdir -p "$(dirname $SERVICE_OVERRIDE)"
|
||||
cat <<EOF | _sudo "create systemd unit override" tee "$SERVICE_OVERRIDE"
|
||||
[Service]
|
||||
$1
|
||||
EOF
|
||||
}
|
||||
|
||||
# Gather all non-empty proxy environment variables into a string
|
||||
create_systemd_proxy_env() {
|
||||
vars="http_proxy https_proxy ftp_proxy no_proxy HTTP_PROXY HTTPS_PROXY FTP_PROXY NO_PROXY"
|
||||
for v in $vars; do
|
||||
if [ "x${!v:-}" != "x" ]; then
|
||||
echo "Environment=${v}=${!v}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
handle_network_proxy() {
|
||||
# Create a systemd unit override with proxy environment variables
|
||||
# if any proxy environment variables are not empty.
|
||||
PROXY_ENV_STRING=$(create_systemd_proxy_env)
|
||||
if [ -n "${PROXY_ENV_STRING}" ]; then
|
||||
create_systemd_override "${PROXY_ENV_STRING}"
|
||||
fi
|
||||
}
|
||||
|
||||
poly_validate_assumptions() {
|
||||
if [ "$(uname -s)" != "Linux" ]; then
|
||||
failure "This script is for use with Linux!"
|
||||
fi
|
||||
}
|
||||
|
||||
poly_service_installed_check() {
|
||||
[ "$(systemctl is-enabled nix-daemon.service)" = "linked" ] \
|
||||
|| [ "$(systemctl is-enabled nix-daemon.socket)" = "enabled" ]
|
||||
}
|
||||
|
||||
poly_service_uninstall_directions() {
|
||||
cat <<EOF
|
||||
$1. Delete the systemd service and socket units
|
||||
|
||||
sudo systemctl stop nix-daemon.socket
|
||||
sudo systemctl stop nix-daemon.service
|
||||
sudo systemctl disable nix-daemon.socket
|
||||
sudo systemctl disable nix-daemon.service
|
||||
sudo systemctl daemon-reload
|
||||
EOF
|
||||
}
|
||||
|
||||
poly_service_setup_note() {
|
||||
cat <<EOF
|
||||
- load and start a service (at $SERVICE_DEST
|
||||
and $SOCKET_DEST) for nix-daemon
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
poly_configure_nix_daemon_service() {
|
||||
_sudo "to set up the nix-daemon service" \
|
||||
systemctl link "/nix/var/nix/profiles/default$SERVICE_SRC"
|
||||
|
||||
_sudo "to set up the nix-daemon socket service" \
|
||||
systemctl enable "/nix/var/nix/profiles/default$SOCKET_SRC"
|
||||
|
||||
handle_network_proxy
|
||||
|
||||
_sudo "to load the systemd unit for nix-daemon" \
|
||||
systemctl daemon-reload
|
||||
|
||||
_sudo "to start the nix-daemon.socket" \
|
||||
systemctl start nix-daemon.socket
|
||||
|
||||
_sudo "to start the nix-daemon.service" \
|
||||
systemctl start nix-daemon.service
|
||||
|
||||
}
|
||||
|
||||
poly_group_exists() {
|
||||
getent group "$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_group_id_get() {
|
||||
getent group "$1" | cut -d: -f3
|
||||
}
|
||||
|
||||
poly_create_build_group() {
|
||||
_sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
|
||||
groupadd -g "$NIX_BUILD_GROUP_ID" --system \
|
||||
"$NIX_BUILD_GROUP_NAME" >&2
|
||||
}
|
||||
|
||||
poly_user_exists() {
|
||||
getent passwd "$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_user_id_get() {
|
||||
getent passwd "$1" | cut -d: -f3
|
||||
}
|
||||
|
||||
poly_user_hidden_get() {
|
||||
echo "1"
|
||||
}
|
||||
|
||||
poly_user_hidden_set() {
|
||||
true
|
||||
}
|
||||
|
||||
poly_user_home_get() {
|
||||
getent passwd "$1" | cut -d: -f6
|
||||
}
|
||||
|
||||
poly_user_home_set() {
|
||||
_sudo "in order to give $1 a safe home directory" \
|
||||
usermod --home "$2" "$1"
|
||||
}
|
||||
|
||||
poly_user_note_get() {
|
||||
getent passwd "$1" | cut -d: -f5
|
||||
}
|
||||
|
||||
poly_user_note_set() {
|
||||
_sudo "in order to give $1 a useful comment" \
|
||||
usermod --comment "$2" "$1"
|
||||
}
|
||||
|
||||
poly_user_shell_get() {
|
||||
getent passwd "$1" | cut -d: -f7
|
||||
}
|
||||
|
||||
poly_user_shell_set() {
|
||||
_sudo "in order to prevent $1 from logging in" \
|
||||
usermod --shell "$2" "$1"
|
||||
}
|
||||
|
||||
poly_user_in_group_check() {
|
||||
groups "$1" | grep -q "$2" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_user_in_group_set() {
|
||||
_sudo "Add $1 to the $2 group"\
|
||||
usermod --append --groups "$2" "$1"
|
||||
}
|
||||
|
||||
poly_user_primary_group_get() {
|
||||
getent passwd "$1" | cut -d: -f4
|
||||
}
|
||||
|
||||
poly_user_primary_group_set() {
|
||||
_sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
|
||||
usermod --gid "$2" "$1"
|
||||
|
||||
}
|
||||
|
||||
poly_create_build_user() {
|
||||
username=$1
|
||||
uid=$2
|
||||
builder_num=$3
|
||||
|
||||
_sudo "Creating the Nix build user, $username" \
|
||||
useradd \
|
||||
--home-dir /var/empty \
|
||||
--comment "Nix build user $builder_num" \
|
||||
--gid "$NIX_BUILD_GROUP_ID" \
|
||||
--groups "$NIX_BUILD_GROUP_NAME" \
|
||||
--no-user-group \
|
||||
--system \
|
||||
--shell /sbin/nologin \
|
||||
--uid "$uid" \
|
||||
--password "!" \
|
||||
"$username"
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script installs the Nix package manager on your system by
|
||||
# downloading a binary distribution and running its installer script
|
||||
# (which in turn creates and populates /nix).
|
||||
|
||||
{ # Prevent execution if this script was only partially downloaded
|
||||
oops() {
|
||||
echo "$0:" "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
tmpDir="$(mktemp -d -t nix-binary-tarball-unpack.XXXXXXXXXX || \
|
||||
oops "Can't create temporary directory for downloading the Nix binary tarball")"
|
||||
cleanup() {
|
||||
rm -rf "$tmpDir"
|
||||
}
|
||||
trap cleanup EXIT INT QUIT TERM
|
||||
|
||||
require_util() {
|
||||
command -v "$1" > /dev/null 2>&1 ||
|
||||
oops "you do not have '$1' installed, which I need to $2"
|
||||
}
|
||||
|
||||
case "$(uname -s).$(uname -m)" in
|
||||
Linux.x86_64) system=x86_64-linux; hash=@binaryTarball_x86_64-linux@;;
|
||||
Linux.i?86) system=i686-linux; hash=@binaryTarball_i686-linux@;;
|
||||
Linux.aarch64) system=aarch64-linux; hash=@binaryTarball_aarch64-linux@;;
|
||||
Darwin.x86_64) system=x86_64-darwin; hash=@binaryTarball_x86_64-darwin@;;
|
||||
*) oops "sorry, there is no binary distribution of Nix for your platform";;
|
||||
esac
|
||||
|
||||
url="https://nixos.org/releases/nix/nix-@nixVersion@/nix-@nixVersion@-$system.tar.xz"
|
||||
|
||||
tarball="$tmpDir/$(basename "$tmpDir/nix-@nixVersion@-$system.tar.xz")"
|
||||
|
||||
require_util curl "download the binary tarball"
|
||||
require_util tar "unpack the binary tarball"
|
||||
|
||||
echo "downloading Nix @nixVersion@ binary tarball for $system from '$url' to '$tmpDir'..."
|
||||
curl -L "$url" -o "$tarball" || oops "failed to download '$url'"
|
||||
|
||||
if command -v sha256sum > /dev/null 2>&1; then
|
||||
hash2="$(sha256sum -b "$tarball" | cut -c1-64)"
|
||||
elif command -v shasum > /dev/null 2>&1; then
|
||||
hash2="$(shasum -a 256 -b "$tarball" | cut -c1-64)"
|
||||
elif command -v openssl > /dev/null 2>&1; then
|
||||
hash2="$(openssl dgst -r -sha256 "$tarball" | cut -c1-64)"
|
||||
else
|
||||
oops "cannot verify the SHA-256 hash of '$url'; you need one of 'shasum', 'sha256sum', or 'openssl'"
|
||||
fi
|
||||
|
||||
if [ "$hash" != "$hash2" ]; then
|
||||
oops "SHA-256 hash mismatch in '$url'; expected $hash, got $hash2"
|
||||
fi
|
||||
|
||||
unpack=$tmpDir/unpack
|
||||
mkdir -p "$unpack"
|
||||
tar -xf "$tarball" -C "$unpack" || oops "failed to unpack '$url'"
|
||||
|
||||
script=$(echo "$unpack"/*/install)
|
||||
|
||||
[ -e "$script" ] || oops "installation script is missing from the binary tarball!"
|
||||
"$script" "$@"
|
||||
|
||||
} # End of wrapping
|
|
@ -1,13 +1,7 @@
|
|||
# Only execute this file once per shell.
|
||||
if [ -n "$__ETC_PROFILE_NIX_SOURCED" ]; then return; fi
|
||||
if [ -n "${__ETC_PROFILE_NIX_SOURCED:-}" ]; then return; fi
|
||||
__ETC_PROFILE_NIX_SOURCED=1
|
||||
|
||||
# Set up secure multi-user builds: non-root users build through the
|
||||
# Nix daemon.
|
||||
if [ "$USER" != root -o ! -w @localstatedir@/nix/db ]; then
|
||||
export NIX_REMOTE=daemon
|
||||
fi
|
||||
|
||||
export NIX_USER_PROFILE_DIR="@localstatedir@/nix/profiles/per-user/$USER"
|
||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
||||
|
||||
|
@ -49,6 +43,26 @@ if test -w $HOME; then
|
|||
fi
|
||||
fi
|
||||
|
||||
export NIX_SSL_CERT_FILE="@localstatedir@/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
|
||||
export NIX_PATH="@localstatedir@/nix/profiles/per-user/root/channels"
|
||||
export PATH="$HOME/.nix-profile/bin:$HOME/.nix-profile/lib/kde4/libexec:@localstatedir@/nix/profiles/default/bin:@localstatedir@/nix/profiles/default:@localstatedir@/nix/profiles/default/lib/kde4/libexec:$PATH"
|
||||
|
||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||
if [ ! -z "${NIX_SSL_CERT_FILE:-}" ]; then
|
||||
: # Allow users to override the NIX_SSL_CERT_FILE
|
||||
elif [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
|
||||
export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||
elif [ -e /etc/ssl/ca-bundle.pem ]; then # openSUSE Tumbleweed
|
||||
export NIX_SSL_CERT_FILE=/etc/ssl/ca-bundle.pem
|
||||
elif [ -e /etc/ssl/certs/ca-bundle.crt ]; then # Old NixOS
|
||||
export NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
|
||||
elif [ -e /etc/pki/tls/certs/ca-bundle.crt ]; then # Fedora, CentOS
|
||||
export NIX_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
|
||||
else
|
||||
# Fall back to what is in the nix profiles, favouring whatever is defined last.
|
||||
for i in $NIX_PROFILES; do
|
||||
if [ -e $i/etc/ssl/certs/ca-bundle.crt ]; then
|
||||
export NIX_SSL_CERT_FILE=$i/etc/ssl/certs/ca-bundle.crt
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
export NIX_PATH="nixpkgs=@localstatedir@/nix/profiles/per-user/root/channels/nixpkgs:@localstatedir@/nix/profiles/per-user/root/channels"
|
||||
export PATH="$HOME/.nix-profile/bin:@localstatedir@/nix/profiles/default/bin:$PATH"
|
||||
|
|
|
@ -51,14 +51,13 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
|||
unset __nix_defexpr
|
||||
fi
|
||||
|
||||
# Append ~/.nix-defexpr/channels/nixpkgs to $NIX_PATH so that
|
||||
# <nixpkgs> paths work when the user has fetched the Nixpkgs
|
||||
# channel.
|
||||
export NIX_PATH="${NIX_PATH:+$NIX_PATH:}nixpkgs=$HOME/.nix-defexpr/channels/nixpkgs"
|
||||
# Append ~/.nix-defexpr/channels to $NIX_PATH so that <nixpkgs>
|
||||
# paths work when the user has fetched the Nixpkgs channel.
|
||||
export NIX_PATH=${NIX_PATH:+$NIX_PATH:}$HOME/.nix-defexpr/channels
|
||||
|
||||
# Set up environment.
|
||||
# This part should be kept in sync with nixpkgs:nixos/modules/programs/environment.nix
|
||||
NIX_PROFILES="@localstatedir@/nix/profiles/default $NIX_USER_PROFILE_DIR"
|
||||
export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile"
|
||||
|
||||
# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
|
||||
if [ -e /etc/ssl/certs/ca-certificates.crt ]; then # NixOS, Ubuntu, Debian, Gentoo, Arch
|
||||
|
@ -75,10 +74,10 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
|
|||
export NIX_SSL_CERT_FILE="$NIX_LINK/etc/ca-bundle.crt"
|
||||
fi
|
||||
|
||||
if [ -n "${MANPATH}" ]; then
|
||||
if [ -n "${MANPATH-}" ]; then
|
||||
export MANPATH="$NIX_LINK/share/man:$MANPATH"
|
||||
fi
|
||||
|
||||
export PATH="$NIX_LINK/bin:$__savedpath"
|
||||
unset __savedpath NIX_LINK NIX_USER_PROFILE_DIR NIX_PROFILES
|
||||
unset __savedpath NIX_LINK NIX_USER_PROFILE_DIR
|
||||
fi
|
||||
|
|
24
shell.nix
24
shell.nix
|
@ -1,33 +1,13 @@
|
|||
{ useClang ? false }:
|
||||
|
||||
with import <nixpkgs> {};
|
||||
with import (builtins.fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-19.03.tar.gz) {};
|
||||
|
||||
with import ./release-common.nix { inherit pkgs; };
|
||||
|
||||
(if useClang then clangStdenv else stdenv).mkDerivation {
|
||||
name = "nix";
|
||||
|
||||
buildInputs =
|
||||
[ curl bison flex libxml2 libxslt
|
||||
bzip2 xz brotli
|
||||
pkgconfig sqlite libsodium boehmgc
|
||||
docbook5 docbook5_xsl
|
||||
autoconf-archive
|
||||
(aws-sdk-cpp.override {
|
||||
apis = ["s3"];
|
||||
customMemoryManagement = false;
|
||||
})
|
||||
autoreconfHook
|
||||
|
||||
# For nix-perl
|
||||
perl
|
||||
perlPackages.DBDSQLite
|
||||
|
||||
# Tests
|
||||
git
|
||||
mercurial
|
||||
]
|
||||
++ lib.optional stdenv.isLinux libseccomp;
|
||||
buildInputs = buildDeps ++ tarballDeps ++ perlDeps;
|
||||
|
||||
inherit configureFlags;
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// boost/assert.hpp - BOOST_ASSERT(expr)
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// Note: There are no include guards. This is intentional.
|
||||
//
|
||||
// See http://www.boost.org/libs/utility/assert.html for documentation.
|
||||
//
|
||||
|
||||
#undef BOOST_ASSERT
|
||||
|
||||
#if defined(BOOST_DISABLE_ASSERTS)
|
||||
|
||||
# define BOOST_ASSERT(expr) ((void)0)
|
||||
|
||||
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
|
||||
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
||||
|
||||
#else
|
||||
# include <assert.h>
|
||||
# define BOOST_ASSERT(expr) assert(expr)
|
||||
#endif
|
|
@ -1,64 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// format.hpp : primary header
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_FORMAT_HPP
|
||||
#define BOOST_FORMAT_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
|
||||
#if HAVE_LOCALE
|
||||
#include <locale>
|
||||
#else
|
||||
#define BOOST_NO_STD_LOCALE
|
||||
#define BOOST_NO_LOCALE_ISIDIGIT
|
||||
#include <cctype>
|
||||
#endif
|
||||
|
||||
#include <boost/format/macros_default.hpp>
|
||||
|
||||
|
||||
// **** Forward declarations ----------------------------------
|
||||
#include <boost/format/format_fwd.hpp> // basic_format<Ch,Tr>, and other frontends
|
||||
#include <boost/format/internals_fwd.hpp> // misc forward declarations for internal use
|
||||
|
||||
|
||||
// **** Auxiliary structs (stream_format_state<Ch,Tr> , and format_item<Ch,Tr> )
|
||||
#include <boost/format/internals.hpp>
|
||||
|
||||
// **** Format class interface --------------------------------
|
||||
#include <boost/format/format_class.hpp>
|
||||
|
||||
// **** Exceptions -----------------------------------------------
|
||||
#include <boost/format/exceptions.hpp>
|
||||
|
||||
// **** Implementation -------------------------------------------
|
||||
//#include <boost/format/format_implementation.hpp> // member functions
|
||||
|
||||
#include <boost/format/group.hpp> // class for grouping arguments
|
||||
|
||||
#include <boost/format/feed_args.hpp> // argument-feeding functions
|
||||
//#include <boost/format/parsing.hpp> // format-string parsing (member-)functions
|
||||
|
||||
// **** Implementation of the free functions ----------------------
|
||||
//#include <boost/format/free_funcs.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_HPP
|
|
@ -1,96 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// exceptions.hpp
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BOOST_FORMAT_EXCEPTIONS_HPP
|
||||
#define BOOST_FORMAT_EXCEPTIONS_HPP
|
||||
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace io {
|
||||
|
||||
// **** exceptions -----------------------------------------------
|
||||
|
||||
class format_error : public std::exception
|
||||
{
|
||||
public:
|
||||
format_error() { abort(); }
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return "boost::format_error: "
|
||||
"format generic failure";
|
||||
}
|
||||
};
|
||||
|
||||
class bad_format_string : public format_error
|
||||
{
|
||||
public:
|
||||
bad_format_string() { abort(); }
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return "boost::bad_format_string: "
|
||||
"format-string is ill-formed";
|
||||
}
|
||||
};
|
||||
|
||||
class too_few_args : public format_error
|
||||
{
|
||||
public:
|
||||
too_few_args() { abort(); }
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return "boost::too_few_args: "
|
||||
"format-string refered to more arguments than were passed";
|
||||
}
|
||||
};
|
||||
|
||||
class too_many_args : public format_error
|
||||
{
|
||||
public:
|
||||
too_many_args() { abort(); }
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return "boost::too_many_args: "
|
||||
"format-string refered to less arguments than were passed";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class out_of_range : public format_error
|
||||
{
|
||||
public:
|
||||
out_of_range() { abort(); }
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return "boost::out_of_range: "
|
||||
"tried to refer to an argument (or item) number which is out of range, "
|
||||
"according to the format string.";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_EXCEPTIONS_HPP
|
|
@ -1,254 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// feed_args.hpp : functions for processing each argument
|
||||
// (feed, feed_manip, and distribute)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BOOST_FORMAT_FEED_ARGS_HPP
|
||||
#define BOOST_FORMAT_FEED_ARGS_HPP
|
||||
|
||||
#include "boost/format/format_class.hpp"
|
||||
#include "boost/format/group.hpp"
|
||||
|
||||
#include "boost/throw_exception.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace io {
|
||||
namespace detail {
|
||||
namespace {
|
||||
|
||||
inline
|
||||
void empty_buf(BOOST_IO_STD ostringstream & os) {
|
||||
static const std::string emptyStr;
|
||||
os.str(emptyStr);
|
||||
}
|
||||
|
||||
void do_pad( std::string & s,
|
||||
std::streamsize w,
|
||||
const char c,
|
||||
std::ios::fmtflags f,
|
||||
bool center)
|
||||
__attribute__ ((unused));
|
||||
|
||||
void do_pad( std::string & s,
|
||||
std::streamsize w,
|
||||
const char c,
|
||||
std::ios::fmtflags f,
|
||||
bool center)
|
||||
// applies centered / left / right padding to the string s.
|
||||
// Effects : string s is padded.
|
||||
{
|
||||
std::streamsize n=w-s.size();
|
||||
if(n<=0) {
|
||||
return;
|
||||
}
|
||||
if(center)
|
||||
{
|
||||
s.reserve(w); // allocate once for the 2 inserts
|
||||
const std::streamsize n1 = n /2, n0 = n - n1;
|
||||
s.insert(s.begin(), n0, c);
|
||||
s.append(n1, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(f & std::ios::left) {
|
||||
s.append(n, c);
|
||||
}
|
||||
else {
|
||||
s.insert(s.begin(), n, c);
|
||||
}
|
||||
}
|
||||
} // -do_pad(..)
|
||||
|
||||
|
||||
template<class T> inline
|
||||
void put_head(BOOST_IO_STD ostream& , const T& ) {
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
void put_head( BOOST_IO_STD ostream& os, const group1<T>& x ) {
|
||||
os << group_head(x.a1_); // send the first N-1 items, not the last
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
void put_last( BOOST_IO_STD ostream& os, const T& x ) {
|
||||
os << x ;
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
void put_last( BOOST_IO_STD ostream& os, const group1<T>& x ) {
|
||||
os << group_last(x.a1_); // this selects the last element
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
|
||||
template<class T> inline
|
||||
void put_head( BOOST_IO_STD ostream& , T& ) {
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
void put_last( BOOST_IO_STD ostream& os, T& x ) {
|
||||
os << x ;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
void put( T x,
|
||||
const format_item& specs,
|
||||
std::string & res,
|
||||
BOOST_IO_STD ostringstream& oss_ )
|
||||
{
|
||||
// does the actual conversion of x, with given params, into a string
|
||||
// using the *supplied* strinstream. (the stream state is important)
|
||||
|
||||
typedef std::string string_t;
|
||||
typedef format_item format_item_t;
|
||||
|
||||
stream_format_state prev_state(oss_);
|
||||
|
||||
specs.state_.apply_on(oss_);
|
||||
|
||||
// in case x is a group, apply the manip part of it,
|
||||
// in order to find width
|
||||
put_head( oss_, x );
|
||||
empty_buf( oss_);
|
||||
|
||||
const std::streamsize w=oss_.width();
|
||||
const std::ios::fmtflags fl=oss_.flags();
|
||||
const bool internal = (fl & std::ios::internal) != 0;
|
||||
const bool two_stepped_padding = internal
|
||||
&& ! ( specs.pad_scheme_ & format_item_t::spacepad )
|
||||
&& specs.truncate_ < 0 ;
|
||||
|
||||
|
||||
if(! two_stepped_padding)
|
||||
{
|
||||
if(w>0) // handle simple padding via do_pad, not natively in stream
|
||||
oss_.width(0);
|
||||
put_last( oss_, x);
|
||||
res = oss_.str();
|
||||
|
||||
if (specs.truncate_ >= 0)
|
||||
res.erase(specs.truncate_);
|
||||
|
||||
// complex pads :
|
||||
if(specs.pad_scheme_ & format_item_t::spacepad)
|
||||
{
|
||||
if( res.size()==0 || ( res[0]!='+' && res[0]!='-' ))
|
||||
{
|
||||
res.insert(res.begin(), 1, ' '); // insert 1 space at pos 0
|
||||
}
|
||||
}
|
||||
if(w > 0) // need do_pad
|
||||
{
|
||||
do_pad(res,w,oss_.fill(), fl, (specs.pad_scheme_ & format_item_t::centered) !=0 );
|
||||
}
|
||||
}
|
||||
else // 2-stepped padding
|
||||
{
|
||||
put_last( oss_, x); // oss_.width() may result in padding.
|
||||
res = oss_.str();
|
||||
|
||||
if (specs.truncate_ >= 0)
|
||||
res.erase(specs.truncate_);
|
||||
|
||||
if( res.size() - w > 0)
|
||||
{ // length w exceeded
|
||||
// either it was multi-output with first output padding up all width..
|
||||
// either it was one big arg and we are fine.
|
||||
empty_buf( oss_);
|
||||
oss_.width(0);
|
||||
put_last(oss_, x );
|
||||
string_t tmp = oss_.str(); // minimal-length output
|
||||
std::streamsize d;
|
||||
if( (d=w - tmp.size()) <=0 )
|
||||
{
|
||||
// minimal length is already >= w, so no padding (cool!)
|
||||
res.swap(tmp);
|
||||
}
|
||||
else
|
||||
{ // hum.. we need to pad (it was necessarily multi-output)
|
||||
typedef typename string_t::size_type size_type;
|
||||
size_type i = 0;
|
||||
while( i<tmp.size() && tmp[i] == res[i] ) // find where we should pad.
|
||||
++i;
|
||||
tmp.insert(i, static_cast<size_type>( d ), oss_.fill());
|
||||
res.swap( tmp );
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // okay, only one thing was printed and padded, so res is fine.
|
||||
}
|
||||
}
|
||||
|
||||
prev_state.apply_on(oss_);
|
||||
empty_buf( oss_);
|
||||
oss_.clear();
|
||||
} // end- put(..)
|
||||
|
||||
|
||||
} // local namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
void distribute(basic_format& self, T x)
|
||||
// call put(x, ..) on every occurence of the current argument :
|
||||
{
|
||||
if(self.cur_arg_ >= self.num_args_)
|
||||
{
|
||||
if( self.exceptions() & too_many_args_bit )
|
||||
boost::throw_exception(too_many_args()); // too many variables have been supplied !
|
||||
else return;
|
||||
}
|
||||
for(unsigned long i=0; i < self.items_.size(); ++i)
|
||||
{
|
||||
if(self.items_[i].argN_ == self.cur_arg_)
|
||||
{
|
||||
put<T> (x, self.items_[i], self.items_[i].res_, self.oss_ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
basic_format& feed(basic_format& self, T x)
|
||||
{
|
||||
if(self.dumped_) self.clear();
|
||||
distribute<T> (self, x);
|
||||
++self.cur_arg_;
|
||||
if(self.bound_.size() != 0)
|
||||
{
|
||||
while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] )
|
||||
++self.cur_arg_;
|
||||
}
|
||||
|
||||
// this arg is finished, reset the stream's format state
|
||||
self.state0_.apply_on(self.oss_);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace io
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_FEED_ARGS_HPP
|
|
@ -1,135 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// format_class.hpp : class interface
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BOOST_FORMAT_CLASS_HPP
|
||||
#define BOOST_FORMAT_CLASS_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <boost/format/format_fwd.hpp>
|
||||
#include <boost/format/internals_fwd.hpp>
|
||||
|
||||
#include <boost/format/internals.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class basic_format
|
||||
{
|
||||
public:
|
||||
typedef std::string string_t;
|
||||
typedef BOOST_IO_STD ostringstream internal_stream_t;
|
||||
private:
|
||||
typedef BOOST_IO_STD ostream stream_t;
|
||||
typedef io::detail::stream_format_state stream_format_state;
|
||||
typedef io::detail::format_item format_item_t;
|
||||
|
||||
public:
|
||||
basic_format(const char* str);
|
||||
basic_format(const string_t& s);
|
||||
#ifndef BOOST_NO_STD_LOCALE
|
||||
basic_format(const char* str, const std::locale & loc);
|
||||
basic_format(const string_t& s, const std::locale & loc);
|
||||
#endif // no locale
|
||||
basic_format(const basic_format& x);
|
||||
basic_format& operator= (const basic_format& x);
|
||||
|
||||
basic_format& clear(); // empty the string buffers (except bound arguments, see clear_binds() )
|
||||
|
||||
// pass arguments through those operators :
|
||||
template<class T> basic_format& operator%(const T& x)
|
||||
{
|
||||
return io::detail::feed<const T&>(*this,x);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
|
||||
template<class T> basic_format& operator%(T& x)
|
||||
{
|
||||
return io::detail::feed<T&>(*this,x);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// system for binding arguments :
|
||||
template<class T>
|
||||
basic_format& bind_arg(int argN, const T& val)
|
||||
{
|
||||
return io::detail::bind_arg_body(*this, argN, val);
|
||||
}
|
||||
basic_format& clear_bind(int argN);
|
||||
basic_format& clear_binds();
|
||||
|
||||
// modify the params of a directive, by applying a manipulator :
|
||||
template<class T>
|
||||
basic_format& modify_item(int itemN, const T& manipulator)
|
||||
{
|
||||
return io::detail::modify_item_body(*this, itemN, manipulator) ;
|
||||
}
|
||||
|
||||
// Choosing which errors will throw exceptions :
|
||||
unsigned char exceptions() const;
|
||||
unsigned char exceptions(unsigned char newexcept);
|
||||
|
||||
// final output
|
||||
string_t str() const;
|
||||
friend BOOST_IO_STD ostream&
|
||||
operator<< ( BOOST_IO_STD ostream& , const basic_format& );
|
||||
|
||||
|
||||
template<class T> friend basic_format&
|
||||
io::detail::feed(basic_format&, T);
|
||||
|
||||
template<class T> friend
|
||||
void io::detail::distribute(basic_format&, T);
|
||||
|
||||
template<class T> friend
|
||||
basic_format& io::detail::modify_item_body(basic_format&, int, const T&);
|
||||
|
||||
template<class T> friend
|
||||
basic_format& io::detail::bind_arg_body(basic_format&, int, const T&);
|
||||
|
||||
// make the members private only if the friend templates are supported
|
||||
private:
|
||||
|
||||
// flag bits, used for style_
|
||||
enum style_values { ordered = 1, // set only if all directives are positional directives
|
||||
special_needs = 4 };
|
||||
|
||||
// parse the format string :
|
||||
void parse(const string_t&);
|
||||
|
||||
int style_; // style of format-string : positional or not, etc
|
||||
int cur_arg_; // keep track of wich argument will come
|
||||
int num_args_; // number of expected arguments
|
||||
mutable bool dumped_; // true only after call to str() or <<
|
||||
std::vector<format_item_t> items_; // vector of directives (aka items)
|
||||
string_t prefix_; // piece of string to insert before first item
|
||||
|
||||
std::vector<bool> bound_; // stores which arguments were bound
|
||||
// size = num_args OR zero
|
||||
internal_stream_t oss_; // the internal stream.
|
||||
stream_format_state state0_; // reference state for oss_
|
||||
unsigned char exceptions_;
|
||||
}; // class basic_format
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_CLASS_HPP
|
|
@ -1,49 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// format_fwd.hpp : forward declarations, for primary header format.hpp
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_FORMAT_FWD_HPP
|
||||
#define BOOST_FORMAT_FWD_HPP
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class basic_format;
|
||||
|
||||
typedef basic_format format;
|
||||
|
||||
namespace io {
|
||||
enum format_error_bits { bad_format_string_bit = 1,
|
||||
too_few_args_bit = 2, too_many_args_bit = 4,
|
||||
out_of_range_bit = 8,
|
||||
all_error_bits = 255, no_error_bits=0 };
|
||||
|
||||
// Convertion: format to string
|
||||
std::string str(const basic_format& ) ;
|
||||
|
||||
} // namespace io
|
||||
|
||||
|
||||
BOOST_IO_STD ostream&
|
||||
operator<<( BOOST_IO_STD ostream&, const basic_format&);
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_FORMAT_FWD_HPP
|
|
@ -1,256 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library format ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// format_implementation.hpp Implementation of the basic_format class
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BOOST_FORMAT_IMPLEMENTATION_HPP
|
||||
#define BOOST_FORMAT_IMPLEMENTATION_HPP
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// -------- format:: -------------------------------------------
|
||||
basic_format::basic_format(const char* str)
|
||||
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
|
||||
items_(), oss_(), exceptions_(io::all_error_bits)
|
||||
{
|
||||
state0_.set_by_stream(oss_);
|
||||
string_t emptyStr;
|
||||
if( !str) str = emptyStr.c_str();
|
||||
parse( str );
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_STD_LOCALE
|
||||
basic_format::basic_format(const char* str, const std::locale & loc)
|
||||
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
|
||||
items_(), oss_(), exceptions_(io::all_error_bits)
|
||||
{
|
||||
oss_.imbue( loc );
|
||||
state0_.set_by_stream(oss_);
|
||||
string_t emptyStr;
|
||||
if( !str) str = emptyStr.c_str();
|
||||
parse( str );
|
||||
}
|
||||
|
||||
basic_format::basic_format(const string_t& s, const std::locale & loc)
|
||||
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
|
||||
items_(), oss_(), exceptions_(io::all_error_bits)
|
||||
{
|
||||
oss_.imbue( loc );
|
||||
state0_.set_by_stream(oss_);
|
||||
parse(s);
|
||||
}
|
||||
#endif //BOOST_NO_STD_LOCALE
|
||||
|
||||
basic_format::basic_format(const string_t& s)
|
||||
: style_(0), cur_arg_(0), num_args_(0), dumped_(false),
|
||||
items_(), oss_(), exceptions_(io::all_error_bits)
|
||||
{
|
||||
state0_.set_by_stream(oss_);
|
||||
parse(s);
|
||||
}
|
||||
|
||||
basic_format:: basic_format(const basic_format& x)
|
||||
: style_(x.style_), cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false),
|
||||
items_(x.items_), prefix_(x.prefix_), bound_(x.bound_),
|
||||
oss_(), // <- we obviously can't copy x.oss_
|
||||
state0_(x.state0_), exceptions_(x.exceptions_)
|
||||
{
|
||||
state0_.apply_on(oss_);
|
||||
}
|
||||
|
||||
basic_format& basic_format::operator= (const basic_format& x)
|
||||
{
|
||||
if(this == &x)
|
||||
return *this;
|
||||
state0_ = x.state0_;
|
||||
state0_.apply_on(oss_);
|
||||
|
||||
// plus all the other (trivial) assignments :
|
||||
exceptions_ = x.exceptions_;
|
||||
items_ = x.items_;
|
||||
prefix_ = x.prefix_;
|
||||
bound_=x.bound_;
|
||||
style_=x.style_;
|
||||
cur_arg_=x.cur_arg_;
|
||||
num_args_=x.num_args_;
|
||||
dumped_=x.dumped_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
unsigned char basic_format::exceptions() const
|
||||
{
|
||||
return exceptions_;
|
||||
}
|
||||
|
||||
unsigned char basic_format::exceptions(unsigned char newexcept)
|
||||
{
|
||||
unsigned char swp = exceptions_;
|
||||
exceptions_ = newexcept;
|
||||
return swp;
|
||||
}
|
||||
|
||||
|
||||
basic_format& basic_format ::clear()
|
||||
// empty the string buffers (except bound arguments, see clear_binds() )
|
||||
// and make the format object ready for formatting a new set of arguments
|
||||
{
|
||||
BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast<int>(bound_.size()) );
|
||||
|
||||
for(unsigned long i=0; i<items_.size(); ++i){
|
||||
items_[i].state_ = items_[i].ref_state_;
|
||||
// clear converted strings only if the corresponding argument is not bound :
|
||||
if( bound_.size()==0 || !bound_[ items_[i].argN_ ] ) items_[i].res_.resize(0);
|
||||
}
|
||||
cur_arg_=0; dumped_=false;
|
||||
// maybe first arg is bound:
|
||||
if(bound_.size() != 0)
|
||||
{
|
||||
while(cur_arg_ < num_args_ && bound_[cur_arg_] ) ++cur_arg_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_format& basic_format ::clear_binds()
|
||||
// cancel all bindings, and clear()
|
||||
{
|
||||
bound_.resize(0);
|
||||
clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_format& basic_format::clear_bind(int argN)
|
||||
// cancel the binding of ONE argument, and clear()
|
||||
{
|
||||
if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] )
|
||||
{
|
||||
if( exceptions() & io::out_of_range_bit )
|
||||
boost::throw_exception(io::out_of_range()); // arg not in range.
|
||||
else return *this;
|
||||
}
|
||||
bound_[argN-1]=false;
|
||||
clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string basic_format::str() const
|
||||
{
|
||||
dumped_=true;
|
||||
if(items_.size()==0)
|
||||
return prefix_;
|
||||
if( cur_arg_ < num_args_)
|
||||
if( exceptions() & io::too_few_args_bit )
|
||||
boost::throw_exception(io::too_few_args()); // not enough variables have been supplied !
|
||||
|
||||
unsigned long sz = prefix_.size();
|
||||
unsigned long i;
|
||||
for(i=0; i < items_.size(); ++i)
|
||||
sz += items_[i].res_.size() + items_[i].appendix_.size();
|
||||
string_t res;
|
||||
res.reserve(sz);
|
||||
|
||||
res += prefix_;
|
||||
for(i=0; i < items_.size(); ++i)
|
||||
{
|
||||
const format_item_t& item = items_[i];
|
||||
res += item.res_;
|
||||
if( item.argN_ == format_item_t::argN_tabulation)
|
||||
{
|
||||
BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation);
|
||||
std::streamsize n = item.state_.width_ - res.size();
|
||||
if( n > 0 )
|
||||
res.append( n, item.state_.fill_ );
|
||||
}
|
||||
res += item.appendix_;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
namespace io {
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
basic_format& bind_arg_body( basic_format& self,
|
||||
int argN,
|
||||
const T& val)
|
||||
// bind one argument to a fixed value
|
||||
// this is persistent over clear() calls, thus also over str() and <<
|
||||
{
|
||||
if(self.dumped_) self.clear(); // needed, because we will modify cur_arg_..
|
||||
if(argN<1 || argN > self.num_args_)
|
||||
{
|
||||
if( self.exceptions() & io::out_of_range_bit )
|
||||
boost::throw_exception(io::out_of_range()); // arg not in range.
|
||||
else return self;
|
||||
}
|
||||
if(self.bound_.size()==0)
|
||||
self.bound_.assign(self.num_args_,false);
|
||||
else
|
||||
BOOST_ASSERT( self.num_args_ == static_cast<signed int>(self.bound_.size()) );
|
||||
int o_cur_arg = self.cur_arg_;
|
||||
self.cur_arg_ = argN-1; // arrays begin at 0
|
||||
|
||||
self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets..
|
||||
self.operator%(val); // put val at the right place, because cur_arg is set
|
||||
|
||||
|
||||
// Now re-position cur_arg before leaving :
|
||||
self.cur_arg_ = o_cur_arg;
|
||||
self.bound_[argN-1]=true;
|
||||
if(self.cur_arg_ == argN-1 )
|
||||
// hum, now this arg is bound, so move to next free arg
|
||||
{
|
||||
while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_]) ++self.cur_arg_;
|
||||
}
|
||||
// In any case, we either have all args, or are on a non-binded arg :
|
||||
BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]);
|
||||
return self;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
basic_format& modify_item_body( basic_format& self,
|
||||
int itemN,
|
||||
const T& manipulator)
|
||||
// applies a manipulator to the format_item describing a given directive.
|
||||
// this is a permanent change, clear or clear_binds won't cancel that.
|
||||
{
|
||||
if(itemN<1 || itemN >= static_cast<signed int>(self.items_.size() ))
|
||||
{
|
||||
if( self.exceptions() & io::out_of_range_bit )
|
||||
boost::throw_exception(io::out_of_range()); // item not in range.
|
||||
else return self;
|
||||
}
|
||||
self.items_[itemN-1].ref_state_.apply_manip( manipulator );
|
||||
self.items_[itemN-1].state_ = self.items_[itemN-1].ref_state_;
|
||||
return self;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_IMPLEMENTATION_HPP
|
|
@ -1,71 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// free_funcs.hpp : implementation of the free functions declared in namespace format
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_FORMAT_FUNCS_HPP
|
||||
#define BOOST_FORMAT_FUNCS_HPP
|
||||
|
||||
#include "boost/format.hpp"
|
||||
#include "boost/throw_exception.hpp"
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace io {
|
||||
inline
|
||||
std::string str(const basic_format& f)
|
||||
// adds up all pieces of strings and converted items, and return the formatted string
|
||||
{
|
||||
return f.str();
|
||||
}
|
||||
} // - namespace io
|
||||
|
||||
BOOST_IO_STD ostream&
|
||||
operator<<( BOOST_IO_STD ostream& os,
|
||||
const boost::basic_format& f)
|
||||
// effect: "return os << str(f);" but we can try to do it faster
|
||||
{
|
||||
typedef boost::basic_format format_t;
|
||||
if(f.items_.size()==0)
|
||||
os << f.prefix_;
|
||||
else {
|
||||
if(f.cur_arg_ < f.num_args_)
|
||||
if( f.exceptions() & io::too_few_args_bit )
|
||||
boost::throw_exception(io::too_few_args()); // not enough variables have been supplied !
|
||||
if(f.style_ & format_t::special_needs)
|
||||
os << f.str();
|
||||
else {
|
||||
// else we dont have to count chars output, so we dump directly to os :
|
||||
os << f.prefix_;
|
||||
for(unsigned long i=0; i<f.items_.size(); ++i)
|
||||
{
|
||||
const format_t::format_item_t& item = f.items_[i];
|
||||
os << item.res_;
|
||||
os << item.appendix_;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
f.dumped_=true;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_FUNCS_HPP
|
|
@ -1,680 +0,0 @@
|
|||
|
||||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// group.hpp : encapsulates a group of manipulators along with an argument
|
||||
//
|
||||
// group_head : cut the last element of a group out.
|
||||
// (is overloaded below on each type of group)
|
||||
|
||||
// group_last : returns the last element of a group
|
||||
// (is overloaded below on each type of group)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BOOST_FORMAT_GROUP_HPP
|
||||
#define BOOST_FORMAT_GROUP_HPP
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace io {
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
// empty group, but useful even though.
|
||||
struct group0
|
||||
{
|
||||
group0() {}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << ( BOOST_IO_STD ostream& os,
|
||||
const group0& )
|
||||
{
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
struct group1
|
||||
{
|
||||
T1 a1_;
|
||||
group1(T1 a1)
|
||||
: a1_(a1)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group1<T1>& x)
|
||||
{
|
||||
os << x.a1_;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2>
|
||||
struct group2
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
group2(T1 a1,T2 a2)
|
||||
: a1_(a1),a2_(a2)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group2<T1,T2>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3>
|
||||
struct group3
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
group3(T1 a1,T2 a2,T3 a3)
|
||||
: a1_(a1),a2_(a2),a3_(a3)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group3<T1,T2,T3>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4>
|
||||
struct group4
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
T4 a4_;
|
||||
group4(T1 a1,T2 a2,T3 a3,T4 a4)
|
||||
: a1_(a1),a2_(a2),a3_(a3),a4_(a4)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3,class T4>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group4<T1,T2,T3,T4>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_<< x.a4_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5>
|
||||
struct group5
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
T4 a4_;
|
||||
T5 a5_;
|
||||
group5(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5)
|
||||
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group5<T1,T2,T3,T4,T5>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6>
|
||||
struct group6
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
T4 a4_;
|
||||
T5 a5_;
|
||||
T6 a6_;
|
||||
group6(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6)
|
||||
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group6<T1,T2,T3,T4,T5,T6>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
|
||||
struct group7
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
T4 a4_;
|
||||
T5 a5_;
|
||||
T6 a6_;
|
||||
T7 a7_;
|
||||
group7(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7)
|
||||
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group7<T1,T2,T3,T4,T5,T6,T7>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
|
||||
struct group8
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
T4 a4_;
|
||||
T5 a5_;
|
||||
T6 a6_;
|
||||
T7 a7_;
|
||||
T8 a8_;
|
||||
group8(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8)
|
||||
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group8<T1,T2,T3,T4,T5,T6,T7,T8>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
|
||||
struct group9
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
T4 a4_;
|
||||
T5 a5_;
|
||||
T6 a6_;
|
||||
T7 a7_;
|
||||
T8 a8_;
|
||||
T9 a9_;
|
||||
group9(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9)
|
||||
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group9<T1,T2,T3,T4,T5,T6,T7,T8,T9>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
|
||||
struct group10
|
||||
{
|
||||
T1 a1_;
|
||||
T2 a2_;
|
||||
T3 a3_;
|
||||
T4 a4_;
|
||||
T5 a5_;
|
||||
T6 a6_;
|
||||
T7 a7_;
|
||||
T8 a8_;
|
||||
T9 a9_;
|
||||
T10 a10_;
|
||||
group10(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9,T10 a10)
|
||||
: a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9),a10_(a10)
|
||||
{}
|
||||
};
|
||||
|
||||
template <class Ch, class Tr, class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
|
||||
inline
|
||||
BOOST_IO_STD ostream&
|
||||
operator << (BOOST_IO_STD ostream& os,
|
||||
const group10<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>& x)
|
||||
{
|
||||
os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_<< x.a10_;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2>
|
||||
inline
|
||||
group1<T1>
|
||||
group_head( group2<T1,T2> const& x)
|
||||
{
|
||||
return group1<T1> (x.a1_);
|
||||
}
|
||||
|
||||
template <class T1,class T2>
|
||||
inline
|
||||
group1<T2>
|
||||
group_last( group2<T1,T2> const& x)
|
||||
{
|
||||
return group1<T2> (x.a2_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3>
|
||||
inline
|
||||
group2<T1,T2>
|
||||
group_head( group3<T1,T2,T3> const& x)
|
||||
{
|
||||
return group2<T1,T2> (x.a1_,x.a2_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3>
|
||||
inline
|
||||
group1<T3>
|
||||
group_last( group3<T1,T2,T3> const& x)
|
||||
{
|
||||
return group1<T3> (x.a3_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3,class T4>
|
||||
inline
|
||||
group3<T1,T2,T3>
|
||||
group_head( group4<T1,T2,T3,T4> const& x)
|
||||
{
|
||||
return group3<T1,T2,T3> (x.a1_,x.a2_,x.a3_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4>
|
||||
inline
|
||||
group1<T4>
|
||||
group_last( group4<T1,T2,T3,T4> const& x)
|
||||
{
|
||||
return group1<T4> (x.a4_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5>
|
||||
inline
|
||||
group4<T1,T2,T3,T4>
|
||||
group_head( group5<T1,T2,T3,T4,T5> const& x)
|
||||
{
|
||||
return group4<T1,T2,T3,T4> (x.a1_,x.a2_,x.a3_,x.a4_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5>
|
||||
inline
|
||||
group1<T5>
|
||||
group_last( group5<T1,T2,T3,T4,T5> const& x)
|
||||
{
|
||||
return group1<T5> (x.a5_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6>
|
||||
inline
|
||||
group5<T1,T2,T3,T4,T5>
|
||||
group_head( group6<T1,T2,T3,T4,T5,T6> const& x)
|
||||
{
|
||||
return group5<T1,T2,T3,T4,T5> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6>
|
||||
inline
|
||||
group1<T6>
|
||||
group_last( group6<T1,T2,T3,T4,T5,T6> const& x)
|
||||
{
|
||||
return group1<T6> (x.a6_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
|
||||
inline
|
||||
group6<T1,T2,T3,T4,T5,T6>
|
||||
group_head( group7<T1,T2,T3,T4,T5,T6,T7> const& x)
|
||||
{
|
||||
return group6<T1,T2,T3,T4,T5,T6> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7>
|
||||
inline
|
||||
group1<T7>
|
||||
group_last( group7<T1,T2,T3,T4,T5,T6,T7> const& x)
|
||||
{
|
||||
return group1<T7> (x.a7_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
|
||||
inline
|
||||
group7<T1,T2,T3,T4,T5,T6,T7>
|
||||
group_head( group8<T1,T2,T3,T4,T5,T6,T7,T8> const& x)
|
||||
{
|
||||
return group7<T1,T2,T3,T4,T5,T6,T7> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8>
|
||||
inline
|
||||
group1<T8>
|
||||
group_last( group8<T1,T2,T3,T4,T5,T6,T7,T8> const& x)
|
||||
{
|
||||
return group1<T8> (x.a8_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
|
||||
inline
|
||||
group8<T1,T2,T3,T4,T5,T6,T7,T8>
|
||||
group_head( group9<T1,T2,T3,T4,T5,T6,T7,T8,T9> const& x)
|
||||
{
|
||||
return group8<T1,T2,T3,T4,T5,T6,T7,T8> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9>
|
||||
inline
|
||||
group1<T9>
|
||||
group_last( group9<T1,T2,T3,T4,T5,T6,T7,T8,T9> const& x)
|
||||
{
|
||||
return group1<T9> (x.a9_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
|
||||
inline
|
||||
group9<T1,T2,T3,T4,T5,T6,T7,T8,T9>
|
||||
group_head( group10<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> const& x)
|
||||
{
|
||||
return group9<T1,T2,T3,T4,T5,T6,T7,T8,T9> (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_,x.a9_);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9,class T10>
|
||||
inline
|
||||
group1<T10>
|
||||
group_last( group10<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> const& x)
|
||||
{
|
||||
return group1<T10> (x.a10_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
|
||||
// helper functions
|
||||
|
||||
|
||||
inline detail::group1< detail::group0 >
|
||||
group() { return detail::group1< detail::group0 > ( detail::group0() ); }
|
||||
|
||||
template <class T1, class Var>
|
||||
inline
|
||||
detail::group1< detail::group2<T1, Var const&> >
|
||||
group(T1 a1, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group2<T1, Var const&> >
|
||||
( detail::group2<T1, Var const&>
|
||||
(a1, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2, class Var>
|
||||
inline
|
||||
detail::group1< detail::group3<T1,T2, Var const&> >
|
||||
group(T1 a1,T2 a2, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group3<T1,T2, Var const&> >
|
||||
( detail::group3<T1,T2, Var const&>
|
||||
(a1,a2, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3, class Var>
|
||||
inline
|
||||
detail::group1< detail::group4<T1,T2,T3, Var const&> >
|
||||
group(T1 a1,T2 a2,T3 a3, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group4<T1,T2,T3, Var const&> >
|
||||
( detail::group4<T1,T2,T3, Var const&>
|
||||
(a1,a2,a3, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4, class Var>
|
||||
inline
|
||||
detail::group1< detail::group5<T1,T2,T3,T4, Var const&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group5<T1,T2,T3,T4, Var const&> >
|
||||
( detail::group5<T1,T2,T3,T4, Var const&>
|
||||
(a1,a2,a3,a4, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5, class Var>
|
||||
inline
|
||||
detail::group1< detail::group6<T1,T2,T3,T4,T5, Var const&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group6<T1,T2,T3,T4,T5, Var const&> >
|
||||
( detail::group6<T1,T2,T3,T4,T5, Var const&>
|
||||
(a1,a2,a3,a4,a5, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6, class Var>
|
||||
inline
|
||||
detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var const&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var const&> >
|
||||
( detail::group7<T1,T2,T3,T4,T5,T6, Var const&>
|
||||
(a1,a2,a3,a4,a5,a6, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7, class Var>
|
||||
inline
|
||||
detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var const&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var const&> >
|
||||
( detail::group8<T1,T2,T3,T4,T5,T6,T7, Var const&>
|
||||
(a1,a2,a3,a4,a5,a6,a7, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8, class Var>
|
||||
inline
|
||||
detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var const&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var const&> >
|
||||
( detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var const&>
|
||||
(a1,a2,a3,a4,a5,a6,a7,a8, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9, class Var>
|
||||
inline
|
||||
detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var const&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var const& var)
|
||||
{
|
||||
return detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var const&> >
|
||||
( detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var const&>
|
||||
(a1,a2,a3,a4,a5,a6,a7,a8,a9, var)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
|
||||
|
||||
template <class T1, class Var>
|
||||
inline
|
||||
detail::group1< detail::group2<T1, Var&> >
|
||||
group(T1 a1, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group2<T1, Var&> >
|
||||
( detail::group2<T1, Var&>
|
||||
(a1, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2, class Var>
|
||||
inline
|
||||
detail::group1< detail::group3<T1,T2, Var&> >
|
||||
group(T1 a1,T2 a2, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group3<T1,T2, Var&> >
|
||||
( detail::group3<T1,T2, Var&>
|
||||
(a1,a2, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3, class Var>
|
||||
inline
|
||||
detail::group1< detail::group4<T1,T2,T3, Var&> >
|
||||
group(T1 a1,T2 a2,T3 a3, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group4<T1,T2,T3, Var&> >
|
||||
( detail::group4<T1,T2,T3, Var&>
|
||||
(a1,a2,a3, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4, class Var>
|
||||
inline
|
||||
detail::group1< detail::group5<T1,T2,T3,T4, Var&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group5<T1,T2,T3,T4, Var&> >
|
||||
( detail::group5<T1,T2,T3,T4, Var&>
|
||||
(a1,a2,a3,a4, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5, class Var>
|
||||
inline
|
||||
detail::group1< detail::group6<T1,T2,T3,T4,T5, Var&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group6<T1,T2,T3,T4,T5, Var&> >
|
||||
( detail::group6<T1,T2,T3,T4,T5, Var&>
|
||||
(a1,a2,a3,a4,a5, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6, class Var>
|
||||
inline
|
||||
detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group7<T1,T2,T3,T4,T5,T6, Var&> >
|
||||
( detail::group7<T1,T2,T3,T4,T5,T6, Var&>
|
||||
(a1,a2,a3,a4,a5,a6, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7, class Var>
|
||||
inline
|
||||
detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group8<T1,T2,T3,T4,T5,T6,T7, Var&> >
|
||||
( detail::group8<T1,T2,T3,T4,T5,T6,T7, Var&>
|
||||
(a1,a2,a3,a4,a5,a6,a7, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8, class Var>
|
||||
inline
|
||||
detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var&> >
|
||||
( detail::group9<T1,T2,T3,T4,T5,T6,T7,T8, Var&>
|
||||
(a1,a2,a3,a4,a5,a6,a7,a8, var)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T1,class T2,class T3,class T4,class T5,class T6,class T7,class T8,class T9, class Var>
|
||||
inline
|
||||
detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var&> >
|
||||
group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var& var)
|
||||
{
|
||||
return detail::group1< detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var&> >
|
||||
( detail::group10<T1,T2,T3,T4,T5,T6,T7,T8,T9, Var&>
|
||||
(a1,a2,a3,a4,a5,a6,a7,a8,a9, var)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#endif //end- #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST
|
||||
|
||||
|
||||
} // namespace io
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_GROUP_HPP
|
|
@ -1,167 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// internals.hpp : internal structs. included by format.hpp
|
||||
// stream_format_state, and format_item
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BOOST_FORMAT_INTERNALS_HPP
|
||||
#define BOOST_FORMAT_INTERNALS_HPP
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost {
|
||||
namespace io {
|
||||
namespace detail {
|
||||
|
||||
|
||||
// --------------
|
||||
// set of params that define the format state of a stream
|
||||
|
||||
struct stream_format_state
|
||||
{
|
||||
typedef std::ios basic_ios;
|
||||
|
||||
std::streamsize width_;
|
||||
std::streamsize precision_;
|
||||
char fill_;
|
||||
std::ios::fmtflags flags_;
|
||||
|
||||
stream_format_state() : width_(-1), precision_(-1), fill_(0), flags_(std::ios::dec) {}
|
||||
stream_format_state(basic_ios& os) {set_by_stream(os); }
|
||||
|
||||
void apply_on(basic_ios & os) const; //- applies format_state to the stream
|
||||
template<class T> void apply_manip(T manipulator) //- modifies state by applying manipulator.
|
||||
{ apply_manip_body<T>( *this, manipulator) ; }
|
||||
void reset(); //- sets to default state.
|
||||
void set_by_stream(const basic_ios& os); //- sets to os's state.
|
||||
};
|
||||
|
||||
|
||||
|
||||
// --------------
|
||||
// format_item : stores all parameters that can be defined by directives in the format-string
|
||||
|
||||
struct format_item
|
||||
{
|
||||
enum pad_values { zeropad = 1, spacepad =2, centered=4, tabulation = 8 };
|
||||
|
||||
enum arg_values { argN_no_posit = -1, // non-positional directive. argN will be set later.
|
||||
argN_tabulation = -2, // tabulation directive. (no argument read)
|
||||
argN_ignored = -3 // ignored directive. (no argument read)
|
||||
};
|
||||
typedef BOOST_IO_STD ios basic_ios;
|
||||
typedef detail::stream_format_state stream_format_state;
|
||||
typedef std::string string_t;
|
||||
typedef BOOST_IO_STD ostringstream internal_stream_t;
|
||||
|
||||
|
||||
int argN_; //- argument number (starts at 0, eg : %1 => argN=0)
|
||||
// negative values are used for items that don't process
|
||||
// an argument
|
||||
string_t res_; //- result of the formatting of this item
|
||||
string_t appendix_; //- piece of string between this item and the next
|
||||
|
||||
stream_format_state ref_state_;// set by parsing the format_string, is only affected by modify_item
|
||||
stream_format_state state_; // always same as ref_state, _unless_ modified by manipulators 'group(..)'
|
||||
|
||||
// non-stream format-state parameters
|
||||
signed int truncate_; //- is >=0 for directives like %.5s (take 5 chars from the string)
|
||||
unsigned int pad_scheme_; //- several possible padding schemes can mix. see pad_values
|
||||
|
||||
format_item() : argN_(argN_no_posit), truncate_(-1), pad_scheme_(0) {}
|
||||
|
||||
void compute_states(); // sets states according to truncate and pad_scheme.
|
||||
};
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Definitions
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// --- stream_format_state:: -------------------------------------------
|
||||
inline
|
||||
void stream_format_state::apply_on(basic_ios & os) const
|
||||
// set the state of this stream according to our params
|
||||
{
|
||||
if(width_ != -1)
|
||||
os.width(width_);
|
||||
if(precision_ != -1)
|
||||
os.precision(precision_);
|
||||
if(fill_ != 0)
|
||||
os.fill(fill_);
|
||||
os.flags(flags_);
|
||||
}
|
||||
|
||||
inline
|
||||
void stream_format_state::set_by_stream(const basic_ios& os)
|
||||
// set our params according to the state of this stream
|
||||
{
|
||||
flags_ = os.flags();
|
||||
width_ = os.width();
|
||||
precision_ = os.precision();
|
||||
fill_ = os.fill();
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
void apply_manip_body( stream_format_state& self,
|
||||
T manipulator)
|
||||
// modify our params according to the manipulator
|
||||
{
|
||||
BOOST_IO_STD stringstream ss;
|
||||
self.apply_on( ss );
|
||||
ss << manipulator;
|
||||
self.set_by_stream( ss );
|
||||
}
|
||||
|
||||
inline
|
||||
void stream_format_state::reset()
|
||||
// set our params to standard's default state
|
||||
{
|
||||
width_=-1; precision_=-1; fill_=0;
|
||||
flags_ = std::ios::dec;
|
||||
}
|
||||
|
||||
|
||||
// --- format_items:: -------------------------------------------
|
||||
inline
|
||||
void format_item::compute_states()
|
||||
// reflect pad_scheme_ on state_ and ref_state_
|
||||
// because some pad_schemes has complex consequences on several state params.
|
||||
{
|
||||
if(pad_scheme_ & zeropad)
|
||||
{
|
||||
if(ref_state_.flags_ & std::ios::left)
|
||||
{
|
||||
pad_scheme_ = pad_scheme_ & (~zeropad); // ignore zeropad in left alignment
|
||||
}
|
||||
else
|
||||
{
|
||||
ref_state_.fill_='0';
|
||||
ref_state_.flags_ |= std::ios::internal;
|
||||
}
|
||||
}
|
||||
state_ = ref_state_;
|
||||
}
|
||||
|
||||
|
||||
} } } // namespaces boost :: io :: detail
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_INTERNALS_HPP
|
|
@ -1,65 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// internals_fwd.hpp : forward declarations, for internal headers
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_FORMAT_INTERNAL_FWD_HPP
|
||||
#define BOOST_FORMAT_INTERNAL_FWD_HPP
|
||||
|
||||
#include "boost/format/format_fwd.hpp"
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace io {
|
||||
|
||||
namespace detail {
|
||||
struct stream_format_state;
|
||||
struct format_item;
|
||||
}
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
// these functions were intended as methods,
|
||||
// but MSVC have problems with template member functions :
|
||||
|
||||
// defined in format_implementation.hpp :
|
||||
template<class T>
|
||||
basic_format& modify_item_body( basic_format& self,
|
||||
int itemN, const T& manipulator);
|
||||
|
||||
template<class T>
|
||||
basic_format& bind_arg_body( basic_format& self,
|
||||
int argN, const T& val);
|
||||
|
||||
template<class T>
|
||||
void apply_manip_body( stream_format_state& self,
|
||||
T manipulator);
|
||||
|
||||
// argument feeding (defined in feed_args.hpp ) :
|
||||
template<class T>
|
||||
void distribute(basic_format& self, T x);
|
||||
|
||||
template<class T>
|
||||
basic_format& feed(basic_format& self, T x);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace io
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_INTERNAL_FWD_HPP
|
|
@ -1,7 +0,0 @@
|
|||
libraries += libformat
|
||||
|
||||
libformat_NAME = libnixformat
|
||||
|
||||
libformat_DIR := $(d)
|
||||
|
||||
libformat_SOURCES := $(wildcard $(d)/*.cc)
|
|
@ -1,48 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rüdiger Loos's format class
|
||||
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// macros_default.hpp : configuration for the format library
|
||||
// provides default values for the stl workaround macros
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_FORMAT_MACROS_DEFAULT_HPP
|
||||
#define BOOST_FORMAT_MACROS_DEFAULT_HPP
|
||||
|
||||
// *** This should go to "boost/config/suffix.hpp".
|
||||
|
||||
#ifndef BOOST_IO_STD
|
||||
# define BOOST_IO_STD std::
|
||||
#endif
|
||||
|
||||
// **** Workaround for io streams, stlport and msvc.
|
||||
#ifdef BOOST_IO_NEEDS_USING_DECLARATION
|
||||
namespace boost {
|
||||
using std::char_traits;
|
||||
using std::basic_ostream;
|
||||
using std::basic_ostringstream;
|
||||
namespace io {
|
||||
using std::basic_ostream;
|
||||
namespace detail {
|
||||
using std::basic_ios;
|
||||
using std::basic_ostream;
|
||||
using std::basic_ostringstream;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#endif // BOOST_FORMAT_MACROS_DEFAULT_HPP
|
|
@ -1,454 +0,0 @@
|
|||
// -*- C++ -*-
|
||||
// Boost general library 'format' ---------------------------
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
// (C) Samuel Krempp 2001
|
||||
// krempp@crans.ens-cachan.fr
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// ideas taken from Rudiger Loos's format class
|
||||
// and Karl Nelson's ofstream (also took its parsing code as basis for printf parsing)
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// parsing.hpp : implementation of the parsing member functions
|
||||
// ( parse, parse_printf_directive)
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef BOOST_FORMAT_PARSING_HPP
|
||||
#define BOOST_FORMAT_PARSING_HPP
|
||||
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace io {
|
||||
namespace detail {
|
||||
|
||||
template<class Stream> inline
|
||||
bool wrap_isdigit(char c, Stream &os)
|
||||
{
|
||||
#ifndef BOOST_NO_LOCALE_ISIDIGIT
|
||||
return std::isdigit(c, os.rdbuf()->getloc() );
|
||||
# else
|
||||
using namespace std;
|
||||
return isdigit(c);
|
||||
#endif
|
||||
} //end- wrap_isdigit(..)
|
||||
|
||||
template<class Res> inline
|
||||
Res str2int(const std::string& s,
|
||||
std::string::size_type start,
|
||||
BOOST_IO_STD ios &os,
|
||||
const Res = Res(0) )
|
||||
// Input : char string, with starting index
|
||||
// a basic_ios& merely to call its widen/narrow member function in the desired locale.
|
||||
// Effects : reads s[start:] and converts digits into an integral n, of type Res
|
||||
// Returns : n
|
||||
{
|
||||
Res n = 0;
|
||||
while(start<s.size() && wrap_isdigit(s[start], os) ) {
|
||||
char cur_ch = s[start];
|
||||
BOOST_ASSERT(cur_ch != 0 ); // since we called isdigit, this should not happen.
|
||||
n *= 10;
|
||||
n += cur_ch - '0'; // 22.2.1.1.2 of the C++ standard
|
||||
++start;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void skip_asterisk(const std::string & buf,
|
||||
std::string::size_type * pos_p,
|
||||
BOOST_IO_STD ios &os)
|
||||
// skip printf's "asterisk-fields" directives in the format-string buf
|
||||
// Input : char string, with starting index *pos_p
|
||||
// a basic_ios& merely to call its widen/narrow member function in the desired locale.
|
||||
// Effects : advance *pos_p by skipping printf's asterisk fields.
|
||||
// Returns : nothing
|
||||
{
|
||||
using namespace std;
|
||||
BOOST_ASSERT( pos_p != 0);
|
||||
if(*pos_p >= buf.size() ) return;
|
||||
if(buf[ *pos_p]=='*') {
|
||||
++ (*pos_p);
|
||||
while (*pos_p < buf.size() && wrap_isdigit(buf[*pos_p],os)) ++(*pos_p);
|
||||
if(buf[*pos_p]=='$') ++(*pos_p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void maybe_throw_exception( unsigned char exceptions)
|
||||
// auxiliary func called by parse_printf_directive
|
||||
// for centralising error handling
|
||||
// it either throws if user sets the corresponding flag, or does nothing.
|
||||
{
|
||||
if(exceptions & io::bad_format_string_bit)
|
||||
boost::throw_exception(io::bad_format_string());
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool parse_printf_directive(const std::string & buf,
|
||||
std::string::size_type * pos_p,
|
||||
detail::format_item * fpar,
|
||||
BOOST_IO_STD ios &os,
|
||||
unsigned char exceptions)
|
||||
// Input : a 'printf-directive' in the format-string, starting at buf[ *pos_p ]
|
||||
// a basic_ios& merely to call its widen/narrow member function in the desired locale.
|
||||
// a bitset'excpetions' telling whether to throw exceptions on errors.
|
||||
// Returns : true if parse somehow succeeded (possibly ignoring errors if exceptions disabled)
|
||||
// false if it failed so bad that the directive should be printed verbatim
|
||||
// Effects : - *pos_p is incremented so that buf[*pos_p] is the first char after the directive
|
||||
// - *fpar is set with the parameters read in the directive
|
||||
{
|
||||
typedef format_item format_item_t;
|
||||
BOOST_ASSERT( pos_p != 0);
|
||||
std::string::size_type &i1 = *pos_p,
|
||||
i0;
|
||||
fpar->argN_ = format_item_t::argN_no_posit; // if no positional-directive
|
||||
|
||||
bool in_brackets=false;
|
||||
if(buf[i1]=='|')
|
||||
{
|
||||
in_brackets=true;
|
||||
if( ++i1 >= buf.size() ) {
|
||||
maybe_throw_exception(exceptions);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// the flag '0' would be picked as a digit for argument order, but here it's a flag :
|
||||
if(buf[i1]=='0')
|
||||
goto parse_flags;
|
||||
|
||||
// handle argument order (%2$d) or possibly width specification: %2d
|
||||
i0 = i1; // save position before digits
|
||||
while (i1 < buf.size() && wrap_isdigit(buf[i1], os))
|
||||
++i1;
|
||||
if (i1!=i0)
|
||||
{
|
||||
if( i1 >= buf.size() ) {
|
||||
maybe_throw_exception(exceptions);
|
||||
return false;
|
||||
}
|
||||
int n=str2int(buf,i0, os, int(0) );
|
||||
|
||||
// %N% case : this is already the end of the directive
|
||||
if( buf[i1] == '%' )
|
||||
{
|
||||
fpar->argN_ = n-1;
|
||||
++i1;
|
||||
if( in_brackets)
|
||||
maybe_throw_exception(exceptions);
|
||||
// but don't return. maybe "%" was used in lieu of '$', so we go on.
|
||||
else return true;
|
||||
}
|
||||
|
||||
if ( buf[i1]=='$' )
|
||||
{
|
||||
fpar->argN_ = n-1;
|
||||
++i1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-positionnal directive
|
||||
fpar->ref_state_.width_ = n;
|
||||
fpar->argN_ = format_item_t::argN_no_posit;
|
||||
goto parse_precision;
|
||||
}
|
||||
}
|
||||
|
||||
parse_flags:
|
||||
// handle flags
|
||||
while ( i1 <buf.size()) // as long as char is one of + - = # 0 l h or ' '
|
||||
{
|
||||
// misc switches
|
||||
switch (buf[i1])
|
||||
{
|
||||
case '\'' : break; // no effect yet. (painful to implement)
|
||||
case 'l':
|
||||
case 'h': // short/long modifier : for printf-comaptibility (no action needed)
|
||||
break;
|
||||
case '-':
|
||||
fpar->ref_state_.flags_ |= std::ios::left;
|
||||
break;
|
||||
case '=':
|
||||
fpar->pad_scheme_ |= format_item_t::centered;
|
||||
break;
|
||||
case ' ':
|
||||
fpar->pad_scheme_ |= format_item_t::spacepad;
|
||||
break;
|
||||
case '+':
|
||||
fpar->ref_state_.flags_ |= std::ios::showpos;
|
||||
break;
|
||||
case '0':
|
||||
fpar->pad_scheme_ |= format_item_t::zeropad;
|
||||
// need to know alignment before really setting flags,
|
||||
// so just add 'zeropad' flag for now, it will be processed later.
|
||||
break;
|
||||
case '#':
|
||||
fpar->ref_state_.flags_ |= std::ios::showpoint | std::ios::showbase;
|
||||
break;
|
||||
default:
|
||||
goto parse_width;
|
||||
}
|
||||
++i1;
|
||||
} // loop on flag.
|
||||
if( i1>=buf.size()) {
|
||||
maybe_throw_exception(exceptions);
|
||||
return true;
|
||||
}
|
||||
|
||||
parse_width:
|
||||
// handle width spec
|
||||
skip_asterisk(buf, &i1, os); // skips 'asterisk fields' : *, or *N$
|
||||
i0 = i1; // save position before digits
|
||||
while (i1<buf.size() && wrap_isdigit(buf[i1], os))
|
||||
i1++;
|
||||
|
||||
if (i1!=i0)
|
||||
{ fpar->ref_state_.width_ = str2int( buf,i0, os, std::streamsize(0) ); }
|
||||
|
||||
parse_precision:
|
||||
if( i1>=buf.size()) {
|
||||
maybe_throw_exception(exceptions);
|
||||
return true;
|
||||
}
|
||||
// handle precision spec
|
||||
if (buf[i1]=='.')
|
||||
{
|
||||
++i1;
|
||||
skip_asterisk(buf, &i1, os);
|
||||
i0 = i1; // save position before digits
|
||||
while (i1<buf.size() && wrap_isdigit(buf[i1], os))
|
||||
++i1;
|
||||
|
||||
if(i1==i0)
|
||||
fpar->ref_state_.precision_ = 0;
|
||||
else
|
||||
fpar->ref_state_.precision_ = str2int(buf,i0, os, std::streamsize(0) );
|
||||
}
|
||||
|
||||
// handle formatting-type flags :
|
||||
while( i1<buf.size() &&
|
||||
( buf[i1]=='l' || buf[i1]=='L' || buf[i1]=='h') )
|
||||
++i1;
|
||||
if( i1>=buf.size()) {
|
||||
maybe_throw_exception(exceptions);
|
||||
return true;
|
||||
}
|
||||
|
||||
if( in_brackets && buf[i1]=='|' )
|
||||
{
|
||||
++i1;
|
||||
return true;
|
||||
}
|
||||
switch (buf[i1])
|
||||
{
|
||||
case 'X':
|
||||
fpar->ref_state_.flags_ |= std::ios::uppercase;
|
||||
case 'p': // pointer => set hex.
|
||||
case 'x':
|
||||
fpar->ref_state_.flags_ &= ~std::ios::basefield;
|
||||
fpar->ref_state_.flags_ |= std::ios::hex;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
fpar->ref_state_.flags_ &= ~std::ios::basefield;
|
||||
fpar->ref_state_.flags_ |= std::ios::oct;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
fpar->ref_state_.flags_ |= std::ios::uppercase;
|
||||
case 'e':
|
||||
fpar->ref_state_.flags_ &= ~std::ios::floatfield;
|
||||
fpar->ref_state_.flags_ |= std::ios::scientific;
|
||||
|
||||
fpar->ref_state_.flags_ &= ~std::ios::basefield;
|
||||
fpar->ref_state_.flags_ |= std::ios::dec;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
fpar->ref_state_.flags_ &= ~std::ios::floatfield;
|
||||
fpar->ref_state_.flags_ |= std::ios::fixed;
|
||||
case 'u':
|
||||
case 'd':
|
||||
case 'i':
|
||||
fpar->ref_state_.flags_ &= ~std::ios::basefield;
|
||||
fpar->ref_state_.flags_ |= std::ios::dec;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
++i1;
|
||||
if( i1 >= buf.size())
|
||||
maybe_throw_exception(exceptions);
|
||||
else
|
||||
fpar->ref_state_.fill_ = buf[i1];
|
||||
fpar->pad_scheme_ |= format_item_t::tabulation;
|
||||
fpar->argN_ = format_item_t::argN_tabulation;
|
||||
break;
|
||||
case 't':
|
||||
fpar->ref_state_.fill_ = ' ';
|
||||
fpar->pad_scheme_ |= format_item_t::tabulation;
|
||||
fpar->argN_ = format_item_t::argN_tabulation;
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
fpar->ref_state_.flags_ |= std::ios::uppercase;
|
||||
break;
|
||||
case 'g': // 'g' conversion is default for floats.
|
||||
fpar->ref_state_.flags_ &= ~std::ios::basefield;
|
||||
fpar->ref_state_.flags_ |= std::ios::dec;
|
||||
|
||||
// CLEAR all floatield flags, so stream will CHOOSE
|
||||
fpar->ref_state_.flags_ &= ~std::ios::floatfield;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
case 'c':
|
||||
fpar->truncate_ = 1;
|
||||
break;
|
||||
case 'S':
|
||||
case 's':
|
||||
fpar->truncate_ = fpar->ref_state_.precision_;
|
||||
fpar->ref_state_.precision_ = -1;
|
||||
break;
|
||||
case 'n' :
|
||||
fpar->argN_ = format_item_t::argN_ignored;
|
||||
break;
|
||||
default:
|
||||
maybe_throw_exception(exceptions);
|
||||
}
|
||||
++i1;
|
||||
|
||||
if( in_brackets )
|
||||
{
|
||||
if( i1<buf.size() && buf[i1]=='|' )
|
||||
{
|
||||
++i1;
|
||||
return true;
|
||||
}
|
||||
else maybe_throw_exception(exceptions);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // detail namespace
|
||||
} // io namespace
|
||||
|
||||
|
||||
// -----------------------------------------------
|
||||
// format :: parse(..)
|
||||
|
||||
void basic_format::parse(const string_t & buf)
|
||||
// parse the format-string
|
||||
{
|
||||
using namespace std;
|
||||
const char arg_mark = '%';
|
||||
bool ordered_args=true;
|
||||
int max_argN=-1;
|
||||
string_t::size_type i1=0;
|
||||
int num_items=0;
|
||||
|
||||
// A: find upper_bound on num_items and allocates arrays
|
||||
i1=0;
|
||||
while( (i1=buf.find(arg_mark,i1)) != string::npos )
|
||||
{
|
||||
if( i1+1 >= buf.size() ) {
|
||||
if(exceptions() & io::bad_format_string_bit)
|
||||
boost::throw_exception(io::bad_format_string()); // must not end in "bla bla %"
|
||||
else break; // stop there, ignore last '%'
|
||||
}
|
||||
if(buf[i1+1] == buf[i1] ) { i1+=2; continue; } // escaped "%%" / "##"
|
||||
++i1;
|
||||
|
||||
// in case of %N% directives, dont count it double (wastes allocations..) :
|
||||
while(i1 < buf.size() && io::detail::wrap_isdigit(buf[i1],oss_)) ++i1;
|
||||
if( i1 < buf.size() && buf[i1] == arg_mark ) ++ i1;
|
||||
|
||||
++num_items;
|
||||
}
|
||||
items_.assign( num_items, format_item_t() );
|
||||
|
||||
// B: Now the real parsing of the format string :
|
||||
num_items=0;
|
||||
i1 = 0;
|
||||
string_t::size_type i0 = i1;
|
||||
bool special_things=false;
|
||||
int cur_it=0;
|
||||
while( (i1=buf.find(arg_mark,i1)) != string::npos )
|
||||
{
|
||||
string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_;
|
||||
|
||||
if( buf[i1+1] == buf[i1] ) // escaped mark, '%%'
|
||||
{
|
||||
piece += buf.substr(i0, i1-i0) + buf[i1];
|
||||
i1+=2; i0=i1;
|
||||
continue;
|
||||
}
|
||||
BOOST_ASSERT( static_cast<unsigned int>(cur_it) < items_.size() || cur_it==0);
|
||||
|
||||
if(i1!=i0) piece += buf.substr(i0, i1-i0);
|
||||
++i1;
|
||||
|
||||
bool parse_ok;
|
||||
parse_ok = io::detail::parse_printf_directive(buf, &i1, &items_[cur_it], oss_, exceptions());
|
||||
if( ! parse_ok ) continue; // the directive will be printed verbatim
|
||||
|
||||
i0=i1;
|
||||
items_[cur_it].compute_states(); // process complex options, like zeropad, into stream params.
|
||||
|
||||
int argN=items_[cur_it].argN_;
|
||||
if(argN == format_item_t::argN_ignored)
|
||||
continue;
|
||||
if(argN ==format_item_t::argN_no_posit)
|
||||
ordered_args=false;
|
||||
else if(argN == format_item_t::argN_tabulation) special_things=true;
|
||||
else if(argN > max_argN) max_argN = argN;
|
||||
++num_items;
|
||||
++cur_it;
|
||||
} // loop on %'s
|
||||
BOOST_ASSERT(cur_it == num_items);
|
||||
|
||||
// store the final piece of string
|
||||
string_t & piece = (cur_it==0) ? prefix_ : items_[cur_it-1].appendix_;
|
||||
piece += buf.substr(i0);
|
||||
|
||||
if( !ordered_args)
|
||||
{
|
||||
if(max_argN >= 0 ) // dont mix positional with non-positionnal directives
|
||||
{
|
||||
if(exceptions() & io::bad_format_string_bit)
|
||||
boost::throw_exception(io::bad_format_string());
|
||||
// else do nothing. => positionnal arguments are processed as non-positionnal
|
||||
}
|
||||
// set things like it would have been with positional directives :
|
||||
int non_ordered_items = 0;
|
||||
for(int i=0; i< num_items; ++i)
|
||||
if(items_[i].argN_ == format_item_t::argN_no_posit)
|
||||
{
|
||||
items_[i].argN_ = non_ordered_items;
|
||||
++non_ordered_items;
|
||||
}
|
||||
max_argN = non_ordered_items-1;
|
||||
}
|
||||
|
||||
// C: set some member data :
|
||||
items_.resize(num_items);
|
||||
|
||||
if(special_things) style_ |= special_needs;
|
||||
num_args_ = max_argN + 1;
|
||||
if(ordered_args) style_ |= ordered;
|
||||
else style_ &= ~ordered;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORMAT_PARSING_HPP
|
|
@ -1,47 +0,0 @@
|
|||
#ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED
|
||||
#define BOOST_THROW_EXCEPTION_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/throw_exception.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// http://www.boost.org/libs/utility/throw_exception.html
|
||||
//
|
||||
|
||||
//#include <boost/config.hpp>
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
# include <exception>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
|
||||
void throw_exception(std::exception const & e); // user defined
|
||||
|
||||
#else
|
||||
|
||||
template<class E> void throw_exception(E const & e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED
|
|
@ -17,6 +17,7 @@
|
|||
#include "store-api.hh"
|
||||
#include "derivations.hh"
|
||||
#include "local-store.hh"
|
||||
#include "legacy.hh"
|
||||
|
||||
using namespace nix;
|
||||
using std::cin;
|
||||
|
@ -37,11 +38,15 @@ static AutoCloseFD openSlotLock(const Machine & m, unsigned long long slot)
|
|||
return openLockFile(fmt("%s/%s-%d", currentLoad, escapeUri(m.storeUri), slot), true);
|
||||
}
|
||||
|
||||
int main (int argc, char * * argv)
|
||||
{
|
||||
return handleExceptions(argv[0], [&]() {
|
||||
initNix();
|
||||
static bool allSupportedLocally(const std::set<std::string>& requiredFeatures) {
|
||||
for (auto & feature : requiredFeatures)
|
||||
if (!settings.systemFeatures.get().count(feature)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int _main(int argc, char * * argv)
|
||||
{
|
||||
{
|
||||
logger = makeJSONLogger(*logger);
|
||||
|
||||
/* Ensure we don't get any SSH passphrase or host key popups. */
|
||||
|
@ -80,7 +85,7 @@ int main (int argc, char * * argv)
|
|||
|
||||
if (machines.empty()) {
|
||||
std::cerr << "# decline-permanently\n";
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
string drvPath;
|
||||
|
@ -90,15 +95,18 @@ int main (int argc, char * * argv)
|
|||
|
||||
try {
|
||||
auto s = readString(source);
|
||||
if (s != "try") return;
|
||||
} catch (EndOfFile &) { return; }
|
||||
if (s != "try") return 0;
|
||||
} catch (EndOfFile &) { return 0; }
|
||||
|
||||
auto amWilling = readInt(source);
|
||||
auto neededSystem = readString(source);
|
||||
source >> drvPath;
|
||||
auto requiredFeatures = readStrings<std::set<std::string>>(source);
|
||||
|
||||
auto canBuildLocally = amWilling && (neededSystem == settings.thisSystem);
|
||||
auto canBuildLocally = amWilling
|
||||
&& ( neededSystem == settings.thisSystem
|
||||
|| settings.extraPlatforms.get().count(neededSystem) > 0)
|
||||
&& allSupportedLocally(requiredFeatures);
|
||||
|
||||
/* Error ignored here, will be caught later */
|
||||
mkdir(currentLoad.c_str(), 0777);
|
||||
|
@ -191,8 +199,10 @@ int main (int argc, char * * argv)
|
|||
storeUri = bestMachine->storeUri;
|
||||
|
||||
} catch (std::exception & e) {
|
||||
printError("unable to open SSH connection to '%s': %s; trying other available machines...",
|
||||
bestMachine->storeUri, e.what());
|
||||
auto msg = chomp(drainFD(5, false));
|
||||
printError("cannot build on '%s': %s%s",
|
||||
bestMachine->storeUri, e.what(),
|
||||
(msg.empty() ? "" : ": " + msg));
|
||||
bestMachine->enabled = false;
|
||||
continue;
|
||||
}
|
||||
|
@ -202,6 +212,8 @@ int main (int argc, char * * argv)
|
|||
}
|
||||
|
||||
connected:
|
||||
close(5);
|
||||
|
||||
std::cerr << "# accept\n" << storeUri << "\n";
|
||||
|
||||
auto inputs = readStrings<PathSet>(source);
|
||||
|
@ -244,9 +256,11 @@ connected:
|
|||
if (!missing.empty()) {
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying outputs from '%s'", storeUri));
|
||||
store->locksHeld.insert(missing.begin(), missing.end()); /* FIXME: ugly */
|
||||
copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs, substitute);
|
||||
copyPaths(ref<Store>(sshStore), store, missing, NoRepair, NoCheckSigs, NoSubstitute);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static RegisterLegacyCommand s1("build-remote", _main);
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
programs += build-remote
|
||||
|
||||
build-remote_DIR := $(d)
|
||||
|
||||
build-remote_INSTALL_DIR := $(libexecdir)/nix
|
||||
|
||||
build-remote_LIBS = libmain libutil libformat libstore
|
||||
|
||||
build-remote_SOURCES := $(d)/build-remote.cc
|
|
@ -1,187 +0,0 @@
|
|||
#include "shared.hh"
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace nix;
|
||||
|
||||
typedef std::map<Path,int> Priorities;
|
||||
|
||||
static bool isDirectory (const Path & path)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(path.c_str(), &st) == -1)
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
return S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
static auto priorities = Priorities{};
|
||||
|
||||
static auto symlinks = 0;
|
||||
|
||||
/* For each activated package, create symlinks */
|
||||
static void createLinks(const Path & srcDir, const Path & dstDir, int priority)
|
||||
{
|
||||
auto srcFiles = readDirectory(srcDir);
|
||||
for (const auto & ent : srcFiles) {
|
||||
if (ent.name[0] == '.')
|
||||
/* not matched by glob */
|
||||
continue;
|
||||
const auto & srcFile = srcDir + "/" + ent.name;
|
||||
auto dstFile = dstDir + "/" + ent.name;
|
||||
|
||||
/* The files below are special-cased to that they don't show up
|
||||
* in user profiles, either because they are useless, or
|
||||
* because they would cauase pointless collisions (e.g., each
|
||||
* Python package brings its own
|
||||
* `$out/lib/pythonX.Y/site-packages/easy-install.pth'.)
|
||||
*/
|
||||
if (hasSuffix(srcFile, "/propagated-build-inputs") ||
|
||||
hasSuffix(srcFile, "/nix-support") ||
|
||||
hasSuffix(srcFile, "/perllocal.pod") ||
|
||||
hasSuffix(srcFile, "/info/dir") ||
|
||||
hasSuffix(srcFile, "/log")) {
|
||||
continue;
|
||||
} else if (isDirectory(srcFile)) {
|
||||
struct stat dstSt;
|
||||
auto res = lstat(dstFile.c_str(), &dstSt);
|
||||
if (res == 0) {
|
||||
if (S_ISDIR(dstSt.st_mode)) {
|
||||
createLinks(srcFile, dstFile, priority);
|
||||
continue;
|
||||
} else if (S_ISLNK(dstSt.st_mode)) {
|
||||
auto target = readLink(dstFile);
|
||||
if (!isDirectory(target))
|
||||
throw Error(format("collision between '%1%' and non-directory '%2%'")
|
||||
% srcFile % target);
|
||||
if (unlink(dstFile.c_str()) == -1)
|
||||
throw SysError(format("unlinking '%1%'") % dstFile);
|
||||
if (mkdir(dstFile.c_str(), 0755) == -1)
|
||||
throw SysError(format("creating directory '%1%'"));
|
||||
createLinks(target, dstFile, priorities[dstFile]);
|
||||
createLinks(srcFile, dstFile, priority);
|
||||
continue;
|
||||
}
|
||||
} else if (errno != ENOENT)
|
||||
throw SysError(format("getting status of '%1%'") % dstFile);
|
||||
} else {
|
||||
struct stat dstSt;
|
||||
auto res = lstat(dstFile.c_str(), &dstSt);
|
||||
if (res == 0) {
|
||||
if (S_ISLNK(dstSt.st_mode)) {
|
||||
auto target = readLink(dstFile);
|
||||
auto prevPriority = priorities[dstFile];
|
||||
if (prevPriority == priority)
|
||||
throw Error(format(
|
||||
"Packages '%1%' and '%2%' have the same priority '%3%'"
|
||||
"use 'nix-env --set-flag priority NUMBER INSTALLED_PKGNAME' "
|
||||
"to change the priority of one of the conflicting packages"
|
||||
" ('0' being the highest priority)"
|
||||
) % srcFile % target % priority);
|
||||
if (prevPriority < priority)
|
||||
continue;
|
||||
if (unlink(dstFile.c_str()) == -1)
|
||||
throw SysError(format("unlinking '%1%'") % dstFile);
|
||||
}
|
||||
} else if (errno != ENOENT)
|
||||
throw SysError(format("getting status of '%1%'") % dstFile);
|
||||
}
|
||||
createSymlink(srcFile, dstFile);
|
||||
priorities[dstFile] = priority;
|
||||
symlinks++;
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::set<Path> FileProp;
|
||||
|
||||
static auto done = FileProp{};
|
||||
static auto postponed = FileProp{};
|
||||
|
||||
static auto out = string{};
|
||||
|
||||
static void addPkg(const Path & pkgDir, int priority)
|
||||
{
|
||||
if (done.find(pkgDir) != done.end())
|
||||
return;
|
||||
done.insert(pkgDir);
|
||||
createLinks(pkgDir, out, priority);
|
||||
auto propagatedFN = pkgDir + "/nix-support/propagated-user-env-packages";
|
||||
auto propagated = string{};
|
||||
{
|
||||
AutoCloseFD fd = open(propagatedFN.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (!fd) {
|
||||
if (errno == ENOENT)
|
||||
return;
|
||||
throw SysError(format("opening '%1%'") % propagatedFN);
|
||||
}
|
||||
propagated = readFile(fd.get());
|
||||
}
|
||||
for (const auto & p : tokenizeString<std::vector<string>>(propagated, " \n"))
|
||||
if (done.find(p) == done.end())
|
||||
postponed.insert(p);
|
||||
}
|
||||
|
||||
struct Package {
|
||||
Path path;
|
||||
bool active;
|
||||
int priority;
|
||||
Package(Path path, bool active, int priority) : path{std::move(path)}, active{active}, priority{priority} {}
|
||||
};
|
||||
|
||||
typedef std::vector<Package> Packages;
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
return handleExceptions(argv[0], [&]() {
|
||||
initNix();
|
||||
out = getEnv("out");
|
||||
if (mkdir(out.c_str(), 0755) == -1)
|
||||
throw SysError(format("creating %1%") % out);
|
||||
|
||||
/* Convert the stuff we get from the environment back into a coherent
|
||||
* data type.
|
||||
*/
|
||||
auto pkgs = Packages{};
|
||||
auto derivations = tokenizeString<Strings>(getEnv("derivations"));
|
||||
while (!derivations.empty()) {
|
||||
/* !!! We're trusting the caller to structure derivations env var correctly */
|
||||
auto active = derivations.front(); derivations.pop_front();
|
||||
auto priority = stoi(derivations.front()); derivations.pop_front();
|
||||
auto outputs = stoi(derivations.front()); derivations.pop_front();
|
||||
for (auto n = 0; n < outputs; n++) {
|
||||
auto path = derivations.front(); derivations.pop_front();
|
||||
pkgs.emplace_back(path, active != "false", priority);
|
||||
}
|
||||
}
|
||||
|
||||
/* Symlink to the packages that have been installed explicitly by the
|
||||
* user. Process in priority order to reduce unnecessary
|
||||
* symlink/unlink steps.
|
||||
*/
|
||||
std::sort(pkgs.begin(), pkgs.end(), [](const Package & a, const Package & b) {
|
||||
return a.priority < b.priority || (a.priority == b.priority && a.path < b.path);
|
||||
});
|
||||
for (const auto & pkg : pkgs)
|
||||
if (pkg.active)
|
||||
addPkg(pkg.path, pkg.priority);
|
||||
|
||||
/* Symlink to the packages that have been "propagated" by packages
|
||||
* installed by the user (i.e., package X declares that it wants Y
|
||||
* installed as well). We do these later because they have a lower
|
||||
* priority in case of collisions.
|
||||
*/
|
||||
auto priorityCounter = 1000;
|
||||
while (!postponed.empty()) {
|
||||
auto pkgDirs = postponed;
|
||||
postponed = FileProp{};
|
||||
for (const auto & pkgDir : pkgDirs)
|
||||
addPkg(pkgDir, priorityCounter++);
|
||||
}
|
||||
|
||||
std::cerr << "created " << symlinks << " symlinks in user environment\n";
|
||||
|
||||
createSymlink(getEnv("manifest"), out + "/manifest.nix");
|
||||
});
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
programs += buildenv
|
||||
|
||||
buildenv_DIR := $(d)
|
||||
|
||||
buildenv_INSTALL_DIR := $(libexecdir)/nix
|
||||
|
||||
buildenv_LIBS = libmain libstore libutil libformat
|
||||
|
||||
buildenv_SOURCES := $(d)/buildenv.cc
|
|
@ -0,0 +1,18 @@
|
|||
Copyright (c) 2014 Chase Geigle
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
#include "attr-set.hh"
|
||||
#include "eval.hh"
|
||||
#include "eval-inline.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -7,30 +7,18 @@
|
|||
namespace nix {
|
||||
|
||||
|
||||
/* Note: Various places expect the allocated memory to be zeroed. */
|
||||
static void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_malloc(n);
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a new array of attributes for an attribute set with a specific
|
||||
capacity. The space is implicitly reserved after the Bindings
|
||||
structure. */
|
||||
Bindings * EvalState::allocBindings(Bindings::size_t capacity)
|
||||
Bindings * EvalState::allocBindings(size_t capacity)
|
||||
{
|
||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings(capacity);
|
||||
if (capacity > std::numeric_limits<Bindings::size_t>::max())
|
||||
throw Error("attribute set of size %d is too big", capacity);
|
||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
|
||||
}
|
||||
|
||||
|
||||
void EvalState::mkAttrs(Value & v, unsigned int capacity)
|
||||
void EvalState::mkAttrs(Value & v, size_t capacity)
|
||||
{
|
||||
if (capacity == 0) {
|
||||
v = vEmptySet;
|
||||
|
|
|
@ -45,9 +45,11 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
|||
|
||||
Path lookupFileArg(EvalState & state, string s)
|
||||
{
|
||||
if (isUri(s))
|
||||
return getDownloader()->downloadCached(state.store, s, true);
|
||||
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
if (isUri(s)) {
|
||||
CachedDownloadRequest request(s);
|
||||
request.unpack = true;
|
||||
return getDownloader()->downloadCached(state.store, request).path;
|
||||
} else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
|
||||
Path p = s.substr(1, s.size() - 2);
|
||||
return state.findFile(p);
|
||||
} else
|
||||
|
|
|
@ -78,4 +78,18 @@ inline void EvalState::forceList(Value & v, const Pos & pos)
|
|||
throwTypeError("value is %1% while a list was expected, at %2%", v, pos);
|
||||
}
|
||||
|
||||
/* Note: Various places expect the allocated memory to be zeroed. */
|
||||
inline void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_MALLOC(n);
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,17 @@
|
|||
#include "globals.hh"
|
||||
#include "eval-inline.hh"
|
||||
#include "download.hh"
|
||||
#include "json.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
|
@ -18,15 +24,8 @@
|
|||
#include <gc/gc.h>
|
||||
#include <gc/gc_cpp.h>
|
||||
|
||||
#define NEW new (UseGC)
|
||||
|
||||
#else
|
||||
|
||||
#define NEW new
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
||||
|
@ -34,7 +33,7 @@ static char * dupString(const char * s)
|
|||
{
|
||||
char * t;
|
||||
#if HAVE_BOEHMGC
|
||||
t = GC_strdup(s);
|
||||
t = GC_STRDUP(s);
|
||||
#else
|
||||
t = strdup(s);
|
||||
#endif
|
||||
|
@ -43,20 +42,6 @@ static char * dupString(const char * s)
|
|||
}
|
||||
|
||||
|
||||
/* Note: Various places expect the allocated memory to be zeroed. */
|
||||
static void * allocBytes(size_t n)
|
||||
{
|
||||
void * p;
|
||||
#if HAVE_BOEHMGC
|
||||
p = GC_malloc(n);
|
||||
#else
|
||||
p = calloc(n, 1);
|
||||
#endif
|
||||
if (!p) throw std::bad_alloc();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v)
|
||||
{
|
||||
checkInterrupt();
|
||||
|
@ -145,6 +130,16 @@ std::ostream & operator << (std::ostream & str, const Value & v)
|
|||
}
|
||||
|
||||
|
||||
const Value *getPrimOp(const Value &v) {
|
||||
const Value * primOp = &v;
|
||||
while (primOp->type == tPrimOpApp) {
|
||||
primOp = primOp->primOpApp.left;
|
||||
}
|
||||
assert(primOp->type == tPrimOp);
|
||||
return primOp;
|
||||
}
|
||||
|
||||
|
||||
string showType(const Value & v)
|
||||
{
|
||||
switch (v.type) {
|
||||
|
@ -159,8 +154,10 @@ string showType(const Value & v)
|
|||
case tApp: return "a function application";
|
||||
case tLambda: return "a function";
|
||||
case tBlackhole: return "a black hole";
|
||||
case tPrimOp: return "a built-in function";
|
||||
case tPrimOpApp: return "a partially applied built-in function";
|
||||
case tPrimOp:
|
||||
return fmt("the built-in function '%s'", string(v.primOp->name));
|
||||
case tPrimOpApp:
|
||||
return fmt("the partially applied built-in function '%s'", string(getPrimOp(v)->primOp->name));
|
||||
case tExternal: return v.external->showType();
|
||||
case tFloat: return "a float";
|
||||
}
|
||||
|
@ -199,8 +196,15 @@ void initGC()
|
|||
|
||||
#if HAVE_BOEHMGC
|
||||
/* Initialise the Boehm garbage collector. */
|
||||
|
||||
/* Don't look for interior pointers. This reduces the odds of
|
||||
misdetection a bit. */
|
||||
GC_set_all_interior_pointers(0);
|
||||
|
||||
/* We don't have any roots in data segments, so don't scan from
|
||||
there. */
|
||||
GC_set_no_dls(1);
|
||||
|
||||
GC_INIT();
|
||||
|
||||
GC_set_oom_fn(oomHandler);
|
||||
|
@ -307,20 +311,32 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
|
|||
|
||||
assert(gcInitialised);
|
||||
|
||||
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
|
||||
|
||||
/* Initialise the Nix expression search path. */
|
||||
if (!settings.pureEval) {
|
||||
if (!evalSettings.pureEval) {
|
||||
Strings paths = parseNixPath(getEnv("NIX_PATH", ""));
|
||||
for (auto & i : _searchPath) addToSearchPath(i);
|
||||
for (auto & i : paths) addToSearchPath(i);
|
||||
}
|
||||
addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs"));
|
||||
addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs", true));
|
||||
|
||||
if (settings.restrictEval || settings.pureEval) {
|
||||
if (evalSettings.restrictEval || evalSettings.pureEval) {
|
||||
allowedPaths = PathSet();
|
||||
|
||||
for (auto & i : searchPath) {
|
||||
auto r = resolveSearchPathElem(i);
|
||||
if (!r.first) continue;
|
||||
allowedPaths->insert(r.second);
|
||||
|
||||
auto path = r.second;
|
||||
|
||||
if (store->isInStore(r.second)) {
|
||||
PathSet closure;
|
||||
store->computeFSClosure(store->toStorePath(r.second), closure);
|
||||
for (auto & path : closure)
|
||||
allowedPaths->insert(path);
|
||||
} else
|
||||
allowedPaths->insert(r.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +350,6 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
|
|||
|
||||
EvalState::~EvalState()
|
||||
{
|
||||
fileEvalCache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -342,25 +357,37 @@ Path EvalState::checkSourcePath(const Path & path_)
|
|||
{
|
||||
if (!allowedPaths) return path_;
|
||||
|
||||
auto i = resolvedPaths.find(path_);
|
||||
if (i != resolvedPaths.end())
|
||||
return i->second;
|
||||
|
||||
bool found = false;
|
||||
|
||||
/* First canonicalize the path without symlinks, so we make sure an
|
||||
* attacker can't append ../../... to a path that would be in allowedPaths
|
||||
* and thus leak symlink targets.
|
||||
*/
|
||||
Path abspath = canonPath(path_);
|
||||
|
||||
for (auto & i : *allowedPaths) {
|
||||
if (isDirOrInDir(path_, i)) {
|
||||
if (isDirOrInDir(abspath, i)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", path_);
|
||||
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", abspath);
|
||||
|
||||
/* Resolve symlinks. */
|
||||
debug(format("checking access to '%s'") % path_);
|
||||
Path path = canonPath(path_, true);
|
||||
debug(format("checking access to '%s'") % abspath);
|
||||
Path path = canonPath(abspath, true);
|
||||
|
||||
for (auto & i : *allowedPaths) {
|
||||
if (isDirOrInDir(path, i))
|
||||
if (isDirOrInDir(path, i)) {
|
||||
resolvedPaths[path_] = path;
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
throw RestrictedPathError("access to path '%1%' is forbidden in restricted mode", path);
|
||||
|
@ -369,13 +396,13 @@ Path EvalState::checkSourcePath(const Path & path_)
|
|||
|
||||
void EvalState::checkURI(const std::string & uri)
|
||||
{
|
||||
if (!settings.restrictEval) return;
|
||||
if (!evalSettings.restrictEval) return;
|
||||
|
||||
/* 'uri' should be equal to a prefix, or in a subdirectory of a
|
||||
prefix. Thus, the prefix https://github.co does not permit
|
||||
access to https://github.com. Note: this allows 'http://' and
|
||||
'https://' as prefixes for any http/https URI. */
|
||||
for (auto & prefix : settings.allowedUris.get())
|
||||
for (auto & prefix : evalSettings.allowedUris.get())
|
||||
if (uri == prefix ||
|
||||
(uri.size() > prefix.size()
|
||||
&& prefix.size() > 0
|
||||
|
@ -422,7 +449,7 @@ Value * EvalState::addConstant(const string & name, Value & v)
|
|||
|
||||
|
||||
Value * EvalState::addPrimOp(const string & name,
|
||||
unsigned int arity, PrimOpFun primOp)
|
||||
size_t arity, PrimOpFun primOp)
|
||||
{
|
||||
if (arity == 0) {
|
||||
Value v;
|
||||
|
@ -433,7 +460,7 @@ Value * EvalState::addPrimOp(const string & name,
|
|||
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
|
||||
Symbol sym = symbols.create(name2);
|
||||
v->type = tPrimOp;
|
||||
v->primOp = NEW PrimOp(primOp, arity, sym);
|
||||
v->primOp = new PrimOp(primOp, arity, sym);
|
||||
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
||||
baseEnv.values[baseEnvDispl++] = v;
|
||||
baseEnv.values[0]->attrs->push_back(Attr(sym, v));
|
||||
|
@ -528,7 +555,7 @@ Value & mkString(Value & v, const string & s, const PathSet & context)
|
|||
{
|
||||
mkString(v, s.c_str());
|
||||
if (!context.empty()) {
|
||||
unsigned int n = 0;
|
||||
size_t n = 0;
|
||||
v.string.context = (const char * *)
|
||||
allocBytes((context.size() + 1) * sizeof(char *));
|
||||
for (auto & i : context)
|
||||
|
@ -547,17 +574,17 @@ void mkPath(Value & v, const char * s)
|
|||
|
||||
inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||
{
|
||||
for (unsigned int l = var.level; l; --l, env = env->up) ;
|
||||
for (size_t l = var.level; l; --l, env = env->up) ;
|
||||
|
||||
if (!var.fromWith) return env->values[var.displ];
|
||||
|
||||
while (1) {
|
||||
if (!env->haveWithAttrs) {
|
||||
if (env->type == Env::HasWithExpr) {
|
||||
if (noEval) return 0;
|
||||
Value * v = allocValue();
|
||||
evalAttrs(*env->up, (Expr *) env->values[0], *v);
|
||||
env->values[0] = v;
|
||||
env->haveWithAttrs = true;
|
||||
env->type = Env::HasWithAttrs;
|
||||
}
|
||||
Bindings::iterator j = env->values[0]->attrs->find(var.name);
|
||||
if (j != env->values[0]->attrs->end()) {
|
||||
|
@ -566,26 +593,37 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
|||
}
|
||||
if (!env->prevWith)
|
||||
throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos);
|
||||
for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
|
||||
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::atomic<uint64_t> nrValuesFreed{0};
|
||||
|
||||
void finalizeValue(void * obj, void * data)
|
||||
{
|
||||
nrValuesFreed++;
|
||||
}
|
||||
|
||||
Value * EvalState::allocValue()
|
||||
{
|
||||
nrValues++;
|
||||
return (Value *) allocBytes(sizeof(Value));
|
||||
auto v = (Value *) allocBytes(sizeof(Value));
|
||||
//GC_register_finalizer_no_order(v, finalizeValue, nullptr, nullptr, nullptr);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Env & EvalState::allocEnv(unsigned int size)
|
||||
Env & EvalState::allocEnv(size_t size)
|
||||
{
|
||||
assert(size <= std::numeric_limits<decltype(Env::size)>::max());
|
||||
if (size > std::numeric_limits<decltype(Env::size)>::max())
|
||||
throw Error("environment size %d is too big", size);
|
||||
|
||||
nrEnvs++;
|
||||
nrValuesInEnvs += size;
|
||||
Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
|
||||
env->size = size;
|
||||
env->size = (decltype(Env::size)) size;
|
||||
env->type = Env::Plain;
|
||||
|
||||
/* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
|
||||
|
||||
|
@ -593,7 +631,7 @@ Env & EvalState::allocEnv(unsigned int size)
|
|||
}
|
||||
|
||||
|
||||
void EvalState::mkList(Value & v, unsigned int size)
|
||||
void EvalState::mkList(Value & v, size_t size)
|
||||
{
|
||||
clearValue(v);
|
||||
if (size == 1)
|
||||
|
@ -628,7 +666,7 @@ void EvalState::mkThunk_(Value & v, Expr * expr)
|
|||
|
||||
void EvalState::mkPos(Value & v, Pos * pos)
|
||||
{
|
||||
if (pos) {
|
||||
if (pos && pos->file.set()) {
|
||||
mkAttrs(v, 3);
|
||||
mkString(*allocAttr(v, sFile), pos->file);
|
||||
mkInt(*allocAttr(v, sLine), pos->line);
|
||||
|
@ -705,7 +743,17 @@ void EvalState::evalFile(const Path & path_, Value & v)
|
|||
}
|
||||
|
||||
printTalkative("evaluating file '%1%'", path2);
|
||||
Expr * e = parseExprFromFile(checkSourcePath(path2));
|
||||
Expr * e = nullptr;
|
||||
|
||||
auto j = fileParseCache.find(path2);
|
||||
if (j != fileParseCache.end())
|
||||
e = j->second;
|
||||
|
||||
if (!e)
|
||||
e = parseExprFromFile(checkSourcePath(path2));
|
||||
|
||||
fileParseCache[path2] = e;
|
||||
|
||||
try {
|
||||
eval(e, v);
|
||||
} catch (Error & e) {
|
||||
|
@ -721,6 +769,7 @@ void EvalState::evalFile(const Path & path_, Value & v)
|
|||
void EvalState::resetFileCache()
|
||||
{
|
||||
fileEvalCache.clear();
|
||||
fileParseCache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -805,7 +854,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
|||
/* The recursive attributes are evaluated in the new
|
||||
environment, while the inherited attributes are evaluated
|
||||
in the original environment. */
|
||||
unsigned int displ = 0;
|
||||
size_t displ = 0;
|
||||
for (auto & i : attrs) {
|
||||
Value * vAttr;
|
||||
if (hasOverrides && !i.second.inherited) {
|
||||
|
@ -879,7 +928,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
|||
/* The recursive attributes are evaluated in the new environment,
|
||||
while the inherited attributes are evaluated in the original
|
||||
environment. */
|
||||
unsigned int displ = 0;
|
||||
size_t displ = 0;
|
||||
for (auto & i : attrs->attrs)
|
||||
env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
|
||||
|
||||
|
@ -890,7 +939,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
|||
void ExprList::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
state.mkList(v, elems.size());
|
||||
for (unsigned int n = 0; n < elems.size(); ++n)
|
||||
for (size_t n = 0; n < elems.size(); ++n)
|
||||
v.listElems()[n] = elems[n]->maybeThunk(state, env);
|
||||
}
|
||||
|
||||
|
@ -1012,22 +1061,22 @@ void ExprApp::eval(EvalState & state, Env & env, Value & v)
|
|||
void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos)
|
||||
{
|
||||
/* Figure out the number of arguments still needed. */
|
||||
unsigned int argsDone = 0;
|
||||
size_t argsDone = 0;
|
||||
Value * primOp = &fun;
|
||||
while (primOp->type == tPrimOpApp) {
|
||||
argsDone++;
|
||||
primOp = primOp->primOpApp.left;
|
||||
}
|
||||
assert(primOp->type == tPrimOp);
|
||||
unsigned int arity = primOp->primOp->arity;
|
||||
unsigned int argsLeft = arity - argsDone;
|
||||
auto arity = primOp->primOp->arity;
|
||||
auto argsLeft = arity - argsDone;
|
||||
|
||||
if (argsLeft == 1) {
|
||||
/* We have all the arguments, so call the primop. */
|
||||
|
||||
/* Put all the arguments in an array. */
|
||||
Value * vArgs[arity];
|
||||
unsigned int n = arity - 1;
|
||||
auto n = arity - 1;
|
||||
vArgs[n--] = &arg;
|
||||
for (Value * arg = &fun; arg->type == tPrimOpApp; arg = arg->primOpApp.left)
|
||||
vArgs[n--] = arg->primOpApp.right;
|
||||
|
@ -1045,9 +1094,15 @@ void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & pos)
|
||||
{
|
||||
std::optional<FunctionCallTrace> trace;
|
||||
if (evalSettings.traceFunctionCalls) {
|
||||
trace.emplace(pos);
|
||||
}
|
||||
|
||||
forceValue(fun, pos);
|
||||
|
||||
if (fun.type == tPrimOp || fun.type == tPrimOpApp) {
|
||||
callPrimOp(fun, arg, v, pos);
|
||||
return;
|
||||
|
@ -1063,10 +1118,8 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
|||
auto & fun2 = *allocValue();
|
||||
fun2 = fun;
|
||||
/* !!! Should we use the attr pos here? */
|
||||
forceValue(*found->value, pos);
|
||||
Value v2;
|
||||
callFunction(*found->value, fun2, v2, pos);
|
||||
forceValue(v2, pos);
|
||||
return callFunction(v2, arg, v, pos);
|
||||
}
|
||||
}
|
||||
|
@ -1076,13 +1129,13 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
|||
|
||||
ExprLambda & lambda(*fun.lambda.fun);
|
||||
|
||||
unsigned int size =
|
||||
auto size =
|
||||
(lambda.arg.empty() ? 0 : 1) +
|
||||
(lambda.matchAttrs ? lambda.formals->formals.size() : 0);
|
||||
Env & env2(allocEnv(size));
|
||||
env2.up = fun.lambda.env;
|
||||
|
||||
unsigned int displ = 0;
|
||||
size_t displ = 0;
|
||||
|
||||
if (!lambda.matchAttrs)
|
||||
env2.values[displ++] = &arg;
|
||||
|
@ -1096,7 +1149,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
|||
/* For each formal argument, get the actual argument. If
|
||||
there is no matching actual argument but the formal
|
||||
argument has a default, use the default. */
|
||||
unsigned int attrsUsed = 0;
|
||||
size_t attrsUsed = 0;
|
||||
for (auto & i : lambda.formals->formals) {
|
||||
Bindings::iterator j = arg.attrs->find(i.name);
|
||||
if (j == arg.attrs->end()) {
|
||||
|
@ -1153,7 +1206,6 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
|||
if (fun.type == tAttrs) {
|
||||
auto found = fun.attrs->find(sFunctor);
|
||||
if (found != fun.attrs->end()) {
|
||||
forceValue(*found->value);
|
||||
Value * v = allocValue();
|
||||
callFunction(*found->value, fun, *v, noPos);
|
||||
forceValue(*v);
|
||||
|
@ -1188,7 +1240,7 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
|
|||
Env & env2(state.allocEnv(1));
|
||||
env2.up = &env;
|
||||
env2.prevWith = prevWith;
|
||||
env2.haveWithAttrs = false;
|
||||
env2.type = Env::HasWithExpr;
|
||||
env2.values[0] = (Value *) attrs;
|
||||
|
||||
body->eval(state, env2, v);
|
||||
|
@ -1294,15 +1346,15 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
|
|||
}
|
||||
|
||||
|
||||
void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos)
|
||||
void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const Pos & pos)
|
||||
{
|
||||
nrListConcats++;
|
||||
|
||||
Value * nonEmpty = 0;
|
||||
unsigned int len = 0;
|
||||
for (unsigned int n = 0; n < nrLists; ++n) {
|
||||
size_t len = 0;
|
||||
for (size_t n = 0; n < nrLists; ++n) {
|
||||
forceList(*lists[n], pos);
|
||||
unsigned int l = lists[n]->listSize();
|
||||
auto l = lists[n]->listSize();
|
||||
len += l;
|
||||
if (l) nonEmpty = lists[n];
|
||||
}
|
||||
|
@ -1314,9 +1366,10 @@ void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, co
|
|||
|
||||
mkList(v, len);
|
||||
auto out = v.listElems();
|
||||
for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
|
||||
unsigned int l = lists[n]->listSize();
|
||||
memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
|
||||
for (size_t n = 0, pos = 0; n < nrLists; ++n) {
|
||||
auto l = lists[n]->listSize();
|
||||
if (l)
|
||||
memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
|
||||
pos += l;
|
||||
}
|
||||
}
|
||||
|
@ -1409,7 +1462,7 @@ void EvalState::forceValueDeep(Value & v)
|
|||
}
|
||||
|
||||
else if (v.isList()) {
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n)
|
||||
for (size_t n = 0; n < v.listSize(); ++n)
|
||||
recurse(*v.listElems()[n]);
|
||||
}
|
||||
};
|
||||
|
@ -1536,7 +1589,6 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
|
|||
if (v.type == tAttrs) {
|
||||
auto i = v.attrs->find(sToString);
|
||||
if (i != v.attrs->end()) {
|
||||
forceValue(*i->value, pos);
|
||||
Value v1;
|
||||
callFunction(*i->value, v, v1, pos);
|
||||
return coerceToString(pos, v1, context, coerceMore, copyToStore);
|
||||
|
@ -1561,7 +1613,7 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
|
|||
|
||||
if (v.isList()) {
|
||||
string result;
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n) {
|
||||
for (size_t n = 0; n < v.listSize(); ++n) {
|
||||
result += coerceToString(pos, *v.listElems()[n],
|
||||
context, coerceMore, copyToStore);
|
||||
if (n < v.listSize() - 1
|
||||
|
@ -1648,7 +1700,7 @@ bool EvalState::eqValues(Value & v1, Value & v2)
|
|||
case tList2:
|
||||
case tListN:
|
||||
if (v1.listSize() != v2.listSize()) return false;
|
||||
for (unsigned int n = 0; n < v1.listSize(); ++n)
|
||||
for (size_t n = 0; n < v1.listSize(); ++n)
|
||||
if (!eqValues(*v1.listElems()[n], *v2.listElems()[n])) return false;
|
||||
return true;
|
||||
|
||||
|
@ -1690,12 +1742,9 @@ bool EvalState::eqValues(Value & v1, Value & v2)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void EvalState::printStats()
|
||||
{
|
||||
bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0";
|
||||
Verbosity v = showStats ? lvlInfo : lvlDebug;
|
||||
printMsg(v, "evaluation statistics:");
|
||||
|
||||
struct rusage buf;
|
||||
getrusage(RUSAGE_SELF, &buf);
|
||||
|
@ -1706,62 +1755,107 @@ void EvalState::printStats()
|
|||
uint64_t bValues = nrValues * sizeof(Value);
|
||||
uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr);
|
||||
|
||||
printMsg(v, format(" time elapsed: %1%") % cpuTime);
|
||||
printMsg(v, format(" size of a value: %1%") % sizeof(Value));
|
||||
printMsg(v, format(" size of an attr: %1%") % sizeof(Attr));
|
||||
printMsg(v, format(" environments allocated count: %1%") % nrEnvs);
|
||||
printMsg(v, format(" environments allocated bytes: %1%") % bEnvs);
|
||||
printMsg(v, format(" list elements count: %1%") % nrListElems);
|
||||
printMsg(v, format(" list elements bytes: %1%") % bLists);
|
||||
printMsg(v, format(" list concatenations: %1%") % nrListConcats);
|
||||
printMsg(v, format(" values allocated count: %1%") % nrValues);
|
||||
printMsg(v, format(" values allocated bytes: %1%") % bValues);
|
||||
printMsg(v, format(" sets allocated: %1% (%2% bytes)") % nrAttrsets % bAttrsets);
|
||||
printMsg(v, format(" right-biased unions: %1%") % nrOpUpdates);
|
||||
printMsg(v, format(" values copied in right-biased unions: %1%") % nrOpUpdateValuesCopied);
|
||||
printMsg(v, format(" symbols in symbol table: %1%") % symbols.size());
|
||||
printMsg(v, format(" size of symbol table: %1%") % symbols.totalSize());
|
||||
printMsg(v, format(" number of thunks: %1%") % nrThunks);
|
||||
printMsg(v, format(" number of thunks avoided: %1%") % nrAvoided);
|
||||
printMsg(v, format(" number of attr lookups: %1%") % nrLookups);
|
||||
printMsg(v, format(" number of primop calls: %1%") % nrPrimOpCalls);
|
||||
printMsg(v, format(" number of function calls: %1%") % nrFunctionCalls);
|
||||
printMsg(v, format(" total allocations: %1% bytes") % (bEnvs + bLists + bValues + bAttrsets));
|
||||
|
||||
#if HAVE_BOEHMGC
|
||||
GC_word heapSize, totalBytes;
|
||||
GC_get_heap_usage_safe(&heapSize, 0, 0, 0, &totalBytes);
|
||||
printMsg(v, format(" current Boehm heap size: %1% bytes") % heapSize);
|
||||
printMsg(v, format(" total Boehm heap allocations: %1% bytes") % totalBytes);
|
||||
#endif
|
||||
if (showStats) {
|
||||
auto outPath = getEnv("NIX_SHOW_STATS_PATH","-");
|
||||
std::fstream fs;
|
||||
if (outPath != "-")
|
||||
fs.open(outPath, std::fstream::out);
|
||||
JSONObject topObj(outPath == "-" ? std::cerr : fs, true);
|
||||
topObj.attr("cpuTime",cpuTime);
|
||||
{
|
||||
auto envs = topObj.object("envs");
|
||||
envs.attr("number", nrEnvs);
|
||||
envs.attr("elements", nrValuesInEnvs);
|
||||
envs.attr("bytes", bEnvs);
|
||||
}
|
||||
{
|
||||
auto lists = topObj.object("list");
|
||||
lists.attr("elements", nrListElems);
|
||||
lists.attr("bytes", bLists);
|
||||
lists.attr("concats", nrListConcats);
|
||||
}
|
||||
{
|
||||
auto values = topObj.object("values");
|
||||
values.attr("number", nrValues);
|
||||
values.attr("bytes", bValues);
|
||||
}
|
||||
{
|
||||
auto syms = topObj.object("symbols");
|
||||
syms.attr("number", symbols.size());
|
||||
syms.attr("bytes", symbols.totalSize());
|
||||
}
|
||||
{
|
||||
auto sets = topObj.object("sets");
|
||||
sets.attr("number", nrAttrsets);
|
||||
sets.attr("bytes", bAttrsets);
|
||||
sets.attr("elements", nrAttrsInAttrsets);
|
||||
}
|
||||
{
|
||||
auto sizes = topObj.object("sizes");
|
||||
sizes.attr("Env", sizeof(Env));
|
||||
sizes.attr("Value", sizeof(Value));
|
||||
sizes.attr("Bindings", sizeof(Bindings));
|
||||
sizes.attr("Attr", sizeof(Attr));
|
||||
}
|
||||
topObj.attr("nrOpUpdates", nrOpUpdates);
|
||||
topObj.attr("nrOpUpdateValuesCopied", nrOpUpdateValuesCopied);
|
||||
topObj.attr("nrThunks", nrThunks);
|
||||
topObj.attr("nrAvoided", nrAvoided);
|
||||
topObj.attr("nrLookups", nrLookups);
|
||||
topObj.attr("nrPrimOpCalls", nrPrimOpCalls);
|
||||
topObj.attr("nrFunctionCalls", nrFunctionCalls);
|
||||
#if HAVE_BOEHMGC
|
||||
{
|
||||
auto gc = topObj.object("gc");
|
||||
gc.attr("heapSize", heapSize);
|
||||
gc.attr("totalBytes", totalBytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (countCalls) {
|
||||
v = lvlInfo;
|
||||
|
||||
printMsg(v, format("calls to %1% primops:") % primOpCalls.size());
|
||||
typedef std::multimap<unsigned int, Symbol> PrimOpCalls_;
|
||||
PrimOpCalls_ primOpCalls_;
|
||||
for (auto & i : primOpCalls)
|
||||
primOpCalls_.insert(std::pair<unsigned int, Symbol>(i.second, i.first));
|
||||
for (auto i = primOpCalls_.rbegin(); i != primOpCalls_.rend(); ++i)
|
||||
printMsg(v, format("%1$10d %2%") % i->first % i->second);
|
||||
|
||||
printMsg(v, format("calls to %1% functions:") % functionCalls.size());
|
||||
typedef std::multimap<unsigned int, ExprLambda *> FunctionCalls_;
|
||||
FunctionCalls_ functionCalls_;
|
||||
for (auto & i : functionCalls)
|
||||
functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i.second, i.first));
|
||||
for (auto i = functionCalls_.rbegin(); i != functionCalls_.rend(); ++i)
|
||||
printMsg(v, format("%1$10d %2%") % i->first % i->second->showNamePos());
|
||||
|
||||
printMsg(v, format("evaluations of %1% attributes:") % attrSelects.size());
|
||||
typedef std::multimap<unsigned int, Pos> AttrSelects_;
|
||||
AttrSelects_ attrSelects_;
|
||||
for (auto & i : attrSelects)
|
||||
attrSelects_.insert(std::pair<unsigned int, Pos>(i.second, i.first));
|
||||
for (auto i = attrSelects_.rbegin(); i != attrSelects_.rend(); ++i)
|
||||
printMsg(v, format("%1$10d %2%") % i->first % i->second);
|
||||
if (countCalls) {
|
||||
{
|
||||
auto obj = topObj.object("primops");
|
||||
for (auto & i : primOpCalls)
|
||||
obj.attr(i.first, i.second);
|
||||
}
|
||||
{
|
||||
auto list = topObj.list("functions");
|
||||
for (auto & i : functionCalls) {
|
||||
auto obj = list.object();
|
||||
if (i.first->name.set())
|
||||
obj.attr("name", (const string &) i.first->name);
|
||||
else
|
||||
obj.attr("name", nullptr);
|
||||
if (i.first->pos) {
|
||||
obj.attr("file", (const string &) i.first->pos.file);
|
||||
obj.attr("line", i.first->pos.line);
|
||||
obj.attr("column", i.first->pos.column);
|
||||
}
|
||||
obj.attr("count", i.second);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto list = topObj.list("attributes");
|
||||
for (auto & i : attrSelects) {
|
||||
auto obj = list.object();
|
||||
if (i.first) {
|
||||
obj.attr("file", (const string &) i.first.file);
|
||||
obj.attr("line", i.first.line);
|
||||
obj.attr("column", i.first.column);
|
||||
}
|
||||
obj.attr("count", i.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getEnv("NIX_SHOW_SYMBOLS", "0") != "0") {
|
||||
auto list = topObj.list("symbols");
|
||||
symbols.dump([&](const std::string & s) { list.elem(s); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1809,7 +1903,7 @@ size_t valueSize(Value & v)
|
|||
if (seen.find(v.listElems()) == seen.end()) {
|
||||
seen.insert(v.listElems());
|
||||
sz += v.listSize() * sizeof(Value *);
|
||||
for (unsigned int n = 0; n < v.listSize(); ++n)
|
||||
for (size_t n = 0; n < v.listSize(); ++n)
|
||||
sz += doValue(*v.listElems()[n]);
|
||||
}
|
||||
break;
|
||||
|
@ -1845,9 +1939,10 @@ size_t valueSize(Value & v)
|
|||
|
||||
size_t sz = sizeof(Env) + sizeof(Value *) * env.size;
|
||||
|
||||
for (unsigned int i = 0; i < env.size; ++i)
|
||||
if (env.values[i])
|
||||
sz += doValue(*env.values[i]);
|
||||
if (env.type != Env::HasWithExpr)
|
||||
for (size_t i = 0; i < env.size; ++i)
|
||||
if (env.values[i])
|
||||
sz += doValue(*env.values[i]);
|
||||
|
||||
if (env.up) sz += doEnv(*env.up);
|
||||
|
||||
|
@ -1876,4 +1971,9 @@ std::ostream & operator << (std::ostream & str, const ExternalValueBase & v) {
|
|||
}
|
||||
|
||||
|
||||
EvalSettings evalSettings;
|
||||
|
||||
static GlobalConfig::Register r1(&evalSettings);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
#include "nixexpr.hh"
|
||||
#include "symbol-table.hh"
|
||||
#include "hash.hh"
|
||||
#include "config.hh"
|
||||
#include "function-trace.hh"
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
@ -34,8 +37,8 @@ struct Env
|
|||
{
|
||||
Env * up;
|
||||
unsigned short size; // used by ‘valueSize’
|
||||
unsigned short prevWith:15; // nr of levels up to next `with' environment
|
||||
unsigned short haveWithAttrs:1;
|
||||
unsigned short prevWith:14; // nr of levels up to next `with' environment
|
||||
enum { Plain = 0, HasWithExpr, HasWithAttrs } type:2;
|
||||
Value * values[0];
|
||||
};
|
||||
|
||||
|
@ -79,7 +82,7 @@ public:
|
|||
|
||||
/* The allowed filesystem paths in restricted or pure evaluation
|
||||
mode. */
|
||||
std::experimental::optional<PathSet> allowedPaths;
|
||||
std::optional<PathSet> allowedPaths;
|
||||
|
||||
Value vEmptySet;
|
||||
|
||||
|
@ -88,6 +91,14 @@ public:
|
|||
private:
|
||||
SrcToStore srcToStore;
|
||||
|
||||
/* A cache from path names to parse trees. */
|
||||
#if HAVE_BOEHMGC
|
||||
typedef std::map<Path, Expr *, std::less<Path>, traceable_allocator<std::pair<const Path, Expr *> > > FileParseCache;
|
||||
#else
|
||||
typedef std::map<Path, Expr *> FileParseCache;
|
||||
#endif
|
||||
FileParseCache fileParseCache;
|
||||
|
||||
/* A cache from path names to values. */
|
||||
#if HAVE_BOEHMGC
|
||||
typedef std::map<Path, Value, std::less<Path>, traceable_allocator<std::pair<const Path, Value> > > FileEvalCache;
|
||||
|
@ -100,6 +111,9 @@ private:
|
|||
|
||||
std::map<std::string, std::pair<bool, std::string>> searchPathResolved;
|
||||
|
||||
/* Cache used by checkSourcePath(). */
|
||||
std::unordered_map<Path, Path> resolvedPaths;
|
||||
|
||||
public:
|
||||
|
||||
EvalState(const Strings & _searchPath, ref<Store> store);
|
||||
|
@ -214,7 +228,7 @@ private:
|
|||
Value * addConstant(const string & name, Value & v);
|
||||
|
||||
Value * addPrimOp(const string & name,
|
||||
unsigned int arity, PrimOpFun primOp);
|
||||
size_t arity, PrimOpFun primOp);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -248,18 +262,18 @@ public:
|
|||
|
||||
/* Allocation primitives. */
|
||||
Value * allocValue();
|
||||
Env & allocEnv(unsigned int size);
|
||||
Env & allocEnv(size_t size);
|
||||
|
||||
Value * allocAttr(Value & vAttrs, const Symbol & name);
|
||||
|
||||
Bindings * allocBindings(Bindings::size_t capacity);
|
||||
Bindings * allocBindings(size_t capacity);
|
||||
|
||||
void mkList(Value & v, unsigned int length);
|
||||
void mkAttrs(Value & v, unsigned int capacity);
|
||||
void mkList(Value & v, size_t length);
|
||||
void mkAttrs(Value & v, size_t capacity);
|
||||
void mkThunk_(Value & v, Expr * expr);
|
||||
void mkPos(Value & v, Pos * pos);
|
||||
|
||||
void concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos);
|
||||
void concatLists(Value & v, size_t nrLists, Value * * lists, const Pos & pos);
|
||||
|
||||
/* Print statistics. */
|
||||
void printStats();
|
||||
|
@ -282,15 +296,15 @@ private:
|
|||
|
||||
bool countCalls;
|
||||
|
||||
typedef std::map<Symbol, unsigned int> PrimOpCalls;
|
||||
typedef std::map<Symbol, size_t> PrimOpCalls;
|
||||
PrimOpCalls primOpCalls;
|
||||
|
||||
typedef std::map<ExprLambda *, unsigned int> FunctionCalls;
|
||||
typedef std::map<ExprLambda *, size_t> FunctionCalls;
|
||||
FunctionCalls functionCalls;
|
||||
|
||||
void incrFunctionCall(ExprLambda * fun);
|
||||
|
||||
typedef std::map<Pos, unsigned int> AttrSelects;
|
||||
typedef std::map<Pos, size_t> AttrSelects;
|
||||
AttrSelects attrSelects;
|
||||
|
||||
friend struct ExprOpUpdate;
|
||||
|
@ -303,6 +317,9 @@ private:
|
|||
/* Return a string representing the type of the value `v'. */
|
||||
string showType(const Value & v);
|
||||
|
||||
/* Decode a context string ‘!<name>!<path>’ into a pair <path,
|
||||
name>. */
|
||||
std::pair<string, string> decodeContext(const string & s);
|
||||
|
||||
/* If `path' refers to a directory, then append "/default.nix". */
|
||||
Path resolveExprPath(Path path);
|
||||
|
@ -316,4 +333,28 @@ struct InvalidPathError : EvalError
|
|||
#endif
|
||||
};
|
||||
|
||||
struct EvalSettings : Config
|
||||
{
|
||||
Setting<bool> enableNativeCode{this, false, "allow-unsafe-native-code-during-evaluation",
|
||||
"Whether builtin functions that allow executing native code should be enabled."};
|
||||
|
||||
Setting<bool> restrictEval{this, false, "restrict-eval",
|
||||
"Whether to restrict file system access to paths in $NIX_PATH, "
|
||||
"and network access to the URI prefixes listed in 'allowed-uris'."};
|
||||
|
||||
Setting<bool> pureEval{this, false, "pure-eval",
|
||||
"Whether to restrict file system and network access to files specified by cryptographic hash."};
|
||||
|
||||
Setting<bool> enableImportFromDerivation{this, true, "allow-import-from-derivation",
|
||||
"Whether the evaluator allows importing the result of a derivation."};
|
||||
|
||||
Setting<Strings> allowedUris{this, {}, "allowed-uris",
|
||||
"Prefixes of URIs that builtin functions such as fetchurl and fetchGit are allowed to fetch."};
|
||||
|
||||
Setting<bool> traceFunctionCalls{this, false, "trace-function-calls",
|
||||
"Emit log messages for each function entry and exit at the 'vomit' log level (-vvvv)"};
|
||||
};
|
||||
|
||||
extern EvalSettings evalSettings;
|
||||
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue