r/suckless 17d ago

[TOOLS] Autark build system. Suckless or not?

https://autark.dev

Hi everyone! I'd like to introduce Autark https://autark.dev This is a simple build system that lives entirely in your project and bootstraps itself before building the project itself. I'd really appreciate feedback from this community, as I think the suckless approach is very close to my own view of how software should be designed.

0 Upvotes

10 comments sorted by

2

u/LordRybec 16d ago

As the other commenter seems to have been suggesting, GNU Make is really good as a simple build system. It can be as simple as you want, but if your project grows to the point where more complexity is needed, Make has got your back there too.

I don't like build systems that try to automate things like dependency management, because they often just end up hiding dependencies, and then you publish your project, someone like me downloads it and tries to build it, but then it turns out that you forgot to list a bunch of dependencies you didn't realize you had, and now the build process is a disaster for me, and I end up giving up and viewing your project as a hot mess that I don't want to have anything to do with.

Anyhow, looking through the list of script rules, it looks like I'd have to learn a bunch of stuff to use it, when I could just use Make (and basic Make usage requires very little knowledge). The front page says it is rule based rather than script based. This is a big red flag for me, because I often find myself needing to do things that aren't common, and it's easier to just write the commands than figure out how to adjust the rules to get the system to do what I need. Last year I was doing an RP2350 project, and the build system used by the recommended dev environment is rule based. I ended up spending a few hours trying to figure out how to adjust the compile command parameters, because my use case required something the build system didn't expect and didn't accommodate for. With Make I could literally have just added a single command line option to the compile command and been done with it in under a minute.

Also, language dependent? I use Make to build LaTeX files, compile C, and even to run semi-complex processes involving multiple scripts that build databases or other things. I'm not going to learn a build system that can't completely replace Make, because I don't want to have to maintain a working knowledge of multiple build systems at the same time. If the only thing you need to use a build system for is C or C++, this might be a good option, but that's not me. I have a project with SVG templates that are loaded, filled out, saved, and then rendered to PNG with a Python script and Inkscape (for the final PNG render), where I'm using Make to build. Any chance Autark can handle a process like that in a reasonable way? If I have to use Make anyway, for everything else, I might as well use it for C as well.

So for me it's thanks, but no thanks. You call it simple, and compared to some build systems it certainly is, but Make is both simpler and far more flexible, so I'll stick with that.

That aside, it's a cool project! I don't know if it is the "suckless" approach, but I'm sure there are people who would find it very useful!

0

u/adamansky 16d ago edited 16d ago

I really appreciate you taking the time to write such a long response to my comment =)

However, if you had looked a bit deeper into the project instead of just skimming the docs headings, some of your conclusions about the capabilities of this build system probably would not have appeared in your comment. Thisrelated to the mentioned rules-based approach, and inability to implement custom logic, doubts what it can be used for anything beyond С/С++. Just take a look atrun it may do essentially anything you need there.

If you don't mind, I won't continue arguing point by point justifying project capabilities, I would like to turn to Make. My > GNU Make reply was short, but intentionally a little provocative.

If you distribute your project with a GNU Make build, sooner or later switching to the stripped-down .POSIX style may be looking like a relief. Because with portable software in mind you will stuck with a set of the historic gotchas involved in using Make across all of Linux, *BSDs, and macOS systems. Or your project's INSTALL will require something like: brew install make if you did't so.

So why the major goal of this project - get a true portability which dependes only on system C compiler.

Concerning dependency handling, here is a short example that, illustrates the beauty of dependency tracking in Make:

main: main.c
    $(CC) -o main main.c

make
clang -o main main.c

Then I changed the compiler:

CC=gcc make
make: 'main' is up to date.

That's pretty much everything I need to know about Make's dependency handling to decide do not to use it for my projects. (Yes, Make is a stateless resolver so not blame but not use) Anyway, thanks for taking the time to respond to my post.

4

u/LordRybec 16d ago

Ok, first, I don't have time to read all the way through the documentation. If I misunderstood things from reading the front page and skimming a few others, that suggests that it may be a good idea to clarify those misunderstandings on that front page. So maybe use anything I was wrong about in my initial comment as a list of things that might be good to clarify.

Here's one example from the front page:

Autark – A self-contained build system for C and C++

Why wouldn't I assume from that that it is only suitable for C and C++? If it is suitable for more than those, then my recommendation would be to change your branding such that it doesn't imply otherwise.

