INPUT := a.tif b.tif c.tif d.tif e.tif

# This is how you could use gdal_merge.py to combine all the input files
# BUT: gdal_merge.py loads them all into memory first, so it can exceed your system memory very easily!
.ONESHELL:
all.gdal_merge.tif : $(INPUT)
 	gdal_merge.py -o $@ -of GTiff -co TILED=YES -co COMPRESS=LZW -co TFW=YES -co BLOCKXSIZE=128 -co BLOCKYSIZE=128 -co NUM_THREADS=ALL_CPUS -ot UInt16 -n 0 $^

# gdalwarp does not suffer from this limitation, but is a bit harder to use, so here's how I do it in a Makefile
all.gdalwarp.tif : $(INPUT)
	# First process has -overwrite (to ensure this won't append to existing file) and the creation options
	gdalwarp -r near -srcnodata 0 -multi -wo NUM_THREADS=ALL_CPUS -q -of GTiff -co TILED=YES -co COMPRESS=LZW -co TFW=YES -co BLOCKXSIZE=128 -co BLOCKYSIZE=128 -overwrite $< $@
	# Subsequent files append to the output of the first process
	$(foreach f,$(filter-out $<,$^),gdalwarp -r near -srcnodata 0 -multi -wo NUM_THREADS=ALL_CPUS -q $f $@;)
