Live data from Hacker News

A Tutorial on Portable Makefiles

nullprogram.com

101–110 of 114 posts

Re: A Tutorial on Portable Makefiles

#101
post #46

Earlier quoted context omitted.

What you're mulling over is the precept for the autotools toolchain.. spare the next generation the same pain we bore :)

carussell is suggesting the opposite of autotools in the sense of making a very restricted tool that only allows portable code (at least within the domain of that tool). By contrast, autotools tries to be expansive in many ways (1) it provides all kinds of bits and pieces of the toolchain, (2) it tries to support all systems by auto-generating build scripts using sniffed the system properties.

Particularly when it's used in combination with gnulib, which has an irritating tendency to build most of glibc if it doesn't recognize your build environment.

Re: A Tutorial on Portable Makefiles

#102

Earlier quoted context omitted.

The author of the blog post you linked to talked a lot about redistributing generated files, and I assumed you linked to it because you agreed with the opinions he expressed. After moving the project folder to a new location you just have to rerun the cmake command to update the project files. CMake attempts to do this automatically when you build.

[A] >>>>>> I just wish it would work with relative paths. It shouldn't break your build to move a folder around. [B] >>>>> AFAIK cmake works perfectly fine with relative paths; what breaks? [A] >>>> I don't think it works: https://ofekshilon.com/2016/08/30/cmake-rants/ [C] >>> it makes no more sense to distribute the project files [A] >> Nobody was talking about redistributing anything. I just said I should be able t…

Actually, I think the reply was basically on target... The complaint in the section of the linked article that APPEARS to be relevant to throwaway613834 is "CMake’s treatment of paths", which is all about the fact that build artifacts of cmake have absolute paths. Build artifacts of cmake, however, are build _output_ and thus shouldn't be relocated, distributed, or checked in (I would argue relocation is a form of redistribution, it's just the simplest possible case). These build artifacts are the output of a specific build, thus they are (as pointed out) a lot like .d files which I also would expect regenerate in the new build environment post moving/modifying. Just like with .o/.d, I would expect to move/distribute/checkin after cleaning these build artifacts, and then regenerate them afterwards. Since this is pretty simple to do, I'm not sure it's worth such a long section in this blog. This is even pointed out (a couple times) in the blog comments. The author also even references why it works this way as a default: "It is really hard to make everything work with relative paths, and you don’t get that much out of it, except lots of maintenance issues and corner cases that do not work." Unless you have spent a while deep-diving into the issues, wouldn't it be prudent to accept the word of the maintainers as pretty close to canonical?

Re: A Tutorial on Portable Makefiles

#103
post #84
post #14

Earlier quoted context omitted.

I'm missing something. Are you saying you want to be able to compile either way /usr/include/stdio.h and /usr/local/include/stdio.h, but remember what the last compilation used and know what header would be used in the next compilation, and if it's different, mark the target as stale and perform the action? I guess you'd need to keep a log of the build and test cpp invocations for diffs. I've never run into this scen…

An obvious case would be a developer supporting multiple versions of a 3rd party library.

This is where I saw the beauty of including dependencies w a project. Even on my own systems, as environments change, things break, and having a stable in-tree reference had paid off.

It's a tough situation, but I find myself leaning to @tedunangst position over the years - usually I try to adapt my machines (incl software) to my needs, but this case I need to take control/responsibility, and here be dragons. Does cmake actually solve this? Do other build systems?

Re: A Tutorial on Portable Makefiles

#104

> Microsoft has an implementation of make called Nmake, which comes with Visual Studio. It’s nearly a POSIX-compatible make, but necessarily breaks [...] Windows also lacks a Bourne shell and the standard unix tools, so all of the commands will necessarily be different. What I've been mulling over is an implementation of make that accepts only a restricted subset of the make syntax, eliding the extensions found in ei…

> What I've been mulling over is an implementation of make that accepts only a restricted subset of the make syntax, eliding the extensions found in either BSD and GNU make

> every bake script is a valid Makefile, which means it is make (albeit a restricted subset).

What do you think about writing a Makefile linter, like `shellcheck` is for shell scripts?

Re: A Tutorial on Portable Makefiles

#106
post #97
post #88

Earlier quoted context omitted.

If an apt-get upgrade fixed an issue in a system header or a library, but the date of the fix predates the last build (quite common; last build from yesterday, fix from two days ago but downloaded today) then make will do nothing (or any subset of the right things but not all) and make clean; make will do the right thing. Relying on time stamps is a design decision that was good for its time, but it is no longer robu…

Typically if a system header has changed or been added due to upgrading a library package you'll need to rerun any configure script anyway (since it very likely checks for header features and those decisions will change). So unless your build system magically makes configure depend on every header file used in every configure test it runs, you'll need to redo a clean build anyway, pretty much. Make has a whole pile o…

apt-get upgrade does not usually upgrade a package, despite the name; 99.9% of the time it applies a bug or security fix, almost never changing any functionality or interface - and would result in the same config script.

And that assumes you actually have a config script, which is also a nontrivial assumption.

Djb redo lets you track e.g. security fixes that change libc.a if you are linking statically, but that's not usually done.

The only build system I know that guaranteed a rebuild whenever and only when it is needed is tup. (Assuming you have only file system inputs)

Re: A Tutorial on Portable Makefiles

#107

Earlier quoted context omitted.

But there's no way in POSIX make itself to assign a value to FILES dynamically - you have to assign the FILES environment var or supply via command line args. POSIX make will expand ${FILES} by the replacement value in commands (and prerequisites but not targets). It then merely happens to be interpreted as part of the command it's placed into.

