6 ms·
GNU make now has a load directive which lets you load up functions written in C -load my_module.o Your makefile can contain instructions to build my_modul
by t43562 2y ago
GNU make now has a load directive which lets you load up functions written in C
-load my_module.o
Your makefile can contain instructions to build my_module.o and they will be automatically triggered.
For example you can create an equality test that works in an expression (ifeq can't be used as part of an expression obviously). For example
FILENAME=file.$(if $(equals $(compression_level),0),tar,.tar.bz3)
The C for this function (without includes and export directives):
char *
func_equals (const char *func_name, unsigned int argc, char **argv)
{
char *result = NULL;
if (strcmp(argv[0], argv[1]) == 0) {
result = gmk_alloc(strlen(argv[0]) + 1); /* not handling failure for simplicity */
strcpy(result, argv[0]);
}
return result;
}
This can be done with a macro but it's ugly and verbose. Macros also slow makefile parsing a lot and for a large build like e.g. an operating system this makes a big difference - it's a penalty you pay every time you run "make" even if you only changed 1 file.
There are plenty of things you cannot do with macros too. $(shell) is a getout card but it drastically slows down large makefiles.
Your module has a setup function which gets called when it's loaded and this adds the function into gmake:
int
equals_gmk_setup (const gmk_floc *flocp)
{
gmk_add_function ("equals", func_equals, 2, 2, GMK_FUNC_DEFAULT);
return 1;
}
Things that are hard/slow to do with macros like arithmetic - comparing, adding and so on are even better candidates. A hash function is great for generating intermediate target names that aren't too long for the filesystem.
My favorite one that I've done is embedding a python interpreter into make - this is very convenient as it's MUCH faster than running a process from $(shell) and it keeps state between uses which can be useful.
- bandrami 2y agoGNU Make also embeds GNU Guile, a criminally underused feature: https://www.gnu.org/software/make/manual/html_node/Guile-Integration.html https://www.gnu.org/software/make/manual/html_node/Guile-Int...
- srik 2y agoTIL thank you!
- bandrami 2y agoI sometimes wonder if we would even have autotools or cmake if people just knew about this one simple trick
- o11c 2y agoAutotools is designed to solve one very important problem: how do you build the GNU tools in the first place if all you have is some obscure Unix from the 1980s. If you already have gnu make, gnu bash, gnu binutils, gnu coreutils, etc. installed then autotools is pointless. I have yet to find evidence of cmake solving a problem (or even having design), though I guess `ccmake` would be kind of cool if it weren't full of nonsense?
- t43562 2y agoI see Autotools as sort of cool if you're porting to a new platform - the tests find out what works and if that's not enough then you have to make some effort to get around it. If you're lucky, however, you put your autotooled code on some completely new OS/hardware and it just builds. Nowadays the proportion of people who are porting the code is probably much smaller but it's still a way of keeping code working on unix with various compiler, architecture variations. IMO cmake just includes windows more effectively - for autotools you'd probably be forced down the cygwin route. I find it a bit easier to work with but it's still a nightmare from hell sometimes.
- bandrami 2y agoThough there's also gnulib, which as part of the autotools process simply replaces system functions with their own stubs. It was a great idea, briefly, and then it became a fiasco.
- wichert 2y agoEven with all the GNU tools available there are still a lot of system-specific things that you may need to know: supported C version, supported C++ version, how to invoke the compiler, correct compiler flags for warnings / desired C or C++ version / etc, where to install things, how to install them and set the right owner and permissions and many many more. Autotools (and cmake) can figure all of that out for you. If you operate in a monoculture and, for example, only deal with a single Linux distribution on a single architecture most or all of this may not be relevant for you. But if you target a more diverse set of environments it can save you a lot of headaches.
- o11c 2y agoIn practice, Guile is usually not compiled in. Whereas I've never seen a version of make without `load` and its supporting infrastructure.
- bandrami 2y agoDebian gives you the option, with make and make-guile equivalent packages. IIRC Slackware simply compiles it in (guile already being there) and Fedora/RHEL leave it out entirely.
- dima55 2y agoYes. It really should be "make" and "make-noguile", but we have what we have. In practice, you actually want the "remake" package. This is a fork of "make" that's a drop-in replacement (since it is the same code), has guile enabled AND contains an interactive debugger.
- be_erik 2y agoI wish rmake was in the standard codebase for most distros. It’s absurdly helpful.
- jhoechtl 2y agoNot for Windows
- kazinator 2y agoIt is criminally under-integrated! The only interface you get into the make internals from Guile is a function to expand a make expression, and a function to eval a makefile fragment. These interfaces only encourage the use of Guile for nothing more than make metaprogramming, an area where more power is not needed. Imagine if Guile access to the rules as data structures or something. And the graph of targets to be updated and what not. Imagine if Guile could be used, say, to override the logic by which a target is considered out of date with respect to its prerequisites. .
- akoboldfrying 2y ago>Imagine if Guile could be used, say, to override the logic by which a target is considered out of date with respect to its prerequisites. That is exactly what I was recently hoping for. Make-as-library is such a compelling idea that I feel like it must have already been done, but I searched for something like this recently and the closest I found was Java's Ant, which gets the as-library part but sadly has no concept of "target is already up-to-date"...
- nrclark 2y ago100% agree. With the current API, there's no real advantage to using Guile over a C extension (other than the choice of language). If the Guile interface could hook into Make's dependency graph, it would be huge game-changer. But as it is, the Guile interface is basically a fancy macro processor. The Guile interface can expand Makefile expressions into values, and can process/evaluate Makefile statements. But there's no way (that I've found) to do something like "remove this dependency from target X", ask "what dependencies does X currently have?", or ask "do you think X is currently up-to-date?".
- kazinator 2y agoI would say there is no advantage of using built-in Guile to call make's eval API over: $(eval $(shell <arbitrary-command>)) where arbitrary-command could run ssh to a virtual machine, running a docker container loaded with Common Lisp ... The Guile approach stays in one process, but that has no value in the context of make, which launches external programs as its principal paradigm.
- dima55 2y agoThat's great. Thanks for pointing it out.
- t43562 2y agoDelighted! :-) Glad someone found it a help