AdSense Mobile Ad

Showing posts with label automake. Show all posts
Showing posts with label automake. Show all posts

Saturday, November 18, 2017

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_GETTEXT macro to check whether NLS should be used. If it should be used, the USE_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 the Makefile:
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




Tuesday, February 25, 2014

Creating an Apple XCode Project Using the GNU Build System (a.k.a. Autotools)

Some posts ago I wrote about two of the best portable C/C++ IDEs, NetBeans and Eclipse CDT, and their support for projects configured and built with the GNU Build System (a.k.a. Autotools). The only shortcoming of these IDEs is the lack of support for Apple frameworks and in another post I showed one possible workaround and provided the ZSH script I use, hosted on GitHub, to automatically create the soft links to include in the C/C++ include paths of your project.

Sometimes, however, it may be desirable to use Apple XCode instead of the aforementioned IDEs. Since there's no native support for the GNU Build System in XCode, some manual configuration must be performed to have XCode use the Makefile (and the other artefacts) generated by autoconf and automake for your project.

In this use case I prefer to maintain the sources completely separated from the XCode project. XCode lets you add references to the source files in a project, so that the physical location of either thing is irrelevant. Moreover, you won't risk polluting the sources with XCode-specific files and adding them by mistake to your source code repository.

Creating the project

First of all, an External Build System project must be created:

Create External Build System project

In the project options window, type the name of the project and your name: since the build is made using your autotools configuration files, these fields are irrelevant and are only used to label the XCode project:

Choose options for the project

Unless you want to use another make binary, you can leave the Build Tool path as is.

After setting up your project options, XCode will ask you the location where your new project must be created.

Configuring the Build Directory

As you know, the sources must be configured with the configure script (created by the GNU Build System) in order for them to be built on a specific platform. Since XCode has no knowledge of this mechanism, you must configure as a build directory a directory where the sources have been configured.

Once again, I prefer configuring the build on a separate directory, instead of doing it directly in the sources folder. This way, I do not pollute the source trees with object files and any other artefact created during configuration and build.

To configure your sources you must perform the following operations:
  • Go to the designated build directory of your XCode project (I usually create the build directory in the project root).
  • Run the configure script from your source root directory:
$ [sources]/configure [opts]

Now, the build directory path must be set into your project configuration:
  • Select the project root node in the Project Navigator pane.
  • Set the build directory in the Directory field, as shown in the following screenshot.

Project build directory

The configuration of the build directory is a one-time task for each target, no matter how many times you reconfigure the build in that folder. If you plan to have more than one kind of build, such as debug build and release builds (each one with different configuration options), just create multiple targets in different build directories (such as build/debug and build/release), each one configured separately. To create a new target in an XCode project, use the File/New/Target menu item.

Adding Sources to the Project

Your new XCode project will be empty and source files must be added to it. To add existing sources to your project you can use the Add files to [project-name] menu item in the File menu or in the contextual menu that appears when you right click over your project root in the Project Navigator pane. Alternatively, you can use the ⌥⌘A shortcut.

In the add files window, choose the files and/or the directories to be added. If you want to, you now have the opportunity to create groups or folder references for any added folders.

Build

Now you are ready to build your sources from XCode using the GNU Build System. And if you wonder where your build output is, in XCode the Log Navigator pane must be used.

Tuesday, September 17, 2013

C/C++ Project Built with GNU Build System (A.K.A. GNU Autotools): NetBeans vs. Eclipse CDT

Recently, I had to work on a C++ project built with the GNU Build System and decided to use the NetBeans IDE. I already use NetBeans for many Java EE projects and since it claims support for the GNU Build System it was natural for me to import the project there.

I encountered some issues due to the fact that the GNU Build System I was using was deployed in my home directory (OS X (1.8) ships old components which I could not use). To try to solve this issue, I decided to try Eclipse CDT.

Neither tool solved that problem, but I had the opportunity of working side-by-side on the same project with two widely used IDEs I never used for serious C++ programming before. After a couple of months I had a very clear idea about what each IDE offered me in this specific use case and made my final decision. This post is not a detailed comparison of all their features: first of all, because I believe that the "Eclipse vs. NetBeans" debate, even though in the C/C++ realm, is more a matter of taste rather than a matter of functionality. Secondly, because there is plenty of information on the internet. What I could not find, and that is the reason I am writing this blog post, is how these tools compare when the GNU Build System is part of the equation.

