# FindLibUSB.cmake

This CMake module provides robust, cross-platform detection and integration of the [libusb](https://libusb.info/) library for your CMake-based project. It can source libusb from a variety of locations, including XMOS XTC Tools, system installations, user-specified library paths, and even building or downloading libusb from source when necessary.

---

## Features

- **Automatic detection of libusb** in XMOS XTC Tools environments (via `XMOS_TOOL_PATH`).
- **System package detection** (via `pkg-config`) on Linux.
- **User-specified library path** fallback (`LIBUSB_LIBRARY_PATH`).
- **Automatic build from source** if a source path is provided (`LIBUSB_SOURCE_PATH`) on Linux and Windows.
- **Automatic download and build** from GitHub if all else fails (`LIBUSB_DOWNLOAD_VERSION`) on Linux and Windows.
- **Windows DLL-to-LIB conversion** for MSVC environments.
- **MacOS support** for XMOS tools and user-specified dylib.
- **Custom CMake target** (`find_libusb_target`) to ensure build dependencies are respected.
- **Clear error messages** for all failure modes.

---

## User-Specifiable Options

All options are settable via `-D` on the CMake command line or in your `CMakeLists.txt` before calling `find_libusb()`:

- **`LIBUSB_LIBRARY_PATH`**  
  Path to a prebuilt, dynamically-linkable libusb library file (e.g., `.so`, `.dll`, `.dylib`).  
  Used if XMOS tools and system detection fail.

- **`LIBUSB_SOURCE_PATH`**  
  Path to the libusb source directory.  
  If set (and previous methods fail), libusb will be built from source at configure/build time (Linux/Windows only).

- **`LIBUSB_DOWNLOAD_VERSION`**  
  Version string (e.g., `1.0.27`).  
  If set (and previous methods fail), libusb will be downloaded from GitHub and built at configure/build time (Linux/Windows only).

---

## Usage

In your `CMakeLists.txt`:

```cmake
list(APPEND CMAKE_MODULE_PATH "<path-to-FindLibUSB.cmake>")
find_libusb(LIBUSB_LIBRARIES LIBUSB_LIBRARY_PATH LIBUSB_TARGET_NAME)
target_link_libraries(your_target PRIVATE ${LIBUSB_LIBRARIES})
add_dependencies(your_target ${LIBUSB_TARGET_NAME})
```

---

## Platform-Specific Behaviour

### Linux

1. **XMOS Tools**: If `XMOS_TOOL_PATH` is set, uses `${XMOS_TOOL_PATH}/lib/libusb-1.0.so`.
2. **pkg-config**: If available, uses system-installed libusb via `pkg-config`.
3. **User Path**: If `LIBUSB_LIBRARY_PATH` is set and exists, uses it.
4. **Build from Source**: If `LIBUSB_SOURCE_PATH` is set, runs `autogen.sh` and `make` to build libusb, using the resulting `.so`.
5. **Download and Build**: If `LIBUSB_DOWNLOAD_VERSION` is set, downloads the specified version from GitHub, builds it, and uses the resulting `.so`.
6. **Failure**: If none of the above succeed, configuration fails with an error.

### Windows

1. **XMOS Tools**: If `XMOS_TOOL_PATH` is set, uses `${XMOS_TOOL_PATH}/lib/libusb-1.0.dll`, converts to `.lib` using `dll_to_lib`.
2. **User Path**: If `LIBUSB_LIBRARY_PATH` is set and is a `.dll`, converts to `.lib` using `dll_to_lib`.
3. **Build from Source**: If `LIBUSB_SOURCE_PATH` is set, builds using MSVC (`msbuild`), then converts the resulting `.dll` to `.lib`.
4. **Download and Build**: If `LIBUSB_DOWNLOAD_VERSION` is set, downloads the specified version from GitHub, builds using MSVC, then converts the resulting `.dll` to `.lib`.
5. **Failure**: If none of the above succeed, configuration fails with an error.

### MacOS

1. **XMOS Tools**: If `XMOS_TOOL_PATH` is set, uses `${XMOS_TOOL_PATH}/lib/libusb-1.0.dylib`.
2. **User Path**: If `LIBUSB_LIBRARY_PATH` is set and exists, uses it.
3. **Failure**: If neither is found, configuration fails with an error.

**Note:**  
- On MacOS, there is **no pkg-config check** and **no source build or download**. You must provide a prebuilt dylib or use XMOS tools.

---

## Output Variables

- **`LIBUSB_LIBRARIES`**: Path(s) to the library file(s) to link against.
- **`LIBUSB_LIBRARY_PATH`**: Path to the resolved library file.
- **`LIBUSB_TARGET_NAME`**: Name of the CMake target that ensures libusb is available/built.

---

## Example

```cmake
# In your CMakeLists.txt
find_libusb(LIBUSB_LIBRARIES LIBUSB_LIBRARY_PATH LIBUSB_TARGET_NAME)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE ${LIBUSB_LIBRARIES})
add_dependencies(my_app ${LIBUSB_TARGET_NAME})
```

---

## Notes

- **Python and Build Tools:**  
  Building from source (Linux/Windows) requires standard build tools (`autogen.sh`, `make` for Linux; MSVC for Windows).
- **Permissions:**  
  Downloading and building at configure time may require network access and write permissions in the build directory.
- **DLL-to-LIB Conversion (Windows):**  
  Requires `DUMPBIN`, `PowerShell`, and `LIB` tools available in your environment.
- **MacOS Limitations:**  
  No automatic build or download. You must provide a prebuilt dylib or use XMOS tools.
- **Multiple CMake Runs:**  
  If you change the method (e.g., set a new `LIBUSB_LIBRARY_PATH`), you may need to clean your build directory.
- **Library Compatibility:**  
  Ensure the libusb binary you provide matches your target architecture and compiler (especially on Windows).
- **Environment Variables:**  
  If using XMOS tools, ensure `XMOS_TOOL_PATH` is set in your environment before running CMake.

---

## Troubleshooting

- **"libusb-1.0 library not found..."**  
  Check that the relevant path or version is set and accessible.
- **Build errors when building from source:**  
  Ensure all build dependencies for libusb are installed (e.g., `autoconf`, `automake`, `libtool`, `make` on Linux).
- **DLL-to-LIB conversion fails:**  
  Ensure you are running in a Visual Studio Developer Command Prompt.

---

## License

This CMake module is provided as-is, under the same license as your project or as appropriate for your use.

---

## Authors

- Angel Cascarino, XMOS
