Readit News logoReadit News
Posted by u/mikewarot 3 years ago
Ask HN: Programming without a build system?
I'm an old MS-DOS / Windows programmer used to Turbo Pascal, Delphi, etc. The old days were simple, in that you compiled code, and gave it to your customers. Everything just works.

Now every time I try to learn something new... there's always a build system in the way, with MSTOICAL it was Autoconf, with switching to Linux, I couldn't get WikidPad to build on Linux, trying to build a lifeboat for Twitter, Python works, but then modules require builds that break.

Is it possible to have a system without Make or the like?

Alternatively, any good resources for the above?

tacostakohashi · 3 years ago
In your MS-DOS / turbo pascal example, there are no third party dependencies. There is just the platform and the libraries that come with the product when you install it, and your code built on top of that. In this scenario, you end up reinventing a lot of wheels in your own app code, although the advantage is that all the code does exactly what you want and nothing ever breaks due to some complicated dependency hell upgrades.

You can do this today with any newfangled languages, just avoid third party libraries, or at least use them as a last resort, and choose options that are stable.

Autoconf is just a complicated system for finding and detecting third party libraries. If an application just uses the standard library, the build system can be very simple and reliable.

Most of your pain is actually due to 'package managers', not build systems per se.

skissane · 3 years ago
> Autoconf is just a complicated system for finding and detecting third party libraries. If an application just uses the standard library, the build system can be very simple and reliable.

Another way to avoid autoconf is vendoring third party libraries. If they are open source, one could just use Git sub modules. You might need to call ‘./configure’ in the vendored library directory, but you don’t need to use autoconf for the application itself

monkpit · 3 years ago
> just use Git submodules

Easier said than done. I have never gotten submodules to work the way I want them to, and I’ve since abandoned the idea completely.

simplotek · 3 years ago
> Autoconf is just a complicated system for finding and detecting third party libraries. If an application just uses the standard library, the build system can be very simple and reliable.

It's slightly more than that.

Autoconf is a Makefile generator. It was designed to do system introspection and perform sanity checks, and configure projects so that they could be built and installed in multiple platforms.

It's always possible to switch back to Makefiles. You'd be foregoing sanity checks, abstractions that come for free, and you'd have to fill in the blanks left out by missing features such as what compiler I use and how to configure the compiler and how to put together Release and Debug builds and how to consume dependencies and where do I install the project.

Complaining about build systems is like complaining about a high level language: you might focus on the bloat, but you completely miss the extra work you have to reinvent the wheel and have to maintain it forever.

sverhagen · 3 years ago
Don't avoid third-party libraries. Unless you're some sort of genius you're constantly going to be reinventing existing wheels, whether it's networking, date, time, leap years, security stuff, and so on. And do you really need your own utility folder for manipulation of strings, lists, and the likes? And as soon as there's one thing you feel isn't worth or possible to build yourself, you need a dependency after all, back to square One. So I wouldn't search a language without a package manager or a build system, but find a good one. And then you may find a language/community with decent culture around their published packages (NPM sure has had its problems there).
II2II · 3 years ago
In the case of the examples you cited, the IDE was the build system. In most cases you were using libraries that shipped with the development tools, so it appeared to be easy to manage since everything was done for you. Using third-party libraries wasn't too bad either. It typically involved changing a couple of parameters in the IDE. From my limited experience with Visual Studio, the same can be said of it.

Much the same can be said of simple Makefiles. If you are targeting your own machine, you can create a couple of variables to track libraries and such then tweak them much as you would tweak the configuration of a traditional IDE. The trouble comes with creating software that other people will build or while building software created by other people. Linux (actually, Unix in general) is notorious for its inconsistencies: libraries and headers aren't always in the same place, sometimes libraries are missing, sometimes one library is used in the place of another. Tools like autoconf help developers to work around that. Of course, modern build systems go a step further by pulling in dependencies.

It probably wouldn't be much of an issue, except for one thing: everyone seems to have their pet build system.

gingerBill · 3 years ago
Odin is a programming language without any silly complex build system, it is as simple as "odin build .", even for large projects.

Linking is done by describing it as part of the code with its `foreign` system [1][2]. The benefit of this approach is that your code itself describes what needs to be linked against what. It also has the benefit that if you don't use a foreign library, it doesn't get linked against due to its minimal dependency system.

