Skip to content

Commit e2a2d8f

Browse files
authored
Merge branch 'master' into use-BUILD_TESTING
2 parents 2caf8c1 + c9ca8e2 commit e2a2d8f

10 files changed

+82
-42
lines changed

CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ if(NOT CMAKE_BUILD_TYPE)
44
set(CMAKE_BUILD_TYPE Release CACHE STRING "Release/Debug")
55
endif()
66

7+
message(STATUS "build type ${CMAKE_BUILD_TYPE}")
78
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
89
include(CheckCXXCompilerFlag)
910

@@ -28,6 +29,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
2829
set(CMAKE_CXX_EXTENSIONS OFF)
2930

3031
enable_cxx_compiler_flag_if_supported(-pedantic)
32+
enable_cxx_compiler_flag_if_supported(-ggdb)
3133

3234
if(MSVC)
3335
add_compile_options(-Zc:__cplusplus)
@@ -38,8 +40,8 @@ endif()
3840

3941
add_subdirectory(src/cpp subprocess)
4042

41-
# TODO testing
4243
if (BUILD_TESTING)
4344
enable_testing()
4445
add_subdirectory(test)
4546
endif(BUILD_TESTING)
47+

README.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,18 @@ All tests pass on linux & mac. Most pass under mingw & MSVC.
175175
- breaking: RunOptions which is used in subprocess::run order is changed to be
176176
identical to python subprocess::run. This effects users using c++20 designated
177177
initializers. Prior versions of compilers didn't seem to care about order.
178-
- fixed #5 cin double closed. Thanks [GerHobbelt](https://github.com/GerHobbelt)
178+
- Thanks to [urs-muff](https://github.com/urs-muff) for windows 64bit support
179+
180+
Thanks [GerHobbelt](https://github.com/GerHobbelt) for the following
181+
182+
- fixed #5 cin double closed.
183+
- `_DCRTIMP` for environ
184+
- order of [check](https://github.com/benman64/subprocess/pull/8/commits/cbf1a7aff1a627c961f93fb39de94601a52ceb0a) fixed, done so to match python ordering
185+
rather than changing example.
186+
187+
- [yurivict](https://github.com/yurivict) Thanks for FREEBSD compatibility (I have no way of testing this)
188+
- [StableAgOH](https://github.com/StableAgOH) thanks for pointing out WC_ERR_INVALID_CHARS macro exists and std::string nullptr fix
189+
179190
180191
# 0.4.0
181192

src/cpp/subprocess/ProcessBuilder.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#else
66
#include <spawn.h>
7-
#ifdef __APPLE__
7+
#if defined(__APPLE__) || defined(__FreeBSD__)
88
#include <sys/wait.h>
99
#else
1010
#include <wait.h>
@@ -160,7 +160,7 @@ namespace subprocess {
160160
case PipeVarIndex::handle:
161161
case PipeVarIndex::option: break;
162162
case PipeVarIndex::string: // doesn't make sense
163-
case PipeVarIndex::istream: // dousn't make sense
163+
case PipeVarIndex::istream: // doesn't make sense
164164
throw std::domain_error("expected something to output to");
165165
case PipeVarIndex::ostream:
166166
pipe_thread(input, std::get<std::ostream*>(output));
@@ -341,7 +341,7 @@ namespace subprocess {
341341
int Popen::wait(double timeout) {
342342
if (returncode != kBadReturnCode)
343343
return returncode;
344-
DWORD ms = timeout < 0? INFINITE : timeout*1000.0;
344+
DWORD ms = timeout < 0 ? INFINITE : (DWORD)(timeout*1000.0);
345345
DWORD result = WaitForSingleObject(process_info.hProcess, ms);
346346
if (result == WAIT_TIMEOUT) {
347347
throw TimeoutExpired("timeout of " + std::to_string(ms) + " expired");
@@ -583,4 +583,4 @@ namespace subprocess {
583583
return completed;
584584
}
585585

586-
}
586+
}

src/cpp/subprocess/ProcessBuilder.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ namespace subprocess {
100100
pid_t pid = 0;
101101
/** The exit value of the process. Valid once process is completed */
102102
int returncode = kBadReturnCode;
103+
std::string cwd;
103104
CommandLine args;
104105

105106
/** calls pipe_ignore_and_close on cout */

src/cpp/subprocess/ProcessBuilder_windows.cpp

+37-16
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "shell_utils.hpp"
1111
#include "environ.hpp"
12+
#include "utf8_to_utf16.hpp"
1213

1314
static STARTUPINFO g_startupInfo;
1415
static bool g_startupInfoInit = false;
@@ -48,7 +49,6 @@ namespace subprocess {
4849
saAttr.lpSecurityDescriptor = NULL;
4950

5051

51-
PROCESS_INFORMATION piProcInfo = {0};
5252
STARTUPINFO siStartInfo = {0};
5353
BOOL bSuccess = FALSE;
5454

@@ -72,7 +72,6 @@ namespace subprocess {
7272
disable_inherit(cin_pair.output);
7373
}
7474

75-
7675
if (cout_option == PipeOption::close) {
7776
cout_pair = pipe_create();
7877
siStartInfo.hStdOutput = cout_pair.output;
@@ -83,7 +82,7 @@ namespace subprocess {
8382
process.cout = cout_pair.input;
8483
disable_inherit(cout_pair.input);
8584
} else if (cout_option == PipeOption::cerr) {
86-
// Do this when stderr is setup bellow
85+
// Do this when stderr is setup below
8786
} else if (cout_option == PipeOption::specific) {
8887
pipe_set_inheritable(cout_pipe, true);
8988
siStartInfo.hStdOutput = cout_pipe;
@@ -109,7 +108,6 @@ namespace subprocess {
109108
if (cout_option == PipeOption::cerr) {
110109
siStartInfo.hStdOutput = siStartInfo.hStdError;
111110
}
112-
const char* cwd = this->cwd.empty()? nullptr : this->cwd.c_str();
113111
std::string args = windows_args(command);
114112

115113
void* env = nullptr;
@@ -130,19 +128,42 @@ namespace subprocess {
130128
if (this->new_process_group) {
131129
process_flags |= CREATE_NEW_PROCESS_GROUP;
132130
}
131+
132+
process.cwd = this->cwd;
133133
// Create the child process.
134-
bSuccess = CreateProcess(program.c_str(),
135-
(char*)args.c_str(), // command line
136-
NULL, // process security attributes
137-
NULL, // primary thread security attributes
138-
TRUE, // handles are inherited
139-
process_flags, // creation flags
140-
env, // environment
141-
cwd, // use parent's current directory
142-
&siStartInfo, // STARTUPINFO pointer
143-
&piProcInfo); // receives PROCESS_INFORMATION
144-
process.process_info = piProcInfo;
145-
process.pid = piProcInfo.dwProcessId;
134+
#if _WIN64
135+
std::u16string cmd_args{ utf8_to_utf16(args) };
136+
bSuccess = CreateProcess(
137+
(LPCWSTR)utf8_to_utf16(program).c_str(),
138+
(LPWSTR)cmd_args.data(), // command line
139+
NULL, // process security attributes
140+
NULL, // primary thread security attributes
141+
TRUE, // handles are inherited
142+
process_flags, // creation flags
143+
env, // environment
144+
(LPCWSTR)(this->cwd.empty() ? nullptr : utf8_to_utf16(this->cwd).c_str()), // use parent's current directory
145+
&siStartInfo, // STARTUPINFO pointer
146+
&process.process_info); // receives PROCESS_INFORMATION
147+
#else
148+
std::string cmd_args{ args };
149+
bSuccess = CreateProcess(
150+
(LPCSTR)program.c_str(),
151+
(LPSTR)cmd_args.data(), // command line
152+
NULL, // process security attributes
153+
NULL, // primary thread security attributes
154+
TRUE, // handles are inherited
155+
process_flags, // creation flags
156+
env, // environment
157+
(LPCSTR)(this->cwd.empty() ? nullptr : this->cwd.c_str()), // use parent's current directory
158+
&siStartInfo, // STARTUPINFO pointer
159+
&process.process_info); // receives PROCESS_INFORMATION
160+
161+
162+
LPCSTR cwd = this->cwd.empty() ? nullptr : (LPCSTR)this->cwd.c_str();
163+
LPCSTR program_arg = (LPCSTR)program.c_str();
164+
LPSTR cmd_args = (LPSTR)args.c_str(); // command line
165+
#endif
166+
process.pid = process.process_info.dwProcessId;
146167
if (cin_pair)
147168
cin_pair.close_input();
148169
if (cout_pair)

src/cpp/subprocess/basic_types.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#ifdef _WIN32
3+
#define NOMINMAX
34
#include <windows.h>
45
#else
56
#include <unistd.h>

src/cpp/subprocess/environ.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
#include "utf8_to_utf16.hpp"
77
using std::to_string;
88

9-
extern "C" char **environ;
9+
#if !defined(_DCRTIMP) // Windows-specific RTL DLL import macro
10+
#define _DCRTIMP
11+
#endif
12+
13+
extern "C" _DCRTIMP char **environ;
1014

1115
namespace subprocess {
1216
Environ cenv;
@@ -131,4 +135,4 @@ namespace subprocess {
131135
result += (char16_t)'\0';
132136
return result;
133137
}
134-
}
138+
}

src/cpp/subprocess/pipe.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ namespace subprocess {
6363
}
6464
ssize_t pipe_read(PipeHandle handle, void* buffer, std::size_t size) {
6565
DWORD bread = 0;
66-
bool result = ReadFile(handle, buffer, size, &bread, nullptr);
66+
bool result = ReadFile(handle, buffer, (DWORD)size, &bread, nullptr);
6767
if (result)
6868
return bread;
6969
return -1;
7070
}
7171

7272
ssize_t pipe_write(PipeHandle handle, const void* buffer, size_t size) {
7373
DWORD written = 0;
74-
bool result = WriteFile(handle, buffer, size, &written, nullptr);
74+
bool result = WriteFile(handle, buffer, (DWORD)size, &written, nullptr);
7575
if (result)
7676
return written;
7777
return -1;

src/cpp/subprocess/shell_utils.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#else
88
#include <unistd.h>
99
#include <spawn.h>
10-
#ifdef __APPLE__
10+
#if defined(__APPLE__) || defined(__FreeBSD__)
1111
#include <sys/wait.h>
1212
#else
1313
#include <wait.h>
@@ -42,7 +42,7 @@ namespace {
4242
if (path.empty())
4343
return false;
4444
return std::filesystem::is_regular_file(path);
45-
} catch (std::filesystem::filesystem_error& e) {
45+
} catch (std::filesystem::filesystem_error&) {
4646
return false;
4747
}
4848
}
@@ -302,4 +302,4 @@ namespace subprocess {
302302
return result;
303303
}
304304

305-
}
305+
}

src/cpp/subprocess/utf8_to_utf16.cpp

+13-13
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,13 @@ namespace subprocess {
112112
std::u16string utf8_to_utf16(const std::string& string) {
113113
static_assert(sizeof(wchar_t) == 2, "wchar_t must be of size 2");
114114
static_assert(sizeof(wchar_t) == sizeof(char16_t), "wchar_t must be of size 2");
115-
int size = string.size()+1;
115+
int size = (int)string.size()+1;
116116
// Determine wstring size (`MultiByteToWideChar` returns the required size if
117117
// its last two arguments are `NULL` and 0).
118118
int r = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
119119
string.c_str(), size, NULL, 0);
120120
if (r == 0) {
121-
return std::u16string();
121+
return {};
122122
}
123123
assert(r > 0);
124124

@@ -127,7 +127,7 @@ namespace subprocess {
127127
wchar_t *wstring = new wchar_t[r];
128128
if (wstring == NULL) {
129129
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
130-
return NULL;
130+
return {};
131131
}
132132

133133
// Now we pass our allocated string and its size as the last two arguments
@@ -137,27 +137,27 @@ namespace subprocess {
137137
wstring, r);
138138
if (r == 0) {
139139
delete [] wstring;
140-
return NULL;
140+
return {};
141141
}
142142
std::u16string result((char16_t*)wstring, r-1);
143143
delete [] wstring;
144144
return result;
145145
}
146146

147-
#ifdef __MINGW32__
147+
#ifndef WC_ERR_INVALID_CHARS
148148
// mingw doesn't define this
149149
constexpr int WC_ERR_INVALID_CHARS = 0;
150150
#endif
151151

152152
std::string utf16_to_utf8(const std::u16string& wstring) {
153-
int size = wstring.size()+1;
153+
int size = (int)wstring.size()+1;
154154
// Determine wstring size (`MultiByteToWideChar` returns the required size if
155155
// its last two arguments are `NULL` and 0).
156156
int r = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
157157
(wchar_t*)wstring.c_str(), size, NULL, 0, NULL, NULL);
158158

159159
if (r == 0) {
160-
return "";
160+
return {};
161161
}
162162
assert(r > 0);
163163

@@ -166,7 +166,7 @@ namespace subprocess {
166166
char *string = new char[r];
167167
if (string == nullptr) {
168168
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
169-
return NULL;
169+
return {};
170170
}
171171

172172
// Now we pass our allocated string and its size as the last two arguments
@@ -176,22 +176,22 @@ namespace subprocess {
176176
string, r, NULL, NULL);
177177
if (r == 0) {
178178
delete [] string;
179-
return NULL;
179+
return {};
180180
}
181181
std::string result(string, r-1);
182182
delete [] string;
183183
return result;
184184
}
185185

186186
std::string utf16_to_utf8(const std::wstring& wstring) {
187-
int size = wstring.size()+1;
187+
int size = (int)wstring.size()+1;
188188
// Determine wstring size (`MultiByteToWideChar` returns the required size if
189189
// its last two arguments are `NULL` and 0).
190190
int r = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
191191
(wchar_t*)wstring.c_str(), size, NULL, 0, NULL, NULL);
192192

193193
if (r == 0) {
194-
return "";
194+
return {};
195195
}
196196
assert(r > 0);
197197

@@ -200,7 +200,7 @@ namespace subprocess {
200200
char *string = new char[r];
201201
if (string == nullptr) {
202202
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
203-
return NULL;
203+
return {};
204204
}
205205

206206
// Now we pass our allocated string and its size as the last two arguments
@@ -210,7 +210,7 @@ namespace subprocess {
210210
string, r, NULL, NULL);
211211
if (r == 0) {
212212
delete [] string;
213-
return NULL;
213+
return {};
214214
}
215215
std::string result(string, r-1);
216216
delete [] string;

0 commit comments

Comments
 (0)