| #!/usr/bin/env -S cmake -P |
| # |
| # Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) |
| # |
| # SPDX-License-Identifier: BSD-2-Clause |
| # |
| |
| message("CMake REPL: Execute cmake commands interactively. (Ctrl-D to exit)") |
| |
| # If this file was included somewhere else then CMAKE_PARENT_LIST_FILE will be set |
| if(NOT "${CMAKE_PARENT_LIST_FILE}" STREQUAL "") |
| message(" Currently included in file: ${CMAKE_PARENT_LIST_FILE}") |
| set(state_dir ${CMAKE_BINARY_DIR}/.repl/) |
| set(history_file ${CMAKE_BINARY_DIR}/.repl/history) |
| else() |
| # If not included by anywhere else, then spew data into the user's home directory |
| # Calculate a thread id to allow running multiple instances |
| file(GLOB tids /proc/self/task/*) |
| list(GET tids 0 tid_path) |
| get_filename_component(tid ${tid_path} NAME) |
| set(state_dir "$ENV{HOME}/.cmakerepl/tid/") |
| set(history_file $ENV{HOME}/.cmakerepl/history) |
| endif() |
| |
| file(MAKE_DIRECTORY ${state_dir}) |
| file(TOUCH ${history_file}) |
| |
| set(prompt "> ") |
| |
| # Write a python read script out to disk. We use this to for obtaining user input |
| # it uses readline to provide history and line editing. Unfortunately it isn't |
| # featured enough to support multiline input. |
| file(WRITE ${state_dir}/read.py "from __future__ import print_function |
| import readline |
| f = open(\"${state_dir}/test\", 'w') |
| readline.read_history_file(\"${history_file}\") |
| try: |
| s = raw_input(\"${prompt}\") |
| print(s, file=f) |
| readline.write_history_file(\"${history_file}\") |
| except EOFError: |
| print(\"set(forever OFF)\", file=f) |
| ") |
| |
| # Declare a short hand run function for executing something on the shell |
| # if this starts name colliding with existing functions in scope it can just be deleted |
| function(run) |
| execute_process( |
| COMMAND ${ARGV} |
| INPUT_FILE /dev/stdin |
| OUTPUT_FILE /dev/stdout |
| ERROR_FILE /dev/stderr |
| ) |
| endfunction() |
| |
| # Start REPL. |
| # This calls the python script that prompts the user for input. |
| # The input is then written out to a file which cmake includes into itself |
| # Including the file results in its execution. |
| # Then we loop back again. |
| # Exiting is implemented by setting the loop variable to false when an EOF exception |
| # is caught in the python script. |
| set(forever ON) |
| while(forever) |
| execute_process( |
| COMMAND python ${state_dir}/read.py |
| INPUT_FILE /dev/stdin |
| OUTPUT_FILE /dev/stdout |
| ERROR_FILE /dev/stderr |
| ) |
| include(${state_dir}/test) |
| endwhile() |