In the previous post in section third party dependencies we introduced pkg-config command to handle third party library dependancies.

Command pkg-config is prefered way in Linux not only to provide list of compiler flags (with --cflags) or libraries (with --libs), but it can be also used to check library version.

For example, let’s say we installed libglm-dev package (provides OpenGL Mathematics) so we can use

tip: use sudo apt install libglm-dev command to install the library

$ pkg-config --list-all|grep -i glm
glm                            GLM - OpenGL Mathematics

command to verify pkg-config knows about GLM library.

note: as shown in previous post we can use pkg-config --cflags --libs glm command for a list of compiler flags and libraries (GLM is header only library so the command returns "")

Then we can use

$ pkg-config --modversion glm
0.9.9.6

to see library version. We can also ask pkg-config whether specific library is installed with

pkg-config --exists 'glm >= 0.9.9.0'

command.

note: version part of the library name >= 0.9.9.0 is optional

The command returns true whether GLM library version 0.9.9.0 or greater is installed or false otherwise.

SCons supports a configure context which can be used to integrate pkg-config --exists PKG command this way

dependencies = ['glm >= 0.9.9.5']

def build():
	env = Environment()

	conf = env.Configure(                                    # 1
		custom_tests={'CheckPkgVersion': check_pkg_version})

	for pkg in dependencies:
		if not conf.CheckPkgVersion(pkg):                     # 2
			print("fatal: '%' package not found" % pkg)
			Exit(1)

	env = conf.Finish()

	env.Program('main.cpp')

# custom pkg-config based package version check
def check_pkg_version(context, pkg):
	context.Message("Checking for '%s' package... " % pkg)
	res = context.TryAction("pkg-config --exists '%s'" % pkg)[0]
	context.Result(res)
	return res

build()

where dependencies variable defines list of dependencies (in our case there is just one dependency there). Line 1 creates configure context as conf variable with a custom test function CheckPkgVersion so we can later call conf.CheckPkgVersion(pkg) on line 2 with a library name (in our case 'glm >= 0.9.9.5').

That is not all, configure context comes with a bunch of predifined functions like CheckCXXHeader(), CheckFunc(), CheckLib(), CheckTypeSize() and many more. So for example we can check iostream header with

if not conf.CheckCXXHeader('iostream'):
	print("We really need 'iostream' header to be installed")
	Exit(1)

code. Watch out SConstruct file for full futured build script sample and main.cpp for source code sample. Running scons command in sample directory produce

$ scons
scons: Reading SConscript files ...
Checking for C++ header file iostream... yes
Checking for 'glm >= 0.9.9.5' package... yes
scons: done reading SConscript files.
scons: Building targets ...
g++ -o main.o -c -std=c++17 -Wall -g -O0 main.cpp
g++ -o main main.o
scons: done building targets.

output.

Pretty cool, what do you think?