---
layout: docs
permalink: /docs/stable-inputs/
title: 'Stable order for inputs'
---
If building your software requires processing several inputs at once, make
sure the order is stable across builds.
A typical example is creating an archive from the content of a
directory. Most filesystems do not guarantee that listing files in a
directory will always result in the same order.
Example Makefile
----------------
The following `Makefile` will result in unreproducible
builds[^sorted-wildcard]:
{% highlight makefile %}
SRCS = $(wildcard *.c)
tool: $(SRCS:.c=.o)
$(CC) -o $@ $^
{% endhighlight %}
Solutions:
a) List all inputs explicitly and ensure they will be processed in that
order.
{% highlight makefile %}
SRCS = util.c helper.c main.c
tool: $(SRCS:.c=.o)
$(CC) -o $@ $^
{% endhighlight %}
b) Sort inputs:
{% highlight makefile %}
SRCS = $(sort $(wildcard *.c))
tool: $(SRCS:.c=.o)
$(CC) -o $@ $^
{% endhighlight %}
[^sorted-wildcard]:
GNU Make used to sort the output of the [wildcard](https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html#Wildcard-Function) function until version 3.82.
Watch out for locale-related issues
-----------------------------------
When sorting inputs, one must ensure that the sorting order is not affected
by the system locale settings. Some locales will not distinguish between
uppercase and lowercase characters.
For example, `tar` will by default use the filesystem order when descending
directories:
{% highlight sh %}
$ tar -cf archive.tar src
{% endhighlight %}
A solution is to use `find` and `sort` but the following might still have
differences when run under different locales:
{% highlight sh %}
$ find src -print0 | sort -z |
tar --no-recursion --null -T - -cf archive.tar
{% endhighlight %}
The locale used to sort files must be specified to avoid any surprises:
{% highlight sh %}
$ find src -print0 | LC_ALL=C sort -z |
tar --no-recursion --null -T - -cf archive.tar
{% endhighlight %}
This might not be the only change required for [Tar and other archive
formats]({{ "/docs/archives/" | relative_url }}) as they usually embed more
metadata problems.