Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support cross-compiling with MinGW #72

Merged
merged 1 commit into from Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -33,6 +33,31 @@ jobs:
- name: Run Tests
run: ctest --test-dir infoware/build

mingw:
name: Linux MinGW (${{matrix.arch.pkg}})
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
arch:
- { pkg: i686, paths: i686 }
- { pkg: x86-64, paths: x86_64 }

steps:
- name: Checkout infoware
uses: actions/checkout@v2
with:
path: infoware

- name: Install apt packages
run: sudo apt update && sudo apt install -y cmake ninja-build g++-mingw-w64-${{matrix.arch.pkg}}

- name: Generate CMake
run: mkdir infoware/build && cd infoware/build && cmake -DCMAKE_BUILD_TYPE=Release -DMINGW_ARCH=${{matrix.arch.paths}} -DCMAKE_TOOLCHAIN_FILE=../.github/workflows/mingw.cmake -G Ninja ..

- name: Build Project
run: cmake --build infoware/build

macos:
name: macOS ${{matrix.os}} ${{matrix.arch}}
runs-on: ${{matrix.os}}
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/mingw.cmake
@@ -0,0 +1,13 @@
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR ${MINGW_ARCH})
set(MINGW_TOOLCHAIN ${MINGW_ARCH}-w64-mingw32)

set(CMAKE_FIND_ROOT_PATH /usr/${MINGW_TOOLCHAIN})
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_C_COMPILER ${MINGW_TOOLCHAIN}-gcc)
set(CMAKE_CXX_COMPILER ${MINGW_TOOLCHAIN}-g++)
set(CMAKE_RC_COMPILER ${MINGW_TOOLCHAIN}-windres)
set(CMAKE_MC_COMPILER ${MINGW_TOOLCHAIN}-windmc)
89 changes: 50 additions & 39 deletions CMakeLists.txt
Expand Up @@ -84,51 +84,62 @@ if(NOT Git_FOUND) # Could be pre-injected
find_package(Git)
endif()

set(INFOWARE_PCI_DATA_DIR infoware_generated CACHE PATH "Output directory for the PCI ids generator")
set(INFOWARE_PCI_DATA_HPP pci_data.hpp)
set(INFOWARE_PCI_DATA_GEN "${INFOWARE_PCI_DATA_DIR}/${INFOWARE_PCI_DATA_HPP}")
set(infoware_pci_ids_error "\
The pci.ids file, downloadable from https://github.com/pciutils/pciids or http://pci-ids.ucw.cz, is required for building infoware, \
and cloned automatically from that GitHub repository by default.\n\
To use a local copy, set INFOWARE_PCI_IDS_PATH to its location.")
if(INFOWARE_PCI_IDS_PATH)
if(NOT EXISTS "${INFOWARE_PCI_IDS_PATH}")
message(WARNING "The specified pci.ids file INFOWARE_PCI_IDS_PATH=${INFOWARE_PCI_IDS_PATH} doesn't seem to exist.")
endif()
set(infoware_pci_ids_file "${INFOWARE_PCI_IDS_PATH}")
elseif(NOT Git_FOUND)
message(SEND_ERROR "Couldn't find a usable git executable in the environment, and the CMake variable INFOWARE_PCI_IDS_PATH is empty.\n${infoware_pci_ids_error}")
else()
# Thanks, @griwes
set(infoware_pci_ids_file "${CMAKE_CURRENT_BINARY_DIR}/pciids/pci.ids")
if(EXISTS "${infoware_pci_ids_file}")
execute_process(COMMAND "${GIT_EXECUTABLE}" remote set-url origin "${INFOWARE_PCI_IDS_REPOSITORY}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pciids")
execute_process(COMMAND "${GIT_EXECUTABLE}" pull
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pciids"
RESULT_VARIABLE infoware_git_pciids_clone_err)
if(NOT CMAKE_CROSSCOMPILING)
if(INFOWARE_PCI_IDS_PATH)
if(NOT EXISTS "${INFOWARE_PCI_IDS_PATH}")
message(WARNING "The specified pci.ids file INFOWARE_PCI_IDS_PATH=${INFOWARE_PCI_IDS_PATH} doesn't seem to exist.")
endif()
set(infoware_pci_ids_file "${INFOWARE_PCI_IDS_PATH}")
elseif(NOT Git_FOUND)
message(SEND_ERROR "Couldn't find a usable git executable in the environment, and the CMake variable INFOWARE_PCI_IDS_PATH is empty.\n${infoware_pci_ids_error}")
else()
execute_process(COMMAND "${GIT_EXECUTABLE}" clone "${INFOWARE_PCI_IDS_REPOSITORY}" -- pciids
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
RESULT_VARIABLE infoware_git_pciids_clone_err)
endif()
if(infoware_git_pciids_clone_err)
message(SEND_ERROR "Cloning/pulling pciids repository from ${INFOWARE_PCI_IDS_REPOSITORY} failed with ${infoware_git_pciids_clone_err}.\n${infoware_pci_ids_error}")
# Thanks, @griwes
set(infoware_pci_ids_file "${CMAKE_CURRENT_BINARY_DIR}/pciids/pci.ids")
if(EXISTS "${infoware_pci_ids_file}")
execute_process(COMMAND "${GIT_EXECUTABLE}" remote set-url origin "${INFOWARE_PCI_IDS_REPOSITORY}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pciids")
execute_process(COMMAND "${GIT_EXECUTABLE}" pull
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pciids"
RESULT_VARIABLE infoware_git_pciids_clone_err)
else()
execute_process(COMMAND "${GIT_EXECUTABLE}" clone "${INFOWARE_PCI_IDS_REPOSITORY}" -- pciids
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
RESULT_VARIABLE infoware_git_pciids_clone_err)
endif()
if(infoware_git_pciids_clone_err)
message(SEND_ERROR "Cloning/pulling pciids repository from ${INFOWARE_PCI_IDS_REPOSITORY} failed with ${infoware_git_pciids_clone_err}.\n${infoware_pci_ids_error}")
endif()
endif()
endif()

