Skip to content

Commit 9ea7787

Browse files
committed
feat: Windows portability — POSIX guards + Win32 API alternatives
- bmi_cache.cppm: flock() → LockFileEx/UnlockFileEx on Windows - probe.cppm, xlings.cppm, cli.cppm, config.cppm, pack.cppm: popen/pclose → _popen/_pclose on Windows - ninja_backend.cppm: GetModuleFileNameA for exe path on Windows - config.cppm: GetModuleFileNameA for MCPP_HOME detection These are the minimum changes needed for MSVC compilation.
1 parent 002af19 commit 9ea7787

7 files changed

Lines changed: 85 additions & 8 deletions

File tree

src/bmi_cache.cppm

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@
1515
// dep cache without trashing manifest.txt (docs/26 §5.4 V2).
1616

1717
module;
18+
#if defined(_WIN32)
19+
#include <io.h>
20+
#include <windows.h>
21+
#else
1822
#include <fcntl.h>
1923
#include <sys/file.h>
2024
#include <unistd.h>
25+
#endif
2126

2227
export module mcpp.bmi_cache;
2328

@@ -184,9 +189,35 @@ stage_into(const CacheKey& key,
184189

185190
namespace {
186191

187-
// Acquire an exclusive non-blocking flock on <dir>/.lock. Returns the fd on
188-
// success (caller closes it to release), or -1 if another mcpp is already
189-
// populating this entry — in which case the caller should skip writing.
192+
// Acquire an exclusive non-blocking lock on <dir>/.lock. Returns a handle
193+
// on success, or -1/INVALID_HANDLE if another mcpp is already populating.
194+
#if defined(_WIN32)
195+
// Windows: use LockFileEx on a file handle
196+
HANDLE try_lock_dir(const std::filesystem::path& dir) {
197+
std::error_code ec;
198+
std::filesystem::create_directories(dir, ec);
199+
auto lockPath = dir / ".lock";
200+
HANDLE h = CreateFileW(lockPath.wstring().c_str(),
201+
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
202+
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
203+
if (h == INVALID_HANDLE_VALUE) return h;
204+
OVERLAPPED ov = {};
205+
if (!LockFileEx(h, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
206+
0, 1, 0, &ov)) {
207+
CloseHandle(h);
208+
return INVALID_HANDLE_VALUE;
209+
}
210+
return h;
211+
}
212+
213+
void release_lock(HANDLE h) {
214+
if (h == INVALID_HANDLE_VALUE) return;
215+
OVERLAPPED ov = {};
216+
UnlockFileEx(h, 0, 1, 0, &ov);
217+
CloseHandle(h);
218+
}
219+
#else
220+
// POSIX: use flock(2)
190221
int try_lock_dir(const std::filesystem::path& dir) {
191222
std::error_code ec;
192223
std::filesystem::create_directories(dir, ec);
@@ -205,6 +236,7 @@ void release_lock(int fd) {
205236
::flock(fd, LOCK_UN);
206237
::close(fd);
207238
}
239+
#endif
208240

209241
} // namespace
210242

@@ -214,6 +246,16 @@ populate_from(const CacheKey& key,
214246
const DepArtifacts& arts)
215247
{
216248
auto cacheDir = key.dir();
249+
#if defined(_WIN32)
250+
HANDLE lockHandle = try_lock_dir(cacheDir);
251+
if (lockHandle == INVALID_HANDLE_VALUE) {
252+
return {};
253+
}
254+
struct LockGuard {
255+
HANDLE h;
256+
~LockGuard() { release_lock(h); }
257+
} guard{ lockHandle };
258+
#else
217259
int lockFd = try_lock_dir(cacheDir);
218260
if (lockFd < 0) {
219261
// Another writer holds the lock; treat as success (they'll do it).
@@ -223,6 +265,7 @@ populate_from(const CacheKey& key,
223265
int fd;
224266
~LockGuard() { release_lock(fd); }
225267
} guard{ lockFd };
268+
#endif
226269

227270
auto cacheBmi = key.bmiDir();
228271
auto cacheObj = key.objDir();

src/build/ninja_backend.cppm

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
module;
1515
#include <cstdio>
1616
#include <cstdlib>
17-
#if defined(__APPLE__)
17+
#if defined(_WIN32)
18+
#include <windows.h>
19+
#elif defined(__APPLE__)
1820
#include <mach-o/dyld.h> // _NSGetExecutablePath
1921
#endif
2022

@@ -116,8 +118,14 @@ bool dyndep_mode_enabled() {
116118

117119
std::filesystem::path mcpp_exe_path() {
118120
std::error_code ec;
119-
#if defined(__APPLE__)
120-
// macOS: use _NSGetExecutablePath
121+
#if defined(_WIN32)
122+
char buf[MAX_PATH];
123+
DWORD len = GetModuleFileNameA(NULL, buf, MAX_PATH);
124+
if (len > 0 && len < MAX_PATH) {
125+
auto p = std::filesystem::canonical(buf, ec);
126+
if (!ec) return p;
127+
}
128+
#elif defined(__APPLE__)
121129
char buf[4096];
122130
uint32_t size = sizeof(buf);
123131
if (_NSGetExecutablePath(buf, &size) == 0) {

src/cli.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
module;
1212
#include <cstdio>
1313
#include <cstdlib>
14+
#if defined(_WIN32)
15+
#define popen _popen
16+
#define pclose _pclose
17+
#endif
1418

1519
export module mcpp.cli;
1620

src/config.cppm

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
module;
1717
#include <cstdio>
1818
#include <cstdlib>
19-
#if defined(__APPLE__)
19+
#if defined(_WIN32)
20+
#include <windows.h>
21+
#define popen _popen
22+
#define pclose _pclose
23+
#elif defined(__APPLE__)
2024
#include <mach-o/dyld.h> // _NSGetExecutablePath
2125
#endif
2226

@@ -164,7 +168,13 @@ std::filesystem::path home_dir() {
164168
return std::filesystem::path(e);
165169

166170
std::error_code ec;
167-
#if defined(__APPLE__)
171+
#if defined(_WIN32)
172+
char _exe_buf[MAX_PATH];
173+
DWORD _exe_len = GetModuleFileNameA(NULL, _exe_buf, MAX_PATH);
174+
std::filesystem::path exe;
175+
if (_exe_len > 0 && _exe_len < MAX_PATH)
176+
exe = std::filesystem::canonical(_exe_buf, ec);
177+
#elif defined(__APPLE__)
168178
char _exe_buf[4096];
169179
uint32_t _exe_size = sizeof(_exe_buf);
170180
std::filesystem::path exe;

src/pack/pack.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818
module;
1919
#include <cstdio> // popen, pclose
20+
#if defined(_WIN32)
21+
#define popen _popen
22+
#define pclose _pclose
23+
#endif
2024

2125
export module mcpp.pack;
2226

src/toolchain/probe.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
module;
44
#include <cstdio> // popen, pclose, fgets, FILE
55
#include <cstdlib> // getenv
6+
#if defined(_WIN32)
7+
#define popen _popen
8+
#define pclose _pclose
9+
#endif
610

711
export module mcpp.toolchain.probe;
812

src/xlings.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
module;
1111
#include <cstdio>
1212
#include <cstdlib>
13+
#if defined(_WIN32)
14+
#define popen _popen
15+
#define pclose _pclose
16+
#endif
1317

1418
export module mcpp.xlings;
1519

0 commit comments

Comments
 (0)