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)
|
target_compile_definitions(mcrogueface PRIVATE Py_ENABLE_SHARED Py_PYCONFIG_H)
|
||||||
endif()
|
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)
|
if(WIN32 AND NOT MCRF_CROSS_WINDOWS)
|
||||||
# MSVC-specific flags
|
# MSVC-specific flags
|
||||||
set_target_properties(mcrogueface PROPERTIES
|
if(NOT MCRF_WINDOWS_CONSOLE)
|
||||||
WIN32_EXECUTABLE TRUE
|
set_target_properties(mcrogueface PROPERTIES
|
||||||
LINK_FLAGS "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
|
WIN32_EXECUTABLE TRUE
|
||||||
|
LINK_FLAGS "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
|
||||||
|
endif()
|
||||||
elseif(MCRF_CROSS_WINDOWS)
|
elseif(MCRF_CROSS_WINDOWS)
|
||||||
# MinGW cross-compilation: use -mwindows to hide console
|
# MinGW cross-compilation
|
||||||
set_target_properties(mcrogueface PROPERTIES
|
if(NOT MCRF_WINDOWS_CONSOLE)
|
||||||
WIN32_EXECUTABLE TRUE
|
# Release: use -mwindows to hide console
|
||||||
LINK_FLAGS "-mwindows")
|
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()
|
endif()
|
||||||
|
|
||||||
# Now the linker will find the libraries in the specified directory
|
# 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
|
#ifndef __PLATFORM
|
||||||
#define __PLATFORM
|
#define __PLATFORM
|
||||||
#define __PLATFORM_SET_PYTHON_SEARCH_PATHS 0
|
#define __PLATFORM_SET_PYTHON_SEARCH_PATHS 1
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
std::wstring executable_path()
|
std::wstring executable_path()
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,21 @@ GameEngine::GameEngine(const McRogueFaceConfig& cfg)
|
||||||
!config.python_mode;
|
!config.python_mode;
|
||||||
|
|
||||||
if (should_load_game) {
|
if (should_load_game) {
|
||||||
|
std::cerr << "[DEBUG] GameEngine: loading default game.py" << std::endl;
|
||||||
|
std::cerr.flush();
|
||||||
if (!Py_IsInitialized()) {
|
if (!Py_IsInitialized()) {
|
||||||
|
std::cerr << "[DEBUG] GameEngine: initializing Python API" << std::endl;
|
||||||
|
std::cerr.flush();
|
||||||
McRFPy_API::api_init();
|
McRFPy_API::api_init();
|
||||||
}
|
}
|
||||||
|
std::cerr << "[DEBUG] GameEngine: importing mcrfpy" << std::endl;
|
||||||
|
std::cerr.flush();
|
||||||
McRFPy_API::executePyString("import mcrfpy");
|
McRFPy_API::executePyString("import mcrfpy");
|
||||||
|
std::cerr << "[DEBUG] GameEngine: executing scripts/game.py" << std::endl;
|
||||||
|
std::cerr.flush();
|
||||||
McRFPy_API::executeScript("scripts/game.py");
|
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.
|
// Note: --exec scripts are NOT executed here.
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include "PyScene.h"
|
#include "PyScene.h"
|
||||||
#include "PythonObjectCache.h"
|
#include "PythonObjectCache.h"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <libtcod.h>
|
#include <libtcod.h>
|
||||||
|
|
||||||
|
|
@ -806,13 +807,26 @@ void McRFPy_API::executeScript(std::string filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* PScriptFile = fopen(script_path.string().c_str(), "r");
|
// Use std::ifstream + PyRun_SimpleString instead of PyRun_SimpleFile
|
||||||
if(PScriptFile) {
|
// PyRun_SimpleFile has compatibility issues with MinGW-compiled code
|
||||||
PyRun_SimpleFile(PScriptFile, script_path.string().c_str());
|
std::ifstream file(script_path);
|
||||||
fclose(PScriptFile);
|
if (!file.is_open()) {
|
||||||
} else {
|
|
||||||
std::cout << "Failed to open script: " << script_path.string() << std::endl;
|
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()
|
void McRFPy_API::api_shutdown()
|
||||||
|
|
|
||||||
40
src/main.cpp
40
src/main.cpp
|
|
@ -7,6 +7,7 @@
|
||||||
#include "PyTexture.h"
|
#include "PyTexture.h"
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
|
|
@ -18,7 +19,6 @@ int main(int argc, char* argv[])
|
||||||
McRogueFaceConfig config;
|
McRogueFaceConfig config;
|
||||||
CommandLineParser parser(argc, argv);
|
CommandLineParser parser(argc, argv);
|
||||||
|
|
||||||
// Parse arguments
|
|
||||||
auto parse_result = parser.parse(config);
|
auto parse_result = parser.parse(config);
|
||||||
if (parse_result.should_exit) {
|
if (parse_result.should_exit) {
|
||||||
return parse_result.exit_code;
|
return parse_result.exit_code;
|
||||||
|
|
@ -128,15 +128,45 @@ int run_python_interpreter(const McRogueFaceConfig& config)
|
||||||
}
|
}
|
||||||
else if (!config.script_path.empty()) {
|
else if (!config.script_path.empty()) {
|
||||||
// Execute script file (sys.argv already set at init time)
|
// Execute script file (sys.argv already set at init time)
|
||||||
FILE* fp = fopen(config.script_path.string().c_str(), "r");
|
// Note: Using PyRun_SimpleString instead of PyRun_SimpleFile for better
|
||||||
if (!fp) {
|
// 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 << "mcrogueface: can't open file '" << config.script_path << "': ";
|
||||||
std::cerr << "[Errno " << errno << "] " << strerror(errno) << std::endl;
|
std::cerr << "[Errno " << errno << "] " << strerror(errno) << std::endl;
|
||||||
|
delete engine;
|
||||||
return 1;
|
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());
|
// Set __file__ before execution
|
||||||
fclose(fp);
|
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) {
|
if (config.interactive_mode) {
|
||||||
// Even if script had SystemExit, continue to interactive mode
|
// Even if script had SystemExit, continue to interactive mode
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue