Trying to figure out how Grunt/Gulp/Broccoli, LESS/SASS/Stylus/Jade, Coffeescript, Uglify, Bower, Browserify, Require.js, AMD/CommonJS, NPM etc all work together is a nightmare.
It's all too hard, so people added Yeoman, Brunch, or other things to generate application configs - but now you need to decide which skeleton/generator you want, which takes you down the JS and CSS framework rabbithole.
Of course the only sane response to all this is to write another build system that doesn't repeat everybody else's mistakes.
In comparison, Makefiles are remarkably usable.
I have a huge concern when I do anything in Javascript about what happens in 1 or 2 years from now when I have to modify a project I built using some Yeoman scaffolding. Is it still going to work? Will those node modules still be there? Can I update them without it breaking everything?
It's really weird for me, coming from the world of C, CVS/Git, Make, Linux, etc. where it's almost _unthinkable_ to introduce changes that would break older versions. Hell even the world "old" generally means 5+ or 10+ years.
The tools you're working with aren't different on this manner - it's not like your tool will magically recode itself to work differently.
I'm seriously considering whether I can use Make for my production website builds - the only issue is Windows support.
For an example of what makes it so awesome:
var img = require('./foo.png') // "/output-path/0dcbbaa701328a3c262cfd45869e351f.png"
Webpack will copy this file (foo.png) to your output folder, and rename it using the file hash, so it does cache-busting.
You don't need to use other build tools, you can just use the webpack CLI. I personally use npm scripts.
Webpack also allows you to setup aliases for modules, as well as load pretty much anything you can imagine. You wanna pull in a module that doesn't use CommonJS and instead exports a global? Webpack has global-loader. AMD is supported as well.
Oh, and this includes a sane development environment, with reload on save, as well as hot loading assets that support it. (Check out react-hot-loader: http://gaearon.github.io/react-hot-loader/, but it works with css as well.)
And you can require css files in your components, and then add the extract-text-webpack-plugin so it'll rip the css from the generated JS bundle!
Aaaaand it handles SourceMaps, so you don't have to worry about some plugins (looking at you gulp) not playing well together.
Finally, it also handles minification, either through a CLI option or in the config.
There are native versions of make. Where you are using dos shell commands to do stuff. MinGW provides Posix compatible native commands. (you can use ls, cat, etc commands). You can use msys which gives you a Posix compatible build env. Finally something like Cigwin provides both a Posix compatible build env and Posix compatible runtime as well.
On the other hand, I downloaded the CUDA SDK. I couldn't even figure out where the GPU compiled code even resided. I suppose I was just supposed to take it as it "just works" (and it did), but it all left me highly uncomfortable.
Then again, never used CUDA so who knows
GNU coreutils (and in general, a lot of the GNU projects) are rather excessively complex and certainly not what I'd advocate "learning by example" from. Take a look at the BSDs' standard utilities for simpler, more straightforward code.
But even if I can eventually understand what some code does, how do I learn why it does it that way?
I believe that the best way to learn "why" is to ask "why not". You will see that a lot of programmers, IMHO unfortunately really don't know why and are just doing what they were taught to. If you don't do X, then either [1] it doesn't matter and you don't actually need to, or [2] it does and you realise the reason why, when you see how X makes things simpler/more efficient for either the programmer or the machine, or both.
Especially when it comes to programming paradigms and stuff like 'best practices'. Theres a lot of cargo-culting in programming culture, and you really shouldn't take it as dogma.
Before C, I was pampered and took everything for granted. Now I appreciated my life more after C and feel blessed every time my IDE gives me a warning.
A sufficiently long include path can give you this problem anyway. I recently tripped over this when I created a "reason.h" and discovered that Windows had a file of the same name deep inside MFC.
It is my understanding that that would be solved by placing your file in a local directory called 'inc/' and having:
#include "inc/reason.h"
instead of: #include <reason.h>
(or just replacing "" with <>).
But I have never programmed in VSC before, so I may be wrong.As for compiler flags, the only ones I ever worry about are `-O`, `-g`, `-c`, CFLAGS and LDFLAGS.
What I've learned is that the way C includes other files/libs is extremely simple. The header files are simply a simple mapping of the code in the `.so` or `.a`. If it's a n `.so`, you can't make it a static executable and if it's `.a` you have to.
I've never worked directly with low-level microcontroller programming, and the extent of my electronics knowledge is some fiddling with arduino. When I did that I used ino (http://inotool.org/) to compile and upload code to the board.
EDIT:
Projects that have good C code include: http://suckless.org/ and the linux kernel (and other stuff by Linus Torvalds). Avoid anything with GNU (most of it's over-engineered)
Make is fairly easy to learn, at least in its basic form. Autoconf is horrendous.
I completely agree. Make is extremely flexible on it's own. I don't understand the need to abstract the build system to generate thousand-line makefiles that are impossible to hand edit.
Of course, that imposes the cost of 100% compatibility on every developer, when most would be happy to just build on today's Linux and call it a day.
> Of course, that imposes the cost of 100% compatibility on every developer, when most would be happy to just build on today's Linux and call it a day.
The reality is that when you use programs built with autotools on systems that aren't mainstream, you'll have troubles. Because the scripts aren't right and were only tested by Linux developers on Linux.
And much of the time, I find it faster and easier to fix a broken makefile than to fix broken autohell.
Exactly. 99% of the time, a broken makefile simply has an incorrect linker path or cflag. When it's not a path, the Makefile is structured in a way that makes sense and is easy to fix. If an autoconf project is broken, I just scrap it and don't even bother trying to build it.
The other issue with autoconf is that it's not standardized. So many of the autoconf projects I've seen have shell scripts (to install it or download deps) mixed in that only add more confusion. Some of them have a configure script. Some have a configure.in, so you have to generate the configure yourself.
100% of the makefiles I've seen have a build, install and clean task. Sure, it's not required, but everybody does it. You can't say the same for autoconf.
* Head First C - David Griffiths
* Expert C Programming: Deep C Secrets - Peter Van Der Linden
BTW: just want to say that you have a fascinating blog! I've just spent last hour only skimming through some of the articles and bookmarking them for later. (Link for the lazy: https://nickdesaulniers.github.io/)
In college I learned how to program embedded systems with C (and ASM). Once I knew how to debug, build, and push it onto the device, it was surprisingly easy and beautiful. There's no confusing and magical abstractions, it's just you and the hardware. You pull up the microcontroller's manual, and as long as you have an idea of what the lingo means, you can make it dance to your will.
Something I disliked was that with both microcontrollers I used, there was dark magic involved in building and uploading your binary. One of the devices provided examples for a specific IDE, so I imported that example and used it as a base. I could keep modifying it and keep adding files, but I never managed to setup a "new" project. The other device was similar, but instead of using an IDE it provided a Makefile, which was nicer.
Does anyone know any good resources on learning and writing real-world C? I've looked at C projects here and there over the years, with the most interesting being GNU Coreutils... But even if I can eventually understand what some code does, how do I learn why it does it that way?
I'd love for a guide that showed things like: "do X and Y because of this and that", "test X and Y by running the following", "write tests using XYZ", "debug X using Tool A, and Y using Tool B", "pull in this library by copying these files into these places, and use it by adding the following lines to the following files", "generate docs by pulling in this tool and set it up by doing the following", etc.
In the web world there's a massive set of problems, but it tends to be easy to find "boilerplate" generators that will get you up and running. And after you've tried out a few of them, you can usually pick up how people are mixing and matching different tools.
EDIT: Another comment linked to "Learn C The Hard Way" [0], and after browsing through the chapters it seems to cover a lot of the topics I'm interested in.
[0] http://c.learncodethehardway.org/book/