Both IDEs Claim Support for the GNU Build System

As stated in the introduction, both IDEs claim support for the GNU Build System and in fact I could build my project in less than 10 minutes in either IDE without previous knowledge. However, setting up my workspace with either tool was a very different experience.

Setting up the project in NetBeans was so easy that at first I thought it ignored the build system altogether. NetBeans imported the sources, configured my OS toolchain, detected the presence of autoconf and automake files, configured the project running configure and built it straight away.

Setting up the project in Eclipse CDT was easy, but not as straightforward as it was with NetBeans, the main difference being Eclipse CDT requiring manual intervention (a click, basically) to setup the GNU Build System in the imported project. On the bright side, as we will see, Eclipse CDT is much more configurable than NetBeans and offers you clean ways to configure how the build system is invoked.

Importing the Sources into a NetBeans Project

Importing the project sources into a NetBeans project is straightforward. First of all, uncompress your source tar-ball somewhere (assuming you created it with make dist). Then, choose File/New Project and select the C/C++ Project with Existing Sources in the New Project dialog, as shown in the next picture.

Create New C++ Project

In the next dialog, just choose the path of your sources and an appropriate tool collection (this project is a C++11 project, so that CLang was chosen on OS X). If you leave the configuration mode to automatic NetBeans will check for the existence of either a make file or a configuration script and will setup your project to configure and build in the its root directory. If you prefer building it in a separate directory or have multiple build configurations, then choose Custom and fine tune your project.

Configure C++ Project

NetBeans will create a new project using your sources, will configure it and make it:

Running configure

Running make

From now on, until you modify your configuration files, you can just build the project in NetBeans and make will be invoked on the generated makefile.

If you need to reconfigure the project, you can select Project/More Build Commands/Reconfigure Project. A configuration dialog will pop up where you can specify additional configure parameters:

Configure parameters

As you have seen, NetBeans offers a very easy way to import a project built with the GNU Build System with almost no user interaction. The basic functionality (configure and make) is there, hidden behind a very thin and intuitive UI layer.

Importing the Sources into an Eclipse CDT Project

Creating a working Eclipse CDT project from the same tar-ball is easy, but not as easy as it is with NetBeans.  First of all, choose File/Import/Existing Code as Makefile Project:

Import Existing Code


In the next dialog, pretty much as in the NetBeans case, the only required user input is the source path.

Configure C++ Project

When Eclipse imports the project it does not detect the presence of GNU Build System configuration files. To configure the build system, the user must select File/New/Convert to a C/C++ Autotools Project (a very bad naming choice, because I would not expect to find this feature in the File/New submenu):

Convert C++ Project to Autotools Project

Once the project has been converted to an Autotools project, Eclipse will run configure and you can start working on it.

Running configure

Since only CLang can properly compile this C++11 project on OS X 1.8, I need to reconfigure the project (basically, to have Eclipse add CXX=clang++ when invoking configure).

Autotools configuration is where Eclipse CDT shines. Autotools settings can be found in the project settings:

Configuring the Build System

As you can see, this is more than what NetBeans offers. Common configure parameters are hierarchically organised in a tree where they can be set with handy UI controls:

Configuring the Compiler

Once the compiler has been set, the project built correctly:

Running make

Comparison

I've been using both environments for a couple of months, switching between one and the other without experiencing any major issue, even working on different platforms, alternating the use of OS X and Linux

According to my experience, I think both IDEs offer a solid working environment featuring a nice integration of the GNU Build System into the UI. On the usability side, I think NetBeans' UI is cleaner, more intuitive and easier to use. I think this is true in general, and it's one of the reasons I usually stick with NetBeans for Java SE and Java EE development.

On the other hand, Eclipse CDT offers much finer control over the build system. As we have seen, the build settings lets you tweak many configure parameters from a handy UI and they can be saved in configurations.

The Eclipse CDT project settings supposedly let you specify alternate paths for the GNU Build System tools:

Configuring the Build System Paths

