mstorsjo/llvm-mingw

Debugging with Wine

cristianadam opened this issue · 1 comments

With Qt Creator 14 one could use the CMAKE_CROSSCOMPILING_EMULATOR set to wine and have a CMake project compiling and running. In my case it was Windows x64 binary running on a Ubuntu 22.04 Arm64.

qtcreator14-cmake-presets-crosscompiling-emulator

I have tried with the 18.1.8 released version, also with lldb-dap, since lldb doesn't work due to missing python bindings in lldb, see #359.

But the debugger doesn't work.

CMakeLists.txt
cmake_minimum_required(VERSION 3.16)

project(Hello LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(Hello main.cpp)

add_custom_command(
    TARGET Hello POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SYSROOT}/bin/libc++.dll" ${CMAKE_BINARY_DIR}
    COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SYSROOT}/bin/libunwind.dll" ${CMAKE_BINARY_DIR}
)
CMakePresets.json
{
    "version": 4,
    "configurePresets":
    [
        {
            "name": "llvm-mingw",
            "displayName": "LLVM MinGW 18.1.8 x64",
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/build",
            "toolchainFile": "llvm-mingw.cmake",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug",
                "CMAKE_CROSSCOMPILING_EMULATOR": "/usr/bin/wine64"
            },
            "vendor": {
                "qt.io/QtCreator/1.0": {
                    "debugger": {
                        "DisplayName": "LLDB Dap 18.1.8 Debugger",
                        "Abis": ["arm-linux-generic-elf-64bit"],
                        "Binary": "$env{HOME}/llvm-mingw/bin/lldb-dap",
                        "EngineType": 1024,
                        "Version": "18.1.8"
                    }
                }
            }
        }
    ]
}
llvm-mingw.cmake
set(_prefix $ENV{HOME}/llvm-mingw/)

if(NOT CMAKE_SYSTEM_NAME)
  set(CMAKE_SYSTEM_NAME Windows)
endif()
if(NOT CMAKE_SYSTEM_PROCESSOR)
  set(CMAKE_SYSTEM_PROCESSOR x86_64)
endif()

set(CMAKE_SYSROOT "${_prefix}${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32" CACHE FILEPATH "" FORCE)

set(ENV{PKG_CONFIG_SYSROOT_DIR} "${CMAKE_SYSROOT}")
if($ENV{PKG_CONFIG_LIBDIR})
  set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig:$ENV{PKG_CONFIG_LIBDIR}")
else()
  set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig")
endif()

# set these before find_program!
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)

# search tools in prefix, then in system search paths
# note that the toolchain will be sourced multiple times and stuff like
# CMAKE_C_COMPILER might be cached - use temp variables with find_program
set(_linker lld)

set(_clang_path)
if(CMAKE_HOST_WIN32)
  set(_clang_path PATH_SUFFIXES LLVM/bin)
endif()

find_program(_clang_exe clang HINTS "${_prefix}bin" NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CACHE ${_clang_path})
find_program(_clangp_exe clang++ HINTS "${_prefix}bin" NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CACHE ${_clang_path})
find_program(_llvm_rc llvm-rc HINTS "${_prefix}bin" NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CACHE ${_clang_path})
find_program(_ld_linker ld.${_linker} HINTS "${_prefix}bin" NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CACHE ${_clang_path})

if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.20")
  cmake_path(GET _clang_exe PARENT_PATH _clang_path)
else()
  get_filename_component(_clang_path "${_clang_exe}" DIRECTORY)
endif()

# test if the system compiler is used
if(_clang_path STREQUAL "${_prefix}bin")
  set(CMAKE_ASM_COMPILER "${_clang_exe}")
  set(CMAKE_C_COMPILER "${_clang_exe}")
  set(CMAKE_CXX_COMPILER "${_clangp_exe}")
else()
  file(GLOB _respath "${_prefix}lib/clang/*")

  set(CMAKE_ASM_COMPILER "${_clang_exe}" "-resource-dir=${_respath}")
  set(CMAKE_C_COMPILER "${_clang_exe}" "-resource-dir=${_respath}")
  set(CMAKE_CXX_COMPILER "${_clangp_exe}" "-resource-dir=${_respath}")
endif()

set(CMAKE_RC_COMPILER "${_llvm_rc}")
set(CMAKE_LINKER "${_ld_linker}")

unset(_clang_path)
unset(_prefix)
unset(_clang_exe)
unset(_clangp_exe)
unset(_llvm_rc)
unset(_ld_linker)

set(CMAKE_C_COMPILER_TARGET ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32)
set(CMAKE_CXX_COMPILER_TARGET ${CMAKE_C_COMPILER_TARGET})
set(CMAKE_ASM_COMPILER_TARGET ${CMAKE_C_COMPILER_TARGET})

set(CMAKE_CXX_FLAGS_INIT "-stdlib=libc++")

if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.29")
  string(TOUPPER ${_linker} CMAKE_LINKER_TYPE)
  set(_linker)
else()
  set(_linker " -fuse-ld=${_linker}")
endif()

set(CMAKE_EXE_LINKER_FLAGS_INIT "--start-no-unused-arguments -stdlib=libc++ -rtlib=compiler-rt -unwindlib=libunwind --end-no-unused-arguments${_linker}")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT}")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT}")
unset(_linker)
main.cpp
#include <iostream>
#include <windows.h>

#if !defined(_M_X64)
#error "not a x86_64 compiler"
#endif

int main() {
  OSVERSIONINFO info{.dwOSVersionInfoSize = sizeof(OSVERSIONINFO)};
  ::GetVersionEx(&info);

  std::cout << "Hello Windows "
            << info.dwMajorVersion << "."
            << info.dwMinorVersion << "."
            << info.dwBuildNumber << " "
            << info.szCSDVersion << "\n";
}

Apparently one can use lldb to debug applications with wine, as seen at https://werat.dev/blog/debugging-wine-with-lldb-and-vscode/

But patches are required to get things up and running.

I think it would be great if LLVM-MinGW could have Linux and macOS toolchains that would have debugging working with wine!

The IDE will have to understand that wine is not the process to be debugged, and it should "remote connect" to the real process.
To date, I haven't found an IDE that covers this transparently, but that's where the work needs to be done.