CTinker is a C project introspection and augmentation tool
Project description
CTinker - C/C++ Project Introspection and Augmentation Tool
C Tinker, pronounced see-tinker (or humorously "stinker", as suggested by Chuck Ocheret) allows you to get in the middle of the build process of a make/Ninja-style project and augment the compilation and linking as well as extract and redirect artifacts using policies you can't implement otherwise even with LDFLAGS/CFLAGS magic.
Problem
More formally the problem CTinker solves can be stated as follows:
I need to get in the middle of a build process of a project I can know intimately but do not control and that I have no intention of maintaining a fork/patches for, or for which I need to obtain runtime dynamic control of the build process.
Solution
Overview
CTinker
is capable of getting in the middle of virtually any build process by:
- Starting in the
supervisor
mode. - Creating a temporary directory full of toolkit-specific (e.g. for LLVM Clang it's
clang
,ar
etc) symlinks referring back toCTinker
executable. - Setting up environ and a local socket to communicate with the
workers
. - Invoking the build process as specified by the user.
- Being invoked for each tool invocation in a
worker
mode (based on environmental variables), communicating with thesupervisor
, sending command-line arguments to thesupervisor
process and then invoking the tool itself. - If specified, invoking
scripting
handlers before and after the build as a whole (in thesupervisor
) and before and after each intercepted tool invocation (in theworker
).
As a further illustration, if the original process invocation chain for a sample build is as follows:
make => clang => lld, => make => clang, => clang => lld
then the same build instrumented with CTinker will produce the following process invocation chain:
ctinker => make => ctinker-clang => clang => ctinker-lld => lld, => make => ctinker-clang => clang, => ctinker-clang => clang => ctinker-lld => lld
Scripting
Scripting is the most powerful part of CTinker
that provides an ability to really change how build functions
at runtime. It is implemented via a visitor pattern, invoking functions specified in the user-supplied script:
def ctinker_start(env: Dict[str, str], work_dir: Path):
"""Invoked by CTinker `supervisor` prior to the main build process
Changes to the `env` dictionary propagate to the main build process.
"""
pass
def ctinker_finish(env: Dict[str, str], work_dir: Path, tool_calls: List[Tuple[Any]], return_code: int):
"""Invoked by CTinker `supervisor` after the main build process exits
`tool_calls` is a `list` of `tuple`s of `(tool, tool_args, return_code, cwd, script_result)`, where `script_result`
is the value returned by `ctinker_after_tool`.
"""
pass
def ctinker_before_tool(env: Dict[str, str], tool: str, tool_args: List[str], work_dir: Path, cwd: Path):
"""Invoked by CTinker `worker` prior to the tool process
Changes to the `env` dictionary propagate to the tool process.
Changes to the `tool_args` list propagate to the tool process.
"""
pass
def ctinker_after_tool(env: Dict[str, str], tool: str, tool_args: List[str], work_dir: Path, cwd: Path,
return_code: int) -> Any:
"""Invoked by CTinker `worker` after the tool process exits
Returned value, **if truthy**, will be stored and will appear
as the last entry in the `tool_calls` passed to `ctinker_finish`
"""
pass
It is guaranteed that ctinker_start
- ctinker_finish
and ctinker_before_tool
- ctinker_after_tool
pairs will
be executed in the same supervisor
and worker
processes respectively and therefore you can pass values between
the start/finish and before/after functions (for example by a global or within the same instance of an object).
Help
$ ctinker --help
usage: ctinker [-h] [-s SCRIPT] [-o OUT] [-f {text,pickle}] [-p PATHS]
[-w WORK_DIR] -t {clang} [-l [{clang,__default}]]
[-L LINKER_TOOL_OVERRIDE]
[--linker-flags-name LINKER_FLAGS_NAME]
...
CTinker project introspection and augmentation tool
positional arguments:
command build command to execute
optional arguments:
-h, --help show this help message and exit
-s SCRIPT, --script SCRIPT
a Python script containing visitor-style hooks
(default: None)
-o OUT, --out OUT a path to a file where all tools, their arguments and
exit codes will be recorded (default: None)
-f {text,pickle}, --format {text,pickle}
the format of the output file (default: text)
-p PATHS, --path PATHS
prepend a leading PATH entry to be inherited by the
invoked command (default: None)
-w WORK_DIR, --work-dir WORK_DIR
sets a work directory to be something other than
current working directory (default: )
-t {clang}, --toolkit {clang}
enable specific compilation interception modes
(default: None)
-l [{clang,__default}], --linker-intercept [{clang,__default}]
intercept linker with --linker-flags-name env var
using the specified toolkit (default: None)
-L LINKER_TOOL_OVERRIDE, --linker-tool-override LINKER_TOOL_OVERRIDE
specify linker tool name directly (may not work if no
toolkit provides it) (default: None)
--linker-flags-name LINKER_FLAGS_NAME
specify linker environmental variable (default:
LDFLAGS)
Example
TBW
Troubleshooting
- Printing to
sys.stdout
from theworker
is dangerous as the stdout is often interpreted by the invoking tool which can lead to a crash in the tool expecting certain data format.print("debug!", file=sys.stderr)
is generally safe.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file ctinker-0.0.4.tar.gz
.
File metadata
- Download URL: ctinker-0.0.4.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.8.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f4625dcf840176d4498eb821118293fdf105a61526a36d02104a019b1239810a |
|
MD5 | 58547df6a4a7402ade1d5aad97c31f36 |
|
BLAKE2b-256 | a3634e60d5bd62df15e612bcd744b306e1445da63da8e5bf8fa8ce4ce34bcb0e |
File details
Details for the file ctinker-0.0.4-py3-none-any.whl
.
File metadata
- Download URL: ctinker-0.0.4-py3-none-any.whl
- Upload date:
- Size: 14.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.46.0 CPython/3.8.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | cf21f67aa437d664aa2c83471d5e369805a62a0d2727dda1006691cca14136a7 |
|
MD5 | b0c01512b9b4042e515c874704df34c0 |
|
BLAKE2b-256 | 9afd18b77a6c2a7315b5d3037f8de11e20479f6c0fac72432dcb9f7ab0cce3f5 |