If you want to see huge examples of this, I recommend checking out the vendor library collection[3].

n.b. I am the creator of Odin, and one of the original goals was to create a language that didn't necessitate a complex build system and just get to programming. Requiring a complex build system and package manager are anti-features in my opinion and make programming a worse experience to use. Odin borrows heavily from (in order of philosophy and impact): Pascal, C, Go, Oberon-2, Newsqueak, GLSL.[4]

Niklaus Wirth and Rob Pike have been the programming language design idols throughout this project.

[1] https://odin-lang.org/docs/overview/#foreign-system

[2] https://odin-lang.org/news/binding-to-c/

[3] https://github.com/odin-lang/Odin/tree/master/vendor

[4] https://odin-lang.org/docs/faq/#what-have-been-the-major-inf...

CPUTranslator · 3 years ago
+1 for Odin. It's a very nice language to use, very rarely has bugs in the compiler, and has never required more than an 'odin build .' to build my projects. It does a lot of things right and removes a lot of the cruft of other languages.
satellites · 3 years ago
In the rare instances where you do have bugs in the compiler, have you been able to resolve them reasonably? Or is it deeper language issues that you then have to work around? Not trying to poke holes; it seems really cool and I want to try it myself soon.
svnpenn · 3 years ago
Odin has poor support for Windows:

https://github.com/odin-lang/Odin/discussions/2047

_gabe_ · 3 years ago
This issue is asking Odin to move away from Visual Studio (by which I assume they just mean the MSVC toolset), which is by far a highly preferred environment for C++ programming on Windows[0]. Saying it has poor support for windows because of this is a bit hyperbolic at best and misleading at worst.

Additionally, the issue has a build script using a different compiler and the asker basically said it wasn't good enough for them.

[0]: https://www.jetbrains.com/lp/devecosystem-2021/cpp/

According to this survey, Visual Studio is preferred by 24% of respondents, just behind VsCode and CLion. And MSVC is the 3rd most popular compiler, just behing gcc and clang. And keep in mind these results are across all C++ developers, not just windows developers.

throwup · 3 years ago
That issue doesn't justify saying it has poor support. Rust is known to have excellent support for Windows, and has the exact same dependency.
hawski · 3 years ago
For simple C or C++ programs I add this snippet at the beginning of the file:

  #if 0
  set -e; [ "$0" -nt "$0.bin" ] &&
  gcc -Wall -Wextra -pedantic -std=c99 "$0" -o "$0.bin"
  exec "$0.bin" "$@"
  #endif
Then make the file executable and you can use it like a script. All the flags are just there and visible.

However it would be preferable to just have a smart enough language tooling to do it without such tricks.

monocasa · 3 years ago
tcc also allows you to run C with

    #/usr/bin/tcc -run
at the beginning of the file. I use that all the time while prototyping C.

stefanos82 · 3 years ago
Very nice!

One question if I may: how can I erase "$0.bin" after its execution?

kardianos · 3 years ago
Yes. Look into Go. Between the conversions and source placement, the built-in "go" tool understands source placement and how to compile everything. No configuration, project file, Makefile, Autoconfig, Configure file needed.
zbentley · 3 years ago
Well, there's still a build system (and an opinionated one!) in the mix, it just happens to be vendored into the same executable that provides the language/compiler. And that's great! A lot of folks like that tight integration.
denton-scratch · 3 years ago
So the solution to this guy's problem with build-systems is to use a different language? (Not just you, several commenters have proposed that solution). It's a bit like saying "Oh, that's because you're using Linux; get a better OS".
spfzero · 3 years ago
Well, he did mention he had tried a few different languages, so maybe they're actually looking for a some of these suggestions?
readme · 3 years ago
it is a solution to his python grievance somewhat

having a decent standard library saves you from needing to use a bunch of 3rd party modules that may or may not need to be compiled

adinisom · 3 years ago
Can confirm.

I don't program in Go but when there's Go software that needs fixing, it's so much easier to "go build" it and fix bugs in this unfamiliar language than it is merely to compile software written in many more familiar languages. Build systems that just work is a huge advantage.

