https://github.com/apirogov/ecpz
Evaluate C++ using Python and Zig
https://github.com/apirogov/ecpz
clang cpp python zig
Last synced: 4 months ago
JSON representation
Evaluate C++ using Python and Zig
- Host: GitHub
- URL: https://github.com/apirogov/ecpz
- Owner: apirogov
- License: mit
- Created: 2025-03-11T01:15:56.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-04-13T14:27:52.000Z (about 1 year ago)
- Last Synced: 2026-01-19T16:46:23.385Z (5 months ago)
- Topics: clang, cpp, python, zig
- Language: C
- Homepage: https://pypi.org/project/ecpz/
- Size: 37.1 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ecpz - **E**valuate **C**++ using **P**ython and **Z**ig
Do you need to evaluate some simple C++ code from inside your application,
and it should work cross-platform (Linux, Mac and Windows) without causing a headache?
You've seen it all, [quine-relay](https://github.com/mame/quine-relay) stopped
being amusing years ago, and you feel the itch for something new?
No problem, *easy-peasy with `ecpz`!*
----
This little package combines the ubiquity of Python and ingeniuity of the Zig
toolchain to give you the ability to compile C++ snippets without pain.
If you have a non-trivial project consisting of more than one source file,
you should probably configure and build it properly using e.g. [CMake](https://github.com/Kitware/CMake).
If you need an interactive C++ code execution environment (i.e. a REPL),
check out [cling](https://github.com/root-project/cling).
But if for some reason you need to produce and execute some ad-hoc throw-away
C++ snippets as a part of your workflow, `ecpz` might be just what you need!
## Usage
Install `ecpz` using `pip` or `uv` and check `ecpz --help` for all options.
In the following, the features of `ecpz` are illustrated by some examples.
### `ecpz run`
Compile and run a single source file provided either as argument or via standard input.
For example, create `hello.cpp`:
```cpp
#include
int main() {
std::println("Hello world!");
}
```
And run it:
```bash
$ cat hello.cpp | ecpz --clang-arg -std=c++23 run
Hello world!
```
### `ecpz print`
Evaluates some expressions and pretty-print them using `std::print(ln)` *(note that this automatically implies `-std=c++23`)*.
For example, create a header `prelude.hpp`:
```cpp
#include
#include
inline double tau() {
return 2 * std::numbers::pi;
}
```
And now run:
```bash
$ ecpz --prelude prelude.hpp print "{:.3f} {} {} {}" "tau()" "[](){ int i=0; ++i; return i; }()" "std::is_same_v" "std::is_same_v"
6.283 1 false true
```
You can set the `ECPZ_PRELUDE` environment variable to the path of your custom
header to make it always included by default. Note that as usual, CLI arguments
override equivalent environment variables.
### Creating a Quine
Usually, using I/O to let code open itself directly is forbidden and considered bad sportsmanship.
Everybody agrees that the following things are clear cases of cheating:
* reading a hard-coded string filename
* using the `argv[0]` trick to reflect back the name of the current file/executable
* reading the file using some compile- or runtime reflection capabilities of the programming language
* adding and using a special `quine` command in a custom programming language or environment
We will do none of these things. Create some source file `FILE` with the following content:
```cpp
#include "ecpz/subprocess.hpp"
int main(int i, char** a) {
using b = std::istreambuf_iterator; using c = std::string;
auto d = [](auto e){ std::ifstream f(e, std::ios::binary); return c(b(f), b()); };
std::vector e(i+3, a[i-1]); e[0]="ecpz"; e[1]="run";
auto f = i%2 == 0 ? subprocess::run(e).output : d(a[i-1]);
subprocess::set_bin(); std::cout<
Spoiler
Nobody ever said that we cannot just...
* run a C++ source file through `ecpz`,
* which uses a Python package,
* which provides the `zig` toolchain,
* which provides `clang`,
* to compile and then run the program, which
* runs its arguments through `ecpz`,
* compiling and then running the same program, which now finally
* prints the file passed to it as the argument
Or, at least *I* did not get the memo that this is illegal.
In that case I apologize for wasting your time.
But even *if* this is still cheating -
isn't cheating in glorious ways not also a form of *art*?
## Limitations
The following issues are fixable, i.e. only a matter of more effort and time:
* currently only synchronous execution is supported, no I/O buffering or streaming
* currently it is not possible to pipe input data into `ecpz run` to pass it as stdin
## Acknowledgements
Thanks to [sheredom](https://github.com/sheredom)
for creating [subprocess.h](https://github.com/sheredom/subprocess.h),
the only true header-only C(++) subprocess library I could find!