Live data from Hacker News

Show HN: My C compiler compiled itself

github.com

51–60 of 130 posts

Re: Show HN: My C compiler compiled itself

#51
post #49

Earlier quoted context omitted.

I often use a Python program called 'fabricate', which basically checks every file a command opens, and re-runs the command if any touched file changes. I love it, and I hoped this would become the future of how build-systems are built -- you could automatically parallelise, rebuild, make clean, everything, just by tracking which files are read, and written. It does add a bit of overhead, but I'd be willing to pay th…

That is neat, but also super brittle, and full of abstraction leakiness, potentially leading to both false positives and negatives. Sounds like it would break down with ccache or distcc immediately, for example.

I never had any false negatives, they are basically impossible in this framework, except it does assume if a program, and all it's inputs are unchanged, the output is unchanged, so this is no good for programs which randomly produce different outputs.

ccache can cause things to get built twice, because the first run it sees it tries to read a file, then later writes to it, so it knows something different might happen if you run again -- but then again that is just ccache doing it's thing, so it's quick. Yes, distcc wouldn't work, but then again I find distcc super-brittle (so hard to make sure everything has the same compiler versions, etc), I may have used it 20 years ago, but I don't think I ever would now!

Re: Show HN: My C compiler compiled itself

#52
post #22

Earlier quoted context omitted.

No (if the parent really meant ‘compiler compiler’ which, I think, would be what yacc/bison is).

yacc calls it's a compiler compiler, but it's a parser compiler.

I'd go further and say "parser generator", the generated parser will be compiled by a C compiler after all.

Re: Show HN: My C compiler compiled itself

#53
post #48

Earlier quoted context omitted.

Having 'incrementality', when it isn't actually going to incrementally rebuild things when files change, is (in my experience), worse that having no incrementality at all. Having to remember when I have to manually disable to incrementality is an annoying overhead, and easy to forget. If you can remember exactly when you need to manually skip the incremental build, that's great for you, but I find Make has enough of…

Meh, it can practically never be perfect, without diminishing returns that at some point invalidate the advantage of any incremental builds anyway. As I said, you can let the C compiler generate your header dependencies for you. But that's not enough, because what's with header and libraries that are external for your project? Keep in mind that they will have dependencies, too, and at some point your transitive closu…

I think one fundamental difference between the two of us (I'm guessing here, let me know if I'm wrong), is I'm willing to cope with longer compile times, as long as I always get a correctly built executable (so there are no 'halting problems', if in doubt, rebuild it!), while you would prefer faster build times, even if that then requires sometimes having to do a little manual work when the build system doesn't realise it needs to rebuild? Of course, no system will be 100% perfect, but you can choose where your trade-off point is.

Two reasonable viewpoints, but probably effects how we do our building setups!

Re: Show HN: My C compiler compiled itself

#54
Very cool, congratulations!

I took a 2-second peek at the code, and just wanted to offer a small piece of advice that I think makes it better. Or two, really. Counting is hard.

Instead of (this is from parser.c):

    apply_result *ret = (apply_result*)malloc(sizeof(apply_result));
apply the two common principles of DRY [1] and "don't cast the return value of malloc()" [2] and you get:

    apply_result *ret = malloc(sizeof *ret);
I think the latter is way better.

[1]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself

[2]: https://stackoverflow.com/a/605858

Re: Show HN: My C compiler compiled itself

#55
post #54

Very cool, congratulations! I took a 2-second peek at the code, and just wanted to offer a small piece of advice that I think makes it better. Or two, really. Counting is hard. Instead of (this is from parser.c): apply_result *ret = (apply_result*)malloc(sizeof(apply_result)); apply the two common principles of DRY [1] and "don't cast the return value of malloc()" [2] and you get: apply_result *ret = malloc(sizeof *r…

thanks man!

yes that makes sense. unfortunately 30cc is not able to compile that syntax, and will probably give type-checker errors when passing a void* to pointer of another type. but will implement it sometime soon!

Re: Show HN: My C compiler compiled itself

#57
post #54

Very cool, congratulations! I took a 2-second peek at the code, and just wanted to offer a small piece of advice that I think makes it better. Or two, really. Counting is hard. Instead of (this is from parser.c): apply_result *ret = (apply_result*)malloc(sizeof(apply_result)); apply the two common principles of DRY [1] and "don't cast the return value of malloc()" [2] and you get: apply_result *ret = malloc(sizeof *r…

This kind of condescending advice doesn't help anybody. Redundant casts, like redundant braces, white space, and a plethora of similar choices are stylistic more than anything else.

If you really feel the need to give unsolicited coding style feedback maybe at least spend more than a few seconds looking at the code before you do so. Otherwise it's just rude.

Re: Show HN: My C compiler compiled itself

#58

> Then run ./build.py. This will use the bootstrapped 30cc-compiler to compile 30cc itself. It then again uses the 30cc-compiled compiler to compile 30cc once again. The final compiler is then stored as ./30cc. Why isn't that also done by the Makefile? The only catch I could see is that you'd need to have it build to different output names, but that seems fine for what it is? --- Also, I'm curious - did you find your…

i think it just supports smth like 70% of C. I didn't bother supporting floating-point operators, or arrays (I mean, malloc and pointers are fine) or etc. I just wanted smth small and self-hosting!

Re: Show HN: My C compiler compiled itself

#59
post #55
post #54

Very cool, congratulations! I took a 2-second peek at the code, and just wanted to offer a small piece of advice that I think makes it better. Or two, really. Counting is hard. Instead of (this is from parser.c): apply_result *ret = (apply_result*)malloc(sizeof(apply_result)); apply the two common principles of DRY [1] and "don't cast the return value of malloc()" [2] and you get: apply_result *ret = malloc(sizeof *r…

thanks man! yes that makes sense. unfortunately 30cc is not able to compile that syntax, and will probably give type-checker errors when passing a void* to pointer of another type. but will implement it sometime soon!

Aha, so it doesn't know about void* being compatible with all (object) pointers, but so far just requires the pointers to match exactly? I see.

Not sure why I was down-voted, I think that is ... not nice. :(

Re: Show HN: My C compiler compiled itself

#60
post #48

Earlier quoted context omitted.

Meh, it can practically never be perfect, without diminishing returns that at some point invalidate the advantage of any incremental builds anyway. As I said, you can let the C compiler generate your header dependencies for you. But that's not enough, because what's with header and libraries that are external for your project? Keep in mind that they will have dependencies, too, and at some point your transitive closu…

I think one fundamental difference between the two of us (I'm guessing here, let me know if I'm wrong), is I'm willing to cope with longer compile times, as long as I always get a correctly built executable (so there are no 'halting problems', if in doubt, rebuild it!), while you would prefer faster build times, even if that then requires sometimes having to do a little manual work when the build system doesn't reali…

I think that's fair. On top of that, being a low level system programmer, I think I'm pretty good at realizing/intuiting when something critical changed that needs me to nuke the build dir, i.e. the manual work you mention to force a full recompile (and also good at noticing mismatched headers even through very weird symptoms).

I do have to switch between multiple SDK versions very often for example, and I always either nuke the build dir after doing that, or have separate build dirs per SDK in the first place.

Post reply on HN