sidlls · 3 years ago
Make still helps with go, if for no other reason than to simply provide shortcuts (e.g. `make test` instead of the `go test` command with all its options one has to type out. The Makefiles are generally quite simple, though.
monkpit · 3 years ago
That’s not really any different than a shell script, right?
CPUTranslator · 3 years ago
If you can get into the beta, the Jai programming language by Jonathan Blow ticks the box of "no build system required." With how the build system is managed (just running arbitrary code at compile-time that modifies the build process), I can do this 99% of the time:

  #run compile_to_binary("name_of_binary");
  
  main :: () {
    // ...
  }

  #import "base"; // my own library that has 'compile_to_binary'
I'll go into depth about what this does, but if you're not interested, skip to the final code snippet.

The above code '#run's any procedure at compile-time (in this case 'compile_to_binary' which is defined in the library I imported). That procedure (really a hygienic macro) configures my 'workspace' to compile down to a 'name_of_binary' executable in the current directory. Any third-party libraries I've imported will be linked against automatically as well.

To do this without a dedicated procedure, just put this in the same file as 'main':

  #run {
    options: Build_Options_During_Compile;
    options.do_output = true;
    options.output_executable_name = "name_of_binary";
    set_build_options_dc(options);
  }

  main :: () {
    print("This is all I need to build a project\n");
  }

  #import "Basic";
  #import "SDL"; // or whatever...
Then compile:

  jai above_file.jai
I've done this for projects with hundreds of files that link in SDL, BearSSL, etc.

The best part is neither of these systems are a requirement to build your project. Running the compiler against a Jai file will do everything I do with my own system (I just like having the ability to configure it in code).

Jai has been a breath of fresh air in terms of "just let me write code," so I highly recommend it if you can get in the beta.

BrS96bVxXBLzf5B · 3 years ago
If you can get into the beta. I'm a ten year C++ programmer and focus a lot on games but my dove's song didn't reach Jonathan Blow's ears, or something. I fear I might not be the "right" demographic. Which is disappointing.
CPUTranslator · 3 years ago
I'd say to give it another go. There's a wide range of demographics in the beta, so it could've just been sent at the wrong time! Invites come in waves, usually at the release of a new version, so it could be a month or so before you get a reply.
zbentley · 3 years ago
I think you end up needing automations past a certain project size no matter what (for several reasons; the three largest are discrepancies between test/build and deployment environments, dependency management, and asset transformation if your ecosystem needs that sort of thing; others in these comments have gone into the "why" extensively).

But! I think the "can I get by without needing $big_build_toolchain?" question is excellent, and would recommend that you start by building automations yourself. That means writing small programs (often shell/batch scripts) to smooth over repetitive parts of your build/packaging/deploy process.

That approach yields a ton of understanding about how build/transformation/delivery software work with your platform of choice, and that understanding in turn makes you a way better programmer in a ton of different ways.

Now, this doesn't mean that you should stick with home-rolled automations forever; past a point, they become more or less equivalent to others' build systems and you can switch if you like. But switching to something from a position of full understanding of what it provides is a much easier and friendlier process than "I have to use tools A, B, C, and D just to get 'hello world' working, and don't know what any of those do".

I'd recommend this approach to anyone with the time; it really confers a lot of understanding and confidence. And if you don't have the time/you need a prototype deployed yesterday, don't worry about it; copy the Medium article snippets and learn what the tools actually do some other time--just try to make sure "some other time" isn't "never".

spfzero · 3 years ago
I think this is an excellent suggestion. When you do switch to a full build system you'll be able to troubleshoot any issues a lot faster.
bitwize · 3 years ago
It's perfectly cromulent to write software without a build system -- not even Make. Just write a build.sh script that compiles all the source and links it for you.

But the reality is you'll be giving up the features Make or another build system provides -- things like recompiling only the files that need recompiled, or, more fancily, automatic build configuration and dependency discovery.

When you were building on DOS or Windows, your Borland IDE or whatever handled these details for you. In the Unix world, everybody relies on a constellation of small tools to handle different aspects of the build process rather than just entrusting that to their IDEs.

I bet you can get Clion (C, C++) or Lazarus (Pascal) to work the way you remember Turbo Pascal working. But those only work for their respective languages.

If you really want to go whole hog, vendor any dependencies you have. That is, incorporate them into your project and build them all at once. That way you don't have to worry about builds breaking on systems that don't have them.