[HN Gopher] "Make" as a static site generator (2022)
___________________________________________________________________
"Make" as a static site generator (2022)
Author : bundie
Score : 219 points
Date : 2023-09-10 11:30 UTC (11 hours ago)
(HTM) web link (www.karl.berlin)
(TXT) w3m dump (www.karl.berlin)
| karl42 wrote:
| Author here. Nice to see people appreciate simplicity. If you
| have any questions, feel free to ask!
| dwheeler wrote:
| I've been doing this for decades. It works very well, it can
| handle complex cases, and it ports trivially between different
| hosting systems.
| danielvaughn wrote:
| It's a neat idea, though I have to point out that if you're
| already pushing to Github, you could just push the source and
| Github will publish your markdown as a hosted page:
| https://pages.github.com/
| smarnach wrote:
| Isn't this "cat" as a static site generator target than "make"?
| Make is just the build system invoking the static site generator.
| donatj wrote:
| Just a couple days ago I set up a site with GitHub Pages and used
| a very similar setup.
|
| I learned about envsubst in the process which let me fill in
| values here and there. This is the rough way the homepage works.
| public/index.html: index.md template/header.html
| template/footer.html cat template/header.html >
| public/index.html DATE=$(shell date +%Y-%m-%d)
| envsubst < index.md | npx marked --gif >> public/index.html
| cat template/footer.html >> public/index.html
|
| GitHub's newer version of pages that lets you deploy via GitHub
| Actions rather than being forced into using Jekyll is just so
| amazing. I have converted a bunch of static sites to using it as
| hosting.
| hnarayanan wrote:
| Just as straightforward as this is another method that has
| worked for me for years (decades?).
|
| Server Side Includes.
|
| Have a separate files for the header, content and footer and
| only edit the content files.
| donatj wrote:
| I was there 3,000 years ago... I used SSI's in the late
| 90s/early 2000's before replacing all that with PHP which was
| a huge step up at the time. I am more than familiar.
|
| The convenience here is largely in being able to use GitHub
| Pages to host the page while being able to do almost anything
| you want for a build process. It's really neat.
| rambambram wrote:
| I like it that (almost) every dev blog I come across on HN has an
| RSS feed.
|
| For every interesting article that I read here I follow the feed.
| Whether you have a Wordpress site, a Bear Blog, a Micro blog, a
| blog on Havenweb, or a feed on your self-built site, I add them
| to the 'Really Social Sites' module of Hey Homepage.
|
| Ultimately, I would like to publish this list of blogs, just like
| Kagi now does with their Small Web initiative. But I guess
| curating is key to adding quality. And when I think about
| curating, starting some kind of online magazine seems only
| natural.
| MuffinFlavored wrote:
| I'm trying to understand (as a dev) if there is something
| "wrong with me" for not wanting to have my own blog. Where do
| people get the "entitlement" (I mean that in the best way
| possible) to share with other people/assume other people care
| what they are working on? It feels like a competition
| sometimes. "I need to work on something as cool as possible so
| I'll get some likes/impressions on my blog".
|
| Collaboration is obviously cool and only works with making it
| all public, I just don't know where "I'm doing this because I
| think it's cool" and "I'm going to put effort in to share it
| with others to get reactions"
| rambambram wrote:
| I don't think there's something wrong with you. I also think
| there's nothing wrong with people sharing _interesting_
| stuff, whether they do it ultimately for shallow likes or for
| ... you know... just sharing _interesting_ stuff.
|
| On a side note, I get the "entitlement" from nobody. I take
| it. I also mean that in the best way possible. Nobody's
| asking for my software, my (future) articles, my point of
| view, etc. Still, I make stuff and sometimes share stuff. I
| think it can be a net value for some people (definitely not
| for everyone). This is only the reasoning behind it, the main
| motivator was me realizing I matter as a human being and I
| have only one life to live. I learned that because of
| experiencing a 'dark night of the soul' a couple of years
| back. Luckily I got through. And to be honest, if it wasn't
| for the internet - made up of personal websites and real
| people sharing their own experience on forums - that taught
| me everything there is to know about Cluster B disordered
| personalities (just an example, _cough_ nothing personal
| _cough_ ), I don't think I would be sitting here typing this
| lengthy response.
|
| I realized I can not sit back, enjoy the decline of the
| internet, and only complain about it. I would love to see the
| web have a lot of personal websites and blogs about every
| kind of subject, so I started to build a website software.
| The web/internet, and all the information shared and made
| easily accessible, made me able to save myself. I was
| probably helped more by some random dude who put up a website
| fifteen years ago with everything he knew about certain stuff
| than I was helped by anything else.
| jaw wrote:
| I have a blog, but I mostly assume people _don't_ care what
| I'm doing or thinking. Some of my posts have probably never
| been read by anybody. I still personally find it worthwhile
| for a few reasons:
|
| - The mere possibility that someone will see it pushes me to
| put more thought and effort into what I write. Sometimes this
| reveals weaknesses in my ideas that I would have glossed over
| if I were just writing private notes for myself; sometimes it
| leads me to actually change my opinions. It also means the
| blog posts are easier for me to understand / get value out of
| than notes are if I come back and reread them years later.
|
| - It creates opportunities for people to connect with me
| which can pay off at unexpected times. Occasionally people
| have reached out to me to say a post helped them or resonated
| with them, or to give a thoughtful reply or ask a question.
| Those sorts of interactions are really satisfying even if
| they're rare. (One time, I was interviewing for a dev job and
| the interviewer asked a question about a post I'd written on
| the philosophy of John Rawls, and how it could connect to
| software engineering. I found that absolutely delightful.)
|
| - It's just nice to have an outlet when I feel like writing
| about something.
| eep_social wrote:
| I think the bloggers are a classic vocal minority, nothing to
| feel weird about.
| rambambram wrote:
| > a classic vocal minority
|
| Not saying you're right or wrong, but I myself don't want
| to look at it like it's a competition of the loudest
| people.
|
| I've read so many blogs through HN over the last years, and
| every one of 'em had something interesting to say while
| also portraying something personal from the author. Whether
| that's a nice layout, nice color scheme, or even some nice
| jokes in their bio text.
|
| To me, it can not get any more human than this. Pure
| individuals connecting on a world wide web. By links, by
| email, by RSS feeds. All without big tech.
| eep_social wrote:
| I agree with everything you wrote -- what I was trying to
| communicate is that there's no shame in not feeling the
| urge to share as it happens to be that the vast majority
| of us, like the gp post, don't but that's not easy to see
| or quantify.
|
| Aside, I almost wrote "silent majority" but that seemed
| like it was veering towards politics so I went with vocal
| minority; I suspect there is a better term out there but
| I didn't find it quickly.
| rambambram wrote:
| I admit I interpreted more in your short post than was
| there. People definitely should not feel shame for not
| feeling an urge to share!
|
| I still encourage people to share though, because I think
| a lot of people would like to read personal stuff about
| topics that interest them. Doesn't even have to be with
| your name and all next to it, anonymous/pseudonymous
| homepages are usually possible.
|
| Therefor I offer free websites (on a subdomain though)
| for people that would like to write or post photos about
| their hobbies. And know that there are way more
| possibilities to go online, just look at the OP of this
| thread with a nice SSG.
| eep_social wrote:
| > I offer free websites
|
| And I am so glad you do!
|
| Writing my longer reply I realized that early social
| media is a strong counterpoint -- people absolutely loved
| to share when the barrier to doing so was low, the
| platforms hadn't been given over to commercialization,
| and it was less obvious that those details were going to
| be ingested into an advertising profile. It sounds like
| you offer a bit of that without the motive or intent that
| turned mainstream social media into what it is and I
| think that's great!
| rambambram wrote:
| Thanks!
|
| Yeah, somewhere between the homepages and webrings of the
| nineties and the added social functionality of the early
| social media platforms. Ideally without the platforms and
| their incentives. The web itself is already a social
| platform, a social medium. No need for more layers,
| especially if they ultimately are against my interests. I
| think RSS still holds the potential to connect individual
| websites/people, albeit in a slightly (or maybe even
| fundamental?) different way than the social media
| platforms do.
|
| Question: what would be your number one topic/subject to
| blog about, other than anything tech related?
| sureglymop wrote:
| I use make and pandoc as my static site generator! Generates a
| good website from my markdown notes.
| gigatexal wrote:
| I do this too! But my make-fu isn't as good. I'll use what I
| learned from here to make it better.
| denvaar wrote:
| It's fun to make your own SSG tool, and this is a great example
| of keeping it simple.
|
| It's also interesting to read so many comments of people doing
| similar things.
|
| For my own site, I find that I want an SSG tool that is simple,
| intuitive, and stays out of the way. With these goals in mind, I
| have been able to slowly improve my tool over and over. It's been
| awesome to be able to do more using less.
| nonethewiser wrote:
| It also makes you realize what they actually are.
| adityaathalye wrote:
| Absolutely! What mental model did you arrive at?
|
| Mine is "an SSG is just a source to HTML compiler and
| compositor, plus file organiser".
|
| I reviewed a few tools (jekyll, emacs.love/weblorg, hugo),
| and ended up making mine in big part because I went down the
| rabbit hole of "well, why is this part here? why is it like
| this? why can't we do this other thing? wow this bit is cool,
| how do I make it myself?".
| bachmeier wrote:
| As long as we're sharing our own projects...
|
| One of the things I did during the pandemic lockdown was work on
| the simplest possible blog in a single html file. Something that
| requires essentially no technical knowledge beyond typing text
| into a file. I recently dusted it off and yesterday I posted the
| most recent iteration.
|
| Demo: https://bachmeil.github.io/minblog/blog.html
|
| Source: https://github.com/bachmeil/minblog/blob/main/blog.html
|
| There's very little styling, but that's not the objective (and
| it'd be trivial to add).
| [deleted]
| mkoryak wrote:
| > There are no exotic dependencies, nothing to maintain and you
| can quickly adapt it to your needs.
|
| Yeah kinda, except that most people making static sites aren't
| the people who know Make.
| jetrink wrote:
| I regularly see people on HN who have a static site for their
| personal site or blog. There's a niche for this kind of thing.
| rcarmo wrote:
| Up until a certain point, yes. Then you start wanting back
| links, navigation, etc., and doing that with make alone
| doesn't quite work, especially if you have a deep tree of
| files - single folder sites don't typically have a lot of
| content in them.
|
| (My site is generated by a Python commit webhook that indexes
| new files, diffs an Azure storage container and uploads
| updated files only).
| envsubst wrote:
| it's a crazy concept, but people are willing to learn to use a
| new tool for their hobby project.
| girishso wrote:
| Most Static Site Generators generate blog from markdown, which is
| not feasible for projects like company websites etc. For such
| projects I like Middleman (https://middlemanapp.com) which
| provides layouts/partials and things like haml templates.
| petepete wrote:
| Nanoc is great in cases like this too. It does less out of the
| box than Middleman but is easier to extend.
|
| https://nanoc.app/
| defanor wrote:
| I used a shell script for that, but vaguely thought of changing
| to a Makefile for a while, and finally did now, thanks to the
| article reminding of that; it is more appropriate. Though the
| shell script still invokes make, and then rsync, since rsync
| seems less appropriate for a Makefile. But now it synchronizes
| fewer files.
|
| As a side note, I am quite happy with XSLT templates to produce
| the pages (instead of attaching a static header, as in the
| article), as well as to generate indexes and an Atom feed.
| liveoneggs wrote:
| hey I wrote almost this exact blog post 15(ish?) years ago except
| mine used m4 as an "exotic dependency" ;)
| tiehuis wrote:
| I as well moved to this sort of approach a few years ago [1].
| Definitely like the simple approach and it just stays out of the
| way.
|
| [1] https://tiehu.is/blog/blog1
| adityaathalye wrote:
| I love the code [1]. Mine [2] is a bit over engineered because I
| wanted hot-reloading (without JS), and it was a delightful yak
| shave.
|
| But the basic idea is the same --- heredocs for templating, using
| a plaintext -> html compiler (pandoc in my case), an intermediate
| CSV for index generation. Also some handy sed-fu [3] to lift out
| front matter. Classic :)
|
| Very nice!
|
| [1] https://github.com/karlb/karl.berlin/blob/master/blog.sh
|
| [2] https://github.com/adityaathalye/shite
|
| [3] I'm doing this:
| https://github.com/adityaathalye/shite/blob/master/bin/templ...
| case ${file_type} in org ) #
| Multiline processing of org-style header/preamble syntax, boxed
| # between begin/end markers we have defined. We use org-mode's
| own # comment line syntax to write the begin/end
| markers. # cf. https://orgmode.org/guide/Comment-
| Lines.html sed -n -E \ -e
| '/^\#\s+shite_meta/I,/^\#\s+shite_meta/I{/\#\s+shite_meta.*/Id;
| s/^\#\+(\w+)\:\s+(.*)/\L\1\E,\2/Ip}' ;;
| md ) # Multiline processing of Jekyll-style YAML
| front matter, boxed # between `---` separators.
| sed -n -E \ -e
| '/^\-{3,}/,/^\-{3,}/{/^\-{3,}.*/d;
| s/^(\w+)\:\s+(.*)/\L\1\E,\2/Ip}' ;;
| html ) # Use HTML meta tags and parse them,
| according to this convention: # <meta
| name="KEY" content="VALUE"> # cf.
| https://developer.mozilla.org/en-
| US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML
| sed -n -E \ -e
| 's;^\s?<meta\s+name="?(\w+)"?\s+content="(.*)">;\L\1\E,\2;Ip'
| ;; esac
| maccard wrote:
| Seeing these sorts of scripts is exactly why we don't write our
| own, and use something like esbuild and vite.
| adityaathalye wrote:
| Well, I have my reasons and you have yours!
|
| For example,
|
| A) Most importantly, I wanted to tinker and have fun!
|
| B) I already use Bash at work and stuff, so it's easy for me.
|
| C) I am generally averse to fast-changing dependencies, and
| giant dependency trees, so that rules out most scripting
| languages.
|
| Besides, if you peruse the README, you will see that my code
| guarantee is "works on my machine". Your mileage will vary
| tremendously :)
| maccard wrote:
| If it's just for fun then write your bundler in assembly
| for all I care!
| adityaathalye wrote:
| You never know :)
| rcarmo wrote:
| I found his GEMINI approach quite funny - it strips out most of
| the formatting with a regexp.
|
| There is a bit of a limitation, though - I organize posts by
| namespace and with the date in the URL, and make can't really
| handle that directly.
| karl42 wrote:
| > I found his GEMINI approach quite funny - it strips out
| most of the formatting with a regexp.
|
| Do you mean the regexp in
| https://github.com/karlb/karl.berlin/blob/master/blog.sh#L4 ?
| It doesn't remove the formatting, just HTML comments (because
| they would show up on the page, otherwise) and rel="me"
| attributes (because they don't work with md2gemini). Feel
| free to read the blog post about adding Gemini support for
| more details: https://www.karl.berlin/gemini-blog.html
| adityaathalye wrote:
| Huh, I previously skim-read the code and didn't notice the
| GEMINI regex detail. I wonder why they're doing that.
|
| Re: namespace organisation. I thought about that a lot, and
| decided to adopt namespace-only convention for symmetry
| between text file layout, html file layout, and url scheme.
|
| I've treated Date/time as metadata, which I can use to
| organise index pages. If I get to years worth of posts, then
| I'll group them by year/month or something reasonable.
| Likewise tags. I debated tags _and_ categories. But I decided
| on "everything is a post with tags, and categories will
| emerge based on topical coverage + post format".
| superlopuh wrote:
| Is there a GitHub workflow available for this or similar tool?
| askiiart wrote:
| I did something similar for mine, I do markdown-to-html using
| pandoc, then replace the language labels using find (so that
| prism.js works). I've got it all running via a little Python
| script (I would've done bash but I'm terrible at it) to generate
| all the the files easily, rather than going through one-by-one:
| https://git.askiiart.net/askiiart/askiiart-net/src/branch/ma...
|
| I might move to something make-based like this, looks
| interesting.
| mjburgess wrote:
| just use (gnu) parallel
| bradley_taunt wrote:
| I was instantly inspired by Karl's work on his "blog.sh" shell
| script[0] that he mentions in this article. I took it and tweaked
| it to create my own minimalist SSG called "barf"[1]. That
| wouldn't exist if Karl didn't share his wonderful work publicly!
|
| [0]: https://github.com/karlb/karl.berlin/blob/master/blog.sh
| [1]: https://barf.bt.ht
| adityaathalye wrote:
| Ah, a fellow person of culture. Mine is called shite [1], which
| makes my site [2]. The name alludes to the software quality :)
|
| What I like most about it is I haven't had to upgrade anything,
| and don't expect to forever. And a close second; it "hot
| reloads" without javascript.
|
| [1] https://github.com/adityaathalye/shite
|
| [2] https://evalapply.org
| gnyman wrote:
| Haha I sense a trend for these home grown static site
| generators :-)
|
| Yours are much more advanced, but a few years back I made a
| minimal PHP static page generator and named it...
|
| PHP keep It Stupid Simple, or in short P.I.S.S.
|
| https://blog.nyman.re/2020/10/11/introducing-piss-a.html
| adityaathalye wrote:
| Well, if you see my templating code, I've basically written
| PHP, but in Bash :D
| lacrosse_tannin wrote:
| I'm gonna use bazel
| adriangrigore wrote:
| Shameless plug for my shell based static site generator
| https://mkws.sh. You can replace the bin/mkws script with a Plan9
| mk file anytime.
| prabal97 wrote:
| Very cool! How long did it take you to make something like
| this?
| adriangrigore wrote:
| Well, I implemented the main idea in a day or two. That being
| the pp preprocessor. The rest, I really can't remember, it
| was mainly grunt work to see what are the minimum things a
| web site is required to have. I still have some stuff to
| remove.
| marcodiego wrote:
| A friend of mine described using make to generate scientific
| papers. He explained that if he changed a single test file, the
| entire paper could be regenerated including running tests and
| generating graphs the changed test with a single command.
| w4rh4wk5 wrote:
| I did some similar experiments some time ago. It includes
| Makefiles, Rakefiles, SASS, Ruby erb, Jade, m4, and a few other
| tools.
|
| https://github.com/W4RH4WK/static-page-generators
|
| Over all, I quite like Ruby since it comes with rake and erb.
| maccard wrote:
| Rake is probably my favourite of them all, but it adds a
| dependency on ruby. We've settled with using make and accepting
| the limitations
| superkuh wrote:
| Or maybe don't make a site generator and just make a website
| using HTML files? You'll spend a lot less time painting the shed
| and a lot more time actually putting your ideas/content on the
| website.
|
| If you want templating then use server side includes. It's much
| less attack surface than say, PHP or some complex CMS, but you
| can still just make a footer.html and stick in at the bottom of
| every other .html page easily and avoid the one problem with file
| based sites: updating shared bits.
| ttfkam wrote:
| If only there were a way to make consistent structure in an
| online document (such as hypertext) and separate the styling
| into distinct files. Even better, what if we could make
| separate styling for mobile, desktop, and printing, all with
| the same content?
|
| If only it were possible using existing standard web
| technology. Sadly it was never designed with such goals in
| mind.
|
| /s
| ivanstojic wrote:
| Tossing mine in the pot too: make + pandoc:
| https://ordecon.com/2020/07/pandoc-as-a-site-generator/index...
| m000 wrote:
| Adding a pinch of m4 [1] can give you a bit more of flexibility
| while sticking with the same barebones approach.
|
| I used to maintain a small website built like that some 20 years
| back. But I can't see the model working today, personal websites
| excluded. The problem is that the approach essentially enforces
| Web 1.0 roles: You either need every contributing user to be
| html-proficient, or someone willing to assume the drudgery of
| being the "webmaster".
|
| [1] https://en.wikipedia.org/wiki/M4_(computer_language)
| gizmo686 wrote:
| There is no such thing as a "pinch of m4". You start a clean
| project promising that you won't touch m4 this time. Then you
| add a small m4 invocation to save yourself from some
| boilerplate.
|
| A year later, when you are trying to figure out why all
| instances of the word "cat" are silently disapearing from your
| website, you dig through 5 layers of macro expansions to
| discover that a junior dev tried implementing a for loop
| instead of copying it from the manual and messed up the
| quotation marks.
|
| Having solved the immediate issue, you decide that debbuging
| your DSL is too hard, so you import M4 macro file you have been
| copying between projects. You then spend a day replacinf all
| usages of 'define' with your macro-creating-macro that adds
| comments to the output enabling your stacktrace generation
| script to work.
|
| Next project, I am putting down a hard rule: no m4! (Except for
| maybe that one instance)
| JoelMcCracken wrote:
| Please write more to this story
| gizmo686 wrote:
| Not "this" story. Everything above has happened on several
| projects. The cat thing comes up because it is tricky to
| expand two macros next to each other without whitespace. So
| if you do: define(`foo',`hello')
| define(`bar',`world') foo bar foobar
|
| You will get: hello world foobar
|
| Working around this gets tricky, so someone inevitably ends
| up writing a cat-like macro such that you can do
| cat(foo,bar)
|
| To get helloworld.
|
| A side effect of this is that now "cat" is really "cat()"
| which expands to "". You can work around this by doing
| `cat'. However, if `cat' is used as an argument to another
| macro (such as a for loop), the quotation only prevents
| escaping the first time. When the for macro is expanded,
| the quotation marks are stripped, giving you just "cat",
| which gets expanded again. A correctly written for macro
| would add new quotes as needed, but I have never seen
| someone correctly write such a macro without just copying
| it.
|
| Not sure if I have seen this interaction specifically with
| for and cat, but I have seen an interaction like it on
| almost every project that used m4.
| mhitza wrote:
| You can place an empty "expansion" in that line to get
| the behavior you want without an additional cat-like
| function foo`'bar
|
| I only know of this feature because recently read the
| manual page for m4, and it's mentioned rather early in
| there, but might have been not as well emphasized in past
| iterations of the manual.
| gnubison wrote:
| For completions sake, though, the easy way to do it is:
| foo`'bar
|
| The empty quotes make foo and bar separate words.
| js2 wrote:
| I've only ever used m4 via autoconf and sendmail
| configuration files, so I don't know if it's m4 that has the
| bizarre syntax or whether it's autoconf's and sendmail's use
| of it. I'm not sure I've ever tried to use m4 directly for
| anything.
| _ache_ wrote:
| I know that story too well. Finally, I thought that if I have
| to code, I should just use a programming language.
|
| Now, I use nodeJS to replace every m4 file with mustache.js
| and some JS logic and I don't feel limited anymore. The
| complexity doesn't increase much.
| tannhaeuser wrote:
| Rather than relying on generic text substitution using m4 or
| perl or whatever, I suggest using SGML, the basis and common
| superset of HTML and XML, which comes with easy type checked
| text macro (entity) expansion for free or even type-aware
| parametric macro expansion. Where "type" refers to the regular
| content type of a markup element (ie. its allowed child
| elements and their expected order) but also considers expansion
| and escaping into attributes or other context such CDATA or
| RCDATA. Only SGML can extend to the case of properly
| expanding/escaping potentially malicious user comments with
| custom rules such as eg. allowing span-level markup but
| disallowing script elements, does markdown or other Wiki syntax
| expansion into HTML, can import external/syndicated HTML
| content, produce RSS and outlines for navigation, etc. Works
| well for nontrivial static site preparation tasks on the
| command-line; cf. linked tutorial and command line reference.
|
| [1]: https://sgmljs.net/docs/producing-html-tutorial/producing-
| ht...
|
| [2]: https://sgmljs.net/docs/sgmlproc-manual.html
| layer8 wrote:
| What is sgmljs? There doesn't seem to be any explanation on
| the site.
| tannhaeuser wrote:
| A comprehensive package for processing, converting, and
| serving SGML on the command line, on the server side, or in
| the browser; see [1]. Also features SGML DTDs (grammars)
| for W3C HTML 5, 5.1, 5.2, and Review Drafts January 2020
| and 2023, which are the latest non-volatile W3C and WHATWG
| HTML recommendations/spec versions.
|
| [1]: https://www.npmjs.com/package/sgml
|
| Edit: your comment is a welcome reminder to improve the
| site, which isn't an easy thing to do however due to sheer
| volume of the material, even though it's using SGML for
| shared boilerplate inclusion, ToC/site nav and page nav
| generation, etc. (in fact, by calling sgmlproc from a
| Makefile)
| envsubst wrote:
| Instead of `m4` or `sed` find and replace, the author should
| try `envsubst`. It's a program that replaces bash style
| variable references (for example `$TITLE`) with their value in
| the environment. export CURRENT="..."
| cat page.html | envsubt
| teo_zero wrote:
| The problem is that the $SOMETHING syntax is just too common
| if your site is a technical one, and you'll end up
| substituting too much.
| envsubst wrote:
| You can specify which variable names are valid, reducing
| the likelihood of a collision.
| gjvc wrote:
| I did that once. Never again.
|
| Just because it worked for sendmail is not sufficient
| justification for anything.
| SoftTalker wrote:
| A lot of older unix software config is complicated and
| cryptic.
|
| sendmail, bind, apache, older X11, sudo are examples that
| come to mind.
| q3k wrote:
| > a pinch of m4
|
| nononononononononono for the love of everything please no
|
| m4 isn't even a good esolang!
| Tomte wrote:
| You need to combine it with Perl and a collection of other
| special passes, of course: https://web.archive.org/web/201803
| 09134414/http://thewml.org...
| PaulHoule wrote:
| At the dawn of the age of PHP, I created a user management
| system (registration, verification, admin interface, ...)
| that was based on well-established ideas (how login worked at
| Yahoo, Amazon, and every other process major site) but got no
| traction at all as a open source project. In any language
| that wasn't PHP it would be necessary to write an
| "authentication module" which as about 50lines of cookie
| handling code. Multiple times I managed to out several
| existing apps together and make an advanced web site.
|
| About 10 years ago the idea suddenly got traction once it was
| legitimized by the SAAS fad, I would tell people "don't you
| know they're going to end the free tier or go out of business
| or both?" and sure enough they did.
|
| Anyhow, I bring it up because the system used M4 to
| interpolate variables into PHP, other languages, shell
| scripts, SQL scripts, etc.
| gabereiser wrote:
| Ugh, I know exactly how this feels. You resist the urge so
| hard to say "I told you so" and instead relish in the fact
| that you saw it. "The Way", so to speak.
|
| I remember having to write cgi cookie handling code. I
| remember having to write session-cookie sync code. PHP was
| a small slice of heaven in the cgi world. Until it wasn't.
| Still, being able to import libraries of script functions
| without having to recompile was wizardry. The problem with
| php now is they let a certain product somewhat dictate
| their direction. Class namespaces with slashes is the
| ugliest design choice.
|
| What was your oss project that couldn't get traction?
| kazinator wrote:
| The benefit of make is that large programs that are built by slow
| compilers can be incrementally rebuilt much faster in the face of
| small changes. Something that would take 40 minutes to do a full
| rebuild can build in three seconds or whatever.
|
| If your static site can be generated from scratch in under a
| second by just catting a few hundred HTML files with a common
| header, there is no benefit to using make over a script. You only
| risk performing an incomplete build due to a bug in the
| dependencies.
| toast0 wrote:
| If the file dependencies don't actually matter, you can mark
| the build targets as .phony
|
| And still get to have things like make build vs make push, etc.
| kazinator wrote:
| If dependencies don't matter, make isn't the right tool.
|
| Your scripted actions can be ./build and ./push.
|
| If you feel you need to type the name of a tool before your
| command, you can do that: sh build, sh push.
| mosselman wrote:
| This amazing course by Avdi Grimm on make and rake for the same
| purpose has completely changed my understanding of rake and I
| recommend anyone checking it out:
|
| https://graceful.dev/courses/acapa/
| PaulHoule wrote:
| Funny I am setting up a blog with Pelican which uses "make" for
| executive control.
| jez wrote:
| A problem with this approach is that deleting a file from source/
| does not delete it from build/.
|
| In my own projects, simply rebuilding the whole site is fast
| enough, so I opt to remove the whole build folder before a
| rebuild:
|
| https://github.com/jez/jez.github.io/blob/source/Makefile#L1...
|
| This defeats a big part of why you'd want a build system in the
| first place (incremental builds), but at least if you know the
| page you want to regenerate you can still `make` that file
| directly.
|
| If there's a common workaround for this pattern in makefiles I'd
| love to learn it.
| linkdd wrote:
| Something like this should do the trick:
| rm/%.html: @rm -f source/%.html build/%.html
|
| Run with: $ make rm/page.html
| [deleted]
| Jhsto wrote:
| I use Nix, so I get incremental builds and your problem goes
| away.
| schemescape wrote:
| You're using Nix to drive your static site generation? If so,
| please share more details because that sounds intriguing!
| Jhsto wrote:
| Here you go: https://juuso.dev/blogPosts/nix-as-a-static-
| site-generator/n...
| schemescape wrote:
| Wow, I ask and a blog post just appears!
|
| My initial reaction is: I should probably get around to
| learning about Flakes. I'm not sure I'd want each blog
| post to pin its templates, but it's nice to have that
| choice.
| __MatrixMan__ wrote:
| I was just reading this and thinking that `nix build` would
| do the same trick even more nicely.
| Jhsto wrote:
| I posted a link to the other comment, but here it is for
| you as well: https://juuso.dev/blogPosts/nix-as-a-static-
| site-generator/n...
| __MatrixMan__ wrote:
| I admire how nimble you are. I aspire to write blog posts
| at the drop of a hat like this, but I rarely do.
|
| I also like the use of flake inputs for content.
|
| It reminds me of a world that I've been imagining where
| the conclusions in scientific papers are generated as a
| flake outputs (an adjacent output would be the human
| readable thing, a PDF or whatever).
|
| In this world, you can just run `nix flake update && nix
| build`, and if a paper that you cite published an update
| which invalidates your conclusion, you know right away
| because their output is your input, so your build fails.
|
| We think about repeatable builds being for executable
| binaries, but they could equally well be for conclusions
| and assumptions.
|
| Perhaps nix is too big of a hammer for the job, but it
| seems like the best shot we have at achieving this
| without also constraining the scientist re: tooling.
|
| I realize that you don't want to be storing mountains of
| data in the nix store, but it would work just as well if
| the output in question is an IPFS CID, to be resolved
| during the build instead. The publisher can then be in
| charge of keeping that CID pinned and of notifying
| scientists when they're "build" starts failing.
| Jhsto wrote:
| > I admire how nimble you are. I aspire to write blog
| posts at the drop of a hat like this, but I rarely do.
|
| Thanks! I took up blogging more often as of recent, and
| for me, having a manageable system is a large part of
| that. The last thing I want to happen on a Sunday evening
| is breaking some page of my website. That being said, I
| hope to one day make the workflow easier.
|
| > It reminds me of a world that I've been imagining where
| the conclusions in scientific papers are generated as a
| flake outputs (and adjacent output would be the human
| readable thing, a PDF or whatever).
|
| I happen to be a reviewer for software artifacts in a
| scientific journal, and I often use Nix here. Not that
| many projects do use it, but if I'm able to reproduce it
| with Nix, then I know the author has not missed any
| implicit dependencies. I like to imagine it's also useful
| for the authors as a feedback, whether they use Nix or
| not.
|
| > I realize that you don't want to be storing mountains
| of data in the nix store, but it would work just as well
| if the output in question is an IPFS CID, to be resolved
| during the build instead.
|
| I maintain separate build serves of my own using Nix
| integrations and the Nix cache is quite large already (so
| called remote builders) sitting at around 500GB. I host
| these at Hetzner.
|
| I have also thought adding IPFS integration for my
| website, but haven't got around to it.
| __MatrixMan__ wrote:
| > I happen to be a reviewer for software artifacts in a
| scientific journal
|
| That's very cool. I have a question for you.
|
| I'm taking a bioinformatics class, despite not having the
| chemistry prerequisites. I'm getting a crash course in
| biochem, and the rest of the class benefits from having
| an expert in what-kind-of-quotes-to-use.
|
| I've been thinking: would it be helpful if the care and
| maintenance of these compute environments wasn't left to
| each scientist but was instead aggregated (perhaps per-
| class or per-university)?
|
| We're setting these chemists up with conda in Ubuntu in
| WSL in a terminal whose startup command activates the
| conda environment. Not exactly a recipe for
| reproducibility after they get a new laptop.
|
| What if certain compute-heavy classes published flakes
| which the students could...
|
| a) use while taking the class so we stop wasting time on
| troubleshooting ssl deps via conda
|
| b) reference in publications after the fact. They could
| say:
|
| > Here's a Jupyter notebook, download it and run it in
| the UCCS biochem environment like so: `nix run
| github:UCCS/CHEM4573?rev=16afd67`, its output lets us
| make the following conclusions...
|
| I know it would be helpful for the students in the class.
| Do you think it would be helpful to them later on when
| they were publishing things?
|
| I'm thinking about packaging the dependencies for this
| class, giving it to the teacher, and pitching it to the
| university:
|
| > Set up a technical fellowes program. Waive tuition for
| us nerds and in exchange we'll support your students and
| faculty through the maintenance of these environments.
|
| I don't mind paying tuition so much, but I'd like to do
| something to get a bit more cross pollination going
| between scientists in need of tech support and techies in
| need of something meaningful to work on.
|
| Am I dreaming here, or would it solve some problems? Do
| you think I have a shot at convincing anybody?
| Jhsto wrote:
| Couple of thoughts:
|
| > I've been thinking: would it be helpful if the care and
| maintenance of these compute environments wasn't left to
| each scientist but was instead aggregated (perhaps per-
| class or per-university)?
|
| This is definitely something that Nix can abstract quite
| well. In my company we have [an infrastructure of
| computers](https://github.com/ponkila/homestaking-infra)
| that we manage with NixOS. We have gone over the system
| such that `cd` into a directory "conjures" the
| environment using devenv or direnv. We don't do anything
| too fancy yet, but we have a project commencing next
| month in which we start to also manage routers this way.
| We speculate that this will help us to do things such as
| follows: register new node, and it gets automatically
| imported by the router which establishes DNS entries and
| SSH keys for each user. The idea is that we could have
| different "views" of the infrastructure depending on the
| user which the router could control. For administrators,
| we have a separate UI created with React that pulls NixOS
| configuration declarations from a git repository (note:
| these don't have to be public) and shows how the nodes
| connect with each other. The UI is still under
| construction, but imagine this but now with more nodes:
| https://imgur.com/a/obBfRk0. We have this set up at
| https://homestakeros.com.
|
| Depending on a project you are working on, you could then
| have a subset of the infrastructure be shown to the user
| and have things such as SSH aliases and other niceties
| set up on `cd` in. When you `cd` out, then your view is
| destroyed.
|
| We have quite overengineered this approach -- we run the
| nodes from RAM. NixOS has the idea of "delete your
| darlings" which is having a temporary rootfs. We have
| gone the extra mile that we don't even store the OS on
| the computer, the computers boot via PXE and load the
| latest image from the router (though any HTTP server will
| do, I boot some from CloudFlare). We do this because it
| also forces the administrators to document changes that
| they do -- there is nothing worse than starting to call
| up people when theres is downtime and try to figure your
| way back up from what the mutations are. PXE booting
| establishes a working initial state for each node -- you
| just reboot the computer, and you are guaranteed to get
| into a working initial state. I'm personally big on this
| -- all my servers and even my laptop works like this. We
| upgrade servers by using kexec -- the NixOS
| configurations produce self-contained kexec scripts and
| ISO images for hypervisors (some stakeholders insist on
| running on Proxmox). I've suggested some kernel changes
| to NixOS which would allow boostrapping arbitrary size
| initial ramdisks, because otherwise you are limited to
| 2GB file size.
|
| > We're setting these chemists up with conda in Ubuntu in
| WSL in a terminal whose startup command activates the
| conda environment. Not exactly setting them up for
| reproducibility if they ever move to a different laptop.
|
| Python in specific is a PITA to setup with Nix, dream2nix
| etc., might help but it's definitely the hardest
| environment to set up of all languages I've tried -- even
| GPGPU environments are easier. Oftentimes, the only
| problem is not the packaging, but also the infrastructure
| used. For that, you could also publish the NixOS
| configurations and maybe distribute the kexec or ISO
| images.
|
| A notable thing is that devenv also allows creation of
| containers from the devShell environment, which may
| further help your case. Researchers could reference
| docker images instead of insisting on everyone to use
| Nix.
|
| In any case, I put some emails on my HN profile so we can
| also take the discussion off platform -- we are looking
| for test users for the holistic approach using PXE, and
| we are currently funded until Q3 next year.
| NGRhodes wrote:
| Not sure on your issue with reproducibility using conda
| is. We (team of RSE working with many researchers) have
| had good success with storing conda environment files in
| git along side the code, only a few commands to get a
| working environment. We provide class room training to
| researchers and provide the training material and
| environments this way.
| theK wrote:
| Reading through your link I caught myself thinking if I
| would put up with all those boilerplate nix steps just to
| add a new page to the site.
|
| Don't get me wrong, I get that you gain big amounts of
| flexibility out of it the way you do it but if we think
| about the tasksat hand, adding a page to a predefined
| blog, it seems a bit involved.
| Jhsto wrote:
| A fair comment, I do not disagree. I do plan to one day
| do an `ls` command on the root Nix file so that the
| manual update to the root flake for both the inputs and
| the RSS feed would be redundant.
| schemescape wrote:
| Not sure if it's a common pattern, but my solution to this was
| to always run a command that deletes all "unexpected" files,
| using GNU Make's "shell" function to enumerate files and the
| "filter-out" function to filter out "expected" outputs. Edit: I
| ensure this runs every time using an ugly hack: running the
| command as part of variable expansion via the "shell" function.
|
| Edit to link my Makefile: https://github.com/jaredkrinke/make-
| blog/blob/main/Makefile
| mftrhu wrote:
| Not sure if anyone actually uses it, but I would approach the
| problem with find, comm, and a sprinkle of sed:
| comm -23 <(find build -type f -iname "*.html" -printf "%P\n" |
| sed 's/\.html$//' | sort) \ <(find source
| -type f -iname "*.md" -printf "%P\n" | sed 's/\.md$//' | sort)
|
| The find commands get you a list of all the files (and only
| files - directories will have to be removed in a separate step)
| in each of the build and source folder, sed chops off the
| extension, while comm -23 compares them, printing only the
| files unique to the build folder, which you can then deal with
| as you see fit ( _e.g._ , by feeding them to xargs rm).
| hawski wrote:
| Using comm was exactly what I did use in my little experiment
| of a barebones SSG.
|
| I did save a list of generated files and compared them. This
| one liner is the meat of the whole solution:
| comm -23 <(awk 'NR>1' "$DSTDIR/build-info") <(find "$SRCDIR"
| -name "*$EXT" -type f -printf "%P\n" | tee >(gen_index) |
| xargs -n1 "$0" "$SRCDIR" "$DSTDIR" | sort | tee -a
| "$DSTDIR/build-info.new") | (cd "$DSTDIR" && xargs rm)
|
| Full source here: https://gist.github.com/hadrianw/060944011a
| cfcadd889d937b960...
| rustybolt wrote:
| > If there's a common workaround for this pattern in makefiles
| I'd love to learn it.
|
| "make clean"?
| dmd wrote:
| How does that solve the problem? That forces a total rebuild,
| which is exactly what he said he didn't want.
| rustybolt wrote:
| Yes, I didn't read properly.
|
| I guess you could do some magic to delete "unexpected"
| files, but are there tools which do solve this problem?
| IshKebab wrote:
| The cleanest way to do it is essentially "make install".
| You do all the heavy build steps into a build directory,
| and then the final stage is to delete the "output"
| directory and copy all the files you need there.
| Incremental builds should still be pretty fast since the
| only repeated action is copying files (and you could link
| them if you want instead).
| Karellen wrote:
| This is the way, because intermediate build artefacts
| also end up in `build/`. You don't want those in your
| `output/` directory, but you also don't want to delete
| them because they help speed up the incremental builds.
|
| Edit: `make install` also protects you against broken
| builds breaking your live site.
| cratermoon wrote:
| Conventionally, install puts the outputs in their where
| they will live for use. It does so in a way that 'make
| uninstall' will leave things as they were before install.
| The install target should also run any pre- and post-
| install commands. There's also a 'make dist' convention,
| to build a release tarball.
| bogwog wrote:
| I think the best solution is to use something like webpack or
| vite or whatever. These usually have their own dev server and
| can watch directories for changes.
|
| My personal site is also using a custom make-like ssg, but
| after spending a disproportionate amount of time writing the
| bundling/packaging code, I decided to just switch over to one
| of these tools. It's a solved problem, and it greatly reduced
| the complexity of my site.
| throwaway858 wrote:
| The shake build system (a general-purpose build system similar-
| to/better-than make) has a "prune" feature for exactly this
| purpose:
|
| http://neilmitchell.blogspot.com/2015/04/cleaning-stale-file...
|
| But I think the best solution (that also works with make) is to
| have a "make dist" target that creates a final .tar.gz archive
| of the result. If the rule is written properly then it won't
| contain any stale files. The disadvantage is for large project
| it may be slow, but you are not supposed to use this rule
| during development (where it is useless anyway), only for
| releases (which still can be built incrementally -- only the
| final .tar.gz needs to be created from scratch)
| jrm4 wrote:
| Interesting. So I'm a weird sort, I imagine, in that I'm the type
| that has been using Linux and shell scripts for 20+ years, but
| never actually done any big-time coding, and thus I really don't
| know "make."
|
| Point being, I do something very similar to this; except I first
| simply write/create my website in Zim-wiki, but then I have a
| bunch of little tasks to "clean up," i.e. fix/modify some links
| and then use the Canvas API to update my main course page (which,
| because I hate Canvas that much, simply links out to my own
| site).
|
| Why make instead of shell scripts?
| dahart wrote:
| As someone who also writes a lot of shell scripts and has for
| decades, I'd guess that if you learn just a little make, you'll
| find lots of non-coding uses for it and wish you'd learned it
| earlier. ;) It's just another great unix tool that is sometimes
| very handy to augment shell scripts when you need it, not
| unlike find+grep+sort, cut+join, awk+sed, gnu parallel, etc.. I
| think make is under-appreciated for its uses outside of code
| compilation. I use it anytime I'm making gnuplots, or doing
| image processing on the command line, for example. Whenever you
| have a batch of files to process, and the batch might need to
| re-run, and it transforms into other files or a single big
| file, then make may be the right tool
|
| Make has at its core one thing that would be pretty tedious to
| do in shell scripts: update the target (output) file _only_ if
| it's older than the prerequisite (dependency /input) file(s).
| This applies transitively to files that depend on other files
| that might change during the run of make, which is the part
| that really separates make from a shell script.
|
| The thing you do when the target needs updating is run a little
| snippet of shell script, so that part you already know.
|
| After learning how a rule works, you can combine it with
| 'pattern rules' to abstract a rule over all files that share a
| common prefix or common extension. Suddenly you have a loop but
| without any loop syntax, and can process a thousand files on
| demand with 2 lines of make - and without modification you can
| change a single input file, have it process only a single
| output file, and not waste your time re-running the 999 other
| files.
|
| Also pro-tip: make will run in parallel if you use -j, and it
| will do it without breaking any dependency chains. If you have
| a process that turns text files into sql files and then turns
| this sql files into html files (possibly nonsensical example),
| make running in parallel will not blindly update html files
| first, it will run parallel jobs in the correct dependency
| order. You can use make to build something like gnu parallel,
| but is able to resume a batch job that was interrupted in the
| middle!
| 0cf8612b2e1e wrote:
| My number one reason to use make is to have a single
| centralized location for project commands. If I see a Makefile
| at the root, I can quickly scan it and have an overview of what
| high level actions I might execute.
|
| Note that I have recently switched to Just
| (https://github.com/casey/just). While not technically the
| exact feature set as make, it covers all of the ground for what
| I typically do. It gets the benefit of history and discards a
| lot of make cruft to make a more predictable experience.
| aquova wrote:
| Makefiles honestly are just glorified shell scripts. Some of
| the syntax is a little odd, but you trade that for a more
| standarized format and the ability to add different build
| options without mucking around with argparse yourself.
| thaumasiotes wrote:
| > Makefiles honestly are just glorified shell scripts.
|
| Not really. The concept of a script is "do these things in
| this order".
|
| The concept of a makefile is "here are a bunch of things that
| might or might not need to be done, you figure it out".
| p4bl0 wrote:
| My personal website (https://pablo.rauzy.name/) used to be
| generated using a simple Makefile.
|
| Then I added features like news and an RSS feed, a way to
| automatically list my research publications and course materials,
| a list of books filterable with tags, etc. So now it still is a
| Makefile but the Makefile itself is a bit simpler than it used to
| be, but it calls a few Bash scripts that in particular make use
| of the awesome xml2 and 2xml utilities to be able to manipulate
| HTML in a line-oriented manner using the core utils (grep and sed
| mostly).
|
| On top of that I have a few git hooks that call make
| automatically when needed, in particular on the remote server
| where the website is hosted so that the public version is rebuilt
| when I push updates the repository there.
|
| It's been working like a charm for _years_! My git history goes
| back to 2009.
|
| EDIT: I just had a look at the first commits...
| beccad7 (FIRST_VERSION) Initial commit d1cc6d7 adding
| link to Google Reader shared items 6ccfd0c fix typo
| d337959 adding link to Identi.ca account
|
| ... 15 years have passed indeed.
| e12e wrote:
| > xml2 and 2xml utilities
|
| Seems somewhat abandoned?
|
| https://github.com/cryptorick/xml2
|
| https://manpages.debian.org/unstable/xml2/2xml.1.en.html
| enriquto wrote:
| s/abandoned/crystalized/g
| tannhaeuser wrote:
| If converting markup to/from line format is your thing to put
| awk, perl, and other line-oriented tools to use, there's also
| the ESIS format understood by traditional SGML tools and used
| by SGML formal test suites even.
| Kiuhrly wrote:
| Wow, this is almost exactly what I was planning to do for my
| site. For another small project, I wrote a tiny shell script as a
| makeshift "bundler" (just embeds the CSS and JS inside the HTML)
| with the goal of also being able to serve the unbuilt files
| locally: sed \ -e '/[/][/]script/r
| index.js' -e '/[/][/]script/d' \ -e '/ <script defer
| src="[.][/]index[.]js"><[/]script>/d' \ -e
| '/[/][*]style[*][/]/r styles.css' -e '/[/][*]style[*][/]/d' \
| -e '/ <link rel="stylesheet" href="styles[.]css">/d' \
| index.html
|
| The HTML contains something like this: <link
| rel="stylesheet" href="styles.css"> <style>
| /*style*/ </style>
|
| and the script just deletes the <link> tag and replaces the /
| _style_ / comment with the contents of styles.css. Definitely not
| my finest work but it worked well enough.
| TekMol wrote:
| What does make bring to the table here compared to a shellscript
| which loops over the files in the source dir?
| oftenwrong wrote:
| Make provides incremental execution of the build graph. It is
| aware of the dependency graph, and the state of inputs and
| outputs. It will (ideally) only execute the minimal build rules
| necessary.
|
| A shell script that checks file mtimes to determine what has
| already been built, and therefore what can be skipped, is close
| in spirit.
|
| Make variants like GNU Make have additional functionality, like
| automatic concurrent execution of parts of the build graph.
| jameshart wrote:
| "No exotic dependencies and nothing to maintain"
|
| Oh really?: sed -E 's|(href="$(subst
| source,,$<))|class="current" \1|' header.html | cat - $< > $@
|
| a sed script that modifies HTML fragments isn't _nothing_. And
| this just does _one_ thing that you might want to customize in
| the header for each page. It doesn 't do things like handle pages
| having different <title> tags. Every feature like this that you
| come up with becomes another thing to maintain, and another thing
| that can catch you out later. When you come back to fix this
| later, will you even remember what it's supposed to do?
|
| From a web publishing point of view, make and sed _are_ exotic
| dependencies. There 's not going to be a bunch of helpful
| pointers online to help you debug issues with using them for this
| purpose. When you google how to fix your sed regex to match
| specific HTML attributes and not match others, you're going to
| find stack overflow posts about Zalgo, not quick answers.
| [deleted]
| tyingq wrote:
| The syntax takes a little trial and error and usually finding
| real-world examples, but I like "make".
|
| I had one project that involved downloading a jdk, using it to
| build a project specific jre, patching some class files with
| local java sources, bundling it, etc.
|
| Without being a make expert, it took me a couple of hours of
| reading, finding examples, etc...but now I have the dependency
| stuff working perfectly. Where it now only re-downloads or re-
| builds things if something upstream from it changed, handles
| errors well and points out what broke, etc.
|
| All that to say, for some things, it's worth looking into for
| it's built-in dependency chain stuff. When you need to run
| arbitrary outside scripts/tools, it sometimes does things that
| other build tools can't (gradle in my case, couldn't easily do
| this, or at least I couldn't figure out how).
| dijit wrote:
| Make is _excellent_ for tasks where you have a file that needs
| to exist and steps that reliably cause it to exist.
|
| Excellent too for building a tree of things that depend on
| prior stages; in your example needing java to run a java applet
| which generates a file.
|
| the syntax takes some getting used to, but in those cases there
| is little better.
|
| But I do find people using it as a glorified task runner and it
| _works_ but it's quite possibly the least ergonomic tool
| available. - especially for things like making docker images,
| which I see extremely often
| maccard wrote:
| There's not really any better option though. Once you start
| setting environment variables, customising tagging, adding
| file prerequisites, handling building from a different
| directory (monorepo requiring access to shared resources),
| you need some sort of wrapper, with options, argparsinc and
| some rudimentary dependency checking. Make is a super low
| barrier to entry solution that with a small workaround (phony
| targets) gives you all of the above.
___________________________________________________________________
(page generated 2023-09-10 23:00 UTC)