Skip to content

Instantly share code, notes, and snippets.

@antmd
Last active April 10, 2019 13:57
Show Gist options
  • Save antmd/d2ec655257885c4100225e91915189b4 to your computer and use it in GitHub Desktop.
Save antmd/d2ec655257885c4100225e91915189b4 to your computer and use it in GitHub Desktop.
Python script for querying CMake project model
#!/usr/bin/env python3
import pexpect
import re
import sys
import time
import json
import os
from os import path
from pprint import pprint as pp
from pprint import pformat
import begin
cmk_req_fmt = '[== "CMake Server" ==[\n{}\n]== "CMake Server" ==]'
cmk_response = re.compile(r'''==\[\s*(.*)\s*\]==''')
log_messages=False
cookie='cmakeq{}'.format(os.getpid())
def parse_response(proc):
proc.expect(cmk_response)
resp = proc.match.group(1)
return json.loads(resp)
def send_receive(proc, snd=None):
if snd is not None:
if isinstance(snd, str):
snd = json.loads(snd)
snd['cookie'] = cookie
if log_messages:
print("SEND >>>>>>>>>>>>>>>>>>>>\n{}".format(pformat(snd)))
snd = json.dumps(snd)
proc.sendline(cmk_req_fmt.format(snd))
resp = parse_response(proc)
if 'cookie' in resp:
while resp['cookie'] != cookie:
resp = parse_response(proc)
if log_messages:
print("RECV <<<<<<<<<<<<<<<<<<<<\n{}".format(pformat(resp)))
return resp
def send_receive_multi(proc, msg, snd=None):
resp = send_receive(proc, snd)
while 'inReplyTo' not in resp or resp['inReplyTo'] != msg or resp['type'] != 'reply':
resp = send_receive(proc)
return resp
def cmk_handshake(source_dir, build_dir, major=1):
protov = {'major':major}
return {"type":"handshake",
"protocolVersion":protov,
"sourceDirectory":source_dir,
"buildDirectory":build_dir,
"generator":"Unix Makefiles"
}
def cmk_query_globals():
return {"type":"globalSettings"}
def cmk_query_codemodel():
return {"type":"codemodel"}
def cmk_configure(build_type='Debug'):
return {"type":"configure",
"cacheArguments":[
"-DCMAKE_BUILD_TYPE={}".format(build_type)
]}
def cmk_generate():
return {"type":"compute"}
@begin.start
def main(source_dir, build_dir, trace=False):
global log_messages
log_messages = trace
source_dir = path.abspath(source_dir)
build_dir = path.abspath(build_dir)
os.chdir(build_dir)
cmk = pexpect.spawn('cmake -E server --experimental --debug', encoding='utf-8', maxread=1024*50) # , logfile=sys.stdout)
hello = send_receive(cmk)
major = hello['supportedProtocolVersions'][0]['major']
resp = send_receive(cmk, cmk_handshake(source_dir, build_dir, major))
print("Configuring...", file=sys.stderr)
resp = send_receive_multi(cmk, 'configure', cmk_configure())
print("Generating...", file=sys.stderr)
resp = send_receive_multi(cmk, 'compute', cmk_generate())
print("Querying...", file=sys.stderr)
resp = send_receive_multi(cmk, 'codemodel', cmk_query_codemodel())
pp(resp)
cmk.terminate()
begins==0.9
pexpect==4.7.0

Usage

./cmakeq.py ~/src ~/src/build > codemodel.json

Find all shared libraries:

jq '.configurations[].projects[].targets[] | select(.type == "SHARED_LIBRARY") | .name' codemodel.json

Find all top-level buildables:

jq '.configurations[].projects[].targets[] | select(.type == "SHARED_LIBRARY" or .type == "EXECUTABLE" or .type == "STATIC_LIBRARY") | .name' codemodel.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment