
Don't remove the $(nop) command below - tambourine_man
https://github.com/rust-lang/rust/blob/efec34a95a76212b2324d98f3f6d94a1397c2544/mk/prepare.mk#L44-L51
======
Retr0spectrum
It was removed here, with a partial explanation:

[https://github.com/rust-
lang/rust/commit/fca66702a44038b14d8...](https://github.com/rust-
lang/rust/commit/fca66702a44038b14d8f9bd282ad56c04e9fdcf6)

    
    
        "Adding blank lines means two steps from different defines will not end up on the same line."

~~~
kibwen
I was about to say, don't bother submitting a patch to fix this, as last week
rustc completely moved away from make, deleting all its makefiles in the
process: [https://github.com/rust-
lang/rust/pull/39431](https://github.com/rust-lang/rust/pull/39431)

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

~~~
pitterpatter
I blame this twitter thread :P

[https://twitter.com/Gankro/status/831955401109360640](https://twitter.com/Gankro/status/831955401109360640)

~~~
estsauver
The thing I actually kind of think is amazing is that someone said "This isn't
working... why don't I try putting in a $(nop) here...?"

~~~
chc
Maybe there was something else there before, and it stopped working when they
removed it, so they tried adding back the most minimal thing they could think
of as a sanity check.

~~~
hn_user2
"Why doesn't this work?". Add debug statement. "Huh, now this works". Take out
debug statement. "Huh, now it doesn't work". Try no-op. Table flip. Commit.

~~~
Beltiras
I love Heisenbugs because I have seen one in the wild. It's the most absurd
thing ever.

------
Gankro
Ah good, now the whole world gets to enjoy the greatest Makefile ever. For
other curiosities of Rust's history and bootstrapping process, I recommend
brson's annotated stdlib:

[https://github.com/brson/annotated-std-
rs/commit/e50c2b16455...](https://github.com/brson/annotated-std-
rs/commit/e50c2b16455ceff29488bf1f058b6c10906ef990)

~~~
Retr0spectrum
That was a much more interesting read than I anticipated.

~~~
tomcam
Thanks, that sucked me in. Starting after line 93 it gets downright
fascinating. Have written commercial compilers but not self-hosted so it was
illuminating

------
lowbloodsugar
Reminds me of the R4300 multiply bug, and the lazy compiler fix that just
always emitted a nop between them if it saw two mults in a row. It was a real,
hardware bug tho.

~~~
dfox
Very often hardware bugs can be worked around by well-placed NOP.

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)

~~~
throwanem
Which MSPs, if I may? I use some of their 2xxx hobbyist line (since I'm a
hobbyist), and this sounds like the kind of PITA that I'm not nearly enough of
an embedded dev to avoid tearing my hair out over.

~~~
jlubawy
The MSP430x5xx and MSP430x6xx families have this problem. From the user-guide
[1]:

> 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.

[1] [http://www.ti.com/lit/pdf/slau208](http://www.ti.com/lit/pdf/slau208)

~~~
dfox
What I described happened on G2553 with USCI_A in SPI mode. Given the fact
that various code samples on the net do not handle this behavior it seems that
it is either happening only for some configurations or only on some versions
of the HW. But: when you see even bytes on SPI dropped or replaced with
previous ones, add NOP.

------
flukus
Looks like they're using make as way to much of a programming language instead
of the IMO much better declarative approach, way too many loops and function
calls rather than dependencies. I'm not sure but it also looks like it's
building too many things instead of different build for different
configurations.

~~~
_yosefk
I dunno, I've never seen a readable Makefile in any system above say 300
files. If you could write readable declarative Makefiles getting the job done,
would there be autotools? This is not to say that autotools get the job done
beautifully, just that their existence demonstrates how the problem gets us
all contort violently to terrible effect like a wounded animal screaming and
running into trees.

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.

~~~
flukus
> I dunno, I've never seen a readable Makefile in any system above say 300
> files.

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-...](http://flukus.github.io/2016/11/30/2016_11_30_Rediscovering-
Make/)), 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.

~~~
_yosefk
You use $(shell) and sed in there which I don't think is much different from
$(foreach), and perhaps it's gnarlier. Perhaps my counterpoint is "a build
system is a program using a library/framework for scheduling work based on
dependencies" and make's insistence on builds being about the dependency graph
and delegating programming to shell commands and afterthoughts like $foreach,
plus its very painful evaluation model with unclear order make for a terrible
programming environment.

~~~
flukus
A big difference is that using sed is producing a single known output that is
clearly evident, it's much less clear what all the loops and calls is
producing, it may even be an example of premature abstraction.

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.

~~~
_yosefk
Well, I guess I agree with Rob Pike in that the "tools doing one job and doing
it well philosophy is dead and the eulogy was delivered by Perl." I think you
should write build rules in a programming language and a programming language
is something that doesn't make you upgrade to a new version to avoid shelling
out to find. Let's agree to disagree :-)

------
klank
Reminds me of a bug we encountered building mobile devices.

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.

------
botverse
Reminds me of the story of The Magic Switch:

[https://news.ycombinator.com/item?id=181045](https://news.ycombinator.com/item?id=181045)

------
s_kilk
Reminds me of the time my team found a bug in the .Net C# compiler. A whole
branch of an if/else statement was being ignored, as in, it simply wasn't
present in the emitted IL.

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.

------
kozak
A better comment would describe a test case that would allow to quickly
confirm that the command can be removed when the compiler bug is fixed.
Because otherwise it can be there for ages, because everyone will be afraid of
touching the code.

------
patmcguire
There's a story I've heard that ends with the real reason being that the
author thought it would be funny to have people asking him why there were
three consecutive nops years after the fact.

------
josteink
Ah good old makefiles. This reminds me of this one which I discovered via a
recent HN-submission[1].

Falsehoods programmers believe about build systems:
[http://pozorvlak.livejournal.com/174763.html](http://pozorvlak.livejournal.com/174763.html)

[1]
[https://news.ycombinator.com/item?id=13637102](https://news.ycombinator.com/item?id=13637102)

------
oneplane
I wonder what voodoo it actually does. Would this be traceable in the
compiler?

~~~
jschwartzi
This is a makefile, so no. What you could do is replace the $(eval $(call
PREPARE_LIB,libname-glob)) lines wherever they are with $(info $(call
PREPARE_LIB,libname-glob)) and see what actually expands. But I suspect
they've either tried that, or the usage of this macro in conjunction with
other macros is so complex that it's not super-easy to parse the output and
find the problem.

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.

~~~
dima55
Merry christmas:
[http://bashdb.sourceforge.net/remake/](http://bashdb.sourceforge.net/remake/)

------
hgdsraj
There's likely a data bubble or dependency in the CPU pipeline that needs an
extra few picoseconds to fetch the correct data.

~~~
shawnz
What is a "data bubble"? How would what you're describing not be a hardware
bug?

~~~
throwanem
> What is a "data bubble"?

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.

