diff --git a/CMakeLists.txt b/CMakeLists.txt index 73bb07147..e69844b11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,12 +219,16 @@ endif() # ------------------------------------- # Find libreadline -find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE}) -if(HAVE_LIBREADLINE) - set(LIB_LIBREADLINE ${HAVE_LIBREADLINE}) - find_library(LIB_NCURSES NAMES ncurses) -elseif(MSVC) - set(HAVE_LIBREADLINE 1) +if(MSVC) + set(HAVE_LIBREADLINE "Embedded MSVC") +elseif(MINGW) + set(HAVE_LIBREADLINE "Embedded MINGW") +else() + find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE}) + if(HAVE_LIBREADLINE) + set(LIB_LIBREADLINE ${HAVE_LIBREADLINE}) + find_library(LIB_NCURSES NAMES ncurses) + endif() endif() #------------------------------------- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 02bad6894..ef0712741 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,9 +50,15 @@ endif() include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) add_compile_definitions(CONFIG_DIR=\"${CONFIG_DIR}\") + +set(EXTRA_WINDOWS_SOURCES) +set(EXTRA_WINDOWS_INCLUDES) +set(EXTRA_WINDOWS_RESOURCES) +set(EXTRA_WINDOWS_LIBRARIES) + if(WIN32 OR MINGW) - set(EXTRA_WINDOWS_RESOURCES "${PROJECT_BINARY_DIR}/src/windows.rc") - set(EXTRA_WINDOWS_LIBRARIES setupapi hid ws2_32) + list(APPEND EXTRA_WINDOWS_RESOURCES "${PROJECT_BINARY_DIR}/src/windows.rc") + list(APPEND EXTRA_WINDOWS_LIBRARIES setupapi hid ws2_32) endif() if(MSVC) @@ -66,15 +72,20 @@ if(MSVC) add_compile_options(/wd4244) # warning C4244: conversion from '...' to '...', possible loss of data add_compile_options(/wd4267) # warning C4267: conversion from '...' to '...', possible loss of data - set(EXTRA_WINDOWS_SOURCES ${EXTRA_WINDOWS_SOURCES} + list(APPEND EXTRA_WINDOWS_SOURCES "msvc/getopt.c" "msvc/gettimeofday.c" "msvc/usleep.cpp" "msvc/readline.cpp" ) - set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES} - "msvc" - ) + list(APPEND EXTRA_WINDOWS_INCLUDES "msvc") +elseif(MINGW) + enable_language(CXX) + + set(LIB_MATH m) + add_compile_options(-Wall -Wextra -Wno-unused-parameter) + list(APPEND EXTRA_WINDOWS_SOURCES "mingw/readline.cpp") + list(APPEND EXTRA_WINDOWS_INCLUDES "mingw") else() set(LIB_MATH m) add_compile_options(-Wall -Wextra -Wno-unused-parameter) @@ -260,7 +271,7 @@ add_library(libavrdude xbee.c ${FLEX_Parser_OUTPUTS} ${BISON_Parser_OUTPUTS} - "${EXTRA_WINDOWS_SOURCES}" + ${EXTRA_WINDOWS_SOURCES} ) set_target_properties(libavrdude PROPERTIES @@ -274,8 +285,9 @@ target_include_directories(libavrdude PUBLIC "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}" "${LIBUSB_COMPAT_DIR}" - "${EXTRA_WINDOWS_INCLUDES}" + ${EXTRA_WINDOWS_INCLUDES} ) target_link_libraries(libavrdude @@ -302,11 +314,15 @@ add_executable(avrdude developer_opts_private.h whereami.c whereami.h - "${EXTRA_WINDOWS_RESOURCES}" + ${EXTRA_WINDOWS_RESOURCES} ) target_link_libraries(avrdude PUBLIC libavrdude) +if(MINGW) + target_link_options(avrdude PRIVATE -static) +endif() + # ===================================== # Install # ===================================== diff --git a/src/mingw/readline.cpp b/src/mingw/readline.cpp new file mode 100644 index 000000000..4fed1b1e5 --- /dev/null +++ b/src/mingw/readline.cpp @@ -0,0 +1,95 @@ +// +// readline.cpp +// Copyright (C) 2022 Marius Greuel +// SPDX-License-Identifier: GPL-2.0-or-later +// + +#include +#include +#include +#include +#include +#include +#include "readline/readline.h" +#include "readline/history.h" + +int rl_readline_version = 0x0502; + +static rl_vcpfunc_t* rl_handler; +static std::unique_ptr rl_thread; +static std::mutex rl_mutex; +static std::string rl_line; +static bool rl_has_line = false; + +static void get_line_thread() +{ + std::string line; + std::getline(std::cin, line); + + const std::lock_guard lock(rl_mutex); + rl_line = line; + rl_has_line = true; +} + +static void call_handler(const char* string) +{ + if (rl_thread) + { + rl_thread->join(); + rl_thread = nullptr; + } + + if (rl_handler != nullptr) + { + if (string == nullptr) + { + rl_handler(nullptr); + } + else + { + rl_handler(_strdup(string)); + } + } +} + +int rl_input_available(void) +{ + return 1; +} + +void rl_callback_read_char(void) +{ + if (std::cin.eof()) + { + call_handler(nullptr); + } + else if (!rl_thread) + { + rl_thread = std::make_unique(get_line_thread); + } + else + { + const std::lock_guard lock(rl_mutex); + if (rl_has_line) + { + rl_has_line = false; + call_handler(rl_line.c_str()); + } + } +} + +void rl_callback_handler_install(char* prompt, rl_vcpfunc_t* handler) +{ + rl_handler = handler; + + std::cout << prompt; +} + +void rl_callback_handler_remove(void) +{ + rl_handler = nullptr; +} + +void add_history(const char*) +{ +} diff --git a/src/mingw/readline/history.h b/src/mingw/readline/history.h new file mode 100644 index 000000000..86a7b0a8c --- /dev/null +++ b/src/mingw/readline/history.h @@ -0,0 +1,17 @@ +// +// history.h +// Copyright (C) 2022 Marius Greuel +// SPDX-License-Identifier: GPL-2.0-or-later +// + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void add_history(const char* string); + +#ifdef __cplusplus +} +#endif diff --git a/src/mingw/readline/readline.h b/src/mingw/readline/readline.h new file mode 100644 index 000000000..6a7d7a555 --- /dev/null +++ b/src/mingw/readline/readline.h @@ -0,0 +1,24 @@ +// +// readline.h +// Copyright (C) 2022 Marius Greuel +// SPDX-License-Identifier: GPL-2.0-or-later +// + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (rl_vcpfunc_t)(char* line); + +extern int rl_readline_version; + +int rl_input_available(void); +void rl_callback_read_char(void); +void rl_callback_handler_install(char* prompt, rl_vcpfunc_t* handler); +void rl_callback_handler_remove(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/term.c b/src/term.c index 6242b1457..c614ce22c 100644 --- a/src/term.c +++ b/src/term.c @@ -2086,7 +2086,7 @@ static int term_running; // Any character in standard input available (without sleeping)? static int readytoread() { -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(MINGW) return rl_input_available(); #elif defined(WIN32) HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);