librats 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/binding.gyp +1 -0
  2. package/native-src/3rdparty/android/ifaddrs-android.c +600 -0
  3. package/native-src/3rdparty/android/ifaddrs-android.h +54 -0
  4. package/native-src/CMakeLists.txt +360 -0
  5. package/native-src/LICENSE +21 -0
  6. package/native-src/src/bencode.cpp +485 -0
  7. package/native-src/src/bencode.h +145 -0
  8. package/native-src/src/bittorrent.cpp +3682 -0
  9. package/native-src/src/bittorrent.h +731 -0
  10. package/native-src/src/dht.cpp +2342 -0
  11. package/native-src/src/dht.h +501 -0
  12. package/native-src/src/encrypted_socket.cpp +817 -0
  13. package/native-src/src/encrypted_socket.h +239 -0
  14. package/native-src/src/file_transfer.cpp +1808 -0
  15. package/native-src/src/file_transfer.h +567 -0
  16. package/native-src/src/fs.cpp +639 -0
  17. package/native-src/src/fs.h +108 -0
  18. package/native-src/src/gossipsub.cpp +1137 -0
  19. package/native-src/src/gossipsub.h +403 -0
  20. package/native-src/src/ice.cpp +1386 -0
  21. package/native-src/src/ice.h +328 -0
  22. package/native-src/src/json.hpp +25526 -0
  23. package/native-src/src/krpc.cpp +558 -0
  24. package/native-src/src/krpc.h +145 -0
  25. package/native-src/src/librats.cpp +2715 -0
  26. package/native-src/src/librats.h +1729 -0
  27. package/native-src/src/librats_bittorrent.cpp +167 -0
  28. package/native-src/src/librats_c.cpp +1317 -0
  29. package/native-src/src/librats_c.h +237 -0
  30. package/native-src/src/librats_encryption.cpp +123 -0
  31. package/native-src/src/librats_file_transfer.cpp +226 -0
  32. package/native-src/src/librats_gossipsub.cpp +293 -0
  33. package/native-src/src/librats_ice.cpp +515 -0
  34. package/native-src/src/librats_logging.cpp +158 -0
  35. package/native-src/src/librats_mdns.cpp +171 -0
  36. package/native-src/src/librats_nat.cpp +571 -0
  37. package/native-src/src/librats_persistence.cpp +815 -0
  38. package/native-src/src/logger.h +412 -0
  39. package/native-src/src/mdns.cpp +1178 -0
  40. package/native-src/src/mdns.h +253 -0
  41. package/native-src/src/network_utils.cpp +598 -0
  42. package/native-src/src/network_utils.h +162 -0
  43. package/native-src/src/noise.cpp +981 -0
  44. package/native-src/src/noise.h +227 -0
  45. package/native-src/src/os.cpp +371 -0
  46. package/native-src/src/os.h +40 -0
  47. package/native-src/src/rats_export.h +17 -0
  48. package/native-src/src/sha1.cpp +163 -0
  49. package/native-src/src/sha1.h +42 -0
  50. package/native-src/src/socket.cpp +1376 -0
  51. package/native-src/src/socket.h +309 -0
  52. package/native-src/src/stun.cpp +484 -0
  53. package/native-src/src/stun.h +349 -0
  54. package/native-src/src/threadmanager.cpp +105 -0
  55. package/native-src/src/threadmanager.h +53 -0
  56. package/native-src/src/tracker.cpp +1110 -0
  57. package/native-src/src/tracker.h +268 -0
  58. package/native-src/src/version.cpp +24 -0
  59. package/native-src/src/version.h.in +45 -0
  60. package/native-src/version.rc.in +31 -0
  61. package/package.json +2 -8
  62. package/scripts/build-librats.js +59 -12
  63. package/scripts/prepare-package.js +133 -37