Updated, thank you. Assigning the results of a command to a variable is not POSIX Make. However, both FreeBSD's Make and GNU Make support it. There's the proposal to add it to POSIX Make: http://austingroupbugs.net/view.php?id=337 Another thing I wanted to add to the main post: since POSIX Make doesn't have conditionals, GNU Make and bmake both have different ways of doing them. If you look through FreeBSD's Make fil…

POSIX Make supports conditional constructs by way of recursive macro expansion. I've found it to be not much more clunky than GNU Make's conditional constructs. (Recently I've come to appreciate the simplicity and consistency of the BSD extensions, even though I don't use them. GNU Make syntax quickly becomes impenetrable.) And as you say, shell invocation from macros isn't yet supported by POSIX but _can_ be done portably. GNU Make supports $(shell COMMAND), everybody else supports $(COMMAND:sh), nobody supports both, and where not supported they expand to the empty string.[1] Here's a simplified example from my proof-of-concept library from https://github.com/wahern/autoguess/blob/config-guess/config...

  BOOL,true = true
  BOOL,1 = true
  BOOL,false = false
  BOOL,0 = false
  BOOL, = false

  OS.exec = uname -s | tr '[A-Z]' '[a-z]'
  OS = $(shell $(OS.exec))$(OS.exec:sh)
  OS.darwin.test,darwin = true
  OS.is.darwin = $(BOOL,$(OS.darwin.test,$(OS)))

  # Usage: $(SOFLAGS.shared) - for creating regular shared libraries
  SOFLAGS.shared.if.darwin.true = -dynamiclib
  SOFLAGS.shared.if.darwin.false = -shared
  SOFLAGS.shared = $(SOFLAGS.shared.if.darwin.$(OS.is.darwin))

  SOFLAGS = $(SOFLAGS.shared)

  show:
  	@echo "SOFLAGS=$(SOFLAGS)"
I try to keep my stuff portable across AIX, FreeBSD, Linux/glibc, Linux/musl, macOS, NetBSD, OpenBSD, and Solaris. I used to just require GNU Make, with makefiles that looked like:

  .POSIX:

  all:
          +gmake -f GNUmakefile all

  .DEFAULT:
          +gmake -f GNUmakefile $
but now I'm moving my projects over to the more portable, dependency-less method. It makes things so much easier to be able to run `make test` without having to worry about first installing unnecessary dependencies, or often any dependencies whatsoever. When you're juggling a dozen VMs, trying to track the latest couple of releases of a platform, simplicity is key. Plus, more easily programmable environments encourage overly complex solutions which become maintenance burdens over months and years. With GNU Make I was always unable to resist the urge to turn every repetitious rule into a template, for example. Sticking to purely portable constructs means I'm forced to be smarter about how to approach something, including recognizing when something is best left un-automated.

[1] It's nice that POSIX will be formalizing the "!=" construct, but unfortunately it's not supported by Solaris make, and macOS will be forever stuck on GNU Make 3.81 which also lacks support.

Re: A Tutorial on Portable Makefiles

#108
post #91
post #90

Earlier quoted context omitted.

Meson ( https://www.mesonbuild.com/ ) seems to have a lot of momentum; GNOME has just adopted it. It is designed around a non-Turing complete, object-oriented DSL, plus extension modules written in Python.

Beyond being adopted by GNOME, I have hardly heard of it being used in another context.

systemd, Wayland and Xorg are switching too.

Re: A Tutorial on Portable Makefiles

#109

Earlier quoted context omitted.

> But speaking as a former FreeBSD user, this is pretty easy to figure out after your first time seeing the flood of syntax errors. I seem to be about the only person that makes use of the following feature, but FreeBSD and GNU make will in addition to looking for a file named Makefile, also look for BSDmakefile or GNUmakefile respectively. So when I write a makefile with GNU make specific contents, I name it GNUmake…

Nowadays I write a GNUmakefile, then add a Makefile with a message telling people to use gmake. Same idea.

i have this in a (hand-written) configure script:

    case "$(uname -s)" in
    Darvin|Linux)
      MAKE=make
      GMAKE=$MAKE
    ;;
    DragonFly|*BSD)
      MAKE=make
      GMAKE=gmake
    ;;
    *)
      MAKE=gmake
      GMAKE=$MAKE
    ;;
    esac

    ...

    if test "$MAKE" != "$GMAKE"; then
      case "$(uname -s)" in
      DragonFly|*BSD)
        populate $rootdir/Makefile.in Makefile
      ;;
      esac
    fi

    cat 
$rootdir/Makefile.in contains

    all .DEFAULT:
      @@GMAKE@ --no-print-directory "$@"

Re: A Tutorial on Portable Makefiles

#110
post #81
post #76

Earlier quoted context omitted.

CMake is rather crufty itself. There are many better options these days.

I would love for this to be true, but I'm afraid I don't have any evidence that it is. What are the better options you'd recommend? More specifically, Google's Bazel [0] is the most serious attempt I know of to replace CMake/autotools, but it only just began to support Windows [1] and requires the JDK. Say what you will about CMake, but it's a quick-and-easy MSI to install on Windows and has supported Windows for pro…

Boost.Build and QMake are two relatively popular choices that are mature and stable.

I have particularly noticed the uptick in QMake usage in OSS projects lately, probably because it is so straightforward to use for the most common cases. I think it's not more popular than it is only because it's associated with Qt, and many people (wrongly) assume that it can only be used for Qt apps, or that it depends on Qt.

Post reply on HN