Thursday, November 5, 2015

Supporting Out-Of-Source-Code-Tree Build with Autotools

Some opensource code are not trivial to be build out of it's source (code) tree. This is especially true in some opensource libraries because they generate intermediate file(s) which must be handled accordingly. But, fear not, there are two Autoconf constructs (or rather internal variables) that can help you tame this wild library code. They are $(top_srcdir) and $(top_builddir). Refer to Autoconf Preset Output Variables for their details.

I'll take libevent as a real-world example because this library generates an intermediate header file at build time which must be included in the build process (event-config.h). This is where $(top_srcdir) and $(top_builddir) come into play. If you want to be able to build out-of-source-tree, you need to include this generated file into your application code that uses libevent. You use $(top_builddir) for that. In the meantime, you also need to include the "ordinary" include file in the source tree, and that's where $(top_srcdir) comes into play.

Let's assume, your source tree looks like below and your application links to this particular libevent version statically:
.
├── libevent-2.0.22-stable
│   ├── autom4te.cache
│   ├── compat
│   │   └── sys
│   ├── include
│   │   └── event2
│   ├── m4
│   ├── sample
│   ├── test
│   └── WIN32-Code
│       └── event2
└── your_application_code_dir

In your_application_code_dir, you need to have a Makefile.am file with the following contents:
### NOTE:
### $(top_builddir) is required for libevent because there is 
### an include file (event-config.h) that is generated at build-time.
### This file will be in the build directory instead of the source code 
### directory if you build out-of-tree.
###
AM_CPPFLAGS = -I$(top_srcdir)/libevent-2.0.22-stable/include \
       -I$(top_builddir)/libevent-2.0.22-stable/include
  

## Omitted for clarity .. 

bin_PROGRAMS = your_program_name

your_program_name_SOURCES = your_program_name.c
your_program_name_LDADD = $(top_builddir)/libevent-2.0.22-stable/libevent_core.la

## Omitted for clarity .. 
The code in Makefile.am above (placed in your_application_code_dir) should be enough to make it possible to build libevent out-of-source-tree. As you see, both the include file in the build directory (out of the source code tree) and the include file in the source code tree are included. This should make it less of hassle to keep your source code tree clean all the time. Especially if you are using RCS such as subversion, git or mercurial.

Hopefully this helps those who intend to always build autotools code out-of-(source)-tree.

Saturday, October 31, 2015

Fixing Tmux Mouse Issue

Checkout your tmux version if you've been experiencing mouse-related issue in tmux recently. This is the command:
me@machine $  tmux -V
That should show your tmux version. If you're using Tmux version 2.1, your old mouse configuration in .tmux.conf is no longer valid. The following shows the valid .tmux.conf configuration lines for mouse support in Tmux version 2.1:
#Mouse works as expected
set -g mouse on
#setw -g mode-mouse on #tmux version < 2.1
#set -g mouse-select-pane on  #tmux version < 2.1
#set -g mouse-resize-pane on  #tmux version < 2.1
#set -g mouse-select-window on  #tmux version < 2.1
The commented-out lines are from tmux version < 2.1. There is only one mouse setting in Tmux v2.1, that is "mouse". I got my tmux working as before after this change.

Note:
Primary source of information: [SOLVED] Tmux 2.1 new mouse config issues - can't scroll (It helps despite failing to show the use of the new option in tmux.conf).

Friday, October 30, 2015

Modifying Memcached Configuration in Arch Linux

It's not quite trivial to modify Memcached server configuration in Arch Linux because it's entirely managed via systemd, at least for those not well-versed with systemd. This is the command to modify Memcached server configuration in Arch Linux via systemd's systemctl:
root@darkstar # systemctl edit memcached.service --full
The command should spawn the default text editor configured to be used by systemctl. You can make your changes in the editor and save it. Systemd will apply your changes accordingly.

Wednesday, October 14, 2015

