# MTPKit Native Build System

This directory contains scripts to build the native dependencies for MTPKit:

- **libusb** (v1.0.27) - USB library for device communication
- **libkalam** - Go-based MTP bridge (built from go-mtpfs + custom kalam_bridge.go)

The build system produces universal (arm64 + x86_64) dynamic libraries that are committed to `MTPKit/Native/`.

## Prerequisites

Install the following tools via Homebrew (development only - not required at runtime):

```bash
brew install go autoconf automake libtool
```

## Build Commands

All commands should be run from this directory (`MTPKit/NativeBuild/`).

| Command | Description |
|---------|-------------|
| `make all` | Build all dependencies (libusb first, then libkalam) |
| `make libusb` | Build only libusb |
| `make libkalam` | Build only libkalam (requires libusb to be built first) |
| `make clean` | Remove build artifacts (keeps downloaded sources) |
| `make distclean` | Remove everything including downloads |

### Full Rebuild

```bash
make distclean
make all
```

### Incremental Build

The scripts skip already-built components. To force a rebuild of a specific library:

```bash
rm -rf build/arm64 build/x86_64  # Remove architecture builds
make all                          # Rebuild
```

## Output

Built libraries are placed in `MTPKit/Native/`:

```
MTPKit/Native/
├── libusb-1.0.0.dylib   # Universal libusb binary
├── libkalam.dylib       # Universal libkalam binary
└── libkalam.h           # C header for libkalam exports
```

## Updating Library Versions

### Updating libusb

1. Edit `scripts/build_libusb.sh`
2. Change `LIBUSB_VERSION="1.0.27"` to the new version
3. Run `make distclean && make all`
4. Verify with `lipo -info ../Native/libusb-1.0.0.dylib`
5. Commit the updated dylib

### Updating go-mtpfs / libkalam

1. Edit `scripts/build_libkalam.sh`
2. Change `LIBKALAM_TAG="master"` to a specific commit hash or tag
3. Run `make clean && make libkalam`
4. Verify with `otool -L ../Native/libkalam.dylib`
5. Commit the updated dylib and header

## Verification

After building, verify the libraries are correct:

```bash
# Check architectures (should show arm64 and x86_64)
lipo -info ../Native/libusb-1.0.0.dylib
lipo -info ../Native/libkalam.dylib

# Check linkage (should show @rpath, not absolute paths)
otool -L ../Native/libkalam.dylib
```

Expected `otool -L` output for libkalam:
```
../Native/libkalam.dylib:
    @rpath/libkalam.dylib (...)
    @rpath/libusb-1.0.0.dylib (...)
    /usr/lib/libSystem.B.dylib (...)
    ...
```

## Build Artifacts

The build process creates temporary directories that are **gitignored**:

| Directory | Contents |
|-----------|----------|
| `downloads/` | Downloaded tarballs (cached) |
| `source/` | Extracted/cloned source code |
| `build/` | Per-architecture build outputs |

These directories are **not committed** and should be cleaned before Xcode builds to avoid conflicts with Xcode's filesystem synchronization.

## Technical Notes

### Environment Variable Patch

The build script applies a patch to `kalam_bridge.go` at build time. This fixes an issue where Go's `os.Getenv()` doesn't see environment variables set by Swift's `setenv()` after the library is loaded. The patch uses C's `getenv()` via CGO instead.

### @rpath Linkage

The build scripts use `install_name_tool` to ensure all library references use `@rpath/` instead of absolute paths. This allows the app to find the libraries at runtime regardless of the build machine's directory structure.

### Minimum macOS Version

Libraries are built with `-mmacosx-version-min=14.0` to match the app's deployment target.

## Troubleshooting

### "Library not loaded" at runtime

Check that `otool -L` shows `@rpath/` for all dependencies. If you see absolute paths like `/Users/.../NativeBuild/build/...`, run:

```bash
make clean && make all
```

### Build fails with "go: command not found"

Install Go: `brew install go`

### Build fails with missing autotools

Install build tools: `brew install autoconf automake libtool`

### Xcode shows "no rule to process file" warning

This warning is suppressed by a custom build rule in the MTPKit target. If it appears, the project file may need to be regenerated or opened in Xcode GUI.
