Repository navigation
Add windows support #231
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
base: master
Are you sure you want to change the base?
Add windows support #231
Changes from all commits
a8a37a8
72cf2ef
337979b
cea3623
d0fbee2
08b1f01
7627eda
660d581
78f3e80
6836a3e
a8e8c55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| CI_DESC="CI job cross-compiling to Windows with MinGW, tested with Wine" | ||
| CI_DIR=build-windows | ||
| CI_CACHE_NIX_STORE=true | ||
| NIX_ARGS=( | ||
| --arg windows true | ||
| --arg minimal true | ||
| ) | ||
| CMAKE_ARGS=( | ||
| -G Ninja | ||
| -DCMAKE_SYSTEM_NAME=Windows | ||
| -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER | ||
| -DCMAKE_CROSSCOMPILING_EMULATOR=wine | ||
| # -Wa,-mbig-obj: template-heavy C++ generates >32K COFF sections per .obj; | ||
| # BigCOFF format raises the limit. Must be passed to the assembler via -Wa. | ||
| "-DCMAKE_CXX_FLAGS=-Wa,-mbig-obj" | ||
| ) | ||
| # CXX is set by the nix cross shell to the mingw g++ wrapper; cmake picks | ||
| # it up from the environment, so no CMAKE_CXX_COMPILER override needed. | ||
| BUILD_ARGS=(-k 0) | ||
| # Build native mpgen first (as a code generator for cross-compiled test/example targets). | ||
| MPGEN_PRE_BUILD=1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,17 @@ | |
| #include <memory> | ||
| #endif | ||
|
|
||
| #ifdef WIN32 | ||
| // WIN32_LEAN_AND_MEAN excludes commdlg.h which defines `#define INTERFACE | ||
| // IPrintDialogServices` — this conflicts with capnp::Kind::INTERFACE used | ||
| // in CAPNP_DECLARE_INTERFACE_HEADER. Must be defined before winsock2.h. | ||
| #ifndef WIN32_LEAN_AND_MEAN | ||
| #define WIN32_LEAN_AND_MEAN | ||
| #endif | ||
| #include <windows.h> | ||
| #include <winsock2.h> | ||
| #endif | ||
|
|
||
| namespace mp { | ||
|
|
||
| //! Generic utility functions used by capnp code. | ||
|
|
@@ -289,33 +300,53 @@ std::string ThreadName(const char* exe_name); | |
| //! errors in python unit tests. | ||
| std::string LogEscape(const kj::StringTree& string, size_t max_size); | ||
|
|
||
| //! Convert an argument vector into a single command line string suitable for | ||
| //! CreateProcess, following the quoting rules of CommandLineToArgvW, which | ||
| //! executables use to split the command line back into arguments. Declared | ||
| //! unconditionally (not just on windows) so it can be unit tested on any | ||
| //! platform. | ||
| std::string CommandLineFromArgv(const std::vector<std::string>& argv); | ||
|
|
||
| using Stream = kj::Own<kj::AsyncIoStream>; | ||
|
|
||
| #ifdef WIN32 | ||
| // On Windows, ProcessId is defined to be the local process HANDLE rather than | ||
| // global process ID, because handles are more useful for controlling and | ||
| // waiting for processes. It it possible to obtain the actual process ID from | ||
| // handles by calling the GetProcessId API. | ||
| using ProcessId = HANDLE; | ||
| using SocketId = SOCKET; | ||
| inline constexpr SocketId SocketError{INVALID_SOCKET}; | ||
| #else | ||
| using ProcessId = int; | ||
| using SocketId = int; | ||
| inline constexpr SocketId SocketError{-1}; | ||
|
|
||
| //! Information about parent process passed to child process as a command-line | ||
| //! argument. On unix this is the child socket fd number formatted as a string. | ||
| using SpawnConnectInfo = std::string; | ||
|
|
||
| //! Callback type used by SpawnProcess below. | ||
| using SpawnConnectInfoToArgsFn = std::function<std::vector<std::string>(const SpawnConnectInfo&)>; | ||
| #endif | ||
|
|
||
| //! Spawn a new process that communicates with the current process over a socket | ||
| //! pair. Calls connect_info_to_args callback with a connection string that | ||
| //! needs to be passed to the child process, and executes the argv command line | ||
| //! it returns. Returns child process id and socket id. | ||
| std::tuple<ProcessId, SocketId> SpawnProcess(SpawnConnectInfoToArgsFn&& connect_info_to_args); | ||
|
|
||
| //! Initialize spawned child process using the SpawnConnectInfo string passed to it, | ||
| //! returning a socket id for communicating with the parent process. | ||
| SocketId StartSpawned(const SpawnConnectInfo& connect_info); | ||
| //! pair. Calls spawn_argv callback with a connection string that needs to be | ||
| //! passed to the child process, and executes the argv command line it returns. | ||
| //! Returns child process id and socket id. | ||
| //! | ||
| //! The connection string is just a file descriptor number on unix. On windows, | ||
| //! it is a path to a named pipe the parent process will write | ||
| //! WSADuplicateSocket info to. In both cases, the child process can call | ||
| //! StartSpawned to get a socket handle from the connection string. | ||
| std::tuple<ProcessId, SocketId> SpawnProcess(const std::function<std::vector<std::string>(std::string)>& spawn_argv); | ||
|
|
||
| //! Initialize spawned child process. The connect_info argument is the | ||
| //! connection string SpawnProcess generated in the parent process and passed | ||
| //! to the child on its command line. Returns socket id for communicating with | ||
| //! the parent process. | ||
| SocketId StartSpawned(const std::string& connect_info); | ||
|
ryanofsky marked this conversation as resolved.
|
||
|
|
||
| //! Create a socket pair that can be used to communicate within a process or | ||
| //! between parent and child processes. | ||
| std::array<SocketId, 2> SocketPair(); | ||
|
|
||
| //! Close a socket, throwing a KJ exception on failure. | ||
| void CloseSocket(SocketId fd); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In commit 15aa914: util, test: Add CloseSocket, use SocketId I think this should be used here as well index e8d1533..86616ce 100644
--- a/test/mp/test/spawn_tests.cpp
+++ b/test/mp/test/spawn_tests.cpp
@@ -141,7 +141,7 @@ KJ_TEST("SpawnProcess does not run callback in child")
std::lock_guard<std::mutex> g(target_mutex);
return {"true", std::move(connect_info)};
})};
- ::close(socket);
+ CloseSocket(socket);
int status{0};
// Give the child some time to exit. If it does not, terminate it and
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In commit 15aa914: util, test: Add CloseSocket, use SocketId nit: Since we are not really using fd, so I think the parameter name should be changed to |
||
|
|
||
| //! Start a process and return its process id. Caller should call WaitProcess | ||
| //! on the returned id. | ||
| ProcessId StartProcess(const std::vector<std::string>& args); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.