This feature would be very handy, since it's not uncommon to install updated versions of the tools in an alternate location. Unfortunately, I was unable to have it working properly when the alternate versions are not on the user path (which is when I'd use this customisation in the first place). Even though the correct version is invoked by Eclipse, the "wrong" version (the one in the path) when a tool invokes another one (as in the case of autoreconf). Which seems reasonable, since the GNU Build System are shell scripts. In fact, when I first saw this dialog, I wondered how it could work in my case, in which I've got a local autoconf and automake installation in my home directory.

Considering the IDE as a whole, I still prefer NetBeans to Eclipse CDT. C/C++ support is integrated and the UI is easier and intuitive. Eclipse CDT is certainly more configurable and offers features which NetBeans lacks, such as support for configure.ac and Makefile.am files which NetBeans treats as plain text files. Despite these gaps, though, I believe NetBeans wins on the UI usability side.

Code Formatting

Another of my major concerns with NetBeans for C/C++ was the lack of proper, configurable code formatting tools. For a while I even tried using GNU indent to fill this gap but the workflow was disruptive and prone to error since indent support for C++ is still experimental. Fortunately, this gap has been filled and now you can instruct NetBeans to format your C/C++ code using the most commonly used coding styles, such as:
  • Apache.
  • BSD (ANSI and OpenSolaris).
  • GNU.
  • K&R.
  • Linux Kernel.
  • MySQL.
  • NetBeans.
  • Whitesmiths.

NetBeans Code Formatter

The list of supported styles is in fact longer than what Eclipse CDT currently offers:
  • BSD/Allman.
  • GNU.
  • K&R.
  • Linux.
  • Whitesmiths.

Eclipse Code Formatter

On the other hand, if you need to create a customised style from scratch, Eclipse CDT is still superior as far as customisation options are concerned.

Both code formatters work pretty well and I found only few quirks. Both IDEs offer good tools and I think that nowadays they're equally usable.

Tool Collection Management

NetBeans manages the tool collections of a platform in a clean way, separating the configuration of a tool collection from the configuration of a project. This way, you can change define a new tool collection, or choose another between the available ones in your system, and use it to build a project as a simple drop-in replacement of the original. This is especially handy not only in the case you're testing the build with different tool chains, but also in the case you're building the same project on different platforms.

In the following pictures, you can see the definition of the two tool collections which are available by default on OS X (1.8): clang and gcc.

CLang Tool Collection

GNU Tool Collection

The project I've been working on had to build on both OS X and Linux. When using NetBeans, I can just open the project on either platform and choose the appropriate tool collection. In fact, each time I switched from OS X to Linux, NetBeans detected an invalid tool (CLang++ was not available) and offered to reconfigure the project.

In the following picture you can see how a project can be configured to use a tool collection. Once the tool collection is chosen, NetBeans will automatically reconfigure the project.

Project Configuration

When using Eclipse CDT, on the other hand, the C++ compiler is selected using (or removing altogether) the CXX flag. There's no automatic or easy way to reconfigure the project as NetBeans does and while it's certainly technically easy to change the compiler variable, it's a usability problem. On the usability side, NetBeans clearly wins.

Conclusion

An IDE is a very important tool in the life of a programmer, and choosing an IDE is a very delicate process which may have huge impact on your performance. On the one hand, I often try different IDEs to choose the best one for a specific use case. On the other hand, becoming proficient on an IDE is a process which requires time and, depending on the situation (project scheduling is a tyrant), I feel it's better for me to stick with a well known IDE and be (very) productive from the beginning, rather than switching to a brand new one because it offers features than the former lacks.

If you are already a NetBeans or Eclipse user, stick with it. Most of the times you'll be fine and will not need anything else. Maybe you'll find a solid reason to switch to another IDE, and when that time comes, the best thing is try more than one and decide yourself.

That's what I did. I'm a long time NetBeans user and started the project with it. I found some minor issues and used those problems as an opportunity to investigate other IDEs, such as Eclipse CDT. While working on NetBeans is familiar and comfortable to me, I recognise I was very willing to check out the latest Eclipse CDT (Kepler at the time of writing) and see whether I should reconsider my IDE choice.

At the end I decided to stay with NetBeans because of its usability features, especially the tool collection management, even though Eclipse CDT offers a much finer control over the build system configuration: but being able to easily switch OS and/or tool collection as NetBeans does was the deal-breaker for me.