add_executable(infoware_pci_generator tools/pci_generator.cpp)
set_target_properties(infoware_pci_generator PROPERTIES CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF)

set(INFOWARE_PCI_DATA_HPP pci_data.hpp)
set(INFOWARE_PCI_DATA_GEN "infoware_generated/${INFOWARE_PCI_DATA_HPP}")

add_custom_command(OUTPUT ${INFOWARE_PCI_DATA_GEN}
COMMAND ${CMAKE_COMMAND} -E make_directory infoware_generated/
COMMAND $<TARGET_FILE:infoware_pci_generator> "${infoware_pci_ids_file}" > "infoware_generated/pci_data.hpp"
DEPENDS "${infoware_pci_ids_file}"
COMMENT "Generating ${INFOWARE_PCI_DATA_HPP}")

add_custom_target(infoware_generate_pcis DEPENDS "${INFOWARE_PCI_DATA_GEN}")
add_executable(infoware_pci_generator tools/pci_generator.cpp)
set_target_properties(infoware_pci_generator PROPERTIES CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF)

add_custom_command(OUTPUT ${INFOWARE_PCI_DATA_GEN}
COMMAND ${CMAKE_COMMAND} -E make_directory "${INFOWARE_PCI_DATA_DIR}"
COMMAND $<TARGET_FILE:infoware_pci_generator> "${infoware_pci_ids_file}" > "${INFOWARE_PCI_DATA_GEN}"
DEPENDS "${infoware_pci_ids_file}"
COMMENT "Generating ${INFOWARE_PCI_DATA_HPP}")
add_custom_target(infoware_generate_pcis DEPENDS "${INFOWARE_PCI_DATA_GEN}")
else()
include(ExternalProject)
ExternalProject_Add(infoware_generate_pcis
SOURCE_DIR ${CMAKE_SOURCE_DIR}
PREFIX ${CMAKE_BINARY_DIR}/pci_generator
BINARY_DIR ${CMAKE_BINARY_DIR}/pci_generator
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target infoware_generate_pcis
INSTALL_COMMAND ""
BUILD_ALWAYS ON
CMAKE_ARGS -DINFOWARE_PCI_DATA_DIR:PATH=${CMAKE_BINARY_DIR}/${INFOWARE_PCI_DATA_DIR})
endif()
add_dependencies(infoware infoware_generate_pcis)


Expand All @@ -147,7 +158,7 @@ if(WIN32 AND NOT MSVC)
endif()

if(WIN32)
target_link_libraries(infoware PRIVATE gdi32 version Ole32 OleAut32 wbemuuid ntdll)
target_link_libraries(infoware PRIVATE gdi32 version ole32 oleaut32 wbemuuid ntdll)
endif()


