raspberrypi / pico-sdk

BSD 3-Clause "New" or "Revised" License
3.76k stars 938 forks source link

picotool built by SDK has no USB capability #1827

Closed ali1234 closed 1 week ago

ali1234 commented 3 months ago

To reproduce put the following files in a directory next to the pico-sdk:

CMakeLists.txt: (Note the custom target which runs picotool.)

cmake_minimum_required(VERSION 3.16)

include(../pico-sdk/pico_sdk_init.cmake)

project(testola)

pico_sdk_init()

add_executable(testola main.cpp)

# Link with the pico stdlib
target_link_libraries(testola pico_stdlib)

# Create map/bin/hex/uf2 files
pico_add_extra_outputs(testola)

add_custom_target (flash picotool load -f ${PROJECT_NAME}.uf2 && picotool reboot DEPENDS ${PROJECT_NAME})

main.cpp:

int main() {;}

Run: mkdir build && cd build && cmake .. && make && make flash

Expected result: The built uf2 is loaded to the connected pico over USB.

Actual result:

ERROR: Unknown command: load

COMMANDS:
    info        Display information from the target device(s) or file.
                Without any arguments, this will display basic information for all connected RP2040 devices in BOOTSEL mode
    config      Display or change program configuration settings from the target device(s) or file.
    encrypt     Encrypt the program.
    seal        Add final metadata to a binary, optionally including a hash and/or signature.
    link        Link multiple binaries into one block loop.
    otp         Commands related to the RP2350 OTP (One-Time-Programmable) Memory
    partition   Commands related to RP2350 Partition Tables
    uf2         Commands related to UF2 creation and status
    version     Display picotool version
    coprodis    Post-process coprocessor instructions in disassembly files.
    help        Show general help or help for a specific command

Use "picotool help <cmd>" for more info

This happens because the picotool build could not find libusb, even though I have libusb-1.0-0-dev and pkg-config installed (on Linux):

[11/108] Performing configure step for 'picotoolBuild'
Not searching for unused variables given on the command line.
-- The C compiler identification is GNU 13.2.0
-- The CXX compiler identification is GNU 13.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
.//home/al/Source/Pico/testola/cmake-build-debug/_deps/picotool/
-- Using the single-header code from /home/al/Source/Pico/testola/cmake-build-debug/_deps/picotool-src/lib/nlohmann_json/single_include/
CMake Deprecation Warning at /home/al/Source/Pico/pico-sdk/lib/mbedtls/CMakeLists.txt:23 (cmake_minimum_required):
  Compatibility with CMake < 3.5 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.

-- Found Python3: /usr/bin/python3.12 (found version "3.12.3") found components: Interpreter
-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS
-- Performing Test C_COMPILER_SUPPORTS_WFORMAT_SIGNEDNESS - Success
libUSB is not found - no USB support will be built
-- Configuring done (1.6s)
-- Generating done (0.1s)
-- Build files have been written to: /home/al/Source/Pico/testola/cmake-build-debug/_deps/picotool-build
ali1234 commented 3 months ago

Building picotool manually myself produces a working binary with USB support.

ali1234 commented 3 months ago

Installing my manually built version does not work as a workaround because pico-sdk does not recognize that it is installed, and builds its own copy anyway:

CMake Warning at /home/al/Source/Pico/pico-sdk/tools/Findpicotool.cmake:28 (message):
  No installed picotool with version 2.0.0 found - building from source

  It is recommended to build and install picotool separately, or to set
  PICOTOOL_FETCH_FROM_GIT_PATH to a common directory for all your SDK
  projects

This is then the version that gets used by the custom target.

ali1234 commented 3 months ago

A workaround that does work is to make the custom target use the absolute path to the working picotool:

add_custom_target (flash /home/al/.local/bin/picotool load -f ${PROJECT_NAME}.uf2 && picotool reboot DEPENDS ${PROJECT_NAME})

Of course this won't work on anyone else's computer...

will-v-pi commented 3 months ago

This is by design - when building picotool as part of the SDK we set PICOTOOL_NO_LIBUSB, for speedier compilation. If you want to build a full version of picotool separately and have the SDK use that, see the picotool readme for details of how to make sure the SDK can find your installed picotool.

ali1234 commented 3 months ago

Okay, so those instructions are wrong for Linux. The correct way to do it is to configure picotool with:

cmake -DCMAKE_INSTALL_PREFIX=~/.local ..

And then make install (without root).

Now the SDK will find it without having to pass an additional environment variable to every project.

ali1234 commented 3 months ago

Another workaround (if you don't care which version the SDK uses) is to just use cmake's find_program:

cmake_minimum_required(VERSION 3.16)

find_program(PICOTOOL picotool)

// ... normal project boilerplate here ...

add_custom_target (flash ${PICOTOOL} load -f ${PROJECT_NAME}.uf2 && ${PICOTOOL} reboot DEPENDS ${PROJECT_NAME})

Because find_program is run before the SDK stuff, it will find the version in $PATH, before the SDK shadows it with a broken version.

will-v-pi commented 3 months ago

Okay, so those instructions are wrong for Linux

Can you clarify exactly which bit of the instructions you’re referring to?

For me in Debian, Ubuntu, and macOS, the instructions of

mkdir build
cd build
cmake ..
make
sudo make install

work fine. If you want a non-root install then installing to ~/.local will also work fine, it’s just user preference.

ali1234 commented 3 months ago

The part where this is the only alternative to doing a root install:

Alternatively you can install in a custom path via:

cmake -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR -DPICOTOOL_FLAT_INSTALL=1 ..

In order for the SDK to find picotool in this custom path, you will need to set the picotool_DIR variable in your project, either by passing to -Dpicotool_DIR=$MY_INSTALL_DIR/picotool to your SDK cmake command, or by adding

set(picotool_DIR $MY_INSTALL_DIR/picotool)

to your CMakeLists.txt file.

will-v-pi commented 3 months ago

The part where this is the only alternative to doing a root install:

You're adding the word "only" there...

That's not an exhaustive list of alternatives, just one alternative that'll work with any platform and any install directory. I'll add a note about ~/.local being another alternative for some Linux users who don't want to do a root install

sykacek commented 3 weeks ago

I had exactly same issue, for me, it was caused by holding broken packages (libusb), so installing proper version of them solved the problem.

will-v-pi commented 1 week ago

Closing as by design, and the message printed when compiling has been fixed in develop