We fulfill power fantasies

RSS Feed Back

Crossplatform makefiles (Nmake and GNU Make)

5.8.2019 19:49:37

Here's a handy little cross platform makefile tip I came across recently. The original tip is from user Bevan Collins on StackOverflow. Thanks to him! This tip is useful if you need build stuff using nmake on Windows and GNU Make on what ever platform(s) you're using it on. Heck, it may work with other make implementations, too.

We're going to need 3 files in the same directory:

  • nmake.mk
  • gnu.mk
  • Makefile

Now start your Makefile with the following lines.

# \
!ifndef 0 # \
include nmake.mk # \
!else
include gnu.mk
# \
!endif

Next, place any Nmake-specific variables in nmake.mk and GNU Make specific variables in gnu.mk. You'll want to at least define a variable for the path separator (slash or backslash) and use it for any file paths (I just name the variable 'S').

  • For *nix: S = /
  • For Windows: S = \\

Finally, place all your build targets in the Makefile. Done!

Bevan's include code, as he explains, works because GNU Make recognizes the symbol \ as a line continuation even in comments where as Nmake doesn't.

Why can't we just use ifdefs you ask? That's because conditional statements use different keywords in Nmake and GNU make: nmake ifdef instructions start with an exclamation mark where as GNU make ones don't.

The unfortunate thing about this approach in comparison to two separate, platform-specific makefiles is that you won't be able to benefit from parallelization on Windows if you simply build the same targets on both platforms. That's because while GNU make has the -j flag to process multiple targets in parallel, Nmake lacks similar functionality. If you want to create parallel builds using cl (the Microsoft compiler) on the command line, you must do so at the compiler level (/MP), which means the makefiles' targets are going to inevitably look a little different. If your project isn't too big though, you're unlikely to benefit much from parallel building on Windows - I rather take the maintainability of a single Makefile than that. And I still get to keep away from awful, overly complicated build systems like CMake.