Don't remove the $(nop) command below
github.com
github.com
https://github.com/rust-lang/rust/commit/fca66702a44038b14d8...
"Adding blank lines means two steps from different defines will not end up on the same line."I'm curious how OP even ended up trawling old versions of rustc's makefiles from 2014. I bet there's an interesting story there. :P
https://github.com/rust-lang/rust/tree/master/src/bootstrap
It basically consists of:
1. A python script to make sure you have the correct environment, and that kicks off cargo to compile the program used in step 2. ("rustbuild" proper.)
2. A Rust program that manages the full build (remember, Rust is bootstrapped, so there's three stages...)
3. That build kicks off a number of "cargo build"s for all the components and glues the final result together.
For any project written in Rust, pure Cargo should be enough.
0. This stage is the pre-built compiler
1. This stage is a compiler built with the compiler from stage 0
2. This stage is a compiler built from stage 1.
If the process worked, then stage 1 and stage 2's output should be identical. You can skip stage 2 if you want to skip that verification, and that sounds like what Crystal does.
Normally this wouldn't matter, but Rust also supports compiler plugins written in Rust. These link directly to the compiler that compiles them. With the stage 1 compiler's quirky ABI, the plugins it compiles might not be able to interact with it.
The stage 2 compiler, on the other hand, uses the same set of ifdefs that the stage 1 compiler has. So it was built by a compiler with the same output-ABI as itself, and so plugins have the same ABI.
So:
* snapshot: Built with snapshot ABI, produces snapshot ABI (snapshots are old stage2 compilers)
* stage0-output: built with snapshot ABI, emits stage0 ABI.
* stage1-output: built with stage0 ABI, emits not(stage0) ABI.
* stage2-output: built with not(stage0) ABI, emits not(stage0) ABI.
I'm currently working on crystal's CI infrastructure so that we can have nightly crystal builds (+ CI) for all architectures we support. Currently we release features incrementally such that the compiler can always be built with the latest release, and I'm wondering how much effect relaxing that constraint to the latest nighty would have on development speed.
Someone is working on an alternate compiler so we could try DDC, we'll see.
http://manishearth.github.io/blog/2016/12/02/reflections-on-...
(Of course, that's a proof of concept and not actually in the released binaries :P )
Right now the non-Cargo bits are written in Python (which was already required to build LLVM, so this doesn't add any new dependencies), but those bits could pretty much be written in anything, if needed.
If you are interested, here's a draft Debian Rust packaging policy: https://internals.rust-lang.org/t/debian-rust-packaging-poli.... It is not about packaging Rust itself though but the challenges of packaging software written in Rust.
rustboot, the OCaml Rust implementation, was removed in 6997adf7 on 13 May 2011. It looks like it was fairly actively maintained until then.
A file named src/snapshots.txt showed up in the repository in cb53065a on 2 May 2011, and remained there until 02538d46 on 13 April 2016. During that time, rustc was buildable from specific snapshots of previous versions of rustc, which were listed by both source commit and hashes of binary compilers.
From 13 April 2016 onwards, stable rustc compiles on previous stable Rust, and specific versions are listed in src/stage0.txt in a similar fashion.
So, you can probably take the last version of rustboot (it didn't change between 2 and 13 May 2011), compile that with some version of OCaml, then go from 2011 to 2016 by repeatedly building the newest snapshot possible with your current snapshot, then build stable Rust 1.10 onwards, thereby reducing it to the previously solved problem of verifying that Ken Thompson has not compromised your OCaml compiler.
It turns out that Debian is more permissive than Fedora when it comes to bootstrapping compilers with out-of-archive compilers. Fedora has an actual policy and it allows one-time out-of-archive bootstrapping.
I think this is the underlying issue - the "well, it's a list, so there's got to be something inside the list too" mindset, which makes sense in the real world but is stupid in programming. (Some bad memories at old Visual Basic times come to mind too)
[0] https://en.wikipedia.org/wiki/Whitespace_(programming_langua...
Leaves all the comments intact, though.
Do I even want to know why this is the case?
https://github.com/brson/annotated-std-rs/commit/e50c2b16455...
Last time I did that was on MSP430, where it seems that some integrated peripherals set completion interrupt flag one cycle before the operation really completes. (I'm not sure whether it really is bug, I didn't find this documented anywhere, but for TI's example this does not matter and produces marginally better performance)
> Include at least one instruction between the clear of an interrupt enable or interrupt flag and the EINT instruction. For example: Insert a NOP instruction in front of the EINT instruction.
> Include at least one instruction between DINT and the start of an code sequence that requires protection from interrupts. For example: Insert a NOP instruction after the DINT
Luckily if you use the MSP compiler's intrinsic functions to enable/disable interrupts it takes care of this for you.
True of certain x86 bugs too:
https://blogs.msdn.microsoft.com/oldnewthing/20110112-00/?p=...
https://en.wikipedia.org/wiki/Bubble_(computing)
https://en.wikipedia.org/wiki/Classic_RISC_pipeline#Hazards
More under-appreciated classic RISC trivia:
The MIPS is bi-endian, and it's referred to as SPIM when driving backwards.
For some reason, Sun never got around to making a bi-endian version of SPARC called CRAPS.
A similar trick can be found in this interesting article:
http://www.reenigne.org/blog/8088-pc-speaker-mod-player-how-...
This means that the 8088 will execute the unpatched version of the instruction (as it's already in the prefetch queue by the time it's patched).
I find autotools very complex and bloated, but it tends to make builds for different platforms, cross compilation, dependency checking and other tasks easy for me. It's often easier than dealing with (g)make directly IMHO.
I admit that I despise make and maybe I don't get the beauty (I get the beauty of the idea but I've never seen it result in actual beautiful Makefiles), and maybe if you linked to what you consider a good open source Makefile, we could discuss this in more concrete terms.
The build complexity should be a reflection of the project complexity, not the number of source files. Having to run in multiple environments and separating things into libraries would add complexity for instance, adding a new source file shouldn't. When you start adding calls and loops however, that complexity grows exponentially instead of linearly. This isn't make specific.
> I admit that I despise make and maybe I don't get the beauty (I get the beauty of the idea but I've never seen it result in actual beautiful Makefiles), and maybe if you linked to what you consider a good open source Makefile, we could discuss this in more concrete terms.
Here is one I put together (http://flukus.github.io/2016/11/30/2016_11_30_Rediscovering-...), I tried to make it somewhat real world but there are obviously many caveats, it's dealing with c# (easier to build), dependencies come via nuget, but I think it shows the idea.
The most common anti-pattern I see (again, not just in make) is thinking that there has to be one build that does everything, it will iterate over target OS's and/or environments and produce a build for each one for instance. It's much cleaner to have the OS/environment be one or more parameters and to execute the build script multiple times with the desired parameters.
Developers have a tendency to not realize build scripts are a seperate discipline worth learning.
I don't think relying on shell commands is a bad thing though, it's just part of the unix philosophy, every build tool in existence will call external programs like the compiler itself. I doubt you could find another build tool that can replace values as simply as sed. The shell command would actually be unnecessary on newer versions of make.
Totally agree on the evaluation model though.
Turns out if a certain instruction was executed on a page boundary the CPU would lock up (the gist of the issue anyway, might have had to do with being in an elevated mode as well). Appeared to be a problem in silicon. Unfortunately I can't remember enough details but a NOP or strategically placed variable solved it.
Adding a little `&& 1 == 1` to the conditional made the compiler do the right thing again.
Edit: preemptively, no there wasn't anything special or weird about this conditional.
Falsehoods programmers believe about build systems: http://pozorvlak.livejournal.com/174763.html
Make is so useful that I'm willing to live without things like a debugger and useful error messages in order to have the flexibility to implement a build system.
data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" height="100px" width="100px"><g><path d="M28.1,36.6c4.6,1.9,12.2,1.6,20.9,1.1c8.9-0.4,19-0.9,28.9,0.9c6.3,1.2,11.9,3.1,16.8,6c-1.5-12.2-7.9-23.7-18.6-31.3 c-4.9-0.2-9.9,0.3-14.8,1.4C47.8,17.9,36.2,25.6,28.1,36.6z"/><path d="M70.3,9.8C57.5,3.4,42.8,3.6,30.5,9.5c-3,6-8.4,19.6-5.3,24.9c8.6-11.7,20.9-19.8,35.2-23.1C63.7,10.5,67,10,70.3,9.8z"/><path d="M16.5,51.3c0.6-1.7,1.2-3.4,2-5.1c-3.8-3.4-7.5-7-11-10.8c-2.1,6.1-2.8,12.5-2.3,18.7C9.6,51.1,13.4,50.2,16.5,51.3z"/><path d="M9,31.6c3.5,3.9,7.2,7.6,11.1,11.1c0.8-1.6,1.7-3.1,2.6-4.6c0.1-0.2,0.3-0.4,0.4-0.6c-2.9-3.3-3.1-9.2-0.6-17.6 c0.8-2.7,1.8-5.3,2.7-7.4c-5.2,3.4-9.8,8-13.3,13.7C10.8,27.9,9.8,29.7,9,31.6z"/><path d="M15.4,54.7c-2.6-1-6.1,0.7-9.7,3.4c1.2,6.6,3.9,13,8,18.5C13,69.3,13.5,61.8,15.4,54.7z"/><path d="M39.8,57.6C54.3,66.7,70,73,86.5,76.4c0.6-0.8,1.1-1.6,1.7-2.5c4.8-7.7,7-16.3,6.8-24.8c-13.8-9.3-31.3-8.4-45.8-7.7 c-9.5,0.5-17.8,0.9-23.2-1.7c-0.1,0.1-0.2,0.3-0.3,0.4c-1,1.7-2,3.4-2.9,5.1C28.2,49.7,33.8,53.9,39.8,57.6z"/><path d="M26.2,88.2c3.3,2,6.7,3.6,10.2,4.7c-3.5-6.2-6.3-12.6-8.8-18.5c-3.1-7.2-5.8-13.5-9-17.2c-1.9,8-2,16.4-0.3,24.7 C20.6,84.2,23.2,86.3,26.2,88.2z"/><path d="M30.9,73c2.9,6.8,6.1,14.4,10.5,21.2c15.6,3,32-2.3,42.6-14.6C67.7,76,52.2,69.6,37.9,60.7C32,57,26.5,53,21.3,48.6 c-0.6,1.5-1.2,3-1.7,4.6C24.1,57.1,27.3,64.5,30.9,73z"/></g></svg>(/s)
Indeed, chip architects would struggle to find a way to execute vast quantities of NOPs efficiently until the release of the Itanium in 2001.
(But obviously this has nothing to do with the link, since it's a Makefile, not assembly.)
A common result of moving instructions through early processors at too high a rate to maintain laminar flow. Early cryptographic algorithms in particular were severely limited by such considerations, until the advent of modern pipelining algorithms vastly reduced susceptibility to data cavitation.
As a point of historical interest, the "dataflow" paradigm in programming originated as an alternative approach to solving this problem, which attempted to avoid it entirely by having everything happen at once all over the place through magic. Between the misnomer and the heavy drain on the limited market for wizard labor, it's easy to see why the paradigm, though intriguing and not without useful lessons, failed to gain meaningful traction in the industry - perhaps ironically, there was just too much friction for it ever really to take off.