diff --git a/SConstruct b/SConstruct
index 78090c3a451b8e9b562407d55fc03fe948dcc824..422efe6476878779a0d8a1bbb759403906c60f28 100644
--- a/SConstruct
+++ b/SConstruct
@@ -8,7 +8,7 @@ vars = Variables(None, ARGUMENTS)
 vars.Add(PathVariable('DESTDIR', "Root directory to install in (useful for packaging scripts)", None, PathVariable.PathIsDirCreate))
 vars.Add(PathVariable('prefix', "Where to install in the FHS", "/usr/local", PathVariable.PathAccept))
 
-env = Environment(ENV = {'PATH' : os.environ['PATH']}, variables = vars)
+env = Environment(ENV = {'PATH' : os.environ['PATH']}, variables = vars, tools=['default', 'scanreplace'], toolpath=['tools'])
 
 def calcInstallPath(*elements):
     path = os.path.abspath(os.path.join(*map(env.subst, elements)))
@@ -28,7 +28,8 @@ if 'DESTDIR' in env:
 
 env['libpath'] = calcInstallPath("$prefix", "lib")
 env['incpath'] = calcInstallPath("$prefix", "include", "hammer")
-# TODO: Add pkgconfig
+env['pkgconfigpath'] = calcInstallPath("$prefix", "lib", "pkgconfig")
+env.ScanReplace('libhammer.pc.in')
 
 env.MergeFlags("-std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-attributes")
 
@@ -89,3 +90,4 @@ env.Command('test', 'build/$VARIANT/src/test_suite', 'env LD_LIBRARY_PATH=build/
 
 env.Alias("install", "$libpath")
 env.Alias("install", "$incpath")
+env.Alias("install", "$pkgconfigpath")
diff --git a/libhammer.pc.in b/libhammer.pc.in
new file mode 100644
index 0000000000000000000000000000000000000000..97ded13f8806ab4e3146f9cb79924dfa52521cc7
--- /dev/null
+++ b/libhammer.pc.in
@@ -0,0 +1,10 @@
+prefix=/usr
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: libhammer
+Description: The Hammer parsing library
+Version: 0.9.0
+Cflags: -I${includedir}/hammer
+Libs: -L${libdir} -lhammer
diff --git a/src/SConscript b/src/SConscript
index 03308dd9dcc7b0559ff3c89dfd5b429f5c4d3a9b..a06244b9d6638e2d715e77535a0ba555a12a8cf3 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -64,6 +64,7 @@ libhammer_static = env.StaticLibrary('hammer', parsers + backends + misc_hammer_
 
 env.Install("$libpath", [libhammer_static, libhammer_shared])
 env.Install("$incpath", dist_headers)
+env.Install("$pkgconfigpath", "../../../libhammer.pc")
 
 testenv = env.Clone()
 testenv.ParseConfig('pkg-config --cflags --libs glib-2.0')
diff --git a/tools/scanreplace.py b/tools/scanreplace.py
new file mode 100644
index 0000000000000000000000000000000000000000..5321e4813d9ee0030964c4dd1bcf207710808037
--- /dev/null
+++ b/tools/scanreplace.py
@@ -0,0 +1,15 @@
+from string import Template
+
+def replace_action(target, source, env):
+  open(str(target[0]), 'w').write(Template(open(str(source[0]), 'r').read()).safe_substitute(env))
+  return 0
+
+def replace_string(target, source, env):
+  return "building '%s' from '%s'" % (str(target[0]), str(source[0]))
+
+def generate(env, **kw):
+  action = env.Action(replace_action, replace_string)
+  env['BUILDERS']['ScanReplace'] = env.Builder(action=action, src_suffix='.in', single_source=True)
+
+def exists(env):
+  return 1
diff --git a/tools/scanreplace.pyc b/tools/scanreplace.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c37386cee5c446284c300e734bcd48d69842fc26
Binary files /dev/null and b/tools/scanreplace.pyc differ