mingw toolchain and final fixes for Windows. Closes #162
This commit is contained in:
parent
1f002e820c
commit
1438044c6a
6 changed files with 129 additions and 30 deletions
|
|
@ -135,17 +135,28 @@ if(WIN32 OR MCRF_CROSS_WINDOWS)
|
|||
target_compile_definitions(mcrogueface PRIVATE Py_ENABLE_SHARED Py_PYCONFIG_H)
|
||||
endif()
|
||||
|
||||
# On Windows, set subsystem to WINDOWS to hide console
|
||||
# On Windows, set subsystem to WINDOWS to hide console (release builds only)
|
||||
# Use -DMCRF_WINDOWS_CONSOLE=ON for debug builds with console output
|
||||
option(MCRF_WINDOWS_CONSOLE "Keep console window visible for debugging" OFF)
|
||||
|
||||
if(WIN32 AND NOT MCRF_CROSS_WINDOWS)
|
||||
# MSVC-specific flags
|
||||
if(NOT MCRF_WINDOWS_CONSOLE)
|
||||
set_target_properties(mcrogueface PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
LINK_FLAGS "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
|
||||
endif()
|
||||
elseif(MCRF_CROSS_WINDOWS)
|
||||
# MinGW cross-compilation: use -mwindows to hide console
|
||||
# MinGW cross-compilation
|
||||
if(NOT MCRF_WINDOWS_CONSOLE)
|
||||
# Release: use -mwindows to hide console
|
||||
set_target_properties(mcrogueface PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
LINK_FLAGS "-mwindows")
|
||||
else()
|
||||
# Debug: keep console for stdout/stderr output
|
||||
message(STATUS "Windows console enabled for debugging")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Now the linker will find the libraries in the specified directory
|
||||
|
|
|
|||
34
cmake/toolchains/mingw-w64-x86_64.cmake
Normal file
34
cmake/toolchains/mingw-w64-x86_64.cmake
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# CMake toolchain file for cross-compiling to Windows using MinGW-w64
|
||||
# Usage: cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/mingw-w64-x86_64.cmake ..
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
|
||||
# Specify the cross-compiler (use posix variant for std::mutex support)
|
||||
set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix)
|
||||
set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix)
|
||||
set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
|
||||
|
||||
# Target environment location
|
||||
set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
|
||||
|
||||
# Add MinGW system include directories for Windows headers
|
||||
include_directories(SYSTEM /usr/x86_64-w64-mingw32/include)
|
||||
|
||||
# Adjust search behavior
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
# Static linking of libgcc and libstdc++ to avoid runtime dependency issues
|
||||
# Enable auto-import for Python DLL data symbols
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
|
||||
|
||||
# Windows-specific defines
|
||||
add_definitions(-DWIN32 -D_WIN32 -D_WINDOWS)
|
||||
add_definitions(-DMINGW_HAS_SECURE_API)
|
||||
|
||||
# Disable console window for GUI applications (optional, can be overridden)
|
||||
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mwindows")
|
||||
2
deps/platform/windows/platform.h
vendored
2
deps/platform/windows/platform.h
vendored
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __PLATFORM
|
||||
#define __PLATFORM
|
||||
#define __PLATFORM_SET_PYTHON_SEARCH_PATHS 0
|
||||
#define __PLATFORM_SET_PYTHON_SEARCH_PATHS 1
|
||||
#include <windows.h>
|
||||
|
||||
std::wstring executable_path()
|
||||
|
|
|
|||
|
|
@ -65,11 +65,21 @@ GameEngine::GameEngine(const McRogueFaceConfig& cfg)
|
|||
!config.python_mode;
|
||||
|
||||
if (should_load_game) {
|
||||
std::cerr << "[DEBUG] GameEngine: loading default game.py" << std::endl;
|
||||
std::cerr.flush();
|
||||
if (!Py_IsInitialized()) {
|
||||
std::cerr << "[DEBUG] GameEngine: initializing Python API" << std::endl;
|
||||
std::cerr.flush();
|
||||
McRFPy_API::api_init();
|
||||
}
|
||||
std::cerr << "[DEBUG] GameEngine: importing mcrfpy" << std::endl;
|
||||
std::cerr.flush();
|
||||
McRFPy_API::executePyString("import mcrfpy");
|
||||
std::cerr << "[DEBUG] GameEngine: executing scripts/game.py" << std::endl;
|
||||
std::cerr.flush();
|
||||
McRFPy_API::executeScript("scripts/game.py");
|
||||
std::cerr << "[DEBUG] GameEngine: game.py execution complete" << std::endl;
|
||||
std::cerr.flush();
|
||||
}
|
||||
|
||||
// Note: --exec scripts are NOT executed here.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "PyScene.h"
|
||||
#include "PythonObjectCache.h"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <libtcod.h>
|
||||
|
||||
|
|
@ -806,13 +807,26 @@ void McRFPy_API::executeScript(std::string filename)
|
|||
}
|
||||
}
|
||||
|
||||
FILE* PScriptFile = fopen(script_path.string().c_str(), "r");
|
||||
if(PScriptFile) {
|
||||
PyRun_SimpleFile(PScriptFile, script_path.string().c_str());
|
||||
fclose(PScriptFile);
|
||||
} else {
|
||||
// Use std::ifstream + PyRun_SimpleString instead of PyRun_SimpleFile
|
||||
// PyRun_SimpleFile has compatibility issues with MinGW-compiled code
|
||||
std::ifstream file(script_path);
|
||||
if (!file.is_open()) {
|
||||
std::cout << "Failed to open script: " << script_path.string() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string script_content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
|
||||
// Set __file__ before execution
|
||||
PyObject* main_module = PyImport_AddModule("__main__");
|
||||
PyObject* main_dict = PyModule_GetDict(main_module);
|
||||
PyObject* py_filename = PyUnicode_FromString(script_path.string().c_str());
|
||||
PyDict_SetItemString(main_dict, "__file__", py_filename);
|
||||
Py_DECREF(py_filename);
|
||||
|
||||
PyRun_SimpleString(script_content.c_str());
|
||||
}
|
||||
|
||||
void McRFPy_API::api_shutdown()
|
||||
|
|
|
|||
40
src/main.cpp
40
src/main.cpp
|
|
@ -7,6 +7,7 @@
|
|||
#include "PyTexture.h"
|
||||
#include <Python.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
|
||||
// Forward declarations
|
||||
|
|
@ -18,7 +19,6 @@ int main(int argc, char* argv[])
|
|||
McRogueFaceConfig config;
|
||||
CommandLineParser parser(argc, argv);
|
||||
|
||||
// Parse arguments
|
||||
auto parse_result = parser.parse(config);
|
||||
if (parse_result.should_exit) {
|
||||
return parse_result.exit_code;
|
||||
|
|
@ -128,15 +128,45 @@ int run_python_interpreter(const McRogueFaceConfig& config)
|
|||
}
|
||||
else if (!config.script_path.empty()) {
|
||||
// Execute script file (sys.argv already set at init time)
|
||||
FILE* fp = fopen(config.script_path.string().c_str(), "r");
|
||||
if (!fp) {
|
||||
// Note: Using PyRun_SimpleString instead of PyRun_SimpleFile for better
|
||||
// cross-platform compatibility (PyRun_SimpleFile has issues with MinGW/Wine)
|
||||
|
||||
// Read file contents
|
||||
std::ifstream file(config.script_path);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "mcrogueface: can't open file '" << config.script_path << "': ";
|
||||
std::cerr << "[Errno " << errno << "] " << strerror(errno) << std::endl;
|
||||
delete engine;
|
||||
return 1;
|
||||
}
|
||||
std::string script_content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
|
||||
int result = PyRun_SimpleFile(fp, config.script_path.string().c_str());
|
||||
fclose(fp);
|
||||
// Set __file__ before execution
|
||||
PyObject* main_module = PyImport_AddModule("__main__");
|
||||
PyObject* main_dict = PyModule_GetDict(main_module);
|
||||
PyObject* py_filename = PyUnicode_FromString(config.script_path.string().c_str());
|
||||
PyDict_SetItemString(main_dict, "__file__", py_filename);
|
||||
Py_DECREF(py_filename);
|
||||
|
||||
int result = PyRun_SimpleString(script_content.c_str());
|
||||
|
||||
// Flush Python stdout/stderr to ensure output appears before engine->run() blocks
|
||||
PyObject* sys_module = PyImport_ImportModule("sys");
|
||||
if (sys_module) {
|
||||
PyObject* stdout_obj = PyObject_GetAttrString(sys_module, "stdout");
|
||||
if (stdout_obj) {
|
||||
PyObject_CallMethod(stdout_obj, "flush", NULL);
|
||||
Py_DECREF(stdout_obj);
|
||||
}
|
||||
PyObject* stderr_obj = PyObject_GetAttrString(sys_module, "stderr");
|
||||
if (stderr_obj) {
|
||||
PyObject_CallMethod(stderr_obj, "flush", NULL);
|
||||
Py_DECREF(stderr_obj);
|
||||
}
|
||||
Py_DECREF(sys_module);
|
||||
}
|
||||
|
||||
if (config.interactive_mode) {
|
||||
// Even if script had SystemExit, continue to interactive mode
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue