Skip to content

Commit 4b02caf

Browse files
Copilotjimkring
andcommitted
Add comprehensive GitHub Copilot instructions with validated commands
Co-authored-by: jimkring <[email protected]>
1 parent 0400ae0 commit 4b02caf

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed

.github/copilot-instructions.md

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# reqwest-rs-labview
2+
3+
A Rust FFI library that wraps the reqwest HTTP client for use in LabVIEW applications. It builds shared libraries (.dll, .so, .framework) that LabVIEW can call via the Call Library Function Node.
4+
5+
**Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.**
6+
7+
## Working Effectively
8+
9+
### Bootstrap and Dependencies
10+
- **Install system dependencies on Linux**:
11+
```bash
12+
sudo apt-get update -y
13+
sudo apt-get install -y pkg-config libssl-dev
14+
```
15+
- **Install Rust toolchain** (if not present):
16+
```bash
17+
curl --proto '=https' --tlsv1.2 -sSf https://rustup.rs/sh.sh | sh
18+
source ~/.cargo/env
19+
```
20+
- **Install build tools**:
21+
```bash
22+
cargo install just # Task runner for build scripts
23+
pip3 install ziglang # Required for cross-compilation
24+
cargo install cargo-zigbuild # Cross-compilation tool
25+
```
26+
27+
### Build Commands
28+
- **Build for local platform** (release mode):
29+
```bash
30+
cargo build --release
31+
# Output: target/release/libreqwest_dll.so (Linux)
32+
# Takes 2-3 minutes. NEVER CANCEL. Set timeout to 5+ minutes.
33+
```
34+
- **Debug build** (faster compilation, larger binary):
35+
```bash
36+
cargo build
37+
# Output: target/debug/libreqwest_dll.so (Linux)
38+
# Takes ~20 seconds. Use for development/testing.
39+
```
40+
- **Cross-compile for Linux x86_64**:
41+
```bash
42+
rustup target add x86_64-unknown-linux-gnu
43+
cargo zigbuild --target=x86_64-unknown-linux-gnu --release
44+
# Takes ~45 seconds. Set timeout to 2+ minutes.
45+
```
46+
- **Build for Windows** (requires Windows or cross-compilation setup):
47+
```bash
48+
rustup target add i686-pc-windows-msvc x86_64-pc-windows-msvc
49+
cargo build --target=i686-pc-windows-msvc --release # 32-bit
50+
cargo build --target=x86_64-pc-windows-msvc --release # 64-bit
51+
```
52+
53+
### Just Task Runner
54+
The repository includes a `justfile` with build automation:
55+
```bash
56+
just --list # Show available recipes
57+
```
58+
**NOTE**: The justfile is designed for PowerShell on Windows. On Linux, use the direct cargo commands shown above instead.
59+
60+
### Testing
61+
- **Run the test suite**:
62+
```bash
63+
cargo test
64+
# Takes 1-2 minutes. NEVER CANCEL. Set timeout to 5+ minutes.
65+
# NOTE: Integration tests may fail in network-restricted environments due to httpbin.org dependencies
66+
```
67+
- **Run tests without network-dependent integration tests**:
68+
```bash
69+
cargo test --lib
70+
```
71+
72+
### Code Quality and Linting
73+
- **Format code** (ALWAYS run before committing):
74+
```bash
75+
cargo fmt
76+
```
77+
- **Check formatting**:
78+
```bash
79+
cargo fmt --check
80+
```
81+
- **Run linter** (expect FFI-related warnings - these are normal):
82+
```bash
83+
cargo clippy --all-targets --all-features
84+
# NOTE: Clippy will show warnings about unsafe pointer operations in FFI code - these are expected and normal
85+
```
86+
87+
## Validation Scenarios
88+
89+
After making changes to the Rust code, ALWAYS:
90+
91+
1. **Build successfully**: `cargo build --release` must complete without errors
92+
2. **Format code**: `cargo fmt` must run clean
93+
3. **Test core functionality**: Unit tests should pass (`cargo test --lib`)
94+
4. **Cross-compile test**: Verify cross-compilation still works with `cargo zigbuild`
95+
5. **Check library output**: Verify shared library is generated in `target/release/`
96+
6. **Validate FFI exports**: Check that required FFI functions are exported:
97+
```bash
98+
nm -D target/release/libreqwest_dll.so | grep -E "client_|request_|headers_" | head -5
99+
# Should show exported C functions like client_builder_create, etc.
100+
```
101+
102+
### Complete User Scenario Testing
103+
ALWAYS test these complete scenarios after making changes:
104+
105+
1. **Library Creation and Cleanup**:
106+
- Create a client builder with `client_builder_create()`
107+
- Configure it with timeout and other settings
108+
- Build a client with `client_builder_create_client_and_start()`
109+
- Clean up with `client_destroy()` and `client_builder_destroy()`
110+
111+
2. **Request Building and Execution**:
112+
- Create a request builder from a client
113+
- Configure request headers, body, auth, etc.
114+
- Send request asynchronously
115+
- Monitor progress and read response
116+
- Clean up request resources
117+
118+
3. **Header Management**:
119+
- Create header maps with `headers_create()`
120+
- Add multiple headers with `headers_add()`
121+
- Retrieve all headers with `headers_get_all()`
122+
- Clean up with `headers_destroy()`
123+
124+
### Functional Validation Test
125+
Run this simple C program test to validate basic FFI functionality:
126+
```c
127+
// Save as test_ffi.c and compile with: gcc test_ffi.c -ldl -o test_ffi
128+
#include <stdio.h>
129+
#include <dlfcn.h>
130+
131+
int main() {
132+
void *handle = dlopen("./target/release/libreqwest_dll.so", RTLD_LAZY);
133+
if (!handle) return 1;
134+
135+
void* (*create)() = dlsym(handle, "client_builder_create");
136+
void (*destroy)(void*) = dlsym(handle, "client_builder_destroy");
137+
138+
if (!create || !destroy) { dlclose(handle); return 1; }
139+
140+
void* builder = create();
141+
if (builder == NULL) { dlclose(handle); return 1; }
142+
143+
printf("PASS: FFI functions working correctly\n");
144+
destroy(builder);
145+
dlclose(handle);
146+
return 0;
147+
}
148+
```
149+
150+
### Manual Testing with LabVIEW (if available)
151+
- The built shared libraries are consumed by LabVIEW via the Call Library Function Node
152+
- LabVIEW code is in `lv_src/` directory with `.vi`, `.lvproj`, and `.lvlib` files
153+
- Pre-built libraries are included: `lv_reqwest_32.dll`, `lv_reqwest_64.dll`, `lv_reqwest_64.so`, `lv_reqwest_64.framework.zip`
154+
- Test VI: `lv_src/test_client.vi` can be used to validate functionality
155+
- Example VI: `lv_src/Examples/Example - Download with Progress and Abort (RUST).vi` demonstrates library usage
156+
157+
## Repository Structure
158+
159+
### Key Directories
160+
- `src/`: Rust source code for the FFI library
161+
- `ffi/`: C-compatible FFI function implementations
162+
- `lib.rs`: Main library entry point and exports
163+
- `types.rs`: Rust type definitions used in FFI
164+
- `globals.rs`: Global state management for async operations
165+
- `lv_src/`: LabVIEW source code and pre-built libraries
166+
- `tests/`: Integration tests (require network access)
167+
- `docs/`: Developer and user documentation
168+
169+
### Important Files
170+
- `Cargo.toml`: Rust project configuration - builds as both `cdylib` and `rlib`
171+
- `justfile`: Build automation (PowerShell-based, designed for Windows)
172+
- `.github/workflows/rust.yml`: CI/CD pipeline for building multi-platform libraries
173+
- `mac_build.sh` & `bundle_framework.sh`: macOS-specific build scripts
174+
175+
## Common Tasks
176+
177+
### Building Multi-Platform Libraries
178+
The repository supports building for multiple platforms:
179+
- **Windows**: i686 and x86_64 (32-bit and 64-bit .dll files)
180+
- **Linux**: x86_64 (.so file)
181+
- **macOS**: x86_64 and aarch64 (.framework bundle)
182+
183+
### Cross-Platform Build Process
184+
1. **CI Pipeline**: Uses GitHub Actions with matrix builds on ubuntu-latest, windows-latest, macos-latest
185+
2. **Local Development**: Use `cargo zigbuild` for cross-compilation on Linux
186+
3. **Output Naming**: Libraries are renamed to `lv_reqwest_[32|64].[dll|so]` format
187+
188+
### Working with FFI Code
189+
- **Memory Management**: Follows strict "creator destroys" pattern - if you create it, you must destroy it
190+
- **String Handling**: Uses C-style strings (CString/CStr) for LabVIEW compatibility
191+
- **Error Handling**: Two-tier system - configuration errors vs transport errors
192+
- **Async Operations**: Built on tokio runtime, hidden from LabVIEW callers
193+
- **Thread Safety**: Global runtime and thread-safe data structures manage concurrent operations
194+
- **Pointer Safety**: FFI functions use unsafe pointer operations - clippy warnings are expected and normal
195+
196+
### Common Development Workflows
197+
198+
#### Adding a new FFI function:
199+
1. Add function signature to appropriate module in `src/ffi/`
200+
2. Add `#[unsafe(no_mangle)]` and `pub extern "C"` decorators
201+
3. Add to exports in `src/lib.rs`
202+
4. Build and test: `cargo build --release && cargo test --lib`
203+
5. Format: `cargo fmt`
204+
6. Validate FFI export: `nm -D target/release/libreqwest_dll.so | grep your_function`
205+
206+
#### Modifying existing functionality:
207+
1. Make minimal changes to Rust code
208+
2. Build: `cargo build --release`
209+
3. Run validation tests (see Validation Scenarios section)
210+
4. Update corresponding LabVIEW VIs if FFI signatures changed
211+
5. Format: `cargo fmt`
212+
213+
## Troubleshooting
214+
215+
### Common Build Issues
216+
- **SSL/TLS errors**: Ensure `pkg-config` and `libssl-dev` are installed on Linux
217+
- **Cross-compilation failures**: Verify `ziglang` and `cargo-zigbuild` are properly installed
218+
- **Test failures**: Integration tests require internet access - use `cargo test --lib` for offline testing
219+
220+
### Development Tips
221+
- **FFI Safety**: Be careful with pointer operations - the existing clippy warnings are expected for FFI code
222+
- **Async Runtime**: The library manages a global tokio runtime - don't create additional runtimes
223+
- **LabVIEW Integration**: Changes to FFI signatures require updates to corresponding LabVIEW VIs
224+
- **Platform Testing**: Test library loading in LabVIEW on target platform when possible
225+
226+
### Build Time Expectations
227+
- **Initial clean build (release)**: 2-3 minutes (downloads and compiles all dependencies)
228+
- **Initial clean build (debug)**: 15-20 seconds (much faster, unoptimized)
229+
- **Incremental builds**: 2-10 seconds for small changes
230+
- **Cross-compilation (initial)**: ~45 seconds after dependencies are built
231+
- **Cross-compilation (incremental)**: ~10 seconds for small changes
232+
- **Test suite**: 1-2 minutes (longer in network-restricted environments)
233+
- **Unit tests only**: ~2 seconds (use `cargo test --lib`)
234+
- **Formatting**: < 1 second (`cargo fmt`)
235+
- **Clippy linting**: 20-30 seconds for full check
236+
237+
**CRITICAL TIMING NOTES:**
238+
- NEVER CANCEL builds or tests that appear to hang - Rust compilation can take several minutes
239+
- Always set timeouts to 5+ minutes for `cargo build --release` (first build)
240+
- Set timeouts to 1+ minutes for `cargo build` (debug builds)
241+
- Set timeouts to 2+ minutes for `cargo zigbuild` (first cross-compile)
242+
- Set timeouts to 5+ minutes for `cargo test` (includes network-dependent integration tests)
243+
- Set timeouts to 1+ minutes for `cargo clippy --all-targets --all-features`

0 commit comments

Comments
 (0)