Expand Down
55 changes: 29 additions & 26 deletions src/system/displays/displays_windows.cpp
Expand Up @@ -14,39 +14,42 @@
#include <windows.h>


std::vector<iware::system::display_t> iware::system::displays() {
const struct bundle {
HDC desktop_dc;
std::vector<iware::system::display_t> ret;
} bundle{GetDC(nullptr), {}};
iware::detail::quickscope_wrapper desktop_dc_deleter{[&]() { ReleaseDC(nullptr, bundle.desktop_dc); }};
struct bundle {
nabijaczleweli marked this conversation as resolved.
Show resolved Hide resolved
HDC desktop_dc;
std::vector<iware::system::display_t> ret;
};

EnumDisplayMonitors(
bundle.desktop_dc, nullptr,
[](auto, auto hdc, auto rect, auto userdata) {
auto& bundle = *reinterpret_cast<struct bundle*>(userdata);
static BOOL CALLBACK consume_one_display(HMONITOR, HDC hdc, LPRECT rect, LPARAM userdata) {
auto& bundle = *reinterpret_cast<struct bundle*>(userdata);

const unsigned int desktop_dpi = GetDeviceCaps(bundle.desktop_dc, LOGPIXELSX);
// https://blogs.msdn.microsoft.com/oldnewthing/20101013-00/?p=12543
const unsigned int desktop_bpp = GetDeviceCaps(bundle.desktop_dc, BITSPIXEL) * GetDeviceCaps(bundle.desktop_dc, PLANES);
const double desktop_refresh_rate = GetDeviceCaps(bundle.desktop_dc, VREFRESH);
const unsigned int desktop_dpi = GetDeviceCaps(bundle.desktop_dc, LOGPIXELSX);
// https://blogs.msdn.microsoft.com/oldnewthing/20101013-00/?p=12543
const unsigned int desktop_bpp = GetDeviceCaps(bundle.desktop_dc, BITSPIXEL) * GetDeviceCaps(bundle.desktop_dc, PLANES);
const double desktop_refresh_rate = GetDeviceCaps(bundle.desktop_dc, VREFRESH);


// Sometimes returns 0 – fall back to the desktop's globals if so.
const unsigned int monitor_dpi = GetDeviceCaps(hdc, LOGPIXELSX);
const unsigned int monitor_bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
const double monitor_refresh_rate = GetDeviceCaps(hdc, VREFRESH);
// Sometimes returns 0 – fall back to the desktop's globals if so.
const unsigned int monitor_dpi = GetDeviceCaps(hdc, LOGPIXELSX);
const unsigned int monitor_bpp = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
const double monitor_refresh_rate = GetDeviceCaps(hdc, VREFRESH);

const unsigned int width = std::abs(rect->right - rect->left);
const unsigned int height = std::abs(rect->bottom - rect->top);
const unsigned int width = std::abs(rect->right - rect->left);
const unsigned int height = std::abs(rect->bottom - rect->top);

// See http://stackoverflow.com/a/12654433/2851815 and up for DPI. In short: can't be done too too well, go with best solution.
bundle.ret.push_back({width, height, monitor_dpi ? monitor_dpi : desktop_dpi, monitor_bpp ? monitor_bpp : desktop_bpp,
monitor_refresh_rate ? monitor_refresh_rate : desktop_refresh_rate});
// See http://stackoverflow.com/a/12654433/2851815 and up for DPI. In short: can't be done too too well, go with best solution.
bundle.ret.push_back({width, height, monitor_dpi ? monitor_dpi : desktop_dpi, monitor_bpp ? monitor_bpp : desktop_bpp,
monitor_refresh_rate ? monitor_refresh_rate : desktop_refresh_rate});

return TRUE;
}

std::vector<iware::system::display_t> iware::system::displays() {
const struct bundle bundle {
GetDC(nullptr), {}
};
iware::detail::quickscope_wrapper desktop_dc_deleter{[&]() { ReleaseDC(nullptr, bundle.desktop_dc); }};

return TRUE;
},
reinterpret_cast<LPARAM>(&bundle));
EnumDisplayMonitors(bundle.desktop_dc, nullptr, &consume_one_display, reinterpret_cast<LPARAM>(&bundle));

return std::move(bundle.ret);
}
Expand Down