# CMake Python scripting frontend experiment

**URL:** https://discourse.cmake.org/t/cmake-python-scripting-frontend-experiment/8643
**Category:** Development
**Created:** [July 30, 2023, 9:31pm UTC](https://discourse.cmake.org/t/cmake-python-scripting-frontend-experiment/8643 "2023-07-30T21:31:51Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![ignus2](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ignus2/32/3075_2.png) [@ignus2](https://discourse.cmake.org/u/ignus2)
#### Post date: [July 30, 2023, 9:31pm UTC](https://discourse.cmake.org/t/cmake-python-scripting-frontend-experiment/8643/1 "2023-07-30T21:31:51Z")

</div>

This has come a couple times in the past but now something actually usable is here.

> **[GitHub - ignus2/CMake: CMake Python fronted proof-of-concept](https://github.com/ignus2/CMake/tree/cmakepy)**
>
> cmakepy

I extended CMake with an embedded Python interpreter that allows optionally replacing parts (or the whole) of the configure process with Python. No grand plans, endless discussions, politics, just working code - proof of concept mind you! - you can try out right now.

```auto
#!cmakepy
import cmake

cmake.fn.message("STATUS", "Hello from CMake python")

cmake.cmake_minimum_required("3.25")
cmake.project("pytest", version="0.1", description="Hello from CMake python", languages=["C","CXX"])
cmake.add_executable("pytest", ["main.cpp"])

```

The full CMake command interface is available, so any CMake function can be called from python.

**Works on any file normally executed by CMake**

Just put the text `#!cmakepy` as the first line in any script and it’ll be treated as Python. This includes any file included by CMake `include()` or `add_subdirectory()`.  
This also means that to execute subdir scripts (added by add\_subdirectory()) CMakeLists.txt is still used. Use `#!cmakepy` and it’ll be executed as Python.  
So no CMakeLists.py for now. (Why? Because it was easier to do it this way at the moment…)

**From CMake to Python and back**

Two-way interop between CMake script code and Python code also works, meaning CMake code can call Python functions and vice-versa.

`test.cmake`: Run with: `cmake -P test.cmake`

```auto
function(cmfunc)
    message("Back to CMake: ${ARGN}")
endfunction()

# let's call some python
include(${CMAKE_CURRENT_LIST_DIR}/pyfunc.cmake.py)
pyfunc(first "second;2" third and the;rest "of;the" args)

```

`pyfunc.cmake.py`:

```auto
#!cmakepy
import cmake

def pyfunc(arg1, arg2, arg3, *args):
    print("We're in python now!")
    print(f" arg1 : {arg1}")
    print(f" arg2 : {arg2}")
    print(f" arg3 : {arg3}")
    print(f" *args: {args}")
    # let's call back some CMake
    cmake.fn.cmfunc("Hi", "from", "python")

cmake.export_function(pyfunc)

```

**Where’s the documentation?**

Nowhere, yet. The above should get anyone started.  
The first example above uses hand-written python wrappers (except for message), but those are just a few dummies for now. The raw CMake API and any user-defined CMake functions are available through cmake.fn.XYZ() (note the “.fn.” !).  
Other than that, take a look at `<installdir>/share/cmake-3.27/Modules/CMakePy/cmake.py` for what’s available.

Additional features include: CMake variable access (get/set), scoping between cmake/python function calls, exceptions (propagating through cmake/python boundaries). As to how well they work: YMMV!

**Why do all this?**

To experiment. To be able to better answer “what if?” questions like “What if CMake had another frontend language?”. Now it does - sort of.

Because it is optional and non-intrusive, it’s possible to augment any existing CMake project of any size with Python snippets to experiment with all sorts of scenarios. That’s the primary intent of this experiment.

Have fun!

---

<div class="post-metadata">

### Author: ![cristianadam](https://discourse.cmake.org/user_avatar/discourse.cmake.org/cristianadam/32/124_2.png) [@cristianadam](https://discourse.cmake.org/u/cristianadam)
#### Post date: [July 31, 2023, 1:02pm UTC](https://discourse.cmake.org/t/cmake-python-scripting-frontend-experiment/8643/2 "2023-07-31T13:02:07Z")

</div>

See also [neek78/pycmake: python vs cmake (github.com)](https://github.com/neek78/pycmake) and the corresponding reddit discussion [So I made a branch of CMake that supports Python scripting in addition to regular CMake script : cpp (reddit.com)](https://www.reddit.com/r/cpp/comments/159a61f/so_i_made_a_branch_of_cmake_that_supports_python/)

---

<div class="post-metadata">

### Author: ![ignus2](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ignus2/32/3075_2.png) [@ignus2](https://discourse.cmake.org/u/ignus2)
#### Post date: [July 31, 2023, 1:31pm UTC](https://discourse.cmake.org/t/cmake-python-scripting-frontend-experiment/8643/3 "2023-07-31T13:31:04Z")

</div>

Well well, what are the odds?  
That experiment seems have taken a more opinionated and grand approach, while I took a minimalistic one (the diff size of that branch against mainline CMake is 340k excluding README.rst, mine is 17k), even though the underlying idea is the same. Yet that one doesn’t seems to allow to include() python scripts from CMake, though I don’t think it’d be difficult to do that there either.  
My intent was to get it going with as little code as possible with as little modifications to core CMake functionality as possible (the changes required in existing CMake code itself is around ~50 lines, all the rest is isolated in cmCMakePy.cxx and that itself is also not that much ~200 lines).  
Try both and see which one you prefer.