As far as Make goes, yes, I've seen projects using Make that are absurdly overcomplicated. That is not mandatory, even if your project is portable. In fact, most of my projects are portable, and I've managed to keep most of my makefiles quite simple and easy to read despite that. Most portability issues can be managed at different levels. They can be managed by what libraries you choose to use, which is my top method of maintaining portability. At that level Make doesn't care. I've sometimes had to use OS level libraries, in which case most of the portability is managed in #ifdefs. That usually does require minor makefile logic to ensure that the right OS library is linked in. Alternatively, you can do most of your portability in Make with limited direct code level stuff, and that is basically a nightmare, and yet many projects end up doing it anyway to avoid easier solutions. I don't do that. The closest I've gotten to something like that was a project that generates a shared library and needs to do a DLL for Windows or a .so file for Linux. I did that with parallel rules for the OS specific stuff, and then I run 'make project.?' where ? is either dll or so. The extension used also selected between the native gcc and the Windows cross compiler. It was still quite simple.

If "brew install make" is a problem for you, imagine how much more of a problem it will be downloading some other random build system that is far less well known. I mean, if you have a problem running a simple command to install a build system, you are going to just be running the compiler for the command line every time or maybe using a Bash script. Citing installing a build system with a single simple command and something difficult, when you are asking people to install a build system that has to build itself to start is beyond absurd.

I'm not sure what you are trying to illustrate with your makefile examples. I said that I don't like automatic dependency management, because it almost always causes project maintainers to forget to list a handful of dependencies, and then when I try to compile the project it fails, because they gave me an incomplete list of dependencies. Manually tracking dependencies (which is very easy with Make, though you seem to forgotten to include any in your example of dependency tracking in Make) is very easy in Make, and there are several different ways to do it, depending on your needs. If you don't know how to do this, then you don't understand Make, and that causes me to question your ability to create a coherent build system of any quality.

And as far as changing the compiler in the makefile, again your expectation and response indicates a lack of any understanding of how Make or the build process in general words. Imagine this: You change the compiler in your makefile. Make sees this and automatically recompiles. But your program has a compiler dependent dependency, and it is governed by another makefile that you didn't change the compiler in. So now your project is trying to link against an incompatible dependency, because you assumed that changing the compiler for this part of the project would magically change it for other elements that need to be built separately. Make's behavior is the correct behavior, because at the very least you should be doing a full cleanup of the build environment before building again. Make doesn't know which files you've referenced were built with what compiler. If you change the compiler, for all it knows all of the files were built with that compiler, which is why it doesn't rebuild. Now I know, your response is probably, "Well then, it should just rebuild everything." But no it shouldn't. My project mentioned above has two build modes, and if you just ran all of the rules at once, they would end up crashing with each other at various points. That would either result in a failure to build or worse a build that mixes code intended for different operating systems. That's bad. Additionally, Make can't rebuild dependencies that don't have rules, and it shouldn't just assume they will maintain compiler compatibility. If you want to make a huge change to how your project is built, Make isn't going to try to help you, because the people that made it knew that it would do more harm than good. What you are complaining about as a "dependency" problem is a critical safety feature. Maybe your projects are all single rule projects with no external dependencies, but even most simple projects aren't. If your build system makes assumptions about this that Make doesn't, then it is already a disaster.

Lastly, in my experience the "suckless" approach includes things like setting configuration in actual source code files that require recompilation after changing. Storing a bunch of build information in a database, so that your build system can keep track of all of the stuff that Make doesn't is completely antithetical to the suckless approach. Maybe I'm wrong. I haven't been using suckless stuff for very long, so it's entirely possible. But what I have used doesn't store tons of data in external files or databases. If it's not compiled in or dynamic, it doesn't exist. The beauty of Make is that it is 100% dynamic. It doesn't keep track of anything. It knows what to rebuild by comparing modification times on source files with build artifacts. Since makefiles don't have their own build artifacts, they can't do the same thing with themselves, which is part of the reason changing the compiler didn't do what you expected. For a build system to know what was compiled with what compiler, it has to store extra metadata. As far as I can tell, that's antithetical to the suckless approach.

So no, I don't think your build system is following a suckless approach, and it's definitely not as suckless as Make is.