@@ -0,0 +1,268 @@
1
+ #pragma once
2
+
3
+ #include "bittorrent.h"
4
+ #include "socket.h"
5
+ #include <string>
6
+ #include <vector>
7
+ #include <memory>
8
+ #include <functional>
9
+ #include <chrono>
10
+ #include <atomic>
11
+ #include <mutex>
12
+
13
+ namespace librats {
14
+
15
+ // Forward declarations
16
+ class TrackerClient;
17
+ class HttpTrackerClient;
18
+ class UdpTrackerClient;
19
+
20
+ // Tracker announce event types (BEP 3)
21
+ enum class TrackerEvent {
22
+ NONE = 0,
23
+ COMPLETED = 1,
24
+ STARTED = 2,
25
+ STOPPED = 3
26
+ };
27
+
28
+ // Tracker response structure
29
+ struct TrackerResponse {
30
+ std::string failure_reason;
31
+ std::string warning_message;
32
+ uint32_t interval; // Seconds until next announce
33
+ uint32_t min_interval; // Minimum announce interval
34
+ std::string tracker_id; // Tracker ID for subsequent requests
35
+ uint32_t complete; // Number of seeders
36
+ uint32_t incomplete; // Number of leechers
37
+ uint32_t downloaded; // Number of times downloaded (scrape only)
38
+ std::vector<Peer> peers; // Peer list
39
+ bool success;
40
+
41
+ TrackerResponse()
42
+ : interval(1800), min_interval(900), complete(0), incomplete(0),
43
+ downloaded(0), success(false) {}
44
+ };
45
+
46
+ // Tracker announce request parameters
47
+ struct TrackerRequest {
48
+ InfoHash info_hash;
49
+ PeerID peer_id;
50
+ uint16_t port;
51
+ uint64_t uploaded;
52
+ uint64_t downloaded;
53
+ uint64_t left;
54
+ TrackerEvent event;
55
+ std::string ip; // Optional IP address
56
+ uint32_t numwant; // Number of peers wanted (default 50)
57
+ std::string tracker_id; // Tracker ID from previous response
58
+
59
+ TrackerRequest()
60
+ : port(0), uploaded(0), downloaded(0), left(0),
61
+ event(TrackerEvent::NONE), numwant(50) {}
62
+ };
63
+
64
+ // Callback for tracker responses
65
+ using TrackerResponseCallback = std::function<void(const TrackerResponse& response, const std::string& tracker_url)>;
66
+
67
+ // Base tracker client interface
68
+ class TrackerClient {
69
+ public:
70
+ virtual ~TrackerClient() = default;
71
+
72
+ // Announce to tracker
73
+ virtual bool announce(const TrackerRequest& request, TrackerResponseCallback callback) = 0;
74
+
75
+ // Scrape tracker (optional, not all trackers support this)
76
+ virtual bool scrape(const std::vector<InfoHash>& info_hashes, TrackerResponseCallback callback) = 0;
77
+
78
+ // Get tracker URL
79
+ virtual std::string get_url() const = 0;
80
+
81
+ // Get last announce time
82
+ virtual std::chrono::steady_clock::time_point get_last_announce_time() const = 0;
83
+
84
+ // Get announce interval
85
+ virtual uint32_t get_interval() const = 0;
86
+
87
+ // Check if tracker is working
88
+ virtual bool is_working() const = 0;
89
+ };
90
+
91
+ // HTTP/HTTPS Tracker Client (BEP 3)
92
+ class HttpTrackerClient : public TrackerClient {
93
+ public:
94
+ explicit HttpTrackerClient(const std::string& tracker_url);
95
+ ~HttpTrackerClient() override;
96
+
97
+ bool announce(const TrackerRequest& request, TrackerResponseCallback callback) override;
98
+ bool scrape(const std::vector<InfoHash>& info_hashes, TrackerResponseCallback callback) override;
99
+
100
+ std::string get_url() const override { return tracker_url_; }
101
+ std::chrono::steady_clock::time_point get_last_announce_time() const override { return last_announce_time_; }
102
+ uint32_t get_interval() const override { return interval_; }
103
+ bool is_working() const override { return is_working_; }
104
+
105
+ private:
106
+ std::string tracker_url_;
107
+ std::chrono::steady_clock::time_point last_announce_time_;
108
+ uint32_t interval_;
109
+ std::atomic<bool> is_working_;
110
+ std::string tracker_id_;
111
+
112
+ // Build announce URL with parameters
113
+ std::string build_announce_url(const TrackerRequest& request);
114
+
115
+ // Build scrape URL
116
+ std::string build_scrape_url(const std::vector<InfoHash>& info_hashes);
117
+
118
+ // Parse tracker response (bencode format)
119
+ TrackerResponse parse_response(const std::vector<uint8_t>& data);
120
+
121
+ // Parse compact peer list (BEP 23)
122
+ std::vector<Peer> parse_compact_peers(const std::string& peer_data);
123
+
124
+ // Parse dictionary peer list
125
+ std::vector<Peer> parse_dict_peers(const BencodeValue& peers_list);
126
+
127
+ // HTTP GET request
128
+ std::vector<uint8_t> http_get(const std::string& url);
129
+
130
+ // URL encode string
131
+ std::string url_encode(const std::string& str);
132
+
133
+ // URL encode binary data (for info_hash)
134
+ std::string url_encode_binary(const uint8_t* data, size_t len);
135
+ };
136
+
137
+ // UDP Tracker Client (BEP 15)
138
+ class UdpTrackerClient : public TrackerClient {
139
+ public:
140
+ explicit UdpTrackerClient(const std::string& tracker_url);
141
+ ~UdpTrackerClient() override;
142
+
143
+ bool announce(const TrackerRequest& request, TrackerResponseCallback callback) override;
144
+ bool scrape(const std::vector<InfoHash>& info_hashes, TrackerResponseCallback callback) override;
145
+
146
+ std::string get_url() const override { return tracker_url_; }
147
+ std::chrono::steady_clock::time_point get_last_announce_time() const override { return last_announce_time_; }
148
+ uint32_t get_interval() const override { return interval_; }
149
+ bool is_working() const override { return is_working_; }
150
+
151
+ private:
152
+ std::string tracker_url_;
153
+ std::string hostname_;
154
+ uint16_t port_;
155
+ socket_t socket_;
156
+ std::chrono::steady_clock::time_point last_announce_time_;
157
+ std::chrono::steady_clock::time_point connection_expire_time_;
158
+ uint32_t interval_;
159
+ std::atomic<bool> is_working_;
160
+ int64_t connection_id_;
161
+ std::mutex socket_mutex_;
162
+
163
+ // UDP tracker protocol constants
164
+ static constexpr int64_t PROTOCOL_ID = 0x41727101980LL;
165
+ static constexpr uint32_t ACTION_CONNECT = 0;
166
+ static constexpr uint32_t ACTION_ANNOUNCE = 1;
167
+ static constexpr uint32_t ACTION_SCRAPE = 2;
168
+ static constexpr uint32_t ACTION_ERROR = 3;
169
+
170
+ // Parse tracker URL
171
+ bool parse_url();
172
+
173
+ // Connect to UDP tracker (get connection ID)
174
+ bool connect();
175
+
176
+ // Check if connection is still valid
177
+ bool is_connection_valid();
178
+
179
+ // Send UDP request and receive response
180
+ std::vector<uint8_t> send_request(const std::vector<uint8_t>& request, int timeout_ms = 15000);
181
+
182
+ // Build connect request
183
+ std::vector<uint8_t> build_connect_request(uint32_t transaction_id);
184
+
185
+ // Build announce request
186
+ std::vector<uint8_t> build_announce_request(const TrackerRequest& request, uint32_t transaction_id);
187
+
188
+ // Build scrape request
189
+ std::vector<uint8_t> build_scrape_request(const std::vector<InfoHash>& info_hashes, uint32_t transaction_id);
190
+
191
+ // Parse connect response
192
+ bool parse_connect_response(const std::vector<uint8_t>& data, uint32_t expected_transaction_id);
193
+
194
+ // Parse announce response
195
+ TrackerResponse parse_announce_response(const std::vector<uint8_t>& data, uint32_t expected_transaction_id);
196
+
197
+ // Parse scrape response
198
+ TrackerResponse parse_scrape_response(const std::vector<uint8_t>& data, uint32_t expected_transaction_id);
199
+
200
+ // Parse error response
201
+ std::string parse_error_response(const std::vector<uint8_t>& data);
202
+
203
+ // Generate random transaction ID
204
+ uint32_t generate_transaction_id();
205
+
206
+ // Read 32-bit big-endian integer
207
+ static uint32_t read_uint32_be(const uint8_t* data);
208
+
209
+ // Write 32-bit big-endian integer
210
+ static void write_uint32_be(uint8_t* data, uint32_t value);
211
+
212
+ // Read 64-bit big-endian integer
213
+ static int64_t read_int64_be(const uint8_t* data);
214
+
215
+ // Write 64-bit big-endian integer
216
+ static void write_int64_be(uint8_t* data, int64_t value);
217
+ };
218
+
219
+ // Tracker Manager - manages multiple trackers for a torrent
220
+ class TrackerManager {
221
+ public:
222
+ explicit TrackerManager(const TorrentInfo& torrent_info);
223
+ ~TrackerManager();
224
+
225
+ // Add tracker from URL
226
+ bool add_tracker(const std::string& tracker_url);
227
+
228
+ // Announce to all trackers
229
+ void announce(const TrackerRequest& request, TrackerResponseCallback callback);
230
+
231
+ // Announce to best tracker only
232
+ void announce_to_best(const TrackerRequest& request, TrackerResponseCallback callback);
233
+
234
+ // Scrape all trackers
235
+ void scrape(TrackerResponseCallback callback);
236
+
237
+ // Get number of working trackers
238
+ size_t get_working_tracker_count() const;
239
+
240
+ // Get all tracker URLs
241
+ std::vector<std::string> get_tracker_urls() const;
242
+
243
+ // Check if it's time to announce
244
+ bool should_announce() const;
245
+
246
+ // Get next announce time
247
+ std::chrono::steady_clock::time_point get_next_announce_time() const;
248
+
249
+ private:
250
+ std::vector<std::shared_ptr<TrackerClient>> trackers_;
251
+ mutable std::mutex trackers_mutex_;
252
+ InfoHash info_hash_;
253
+ std::chrono::steady_clock::time_point last_announce_time_;
254
+ uint32_t announce_interval_;
255
+
256
+ // Create tracker client based on URL scheme
257
+ std::shared_ptr<TrackerClient> create_tracker_client(const std::string& tracker_url);
258
+
259
+ // Sort trackers by priority (working trackers first)
260
+ void sort_trackers_by_priority();
261
+ };
262
+
263
+ // Utility functions
264
+ std::string tracker_event_to_string(TrackerEvent event);
265
+ TrackerEvent string_to_tracker_event(const std::string& event_str);
266
+
267
+ } // namespace librats
268
+
@@ -0,0 +1,24 @@
1
+ #include "version.h"
2
+ #include <iostream>
3
+ #include <iomanip>
4
+ #include "rats_export.h"
5
+
6
+ namespace librats {
7
+ namespace version {
8
+
9
+ RATS_API void rats_print_version_info() {
10
+ std::cout << "Version: " << STRING << std::endl;
11
+ std::cout << "Git: " << GIT_DESCRIBE << std::endl;
12
+ std::cout << "Build: " << BUILD << std::endl;
13
+ }
14
+
15
+ RATS_API void rats_print_header() {
16
+ std::cout << ASCII_HEADER << std::endl;
17
+ std::cout << " Version: " << std::left << std::setw(10) << STRING
18
+ << " Build: " << BUILD << std::endl;
19
+ std::cout << " Git: " << GIT_DESCRIBE << std::endl;
20
+ std::cout << " ======================================== " << std::endl;
21
+ std::cout << std::endl;
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,45 @@
1
+ #pragma once
2
+
3
+ #include "rats_export.h"
4
+
5
+ // This file is auto-generated by CMake. Do not edit manually.
6
+ #define LIBRATS_VERSION_MAJOR @VERSION_MAJOR@
7
+ #define LIBRATS_VERSION_MINOR @VERSION_MINOR@
8
+ #define LIBRATS_VERSION_PATCH @VERSION_PATCH@
9
+ #define LIBRATS_VERSION_BUILD @VERSION_BUILD@
10
+ #define LIBRATS_VERSION_STRING "@VERSION_STRING@"
11
+ #define LIBRATS_GIT_DESCRIBE "@GIT_DESCRIBE@"
12
+
13
+ // ASCII Art Header
14
+ #define LIBRATS_ASCII_HEADER \
15
+ " ####### ##### ######## ####### \n" \
16
+ " ## ## ## ## ## ## \n" \
17
+ " ## ## ## ## ## ## \n" \
18
+ " ####### ####### ## ####### \n" \
19
+ " ## ## ## ## ## ## \n" \
20
+ " ## ## ## ## ## ## \n" \
21
+ " ## ## ## ## ## ####### \n" \
22
+ " \n" \
23
+ " P2P Network Communication Library \n" \
24
+ " ====================================== \n"
25
+
26
+ namespace librats {
27
+ namespace version {
28
+ // Version information
29
+ const int MAJOR = LIBRATS_VERSION_MAJOR;
30
+ const int MINOR = LIBRATS_VERSION_MINOR;
31
+ const int PATCH = LIBRATS_VERSION_PATCH;
32
+ const int BUILD = LIBRATS_VERSION_BUILD;
33
+ const char* const STRING = LIBRATS_VERSION_STRING;
34
+ const char* const GIT_DESCRIBE = LIBRATS_GIT_DESCRIBE;
35
+
36
+ // ASCII header
37
+ const char* const ASCII_HEADER = LIBRATS_ASCII_HEADER;
38
+
39
+ // Print version info
40
+ RATS_API void rats_print_version_info();
41
+
42
+ // Print ASCII header with version
43
+ RATS_API void rats_print_header();
44
+ }
45
+ }
@@ -0,0 +1,31 @@
1
+ #include <windows.h>
2
+
3
+ VS_VERSION_INFO VERSIONINFO
4
+ FILEVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@
5
+ PRODUCTVERSION @VERSION_MAJOR@,@VERSION_MINOR@,@VERSION_PATCH@,@VERSION_BUILD@
6
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
7
+ FILEFLAGS 0x0L
8
+ FILEOS VOS__WINDOWS32
9
+ FILETYPE VFT_APP
10
+ FILESUBTYPE VFT2_UNKNOWN
11
+ BEGIN
12
+ BLOCK "StringFileInfo"
13
+ BEGIN
14
+ BLOCK "040904b0"
15
+ BEGIN
16
+ VALUE "CompanyName", "librats Project"
17
+ VALUE "FileDescription", "librats P2P Networking Library - Legitimate networking software"
18
+ VALUE "FileVersion", "@VERSION_STRING@"
19
+ VALUE "ProductName", "librats P2P Networking Library"
20
+ VALUE "ProductVersion", "@VERSION_STRING@"
21
+ VALUE "LegalCopyright", "Copyright (c) librats contributors - MIT License"
22
+ VALUE "OriginalFilename", "rats-client.exe"
23
+ VALUE "InternalName", "librats"
24
+ VALUE "Comments", "Open source peer-to-peer networking library implementing BitTorrent DHT, ICE/STUN NAT traversal, and secure encryption protocols (@GIT_DESCRIBE@)"
25
+ END
26
+ END
27
+ BLOCK "VarFileInfo"
28
+ BEGIN
29
+ VALUE "Translation", 0x409, 1200
30
+ END
31
+ END
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "librats",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Node.js bindings for librats - A high-performance peer-to-peer networking library",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -56,13 +56,7 @@
56
56
  "scripts/**/*",
57
57
  "binding.gyp",
58
58
  "README.md",
59
- "../src/**/*.cpp",
60
- "../src/**/*.h",
61
- "../src/**/*.in",
62
- "../3rdparty/**/*",
63
- "../CMakeLists.txt",
64
- "../LICENSE",
65
- "!../src/main.cpp"
59
+ "native-src/**/*"
66
60
  ],
67
61
  "gypfile": true
68
62
  }
@@ -12,14 +12,47 @@ const isLinux = process.platform === 'linux';
12
12
 
13
13
  // Paths
14
14
  const nodejsRoot = path.resolve(__dirname, '..');
15
- const projectRoot = path.resolve(__dirname, '..', '..');
16
- const buildDir = path.resolve(nodejsRoot, 'build-native'); // Build dir inside nodejs/
17
- const srcDir = path.resolve(projectRoot, 'src');
18
- const cmakeLists = path.resolve(projectRoot, 'CMakeLists.txt');
15
+ const buildDir = path.resolve(nodejsRoot, 'build-native');
16
+
17
+ // Determine source location:
18
+ // 1. When installed from npm: sources are in nodejs/native-src/
19
+ // 2. When developing locally: sources are in project root (../../ from scripts)
20
+ let projectRoot;
21
+ let srcDir;
22
+ let cmakeLists;
23
+
24
+ const nativeSrcDir = path.resolve(nodejsRoot, 'native-src');
25
+ const devProjectRoot = path.resolve(__dirname, '..', '..');
26
+
27
+ if (fs.existsSync(path.join(nativeSrcDir, 'CMakeLists.txt'))) {
28
+ // npm install scenario: use native-src directory
29
+ projectRoot = nativeSrcDir;
30
+ srcDir = path.resolve(nativeSrcDir, 'src');
31
+ cmakeLists = path.resolve(nativeSrcDir, 'CMakeLists.txt');
32
+ console.log('Using bundled source files from native-src/');
33
+ } else if (fs.existsSync(path.join(devProjectRoot, 'CMakeLists.txt'))) {
34
+ // Development scenario: use parent directory
35
+ projectRoot = devProjectRoot;
36
+ srcDir = path.resolve(devProjectRoot, 'src');
37
+ cmakeLists = path.resolve(devProjectRoot, 'CMakeLists.txt');
38
+ console.log('Using source files from project root (development mode)');
39
+ } else {
40
+ console.error('ERROR: Cannot find librats source files.');
41
+ console.error('');
42
+ console.error('Checked locations:');
43
+ console.error(` - ${nativeSrcDir} (npm install)`);
44
+ console.error(` - ${devProjectRoot} (development)`);
45
+ console.error('');
46
+ console.error('If you installed from npm, the package may be corrupted.');
47
+ console.error('Try: npm cache clean --force && npm install librats');
48
+ console.error('');
49
+ console.error('If you are developing locally, make sure you are in the librats repository.');
50
+ process.exit(1);
51
+ }
19
52
 
20
53
  console.log('Building librats native library...');
21
54
  console.log(`Platform: ${process.platform}`);
22
- console.log(`Project root: ${projectRoot}`);
55
+ console.log(`Source root: ${projectRoot}`);
23
56
  console.log(`Build directory: ${buildDir}`);
24
57
 
25
58
  // Check if CMake is installed
@@ -46,17 +79,17 @@ try {
46
79
  process.exit(1);
47
80
  }
48
81
 
49
- // Check if CMakeLists.txt exists
82
+ // Verify CMakeLists.txt exists
50
83
  if (!fs.existsSync(cmakeLists)) {
51
- console.error('ERROR: CMakeLists.txt not found in project root.');
52
- console.error('Make sure all source files are included in the npm package.');
84
+ console.error('ERROR: CMakeLists.txt not found.');
85
+ console.error(`Expected at: ${cmakeLists}`);
53
86
  process.exit(1);
54
87
  }
55
88
 
56
- // Check if src directory exists
89
+ // Verify src directory exists
57
90
  if (!fs.existsSync(srcDir)) {
58
91
  console.error('ERROR: src directory not found.');
59
- console.error('Make sure all source files are included in the npm package.');
92
+ console.error(`Expected at: ${srcDir}`);
60
93
  process.exit(1);
61
94
  }
62
95
 
@@ -64,6 +97,19 @@ if (!fs.existsSync(srcDir)) {
64
97
  if (!fs.existsSync(buildDir)) {
65
98
  console.log(`Creating build directory: ${buildDir}`);
66
99
  fs.mkdirSync(buildDir, { recursive: true });
100
+ } else {
101
+ // Clear CMake cache if it exists to avoid source directory mismatch errors
102
+ const cmakeCache = path.join(buildDir, 'CMakeCache.txt');
103
+ if (fs.existsSync(cmakeCache)) {
104
+ console.log('Clearing existing CMake cache...');
105
+ fs.unlinkSync(cmakeCache);
106
+
107
+ // Also remove CMakeFiles directory for a clean reconfigure
108
+ const cmakeFiles = path.join(buildDir, 'CMakeFiles');
109
+ if (fs.existsSync(cmakeFiles)) {
110
+ fs.rmSync(cmakeFiles, { recursive: true, force: true });
111
+ }
112
+ }
67
113
  }
68
114
 
69
115
  // Helper function to execute commands
@@ -121,7 +167,9 @@ try {
121
167
  cmakeArgs.push('-G "Unix Makefiles"');
122
168
  }
123
169
 
124
- const cmakeConfigCmd = `cmake ${cmakeArgs.join(' ')} ../..`;
170
+ // Calculate the relative path from build directory to source root
171
+ const relativePath = path.relative(buildDir, projectRoot);
172
+ const cmakeConfigCmd = `cmake ${cmakeArgs.join(' ')} "${relativePath}"`;
125
173
  exec(cmakeConfigCmd);
126
174
 
127
175
  // Build the library
@@ -191,4 +239,3 @@ try {
191
239
 
192
240
  process.exit(1);
193
241
  }
194
-