Making Native Language Support (NLS) and gettext Optional
I’ve decided to write this blog post after noticing how many people were asking me to make gettext
optional when building fswatch
. At the beginning I actually thought it was optional. And I never dug any deeper into the matter because, apparently, everybody experiencing this problem was building fswatch
from the repository sources instead of building it from a release tar-ball. I would typically answer to build the release tar-ball instead and I would hear no more complaints.
Making gettext
optional is easy, and should be a best practice when writing a piece of software. However, I’ve seen so many questions in the Internet about this topic that I’ve decided to write a blog post where I would outline the reasons why you should do it and how you should do it using the GNU Autotools.
So, What’s the Issue With Building From Repository Sources?
Actually there’s no issue. But probably many people asking that question don’t know how the Autotools work. Autoconf is a tool whose goal is producing scripts (the ubiquitous
configure
script) that configure the source code before building it to adapt it to the characteristics of the current system. In a typical flow the user does nothing but running configure
. The script will run and will test for the presence of all the features requested by the author. The presence of a feature, or its lack thereof, can then be used to parametrise Makefiles
, or more generally, be used to conditionally drive the execution of other tests or scripts.
The Autotools are not required by end users. The scripts generated by the Autotools are fully independent from them. These script are then bundled with the sources (in a
distribution) which is often called a release tar-ball.
As you can see, the goal of the Autotools is making users’ life simple, not maintainers’. In fact, maintainers need to have the Autotools components they use in order to generate a distribution. These are the sources you typically find in a package repository such as fswatch
. That’s why you don’t find any configure
script in the source repository: it’s created when a release is created and a distribution is packaged.
Perhaps not surprisingly, GNU gettext is one of the components software authors may use conditionally. configure
would then check the build environment to detect the availability of all the required gettext
components and enable Native Language Support (NLS) if all checks succeed.
What’s Special About Gettext?
This Autotools overview doesn’t explain, though, what’s the issue about gettext
. If it’s just one of the many configuration checks performed by configure
, what’s the relationship with the Autotools and the repository sources? The answer is that gettext
provides a tight integration with the Autotools, in the form of ready to use Autoconf and Automake macros to support the gettext operations during a normal workflow, such as:
- Extracting strings from sources.
- Creating template files (POT files).
- Creating translation files (PO files).
- Updating template files.
- Merging changes into translation files.
- Compiling translation files into message catalogs.
- Shipping required files in a distribution.
- Installing message catalogs.
It goes without saying that the maintainers do need gettext
installed in their machines in order to be able to use these macros, to create the configuration scripts and to create a package distribution.
Making gettext Optional
To make gettext
optional, we have to perform at least these operations in the Autoconf configuration file (configure.ac)
:
- Use the
AM_GNU_GETTEX
T macro to check whether NLS should be used. If it should be used, theUSE_NLS
variable would be set to yes. - Create an Automake conditional to propagate this information to the
Makefiles
, perhaps using something in the lines of:
AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.19.4]) AM_CONDITIONAL([USE_NLS], [test "x${USE_NLS}" = "xyes"])</πρε> In the Makefiles, we have to leverage these information to:
- Conditionally distribute NLS-related files such as ABOUT-NLS:
if USE_NLS dist_doc_DATA += ABOUT-NLS endif
- Conditionally execute NLS-related targets. What I typically do is segregating all NLS-related stuff in a directory (
po
) which is conditionally processed by theMakefile
:
if USE_NLS PO_SUBDIR = po endif SUBDIRS = other_paths $(PO_SUBDIR)
All the other Makefile
fragments required to use gettext
, such as defining the LOCALEDIR
to load catalog files and linking against libintl
, do not need to be modified. Even if always adding @LTLIBINTL@
to LDADD
may seem odd at first, the Autoconf output variable LTLIBINTL
is documented to expand to an empty string when NLS is not being used.
# Prepare gettext-related symbols used by programs AM_CPPFLAGS += -DLOCALEDIR=\"$(localedir)\" # Link program against libintl if gettext is being used prog_LDADD += @LTLIBINTL@
Conclusion
This is all that’s required to make gettext
optional in your Autotools package. With these few changes, users will now be able to let configure
automatically determine whether to enable or disable NLS, and even disabling it using the --disable-nls
option:
$ ./configure --disable-nls
Published on System Code Geeks with permission by Enrico Crisostomo, partner at our SCG program. See the original article here: Making Native Language Support (NLS) and gettext Optional Opinions expressed by System Code Geeks contributors are their own. |