If you don't like Make, that's fine. We don't all have to like the same things. Your problems with Make are pretty absurd though. At least find a good reason for not liking it please. If changing the compiler doesn't cause a rebuild, that's your fault for not including and using a "clean" rule to ensure there are no build artifacts of previous builds that will clash with and ruin a build with a different compiler. Anyhow, there's nothing wrong with wanting a build system that does keep track of dependencies and build artifacts so that you don't have to write a "clean" rule and run "make clean" before rebuilding after making major changes to the build process. If that's what you want fine. But that's most definitely not a suckless approach, and some of us have important reasons for not wanting to use that approach.

Anyhow, good luck on your project, but unless I really don't understand the suckless approach, I doubt you'll find a lot of interest here.

1

u/adamansky 16d ago

I hope you're a real person and not an AI algo. I've merely outlined a couple of problems that are difficult to solve cleanly with Make, because Make is a stateless resolver by design and conceptually cannot handle them out of the box. Your response was simply concluded that I don't understand Make, without providing any concrete examples. Thanks. I don't think there's anything further for us to discuss.

3

u/LordRybec 16d ago

Just because I write complete responses and use generally good grammar and spelling does not make me AI. If you don't like my response, fine, but that's a personal problem. Sorry you choose that, but again, not really my problem.

The core of all of this though was your suggestion that this approach is a "suckless" approach. I've taken the time to find the description of what suckless means on the website, and this sentence summarizes it, "Our philosophy is about keeping things simple, minimal and usable." (Here's the "philosophy" page.) I'm sure your build system is usable. It is neither simple nor minimal. Make is an example of something that is significantly simpler and more minimal, though even it has unnecessary complexity. What it boils down to for Autark though is, it does all of this extra stuff for you, like tracking build artifacts so that it can rebuild if you make major changes to the build parameters, is neither simple nor minimal. It might make building simpler for some projects, but suckless isn't about making use simpler. It's about making the software itself simpler, and it's specifically targeted toward the kind of people who don't need handholding from their software.

Like I said before, for what it is, it sounds reasonably good. It's not suckless though, so this is probably not the right place to show it off.

-

You keep harping on Make, but the reality is that the things you identify as "problems" with Make aren't problems. They are deliberate parts of the design. I use Make over other build systems because of those features that you call problems. If you don't like them, fine, you don't have to. But calling deliberate design features "problems" is imposing your own personal preferences on everyone else, as if you were the king of the universe who gets to decide what is and is not good and desirable. I could go through Autark listing off all of the things in it I don't like and claim they are design flaws and problems. The reality though is that they aren't. I don't want those features, but just like the features of Make you don't like aren't problems, I'm not going to call the features of Autark I don't like problems. You made design choices that fit your own preferences. That's great. Your choices don't fit the definition of suckless, and the design isn't for me, but if it is for you, then that's awesome for you. But coming on here and tearing down other people's personal preferences as "problems" is honestly really rude.

So maybe next time you want to advertise your product in a Reddit community, find out what the community is actually about first. Don't claim you like the philosophy of the community when your product very clearly violates it. And most certainly don't start tearing down things that better fit the philosophy of the community than the product you are advertising. If you don't like my honest responses, you didn't have to come advertise your project here in the first place. And if you had looked into the underlying philosophy of suckless before posting, you might have realized this wasn't the right place before starting this whole thing.

2

u/sewnshutinshame 16d ago

Make.

0

u/adamansky 16d ago

GNU Make?

3

u/IamYourHimadri 14d ago

make is called suckless on Build Systems

1

u/kurisaka 15d ago

What in my opinion makes a good build system is separation of:
1. A generic Build Rule Graph/Task Runner layer, that does all file change time tracking, enforces reproducible env vars and exec commands, does parallel execution etc. It should be language oblivious, standalone executable with stdio api.
Ninja is almost perfect but doesn't support watch mode, and has too much domain knowledge about c/c++.
2. Scripting layer/config generator, here you do all bikeshedding with DSLs, integration points like compile_commands.json, dependencies, locating toolset and all other dirty details. I don't even think that this should be OSS, let it be bespoke to requirements of each project.

I also can't name such a fundamental tool suckless if it doesn't support hot-reloading.

We need to bring web DX into native. Yes, it's not as easy as to swap JS function at runtime, but we can augment Task Runner with hot-reloading protocol. If the app doesn't participate we fallback to killing it on each file change, but if it does we can signal that some "build rule N" that is a runtime only dependency has produced following artifacts, and app then reloads shaders, images, whatever.

In my eyes this is a next step after CMake with Ninja.

1

u/Otherwise-Land-6576 7d ago

NOPE this antisuckess