From 4bd3aa7f80e78ca8a5bcfbdebe0e32b3516d075a Mon Sep 17 00:00:00 2001
From: Christoph Alt <christoph.alt@fau.de>
Date: Thu, 20 Feb 2025 18:11:51 +0100
Subject: [PATCH] Moved the bootstrapping of a pystencilssfg installation to
 another file

---
 .../cmake/FindPystencilsSfg.cmake             | 58 ----------------
 standalone/CMakeLists.txt                     | 67 +++++++++++++++++++
 standalone/requirements.txt                   |  5 ++
 tests/integration/test_cmake.py               | 13 +---
 4 files changed, 73 insertions(+), 70 deletions(-)
 create mode 100644 standalone/CMakeLists.txt
 create mode 100644 standalone/requirements.txt

diff --git a/src/pystencilssfg/cmake/FindPystencilsSfg.cmake b/src/pystencilssfg/cmake/FindPystencilsSfg.cmake
index 8790c9d..5efae7a 100644
--- a/src/pystencilssfg/cmake/FindPystencilsSfg.cmake
+++ b/src/pystencilssfg/cmake/FindPystencilsSfg.cmake
@@ -3,9 +3,6 @@ Find-Module for pystencils-sfg.
 
 # Setting the Python interpreter
 
-If the cache CODEGEN_PRIVATE_VENV is true, it will try to create to a own python venv and install the requirements from `CODEGEN_VENV_REQUIREMENTS`.
-If this file does not exists it will download pystencilssfg and pystencils from `PystencilsSfg_URL` and `Pystencils_URL`
-
 If the cache entry PystencilsSfg_PYTHON_INTERPRETER is set, e.g. via the commandline
 (`-DPystencilsSfg_PYTHON_INTERPRETER=<...>`), its value be taken as the Python interpreter
 used to find and run pystencils-sfg.
