CMake: Retrieve build information

CMake has evolved to become quite a beast. It contains a multitude of features which often stay unexplored by the casual user. Today I’d like to show you how to retrieve information about the generated build system.

Let’s say you’re writing your own IDE and you’d at least like to pretend that it comes with built-in cmake support. One of the most basic features is to parse the source files used by the opened “project”. For this, the cmake-file-api (or formerly cmake-server) will come in handy. As the name suggests, it’s a file based API to cmake. This means that we can create files to perform an API request and cmake will provide replies in form of files as well. In this particular case, the files happen to contain JSON content.

As with all of cmake’s documentation, it is extremely precise but doesn’t really provide a quick ‘getting started’ experience as it serves more as a very accurate reference manual than anything else. I’ll show an example here which should provide a good starting point.

Getting a list of sources

Retrieving a list of sources of a target is extremely easy. CMake provides the codemodel object kind which we can obtain through a simple stateless query.

All cmake-file-api exchanges happen inside of <build_dir>/.cmake/api/<api_version>. Currently there’s only API v1.

Step-by-step:

  1. Navigate to your cmake project top-level directory.
  2. Create a build directory build/.
  3. Create the API directory build/.cmake/api/v1/query
  4. Create the file build/.cmake/api/v1/query/codemodel-v2 and leave it empty
  5. Re-run cmake (the configuration step)
  6. CMake should have automatically created the directory build/.cmake/api/v1/reply containing the replies to our query.

And that’s it. CMake will generate various JSON files such as an index file, the codemodel top-level file and one file per target listing all sources amongst other useful information.

Here’s an example of the object library target of my CppProperties library:

{
	"artifacts" : 
	[
		{
			"path" : "lib/CMakeFiles/cppproperties-objs.dir/archiver_xml.cpp.obj"
		},
		{
			"path" : "lib/CMakeFiles/cppproperties-objs.dir/3rdparty/tinyxml2/tinyxml2.cpp.obj"
		}
	],
	"backtrace" : 1,
	"backtraceGraph" : 
	{
		"commands" : 
		[
			"add_library",
			"target_sources"
		],
		"files" : 
		[
			"lib/CMakeLists.txt"
		],
		"nodes" : 
		[
			{
				"file" : 0
			},
			{
				"command" : 0,
				"file" : 0,
				"line" : 22,
				"parent" : 0
			},
			{
				"command" : 1,
				"file" : 0,
				"line" : 30,
				"parent" : 0
			}
		]
	},
	"compileGroups" : 
	[
		{
			"compileCommandFragments" : 
			[
				{
					"fragment" : "-g  "
				},
				{
					"fragment" : "-std=gnu++17"
				}
			],
			"language" : "CXX",
			"sourceIndexes" : 
			[
				7,
				8
			]
		}
	],
	"id" : "cppproperties-objs::@306ed2d68c6501e8728f",
	"name" : "cppproperties-objs",
	"paths" : 
	{
		"build" : "lib",
		"source" : "lib"
	},
	"sourceGroups" : 
	[
		{
			"name" : "Header Files",
			"sourceIndexes" : 
			[
				0,
				1,
				2,
				3,
				4,
				5,
				6
			]
		},
		{
			"name" : "Source Files",
			"sourceIndexes" : 
			[
				7,
				8
			]
		}
	],
	"sources" : 
	[
		{
			"backtrace" : 2,
			"path" : "lib/archiver_xml.hpp",
			"sourceGroupIndex" : 0
		},
		{
			"backtrace" : 2,
			"path" : "lib/exceptions.hpp",
			"sourceGroupIndex" : 0
		},
		{
			"backtrace" : 2,
			"path" : "lib/properties.hpp",
			"sourceGroupIndex" : 0
		},
		{
			"backtrace" : 2,
			"path" : "lib/property.hpp",
			"sourceGroupIndex" : 0
		},
		{
			"backtrace" : 2,
			"path" : "lib/property_ex.hpp",
			"sourceGroupIndex" : 0
		},
		{
			"backtrace" : 2,
			"path" : "lib/property_ex_cpp.hpp",
			"sourceGroupIndex" : 0
		},
		{
			"backtrace" : 2,
			"path" : "lib/property_ex_cpp_modern.hpp",
			"sourceGroupIndex" : 0
		},
		{
			"backtrace" : 2,
			"compileGroupIndex" : 0,
			"path" : "lib/archiver_xml.cpp",
			"sourceGroupIndex" : 1
		},
		{
			"backtrace" : 2,
			"compileGroupIndex" : 0,
			"path" : "lib/3rdparty/tinyxml2/tinyxml2.cpp",
			"sourceGroupIndex" : 1
		}
	],
	"type" : "OBJECT_LIBRARY"
}
comments powered by Disqus