Building C++ Application with Boost Library and Autotools in Linux

In this post, I'm going to present the steps required to build C++ application which uses Boost library in Linux (x86_64) with the help of GNU autotools. Mind you that I'm using Arch Linux distribution. Therefore, please adjust the prerequisites according to your environment.

Prerequisites

  • The usual GCC tools, i.e. g++ compiler, ld linker, etc.
  • GNU autotools: autoconf, automake, etc.
  • autoconf-archive. This is a set of autoconf macros that will help building Boost applications. In Arch Linux, I used pacman to install it. You need to carry-out similar step in your Unix/Linux installation.

Initializing The Build System

I assume that the source code directory entries look like this:
.
├── configure.ac
├── m4
├── Makefile.am
└── src
    ├── main.cpp
    └── Makefile.am

m4 is an empty directory, configure.ac, Makefile.am, and src/Makefile.am are the boiler-plate code required to initialize the autotools build system. The next section shows you contents of the files. Use autoscan and autoreconf to initialize the autotools build system like so:
  1. Run autoscan (in the root source code directory) to create configure.scan template file. You need to copy/rename this file to configure.ac and edit it accordingly.
  2. Run autoreconf to create files required by GNU build tools (GNU make and gcc/g++). The following is how you would run autoreconf to create the files.
    $ autoreconf -fvi
    

Dealing with Boost Modules

Every boost module requires separate dependency library, autoconf macro (in configure.ac) and automake "library entry" (in Makefile.am). Now let's start with configure.ac. Contents of <ROOT_DIR>/configure.ac is as follows:
# configure.ac
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([boost_test], [0.0.1], [me@bug.com])
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

AM_INIT_AUTOMAKE([foreign -Wall -Werror])
m4_ifdef([AM_SILENT_RULES],
    [AM_SILENT_RULES([yes])
])

# Checks for programs.
AC_PROG_CC
AC_PROG_CXX

# Checks for libraries.
AX_BOOST_BASE([1.48],, [AC_MSG_ERROR([This program needs Boost, but it was not found in your system])])
AX_BOOST_SYSTEM
AX_BOOST_DATE_TIME
AX_BOOST_THREAD

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile])
AC_OUTPUT

TODO: Explain the lines that have something to do with Boost (AX_BOOST_*) in configure.ac 

Contents of <ROOT_DIR>/Makefile.am is as follows:
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = bootstrap
SUBDIRS = src
<ROOT_DIR>/src/Makefile.am is as follows:
bin_PROGRAMS = boost_test

AM_CPPFLAGS = $(BOOST_CPPFLAGS)
AM_LDFLAGS = $(BOOST_LDFLAGS)

boost_test_SOURCES = main.cpp
boost_test_LDADD = $(BOOST_SYSTEM_LIB) $(BOOST_THREAD_LIB) $(BOOST_DATE_TIME_LIB) 

TODO: Explain the lines that have something to do with Boost in src/Makefile.am -- $(BOOST_CPPFLAGS) $(BOOST_LDFLAGS) $(BOOST_*_LIB)

Contents of <ROOT_DIR>/src/main.cpp is as follows:
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>

void workerFunc()
{
 boost::posix_time::seconds workTime(3);

 std::cout << "Worker: running" << std::endl;

 // Pretend to do something useful...
 boost::this_thread::sleep(workTime);

 std::cout << "Worker: finished" << std::endl;
}

int main(int argc, char *argv[])
{
 std::cout << "main: startup" << std::endl;

 boost::thread workerThread(workerFunc);

 std::cout << "main: waiting for thread" << std::endl;

 workerThread.join();

 std::cout << "main: done" << std::endl;

 return 0;
}

Pay attention that each Boost module is represented by a single header file which also requires autoconf entry in configure.ac and corresponding library dependency in src/Makefile.am

END NOTE: This post is still incomplete. It's published solely for the benefit of those who can understand it quite well from the source code itself.