@@ -17,66 +14,11 @@ If none of these is set, a Python interpreter will be selected using the `FindPy
 
 #]]
 
-set(CODEGEN_PRIVATE_VENV ON
-    CACHE BOOL
-    "Create a private virtual Python environment inside the build tree for code generation"
-)
-if (DEFINED CACHE{PystencilsSfg_PYTHON_INTERPRETER})
-    set( CODEGEN_PRIVATE_VENV OFF)
-elseif(DEFINED PystencilsSfg_PYTHON_PATH)
-    set( CODEGEN_PRIVATE_VENV OFF)
-endif()
-
 if(NOT DEFINED CACHE{PystencilsSfg_PYTHON_INTERPRETER})
     #   The Python interpreter cache variable is not set externally, so...
     if(DEFINED PystencilsSfg_PYTHON_PATH)
         #   ... either initialize it from the hint variable ...
         set( _sfg_cache_python_init ${PystencilsSfg_PYTHON_PATH} )
-
-    elseif (CODEGEN_PRIVATE_VENV)
-        #   ... or create an own venv ...
-
-        set(CODEGEN_VENV_PATH ${CMAKE_CURRENT_BINARY_DIR}/codegen-venv CACHE PATH "Location of the virtual environment used for code generation")
-        set(_venv_python_exe ${CODEGEN_VENV_PATH}/bin/python)
-
-        find_package( Python COMPONENTS Interpreter REQUIRED )
-
-        if(NOT _sfg_private_venv_done)
-            message( STATUS "Setting up Python virtual environment at ${CODEGEN_VENV_PATH}" )
-
-            #   Create the venv and register its interpreter with pystencils-sfg
-            if(NOT EXISTS ${CODEGEN_VENV_PATH})
-                execute_process(
-                COMMAND ${Python_EXECUTABLE} -m venv ${CODEGEN_VENV_PATH}
-                )
-            endif()
-
-
-            set(CODEGEN_VENV_REQUIREMENTS ${PROJECT_SOURCE_DIR}/requirements.txt CACHE FILEPATH "Location of the requirements installed in the virtual environment used for code generation")
-            if (EXISTS ${CODEGEN_VENV_REQUIREMENTS})
-                message( STATUS "Installing required Python packages from ${CODEGEN_VENV_REQUIREMENTS}" )
-                execute_process( COMMAND ${_venv_python_exe} -m pip install -r ${CODEGEN_VENV_REQUIREMENTS} OUTPUT_QUIET)
-            else()
-                set(Pystencils_URL "git+https://i10git.cs.fau.de/pycodegen/pystencils.git@v2.0-dev" CACHE STRING "Location of pystencils to installed in the virtual environment used for code generation")
-                set(PystencilsSfg_URL "git+https://i10git.cs.fau.de/pycodegen/pystencils-sfg.git" CACHE STRING "Location of pystencils-sfg to installed in the virtual environment used for code generation")
-
-                message( STATUS "Installing required Pystencils from ${Pystencils_URL}" )
-                execute_process(
-                    COMMAND ${_venv_python_exe} -m pip install "${Pystencils_URL}"
-                    OUTPUT_QUIET
-                )
-                message( STATUS "Installing required Pystencils-sfg from ${PystencilsSfg_URL}" )
-                execute_process(
-                    COMMAND ${_venv_python_exe} -m pip install "${PystencilsSfg_URL}"
-                    OUTPUT_QUIET
-                )
-            endif()
-
-            set( _sfg_private_venv_done TRUE CACHE BOOL "" )
-            mark_as_advanced(_sfg_private_venv_done)
-        endif()
-        set(_sfg_cache_python_init ${_venv_python_exe})
-
     else()
         #   ... or, if that is also unset, use the system Python
         find_package( Python COMPONENTS Interpreter REQUIRED )
diff --git a/standalone/CMakeLists.txt b/standalone/CMakeLists.txt
new file mode 100644
index 0000000..5e92833
--- /dev/null
+++ b/standalone/CMakeLists.txt
@@ -0,0 +1,67 @@
+cmake_minimum_required( VERSION 3.24 )
+project(PystencilsSfg_Standalone)
+
+set(CODEGEN_PRIVATE_VENV ON
+    CACHE BOOL
+    "Create a private virtual Python environment inside the build tree for code generation"
+)
+if (DEFINED CACHE{PystencilsSfg_PYTHON_INTERPRETER})
+	set( CACHE{CODEGEN_PRIVATE_VENV} OFF)
+elseif(DEFINED PystencilsSfg_PYTHON_PATH)
+	set( CACHE{CODEGEN_PRIVATE_VENV} OFF)
+endif()
+
+function(codegen_venv_install)
+    if(NOT CODEGEN_PRIVATE_VENV)
+        return()
+    endif()
+
+    if(NOT _sfg_private_venv_done)
+        message( FATAL_ERROR "The private virtual environment for code generation was not initialized yet" )
+    endif()
+
+    execute_process(
+	COMMAND ${PystencilsSfg_PYTHON_INTERPRETER} -m pip install ${ARGV}
+    )
+endfunction()
+
+
+if (CODEGEN_PRIVATE_VENV)
+
+	set(CODEGEN_VENV_PATH ${CMAKE_CURRENT_BINARY_DIR}/codegen-venv CACHE PATH "Location of the virtual environment used for code generation")
+	set(_venv_python_exe ${CODEGEN_VENV_PATH}/bin/python)
+	set(CODEGEN_VENV_PYTHON ${_venv_python_exe})
+
+	find_package( Python COMPONENTS Interpreter REQUIRED )
+
+	if(NOT _sfg_private_venv_done)
+		message( STATUS "Setting up Python virtual environment at ${CODEGEN_VENV_PATH}" )
+
+		#   Create the venv and register its interpreter with pystencils-sfg
+		if(NOT EXISTS ${CODEGEN_VENV_PATH})
+			execute_process( COMMAND ${Python_EXECUTABLE} -m venv ${CODEGEN_VENV_PATH})
+		endif()
+
+
+		set(CODEGEN_VENV_REQUIREMENTS ${PROJECT_SOURCE_DIR}/requirements.txt CACHE FILEPATH "Location of the requirements installed in the virtual environment used for code generation")
+		if (EXISTS ${CODEGEN_VENV_REQUIREMENTS})
+			message( STATUS "Installing required Python packages from ${CODEGEN_VENV_REQUIREMENTS}" )
+			execute_process( COMMAND ${_venv_python_exe} -m pip install -r ${CODEGEN_VENV_REQUIREMENTS} OUTPUT_QUIET)
+		else()
+			message( WARNING "Could not find ${CODEGEN_VENV_REQUIREMENTS}" )
+		endif()
+
+		# get the find pythonsfg file
+		execute_process( 
+			COMMAND ${CODEGEN_VENV_PATH}/bin/sfg-cli cmake make-find-module
+			WORKING_DIRECTORY ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}
+		)
+		# renaming it
+		file(RENAME ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/FindPystencilsSfg.cmake ${CMAKE_FIND_PACKAGE_REDIRECTS_DIR}/pystencilssfg-config.cmake)
+
+		set( _sfg_private_venv_done TRUE CACHE BOOL "" )
+		mark_as_advanced(_sfg_private_venv_done)
+	endif()
+	set(_sfg_cache_python_init ${_venv_python_exe})
+	set(PystencilsSfg_PYTHON_INTERPRETER ${_sfg_cache_python_init} CACHE PATH "Path to the Python executable used to run pystencils-sfg")
+endif()
diff --git a/standalone/requirements.txt b/standalone/requirements.txt
new file mode 100644
index 0000000..82b06ee
--- /dev/null
+++ b/standalone/requirements.txt
@@ -0,0 +1,5 @@
+py-cpuinfo
+# pystencils 2.0 Development Branch
+git+https://i10git.cs.fau.de/pycodegen/pystencils.git@4876f0b774d38fe7644f2b64f80f1291ffa0fa08
+# pystencils-sfg
+git+https://i10git.cs.fau.de/pycodegen/pystencils-sfg.git@dcb77258670abe5bc87f2bd80761594eb304cb90
diff --git a/tests/integration/test_cmake.py b/tests/integration/test_cmake.py
index 05ff2d5..94853ac 100644
--- a/tests/integration/test_cmake.py
+++ b/tests/integration/test_cmake.py
@@ -18,7 +18,7 @@ def test_cmake_project(tmp_path, config_source):
     result = subprocess.run(obtain_find_module_cmd, cwd=CMAKE_PROJECT_DIR)
     assert result.returncode == 0
 
-    cmake_configure_cmd = ["cmake", "-S", CMAKE_PROJECT_DIR, "-B", str(tmp_path), "-DCODEGEN_PRIVATE_VENV=OFF"]
+    cmake_configure_cmd = ["cmake", "-S", CMAKE_PROJECT_DIR, "-B", str(tmp_path)]
     if config_source is not None:
         cmake_configure_cmd.append(f"-D{config_source}=ON")
     configure_result = subprocess.run(cmake_configure_cmd)
@@ -49,14 +49,3 @@ def test_cmake_project(tmp_path, config_source):
     custom_dir_output = tmp_path / "my-output" / "CustomDirTest.hpp"
     assert custom_dir_output.exists()
     assert "#define NOTHING" in custom_dir_output.read_text()
-
-
-def test_cmake_project_autoinstall(tmp_path):
-    obtain_find_module_cmd = ["sfg-cli", "cmake", "make-find-module"]
-
-    result = subprocess.run(obtain_find_module_cmd, cwd=CMAKE_PROJECT_DIR)
-    assert result.returncode == 0
-
-    cmake_configure_cmd = ["cmake", "-S", CMAKE_PROJECT_DIR, "-B", str(tmp_path), "-DCODEGEN_PRIVATE_VENV=ON"]
-    configure_result = subprocess.run(cmake_configure_cmd)
-    assert configure_result.returncode == 0
-- 
GitLab