diff --git a/CMakeLists.txt b/CMakeLists.txt
index 57b60c4f7791..ab6dbdb76df5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -172,7 +172,8 @@ include(detect_dependencies)
# ###############################
# Set UNIX (macOS or Linux) compiler flags (clang or gcc). Set optimization level for debug or release.
-if(UNIX)
+# MinGW is gcc as well, so it takes the same flags.
+if(UNIX OR MINGW)
message(STATUS "Checking supported compiler flags...")
enable_c_compile_option_if_supported("-Wall" "" "PRIVATE")
@@ -229,8 +230,20 @@ if(UNIX)
message(VERBOSE "COMPILE_OPTIONS_PRIVATE: ${COMPILE_OPTIONS_PRIVATE}")
message(VERBOSE "COMPILE_OPTIONS_PUBLIC: ${COMPILE_OPTIONS_PUBLIC}")
message(VERBOSE "COMPILE_OPTIONS_INTERFACE: ${COMPILE_OPTIONS_INTERFACE}")
+ if(MINGW)
+ # the python bindings and the gui exceed the default COFF section limit
+ enable_cxx_compile_option_if_supported("-Wa,-mbig-obj" "" "PUBLIC")
+
+ # HAL marks its api with CORE_API/NETLIST_API/PLUGIN_API, which expand to nothing on MinGW,
+ # so let the linker export everything instead of annotating every symbol by hand.
+ # ld only exports everything by default while nothing is marked dllexport, and pybind11
+ # marks its module entry points, so the flag has to be passed explicitly.
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--export-all-symbols")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--export-all-symbols")
+ endif(MINGW)
+
message(VERBOSE " ")
-endif(UNIX)
+endif(UNIX OR MINGW)
# Enable Debug Symbols for Libcpp on macOS
if(${CMAKE_BUILD_TYPE} EQUAL "Debug" AND APPLE AND CMAKE_HOST_APPLE)
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index e7e932433718..9c99c30a68bc 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -1,6 +1,10 @@
set(SRC main.cpp)
add_executable(hal ${SRC})
+if(MINGW)
+ # UTF-8 active code page, see hal.manifest
+ target_sources(hal PRIVATE hal.rc)
+endif()
set_target_properties(hal PROPERTIES OUTPUT_NAME "hal")
set_target_properties(hal PROPERTIES ENABLE_EXPORTS 1)
set_target_properties(hal PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_RPATH}")
diff --git a/app/hal.manifest b/app/hal.manifest
new file mode 100644
index 000000000000..e6193d09ae89
--- /dev/null
+++ b/app/hal.manifest
@@ -0,0 +1,13 @@
+
+
+
+
+
+ UTF-8
+
+
+
diff --git a/app/hal.rc b/app/hal.rc
new file mode 100644
index 000000000000..7b6eb8c59921
--- /dev/null
+++ b/app/hal.rc
@@ -0,0 +1,2 @@
+// embeds hal.manifest as the application manifest (resource type 24 = RT_MANIFEST)
+1 24 "hal.manifest"
diff --git a/cmake/hal_plugin.cmake b/cmake/hal_plugin.cmake
index f6bbb790c33a..4e581c49cf53 100644
--- a/cmake/hal_plugin.cmake
+++ b/cmake/hal_plugin.cmake
@@ -13,6 +13,10 @@ function(hal_add_plugin target_name)
message(FATAL_ERROR "Can't be both MODULE and SHARED")
elseif(ARG_SHARED)
set(lib_type SHARED)
+ elseif(WIN32)
+ # plugins link against each other, which needs an import library, and Windows does not
+ # produce one for a MODULE library
+ set(lib_type SHARED)
else()
set(lib_type MODULE)
endif()
@@ -54,7 +58,10 @@ function(hal_add_plugin target_name)
if(APPLE AND CMAKE_HOST_APPLE)
set_target_properties(${target_name} PROPERTIES SUFFIX ".so")
set_target_properties(${target_name} PROPERTIES INSTALL_NAME_DIR ${PLUGIN_LIBRARY_INSTALL_DIRECTORY})
- endif(APPLE AND CMAKE_HOST_APPLE)
+ elseif(WIN32)
+ # Python only imports extension modules with the .pyd suffix on Windows
+ set_target_properties(${target_name} PROPERTIES SUFFIX ".pyd")
+ endif()
target_link_libraries(${target_name}
PUBLIC hal::core hal::netlist ${Python3_LIBRARIES} pybind11::pybind11
diff --git a/deps/abc/CMakeLists.txt b/deps/abc/CMakeLists.txt
index f2d08ac38b64..d028c6c91de4 100644
--- a/deps/abc/CMakeLists.txt
+++ b/deps/abc/CMakeLists.txt
@@ -67,6 +67,11 @@ extract_var(SEPARATOR_LIBS ABC_LIBS ${MAKE_OUTPUT})
extract_var(SEPARATOR_CFLAGS ABC_CFLAGS ${MAKE_OUTPUT})
extract_var(SEPARATOR_CXXFLAGS ABC_CXXFLAGS ${MAKE_OUTPUT})
+if(WIN32)
+ # dlopen and the realtime clock live in the CRT on Windows, there is no -ldl or -lrt
+ list(REMOVE_ITEM ABC_LIBS "-ldl" "-lrt")
+endif()
+
if(ABC_USE_NAMESPACE)
set_source_files_properties(${ABC_SRC} PROPERTIES LANGUAGE CXX)
endif()
@@ -90,5 +95,11 @@ list(REMOVE_ITEM ABC_SRC ${ABC_MAIN_SRC})
add_library(libabc-pic EXCLUDE_FROM_ALL ${ABC_SRC})
abc_properties(libabc-pic PUBLIC)
+
+if(WIN32)
+ # without this abc declares its whole api __declspec(dllimport), including inside the library
+ # itself; MinGW exports and imports the symbols on its own
+ target_compile_definitions(libabc-pic PUBLIC WIN32_NO_DLL)
+endif()
set_property(TARGET libabc-pic PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libabc-pic PROPERTY OUTPUT_NAME abc-pic)
diff --git a/deps/abc/src/aig/gia/giaKf.c b/deps/abc/src/aig/gia/giaKf.c
index a823f7262186..0cbb125addcb 100644
--- a/deps/abc/src/aig/gia/giaKf.c
+++ b/deps/abc/src/aig/gia/giaKf.c
@@ -23,7 +23,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/base/cmd/cmdAuto.c b/deps/abc/src/base/cmd/cmdAuto.c
index 8151c2e53458..98cb6a5a2a60 100644
--- a/deps/abc/src/base/cmd/cmdAuto.c
+++ b/deps/abc/src/base/cmd/cmdAuto.c
@@ -29,7 +29,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/base/cmd/cmdStarter.c b/deps/abc/src/base/cmd/cmdStarter.c
index ffb2b752206f..4cea6e660d75 100644
--- a/deps/abc/src/base/cmd/cmdStarter.c
+++ b/deps/abc/src/base/cmd/cmdStarter.c
@@ -27,7 +27,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/base/wlc/wlcPth.c b/deps/abc/src/base/wlc/wlcPth.c
index ddafab23ca57..5a699e888ac4 100644
--- a/deps/abc/src/base/wlc/wlcPth.c
+++ b/deps/abc/src/base/wlc/wlcPth.c
@@ -23,7 +23,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/map/if/ifDsd.c b/deps/abc/src/map/if/ifDsd.c
index ddfc10365a6c..69cb50b7a8fe 100644
--- a/deps/abc/src/map/if/ifDsd.c
+++ b/deps/abc/src/map/if/ifDsd.c
@@ -32,7 +32,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/map/if/ifTest.c b/deps/abc/src/map/if/ifTest.c
index fa9a644437db..4b1ede06f5cf 100644
--- a/deps/abc/src/map/if/ifTest.c
+++ b/deps/abc/src/map/if/ifTest.c
@@ -23,7 +23,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/proof/abs/absPth.c b/deps/abc/src/proof/abs/absPth.c
index f04a20d1c677..d8cb343598e7 100644
--- a/deps/abc/src/proof/abs/absPth.c
+++ b/deps/abc/src/proof/abs/absPth.c
@@ -25,7 +25,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/proof/cec/cecSplit.c b/deps/abc/src/proof/cec/cecSplit.c
index e2fa8ff1da90..f89a00aa9b48 100644
--- a/deps/abc/src/proof/cec/cecSplit.c
+++ b/deps/abc/src/proof/cec/cecSplit.c
@@ -28,7 +28,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/abc/src/sat/bmc/bmcBmcS.c b/deps/abc/src/sat/bmc/bmcBmcS.c
index 8bfda56ba755..f43722c9e878 100644
--- a/deps/abc/src/sat/bmc/bmcBmcS.c
+++ b/deps/abc/src/sat/bmc/bmcBmcS.c
@@ -48,7 +48,7 @@
#ifdef ABC_USE_PTHREADS
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#include "../lib/pthread.h"
#else
#include
diff --git a/deps/igraph-1.0.x/CMakeLists.txt b/deps/igraph-1.0.x/CMakeLists.txt
index 63b9191ace0c..8b50ca1eff76 100644
--- a/deps/igraph-1.0.x/CMakeLists.txt
+++ b/deps/igraph-1.0.x/CMakeLists.txt
@@ -5,7 +5,11 @@ set (IGRAPH_BASE "${CMAKE_BINARY_DIR}/igraph")
set (IGRAPH_DOWNLOAD "${IGRAPH_BASE}/download")
set (IGRAPH_BUILD "${IGRAPH_BASE}/build")
set (IGRAPH_INCLUDES "${IGRAPH_INSTALL}/include")
-set (IGRAPH_LIB "${IGRAPH_INSTALL}/lib/libigraph${CMAKE_SHARED_LIBRARY_SUFFIX}")
+if(WIN32)
+ set (IGRAPH_LIB "${IGRAPH_INSTALL}/lib/${CMAKE_IMPORT_LIBRARY_PREFIX}igraph${CMAKE_IMPORT_LIBRARY_SUFFIX}")
+else()
+ set (IGRAPH_LIB "${IGRAPH_INSTALL}/lib/libigraph${CMAKE_SHARED_LIBRARY_SUFFIX}")
+endif()
set (HAVE_IGRAPH TRUE)
message("-- IGRAPH version 1.0.1 : download and build libigraph${CMAKE_SHARED_LIBRARY_SUFFIX} in ${IGRAPH_BASE}")
diff --git a/deps/subprocess/subprocess/process.h b/deps/subprocess/subprocess/process.h
index 4187b0ecfcb8..71a317de37dc 100644
--- a/deps/subprocess/subprocess/process.h
+++ b/deps/subprocess/subprocess/process.h
@@ -149,7 +149,7 @@ namespace subprocess
//--------------------------------------------------------------------
//Environment Variable types
-#ifndef _MSC_VER
+#ifndef __USING_WINDOWS__
using env_string_t = std::string;
using env_char_t = char;
#else
diff --git a/include/hal_core/arch/arch_win.h b/include/hal_core/arch/arch_win.h
index a0c074bf0a40..b66881a724cc 100644
--- a/include/hal_core/arch/arch_win.h
+++ b/include/hal_core/arch/arch_win.h
@@ -33,7 +33,7 @@
#define LIBRARY_FILE_EXTENSION "dll"
-#define ALTERNATE_LIBRARY_FILE_EXTENSION ""
+#define ALTERNATE_LIBRARY_FILE_EXTENSION "pyd"
#ifdef BUILDING_CORE
#undef CORE_API
diff --git a/include/hal_core/defines.h b/include/hal_core/defines.h
index 71cc23bb2c7f..986c02abae0c 100644
--- a/include/hal_core/defines.h
+++ b/include/hal_core/defines.h
@@ -61,6 +61,10 @@ namespace hal
/* Microsoft */
#define EXPORT __declspec(dllexport)
#define IMPORT __declspec(dllimport)
+#elif defined(_WIN32)
+/* MinGW: symbols are exported via CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS, not per-symbol attributes */
+#define EXPORT
+#define IMPORT
#else
/* other */
#define EXPORTED __attribute__((visibility("default")))
diff --git a/include/hal_core/netlist/boolean_function/solver.h b/include/hal_core/netlist/boolean_function/solver.h
index b0085c8956a1..e56f80defd41 100644
--- a/include/hal_core/netlist/boolean_function/solver.h
+++ b/include/hal_core/netlist/boolean_function/solver.h
@@ -165,11 +165,11 @@ namespace hal
* https://smtlib.cs.uiowa.edu/language.shtml
*
* @param[in] was_killed - Indicates whether solver process was killed.
- * @param[in] stdout - Stdout of solver process.
+ * @param[in] solver_output - Stdout of solver process.
* @param[in] config - SMT solver configuration.
* @returns Ok() and SMT solver result on success, Err() otherwise.
*/
- static Result translate_from_smt2(bool was_killed, std::string stdout, const QueryConfig& config);
+ static Result translate_from_smt2(bool was_killed, std::string solver_output, const QueryConfig& config);
};
} // namespace SMT
} // namespace hal
\ No newline at end of file
diff --git a/include/hal_core/plugin_system/runtime_library.h b/include/hal_core/plugin_system/runtime_library.h
index f7f116d08a43..72dd919823f8 100644
--- a/include/hal_core/plugin_system/runtime_library.h
+++ b/include/hal_core/plugin_system/runtime_library.h
@@ -29,15 +29,20 @@
#include
+// operating system headers have to be included at global scope, not inside namespace hal
+#ifdef _WIN32
+#include
+#else
+#include
+#endif
+
namespace hal
{
// operating systems independent type definitions for function and handle access
#ifdef _WIN32
-#include
using lib_fn_ptr_t = FARPROC;
using handle_ptr_t = HINSTANCE;
#else
-#include
using lib_fn_ptr_t = void (*)();
using handle_ptr_t = void*;
#endif
diff --git a/plugins/dot_viewer/src/dot_viewer_factory.cpp b/plugins/dot_viewer/src/dot_viewer_factory.cpp
index 540c99126f31..bc2e3c306f7a 100644
--- a/plugins/dot_viewer/src/dot_viewer_factory.cpp
+++ b/plugins/dot_viewer/src/dot_viewer_factory.cpp
@@ -46,7 +46,7 @@ namespace hal {
QJsonObject dvObj;
std::filesystem::path relDotPath = ProjectManager::instance()->get_project_directory().get_relative_file_path(dv->filename().toStdString());
- dvObj["filename"] = QString::fromStdString(relDotPath);
+ dvObj["filename"] = QString::fromStdString(relDotPath.string());
dvObj["creator"] = dv->creatorPlugin();
dvFile.write(QJsonDocument(dvObj).toJson(QJsonDocument::Compact));
diff --git a/plugins/gate_libraries/CMakeLists.txt b/plugins/gate_libraries/CMakeLists.txt
index 7a5331ea2242..ead10fda447e 100644
--- a/plugins/gate_libraries/CMakeLists.txt
+++ b/plugins/gate_libraries/CMakeLists.txt
@@ -7,6 +7,9 @@ if(PL_GATE_LIBRARIES OR BUILD_ALL_PLUGINS)
set_property(GLOBAL PROPERTY GATE_LIBS_DEFINITIONS "${CMAKE_CURRENT_SOURCE_DIR}/definitions")
message(STATUS "GATE_LIBS: ${GATE_LIBS}")
foreach(file ${GATE_LIBS})
+ if(IS_DIRECTORY ${file})
+ continue()
+ endif()
get_filename_component(f ${file} NAME)
list(APPEND SOURCE_GATE_LIBS ${CMAKE_CURRENT_SOURCE_DIR}/definitions/${f})
list(APPEND DESTINATION_GATE_LIBS ${CMAKE_BINARY_DIR}/share/hal/gate_libraries/${f})
@@ -24,8 +27,8 @@ if(PL_GATE_LIBRARIES OR BUILD_ALL_PLUGINS)
add_custom_target(update_internal_gate_library_definitions ALL
BYPRODUCTS ${DESTINATION_GATE_LIBS} ${DESTINATION_HELPER_GATE_LIBS}
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/definitions/* ${CMAKE_BINARY_DIR}/share/hal/gate_libraries/
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/definitions/helper_libs/* ${CMAKE_BINARY_DIR}/share/hal/gate_libraries/
+ COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_GATE_LIBS} ${CMAKE_BINARY_DIR}/share/hal/gate_libraries/
+ COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_HELPER_GATE_LIBS} ${CMAKE_BINARY_DIR}/share/hal/gate_libraries/
DEPENDS ${SOURCE_GATE_LIBS} ${SOURCE_HELPER_GATE_LIBS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Update gate library definitions")
diff --git a/plugins/gexf_writer/CMakeLists.txt b/plugins/gexf_writer/CMakeLists.txt
index 37c9060b1ea0..0a7412b1e4c3 100644
--- a/plugins/gexf_writer/CMakeLists.txt
+++ b/plugins/gexf_writer/CMakeLists.txt
@@ -41,7 +41,10 @@ if(PL_GEXF_WRITER OR BUILD_ALL_PLUGINS)
if(APPLE AND CMAKE_HOST_APPLE)
set_target_properties(gexf_writer PROPERTIES SUFFIX ".so")
set_target_properties(gexf_writer PROPERTIES INSTALL_NAME_DIR ${PLUGIN_LIBRARY_INSTALL_DIRECTORY})
- endif(APPLE AND CMAKE_HOST_APPLE)
+ elseif(WIN32)
+ # Python only imports extension modules with the .pyd suffix on Windows
+ set_target_properties(gexf_writer PROPERTIES SUFFIX ".pyd")
+ endif()
target_link_libraries(gexf_writer
PUBLIC gui
diff --git a/plugins/gexf_writer/src/gexf_writer.cpp b/plugins/gexf_writer/src/gexf_writer.cpp
index 9a61b38c6780..7ffdbe5e9468 100644
--- a/plugins/gexf_writer/src/gexf_writer.cpp
+++ b/plugins/gexf_writer/src/gexf_writer.cpp
@@ -37,7 +37,7 @@ namespace hal
{
return ERR("could not write netlist to GEXF file '" + file_path.string() + "': file path is empty");
}
- QString filename = QString::fromStdString(file_path);
+ QString filename = QString::fromStdString(file_path.string());
if (!filename.endsWith(".gexf"))
{
diff --git a/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h b/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h
index ee8fe70631d1..6be0d5300fe9 100644
--- a/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h
+++ b/plugins/graph_algorithm/include/graph_algorithm/netlist_graph.h
@@ -63,6 +63,12 @@ namespace hal
* @enum Direction
* @brief The direction of exploration within the graph.
*/
+// windows.h defines IN and OUT as empty SAL annotation macros
+#ifdef _WIN32
+#undef IN
+#undef OUT
+#endif
+
enum class Direction
{
/**
diff --git a/plugins/gui/CMakeLists.txt b/plugins/gui/CMakeLists.txt
index e80d143a2582..b77a7ffc5763 100644
--- a/plugins/gui/CMakeLists.txt
+++ b/plugins/gui/CMakeLists.txt
@@ -107,7 +107,10 @@ if(PL_GUI OR BUILD_ALL_PLUGINS)
set_target_properties(gui PROPERTIES PREFIX "")
if(APPLE AND CMAKE_HOST_APPLE)
set_target_properties(gui PROPERTIES SUFFIX ".so")
- endif(APPLE AND CMAKE_HOST_APPLE)
+ elseif(WIN32)
+ # Python only imports extension modules with the .pyd suffix on Windows
+ set_target_properties(gui PROPERTIES SUFFIX ".pyd")
+ endif()
target_include_directories(gui
PUBLIC
$
diff --git a/plugins/gui/include/gui/content_manager/content_manager.h b/plugins/gui/include/gui/content_manager/content_manager.h
index 135d88019ecd..f21a17e9428c 100644
--- a/plugins/gui/include/gui/content_manager/content_manager.h
+++ b/plugins/gui/include/gui/content_manager/content_manager.h
@@ -65,6 +65,8 @@ namespace hal
QString mPluginName;
public:
ContentFactory(const QString& nam=QString()) : mPluginName(nam) {;}
+ // factories are deleted through this base, and may have further bases such as ProjectSerializer
+ virtual ~ContentFactory() {;}
QString name() const {return mPluginName; }
virtual ExternalContentWidget* contentFactory() const = 0;
};
diff --git a/plugins/gui/src/content_manager/content_manager.cpp b/plugins/gui/src/content_manager/content_manager.cpp
index de2cf8c34d5e..f7849ae41349 100644
--- a/plugins/gui/src/content_manager/content_manager.cpp
+++ b/plugins/gui/src/content_manager/content_manager.cpp
@@ -54,7 +54,12 @@ namespace hal
auto it = begin();
while (it != end())
if ((*it)->name() == pluginName)
+ {
+ // the factory lives as long as its plugin, deleting it here (while the plugin is still loaded)
+ // also unregisters it from everything it registered with, e.g. as a project serializer
+ delete *it;
it = erase(it);
+ }
else
++it;
diff --git a/plugins/gui/src/export/export_project_dialog.cpp b/plugins/gui/src/export/export_project_dialog.cpp
index 8dc8d54e85ab..f0b02c5897fa 100644
--- a/plugins/gui/src/export/export_project_dialog.cpp
+++ b/plugins/gui/src/export/export_project_dialog.cpp
@@ -19,7 +19,7 @@ namespace hal
ExportProjectDialog::ExportProjectDialog(QWidget *parent)
: QFileDialog(parent), mStatus(NoExport)
{
- QFileInfo pinfo(QString::fromStdString(ProjectManager::instance()->get_project_directory().get_default_filename()));
+ QFileInfo pinfo(QString::fromStdString(ProjectManager::instance()->get_project_directory().get_default_filename().string()));
mProjectName = pinfo.baseName().simplified();
mProjectName.replace(" ","");
setDefaultSuffix(".zip");
diff --git a/plugins/gui/src/file_manager/file_manager.cpp b/plugins/gui/src/file_manager/file_manager.cpp
index f9e3282c8016..365dfeeb015d 100644
--- a/plugins/gui/src/file_manager/file_manager.cpp
+++ b/plugins/gui/src/file_manager/file_manager.cpp
@@ -259,7 +259,7 @@ namespace hal
{
ProjectManager* pm = ProjectManager::instance();
if (pm->get_project_status() == ProjectManager::ProjectStatus::NONE) return;
- QDir shDir(QString::fromStdString(pm->get_project_directory().get_shadow_dir()));
+ QDir shDir(QString::fromStdString(pm->get_project_directory().get_shadow_dir().string()));
if (shDir.exists())
{
shDir.removeRecursively();
@@ -282,6 +282,8 @@ namespace hal
QMessageBox::warning(qApp->activeWindow(),"Aborted", "Cannot create project <" + projdir + ">, no gate library selected");
return;
}
+ QString glSuffix = QFileInfo(gatelib).suffix();
+ gPluginRelay->mGuiPluginTable->loadFeature(FacExtensionInterface::FacGatelibParser,"."+glSuffix);
GateLibrary* glib = gate_library_manager::load(gatelib.toStdString());
if (!glib)
{
@@ -453,7 +455,7 @@ namespace hal
ProjectManager* pm = ProjectManager::instance();
pm->set_project_directory(projPath.toStdString());
- QDir shDir(QString::fromStdString(pm->get_project_directory().get_shadow_dir()));
+ QDir shDir(QString::fromStdString(pm->get_project_directory().get_shadow_dir().string()));
QFileInfo shInfo(shDir.absoluteFilePath(QString::fromStdString(ProjectManager::s_project_file)));
if (shInfo.exists() && shInfo.isFile())
{
diff --git a/plugins/gui/src/file_manager/new_project_dialog.cpp b/plugins/gui/src/file_manager/new_project_dialog.cpp
index 4ea28bc4f816..02e2798111a1 100644
--- a/plugins/gui/src/file_manager/new_project_dialog.cpp
+++ b/plugins/gui/src/file_manager/new_project_dialog.cpp
@@ -65,7 +65,7 @@ namespace hal
for (const std::filesystem::path& path : gate_library_manager::get_all_path())
{
int n = mGateLibraryPath.size();
- QString qName = QString::fromStdString(path.filename());
+ QString qName = QString::fromStdString(path.filename().string());
mGateLibraryMap.insert(qName, n);
QString qPath = QString::fromStdString(path.string());
mGateLibraryPath.append(qPath);
diff --git a/plugins/gui/src/gatelibrary_management/gatelibrary_selection.cpp b/plugins/gui/src/gatelibrary_management/gatelibrary_selection.cpp
index 2090c9e05738..ea602ed3a247 100644
--- a/plugins/gui/src/gatelibrary_management/gatelibrary_selection.cpp
+++ b/plugins/gui/src/gatelibrary_management/gatelibrary_selection.cpp
@@ -133,7 +133,7 @@ namespace hal {
QMap nameMap;
for (const std::filesystem::path& path : gate_library_manager::get_all_path())
{
- QString name = QString::fromStdString(path.filename());
+ QString name = QString::fromStdString(path.filename().string());
mEntries.append(GateLibrarySelectionEntry(name, QString::fromStdString(path.string()), nameMap[name]++));
}
}
diff --git a/plugins/gui/src/main_window/main_window.cpp b/plugins/gui/src/main_window/main_window.cpp
index c35c6607236f..bc314c6d8513 100644
--- a/plugins/gui/src/main_window/main_window.cpp
+++ b/plugins/gui/src/main_window/main_window.cpp
@@ -854,7 +854,7 @@ namespace hal
}
}
- QString qNetlistPath = QString::fromStdString(pm->get_project_directory().get_default_filename(".hal"));
+ QString qNetlistPath = QString::fromStdString(pm->get_project_directory().get_default_filename(".hal").string());
if (!pm->serialize_project(gNetlist))
{
diff --git a/plugins/gui/src/plugin_gui.cpp b/plugins/gui/src/plugin_gui.cpp
index e4068f376386..29605f390052 100644
--- a/plugins/gui/src/plugin_gui.cpp
+++ b/plugins/gui/src/plugin_gui.cpp
@@ -117,7 +117,7 @@ namespace hal
FileManager::get_instance()->openProject(QString::fromStdString(projDir.string()));
break;
case DefaultImport:
- projDir = ProjectDirectory(fileName);
+ projDir = ProjectDirectory(fileName.string());
[[fallthrough]];
// continue with Import
case ImportToProject:
diff --git a/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp b/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp
index 455f58d7e14e..5f338625d7f2 100644
--- a/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp
+++ b/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp
@@ -373,7 +373,7 @@ namespace hal {
void GuiPluginTable::populateTable(bool refresh)
{
- QDir userConfigDir(QString::fromStdString(utils::get_user_config_directory()));
+ QDir userConfigDir(QString::fromStdString(utils::get_user_config_directory().string()));
QMap pluginEntries;
mSettings = new QSettings(userConfigDir.absoluteFilePath("plugins.ini"),QSettings::IniFormat);
@@ -489,6 +489,9 @@ namespace hal {
{
// unload dependencies unless they are required from other side
if (pluginEntries.contains(dep) && pluginEntries.value(dep)->mLoadState > GuiPluginEntry::NotLoaded) continue;
+ // a dependency that was loaded before the dummy load is not ours to unload, this
+ // covers hal_gui itself, which a plugin like dot_viewer depends on
+ if (pluginsBeforeLoad.find(dep.toStdString()) != pluginsBeforeLoad.end()) continue;
plugin_manager::unload(dep.toStdString());
}
}
diff --git a/plugins/gui/src/python/python_code_editor.cpp b/plugins/gui/src/python/python_code_editor.cpp
index dc547040d75d..538b69e37a07 100644
--- a/plugins/gui/src/python/python_code_editor.cpp
+++ b/plugins/gui/src/python/python_code_editor.cpp
@@ -314,14 +314,14 @@ namespace hal
{
if (mRelFilename.isEmpty() || mRelFilename.startsWith('/'))
return mRelFilename;
- QDir projectPydir(QString::fromStdString(ProjectManager::instance()->get_project_directory().get_filename("py")));
+ QDir projectPydir(QString::fromStdString(ProjectManager::instance()->get_project_directory().get_filename("py").string()));
return projectPydir.absoluteFilePath(mRelFilename);
}
void PythonCodeEditor::setFilename(const QString &name)
{
mRelFilename = name;
- QString projectLoc = QString::fromStdString(ProjectManager::instance()->get_project_directory().get_filename("py")) + '/';
+ QString projectLoc = QString::fromStdString(ProjectManager::instance()->get_project_directory().get_filename("py").string()) + '/';
if (name.startsWith(projectLoc))
mRelFilename.remove(0,projectLoc.size());
}
diff --git a/plugins/gui/src/python/python_context.cpp b/plugins/gui/src/python/python_context.cpp
index e3820e299f1d..20e1bf91c0a9 100644
--- a/plugins/gui/src/python/python_context.cpp
+++ b/plugins/gui/src/python/python_context.cpp
@@ -104,9 +104,9 @@ namespace hal
"import io, sys, threading, builtins\n";
for (auto path : utils::get_plugin_directories())
{
- command += "sys.path.append('" + path.string() + "')\n";
+ command += "sys.path.append('" + path.generic_string() + "')\n";
}
- command += "sys.path.append('" + utils::get_library_directory().string()
+ command += "sys.path.append('" + utils::get_library_directory().generic_string()
+ "')\n"
"from hal_gui.console import reset\n"
"from hal_gui.console import clear\n"
diff --git a/plugins/python_shell/src/plugin_python_shell.cpp b/plugins/python_shell/src/plugin_python_shell.cpp
index 4f4c8cc75534..3fe3423ccd0e 100644
--- a/plugins/python_shell/src/plugin_python_shell.cpp
+++ b/plugins/python_shell/src/plugin_python_shell.cpp
@@ -79,7 +79,7 @@ namespace hal
PySys_SetArgv(argc, argv);
PyRun_SimpleString("import sys");
- PyRun_SimpleString(std::string("sys.path.append(\"" + utils::get_library_directory().string() + "\")").c_str());
+ PyRun_SimpleString(std::string("sys.path.append(\"" + utils::get_library_directory().generic_string() + "\")").c_str());
PyRun_SimpleString("from hal_py import *");
PyRun_SimpleString("import hal_py");
diff --git a/src/netlist/boolean_function/simplification_abc.cpp b/src/netlist/boolean_function/simplification_abc.cpp
index a1e8a8899942..d96551cfb3f3 100644
--- a/src/netlist/boolean_function/simplification_abc.cpp
+++ b/src/netlist/boolean_function/simplification_abc.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -797,12 +798,27 @@ namespace hal
// (2.2) compute the right-hand side Boolean function expression via
// in-memory FILE* to mimic the original interface without the
// use of an actual file read/write operation
+#ifdef _WIN32
+ // Windows has no open_memstream, so the data is round-tripped through a temporary file
+ auto stream = std::tmpfile();
+ Hop_ObjPrintVerilog(stream, (Hop_Obj_t*)node->pData, vLevels, 0, 0);
+ std::fflush(stream);
+ std::rewind(stream);
+
+ std::string rhs;
+ char chunk[4096];
+ while (const auto read = std::fread(chunk, 1, sizeof(chunk), stream))
+ {
+ rhs.append(chunk, read);
+ }
+#else
char* rhs{};
size_t len{};
auto stream = open_memstream(&rhs, &len);
Hop_ObjPrintVerilog(stream, (Hop_Obj_t*)node->pData, vLevels, 0, 0);
fflush(stream);
+#endif
// (2.3) assemble "assign $(LHS) = $(RHS);"
ss << "assign " << lhs << " = " << rhs << ";" << std::endl;
diff --git a/src/netlist/boolean_function/solver.cpp b/src/netlist/boolean_function/solver.cpp
index 0ae33dc15867..d6afa12a0b34 100644
--- a/src/netlist/boolean_function/solver.cpp
+++ b/src/netlist/boolean_function/solver.cpp
@@ -539,15 +539,15 @@ namespace hal
return ERR_APPEND(constraints_str.get_error(), "could not translate constraint to SMT-LIB v2: unable to generate translation constraints");
}
- Result Solver::translate_from_smt2(bool was_killed, std::string stdout, const QueryConfig& config)
+ Result Solver::translate_from_smt2(bool was_killed, std::string solver_output, const QueryConfig& config)
{
if (was_killed)
{
return ERR("could not parse SMT result from string: the SMT solver was killed");
}
- auto position = stdout.find_first_of('\n');
- auto [result, model_str] = std::make_tuple(std::string(stdout, 0, position), std::string(stdout, position + 1));
+ auto position = solver_output.find_first_of('\n');
+ auto [result, model_str] = std::make_tuple(std::string(solver_output, 0, position), std::string(solver_output, position + 1));
auto to_lowercase = [](const auto& s) -> std::string {
auto lowercase = s;
diff --git a/src/netlist/gate_library/gate_library_manager.cpp b/src/netlist/gate_library/gate_library_manager.cpp
index e41651485feb..1ebdc4216fcc 100644
--- a/src/netlist/gate_library/gate_library_manager.cpp
+++ b/src/netlist/gate_library/gate_library_manager.cpp
@@ -205,7 +205,7 @@ namespace hal
auto stripped_name = std::filesystem::path(file_path).filename();
log_info("gate_library_manager", "file '{}' does not exist, searching for '{}' in the default gate library directories...", file_path, stripped_name.string());
- auto lib_path = utils::get_file(stripped_name, utils::get_gate_library_directories());
+ auto lib_path = utils::get_file(stripped_name.string(), utils::get_gate_library_directories());
if (lib_path.empty())
{
log_info("gate_library_manager", "could not find gate library file '{}'.", stripped_name.string());
diff --git a/src/netlist/netlist_factory.cpp b/src/netlist/netlist_factory.cpp
index 605ab831a7e0..877d7cf3cdfb 100644
--- a/src/netlist/netlist_factory.cpp
+++ b/src/netlist/netlist_factory.cpp
@@ -10,7 +10,6 @@
#include "hal_core/utilities/project_directory.h"
#include
-#include
namespace hal
{
@@ -46,7 +45,7 @@ namespace hal
std::unique_ptr load_netlist(const std::filesystem::path& netlist_file, const std::filesystem::path& gate_library_file)
{
- if (access(netlist_file.c_str(), F_OK | R_OK) == -1)
+ if (!std::ifstream(netlist_file).good())
{
log_critical("netlist", "could not access file '{}'.", netlist_file.string());
return nullptr;
@@ -81,7 +80,7 @@ namespace hal
std::unique_ptr load_netlist(const std::filesystem::path& netlist_file, GateLibrary* gate_library)
{
- if (access(netlist_file.c_str(), F_OK | R_OK) == -1)
+ if (!std::ifstream(netlist_file).good())
{
log_critical("netlist", "could not access file '{}'.", netlist_file.string());
return nullptr;
@@ -126,7 +125,7 @@ namespace hal
{
std::filesystem::path netlist_file = args.is_option_set("--import-netlist") ? std::filesystem::path(args.get_parameter("--import-netlist")) : pdir.get_default_filename();
- if (access(netlist_file.c_str(), F_OK | R_OK) == -1)
+ if (!std::ifstream(netlist_file).good())
{
log_critical("netlist", "cannot access file '{}'.", netlist_file.string());
return nullptr;
@@ -144,7 +143,7 @@ namespace hal
std::vector> load_netlists(const std::filesystem::path& netlist_file)
{
- if (access(netlist_file.c_str(), F_OK | R_OK) == -1)
+ if (!std::ifstream(netlist_file).good())
{
log_critical("netlist", "could not access file '{}'.", netlist_file.string());
return {};
diff --git a/src/netlist/project_manager.cpp b/src/netlist/project_manager.cpp
index b04c1a012a49..0bb4f0f299fe 100644
--- a/src/netlist/project_manager.cpp
+++ b/src/netlist/project_manager.cpp
@@ -107,7 +107,7 @@ namespace hal
}
if (!success)
return false;
- m_netlist_file = m_proj_dir.get_default_filename(".hal");
+ m_netlist_file = m_proj_dir.get_default_filename(".hal").string();
std::filesystem::create_directory(m_proj_dir.get_filename("py"));
std::filesystem::create_directory(m_proj_dir.get_filename(ProjectDirectory::s_shadow_dir));
@@ -146,9 +146,9 @@ namespace hal
if (gl)
m_gatelib_path = gl->get_path().string();
if (shadow)
- m_netlist_file = m_proj_dir.get_shadow_filename(".hal");
+ m_netlist_file = m_proj_dir.get_shadow_filename(".hal").string();
else
- m_netlist_file = m_proj_dir.get_default_filename(".hal");
+ m_netlist_file = m_proj_dir.get_default_filename(".hal").string();
if (!netlist_serializer::serialize_to_file(m_netlist_save, m_netlist_file))
return false;
diff --git a/src/plugin_system/runtime_library.cpp b/src/plugin_system/runtime_library.cpp
index 94ed59efef3f..9b230363d892 100644
--- a/src/plugin_system/runtime_library.cpp
+++ b/src/plugin_system/runtime_library.cpp
@@ -1,5 +1,7 @@
#include "hal_core/plugin_system/runtime_library.h"
+#include
+
#include "hal_core/utilities/log.h"
namespace hal
@@ -26,7 +28,13 @@ namespace hal
bool RuntimeLibrary::load_library(const std::string& file_name)
{
#ifdef _WIN32
- m_handle = LoadLibrary(file_name.c_str());
+ // plugins link against each other, so the directory of the plugin being loaded has to be
+ // searched for its dependencies as well. SetDllDirectory adds it to the standard search
+ // order, which keeps both the directory of hal itself and PATH in the search.
+ const auto native_path = std::filesystem::absolute(std::filesystem::path(file_name)).make_preferred();
+ SetDllDirectoryA(native_path.parent_path().string().c_str());
+ m_handle = LoadLibraryA(native_path.string().c_str());
+ SetDllDirectoryA(NULL);
#else
m_handle = dlopen((file_name).c_str(), RTLD_GLOBAL | RTLD_LAZY);
#endif
@@ -40,7 +48,18 @@ namespace hal
auto error_message = std::string("");
#ifdef _WIN32
- error_message = "to be implemented for windows based operating systems.";
+ char* buffer = NULL;
+ const auto length =
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, (char*)&buffer, 0, NULL);
+ if (length != 0)
+ {
+ error_message = std::string(buffer, length);
+ while (!error_message.empty() && (error_message.back() == '\n' || error_message.back() == '\r'))
+ {
+ error_message.pop_back();
+ }
+ }
+ LocalFree(buffer);
#else
error_message = dlerror();
#endif
@@ -56,7 +75,8 @@ namespace hal
return true;
}
#ifdef _WIN32
- if (FreeLibrary(m_handle) == 0)
+ // FreeLibrary reports success with a non-zero value, unlike dlclose
+ if (FreeLibrary(m_handle) != 0)
{
log_debug("core", "unloaded library '{}'", m_file_name);
m_handle = NULL;
diff --git a/src/plugin_system/user_feedback.cpp b/src/plugin_system/user_feedback.cpp
index acc26c99e8e0..10fb6c1b3722 100644
--- a/src/plugin_system/user_feedback.cpp
+++ b/src/plugin_system/user_feedback.cpp
@@ -7,8 +7,14 @@
#include
#include
#include
+
+#ifdef _WIN32
+#include
+#include
+#else
#include
#include
+#endif
namespace hal
{
@@ -173,6 +179,19 @@ namespace hal
int ProgressPrinter::get_terminal_width()
{
+#ifdef _WIN32
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &info))
+ {
+ return -1;
+ }
+ const int columns = info.srWindow.Right - info.srWindow.Left + 1;
+ if (columns <= 0 || columns > MAX_PLAUSIBLE_TERMINAL_WIDTH)
+ {
+ return -1;
+ }
+ return columns;
+#else
struct winsize size;
if (ioctl(STDERR_FILENO, TIOCGWINSZ, &size) < 0)
{
@@ -183,6 +202,7 @@ namespace hal
return -1;
}
return size.ws_col;
+#endif
}
} // namespace user_feedback
} // namespace hal
diff --git a/src/python_bindings/CMakeLists.txt b/src/python_bindings/CMakeLists.txt
index bcd1c0d619a1..617de6b84b9f 100644
--- a/src/python_bindings/CMakeLists.txt
+++ b/src/python_bindings/CMakeLists.txt
@@ -20,7 +20,10 @@ target_compile_options(py
set_target_properties(py PROPERTIES PREFIX "")
if(APPLE AND CMAKE_HOST_APPLE)
set_target_properties(py PROPERTIES SUFFIX ".so")
-endif(APPLE AND CMAKE_HOST_APPLE)
+elseif(WIN32)
+ # Python only imports extension modules with the .pyd suffix on Windows
+ set_target_properties(py PROPERTIES SUFFIX ".pyd")
+endif()
target_link_libraries(py PUBLIC PRIVATE ${Python3_LIBRARIES} pybind11::module hal::netlist hal::utilities hal::plugin_system)
install(TARGETS py
EXPORT hal
diff --git a/src/utilities/log.cpp b/src/utilities/log.cpp
index e3ef1cead5df..97a1bab30581 100644
--- a/src/utilities/log.cpp
+++ b/src/utilities/log.cpp
@@ -225,11 +225,6 @@ namespace hal
}
else
{
-#ifdef _WIN32
- // todo: to be implemented for windows
- sink->spdlog_sink = nullptr;
- log_error("stdout", "create_stdout_sink() has to be implemented for Windows.");
-#else
auto stdout_sink = std::make_shared();
stdout_sink->set_color(spdlog::level::trace, stdout_sink->green);
stdout_sink->set_color(spdlog::level::debug, stdout_sink->blue);
@@ -238,7 +233,6 @@ namespace hal
stdout_sink->set_color(spdlog::level::err, stdout_sink->red);
stdout_sink->set_color(spdlog::level::critical, stdout_sink->red_bold);
sink->spdlog_sink = stdout_sink;
-#endif
}
return sink;
diff --git a/src/utilities/project_directory.cpp b/src/utilities/project_directory.cpp
index 0b77742308ce..7fa76bb43b87 100644
--- a/src/utilities/project_directory.cpp
+++ b/src/utilities/project_directory.cpp
@@ -37,7 +37,7 @@ namespace hal {
std::filesystem::path ProjectDirectory::get_default_filename(const std::string& extension) const
{
- std::string name(filename());
+ std::string name(filename().string());
name += extension.empty() ? std::string(".hal") : extension;
std::filesystem::path retval(get_canonical_path());
retval.append(name);
@@ -57,7 +57,7 @@ namespace hal {
std::filesystem::path ProjectDirectory::get_shadow_filename(const std::string& extension) const
{
- std::string name(filename());
+ std::string name(filename().string());
name += extension.empty() ? std::string(".hal") : extension;
std::filesystem::path retval = get_shadow_dir();
retval.append(name);
diff --git a/src/utilities/utils.cpp b/src/utilities/utils.cpp
index d63aa95ce035..21c4c443a40f 100644
--- a/src/utilities/utils.cpp
+++ b/src/utilities/utils.cpp
@@ -28,6 +28,23 @@ namespace hal
{
namespace utils
{
+ namespace
+ {
+ /** Windows does not set HOME, the per-user root is USERPROFILE there. */
+ std::filesystem::path get_home_directory()
+ {
+ for (const char* variable : {"HOME", "USERPROFILE"})
+ {
+ const char* value = std::getenv(variable);
+ if (value != nullptr && *value != '\0')
+ {
+ return std::filesystem::path(value);
+ }
+ }
+ return std::filesystem::temp_directory_path();
+ }
+ } // namespace
+
bool file_exists(const std::string& filename)
{
std::ifstream ifile(filename.c_str());
@@ -37,21 +54,8 @@ namespace hal
bool folder_exists_and_is_accessible(const std::filesystem::path& folder)
{
#ifdef _WIN32
- DWORD ftyp = GetFileAttributesA(folder.c_str());
- if (ftyp == INVALID_FILE_ATTRIBUTES)
- {
- return false; //something is wrong with your path!
- }
-
- if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
- {
- if (0 == access(folder.c_str(), R_OK))
- {
- return true;
- }
- }
-
- return false; // this is not a directory!
+ hal::error_code ec;
+ return std::filesystem::is_directory(folder, ec);
#else
struct stat sb;
@@ -71,12 +75,18 @@ namespace hal
{
char buf[1024] = {0};
#ifdef _WIN32
- DWORD ret = GetModuleFileNameA(NULL, buf, sizeof(buf));
- if (ret == 0 || ret == sizeof(buf))
+ // the wide API hands the path over without any code page conversion, which would throw
+ // for non-ASCII characters (this runs during static initialization of the plugin manager)
+ wchar_t wbuf[MAX_PATH] = {0};
+ DWORD ret = GetModuleFileNameW(NULL, wbuf, MAX_PATH);
+ if (ret == 0 || ret == MAX_PATH)
{
return std::string();
}
- return std::filesystem::path(buf);
+ UNUSED(buf);
+ hal::error_code ec;
+ auto p = std::filesystem::canonical(std::filesystem::path(wbuf), ec);
+ return p.make_preferred().parent_path();
#elif __APPLE__ && __MACH__
uint32_t size = sizeof(buf);
int ret = _NSGetExecutablePath(buf, &size);
@@ -105,10 +115,15 @@ namespace hal
return std::filesystem::path(environ_path).make_preferred();
}
hal::error_code ec;
+#ifdef _WIN32
+ const std::filesystem::path hal_binary = "hal.exe";
+#else
+ const std::filesystem::path hal_binary = "hal";
+#endif
auto bin_dir = get_binary_directory();
while (std::filesystem::exists(bin_dir))
{
- if (std::filesystem::exists(bin_dir / "hal", ec))
+ if (std::filesystem::exists(bin_dir / hal_binary, ec))
{
return bin_dir.parent_path();
}
@@ -118,7 +133,7 @@ namespace hal
}
bin_dir = bin_dir.parent_path();
}
- std::filesystem::path which_result = which("hal");
+ std::filesystem::path which_result = which(hal_binary.string());
if (!which_result.empty())
{
return which_result.parent_path().parent_path();
@@ -129,6 +144,9 @@ namespace hal
std::filesystem::path get_library_directory()
{
std::vector path_hints = {
+#ifdef _WIN32
+ get_base_directory() / "bin/",
+#endif
get_base_directory() / "lib/x86_64-linux-gnu",
get_base_directory() / "lib64/",
get_base_directory() / "lib/",
@@ -156,7 +174,7 @@ namespace hal
std::filesystem::path get_user_share_directory()
{
- std::filesystem::path dir = std::filesystem::path(getenv("HOME")) / ".local/share/hal";
+ std::filesystem::path dir = get_home_directory() / ".local/share/hal";
std::filesystem::create_directories(dir);
return dir;
}
@@ -171,7 +189,7 @@ namespace hal
std::filesystem::path get_user_config_directory()
{
- std::filesystem::path dir = std::filesystem::path(getenv("HOME")) / ".config/hal";
+ std::filesystem::path dir = get_home_directory() / ".config/hal";
std::filesystem::create_directories(dir);
return dir;
}
@@ -199,7 +217,7 @@ namespace hal
get_library_directory() / "hal_plugins/",
get_library_directory() / "plugins/",
get_user_share_directory() / "plugins/",
- std::filesystem::path(getenv("HOME")) / "plugins/",
+ get_home_directory() / "plugins/",
};
return path_hints;
}
@@ -253,7 +271,6 @@ namespace hal
}
#ifdef _WIN32
const char which_delimiter = ';';
- return std::filesystem::path(); // Curerently no support for windows. Sorry ...
#else
const char which_delimiter = ':';
#endif
@@ -263,12 +280,26 @@ namespace hal
hal::error_code ec;
UNUSED(ec);
std::filesystem::path p = std::filesystem::path(folder) / name;
+#ifdef _WIN32
+ // Windows has no executable bit, and callers pass the name without the suffix
+ if (std::filesystem::is_regular_file(p, ec))
+ {
+ return p;
+ }
+ std::filesystem::path with_suffix = p;
+ with_suffix += ".exe";
+ if (std::filesystem::is_regular_file(with_suffix, ec))
+ {
+ return with_suffix;
+ }
+#else
struct stat sb;
if (stat(p.c_str(), &sb) == 0 && sb.st_mode & S_IXUSR)
{
return p;
}
+#endif
}
return std::filesystem::path();
}