raspberrypi / pico-sdk

BSD 3-Clause "New" or "Revised" License
3.63k stars 902 forks source link

picotool 2.0.0 executable is not found during cmake -G #1818

Open shabaz123 opened 1 month ago

shabaz123 commented 1 month ago

Environment: Windows 11, SDK 2.0.0, trying to build a project for the Pico.

The issue is that when trying to perform a cmake -G "NMake Makefiles" .. or cmake -G "Ninja" .. there is a message that picotool is not found and will be built from source.

If the user already has a v2.0.0 picotool executable, it is not detected by the pico-sdk/tools/Findpicotool.cmake file.

I cannot use the Pico Setup for Windows installer, because that is version 1.5.

I believe I have a solution (also described at raspberrypi forum here). The solution is to place the prebuilt picotool.exe into any desired folder, and then set a Windows System environment variable called PICOTOOL_OVERRIDE_DIR to that folder path which contains picotool.exe.

Then, I added the following into the pico-sdk/tools/Findpicotool.cmake file, at the top (after the cmake_minimum_required(VERSION 3.17) line:

# if PICOTOOL_OVERRIDE_DIR system environment variable is set,
# then use that as the folder for the picotool executable
if (DEFINED ENV{PICOTOOL_OVERRIDE_DIR})
    message("PICOTOOL_OVERRIDE_DIR env var is set to '$ENV{PICOTOOL_OVERRIDE_DIR}'")
    add_executable(picotool IMPORTED GLOBAL)
    set_property(TARGET picotool PROPERTY IMPORTED_LOCATION $ENV{PICOTOOL_OVERRIDE_DIR}/picotool)
    # check the picotool version:
    execute_process(COMMAND $ENV{PICOTOOL_OVERRIDE_DIR}/picotool version
                    OUTPUT_VARIABLE PICOTOOL_VERSION
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REGEX MATCH "^picotool v${picotool_VERSION_REQUIRED}" PICOTOOL_VERSION_MATCH ${PICOTOOL_VERSION})
    if (NOT PICOTOOL_VERSION_MATCH)
        message("picotool version response was: ${PICOTOOL_VERSION}")
        message(FATAL_ERROR "PICOTOOL_OVERRIDE_DIR is set to '$ENV{PICOTOOL_OVERRIDE_DIR}', but the version of picotool found is not ${picotool_VERSION_REQUIRED}")
    endif()
endif ()

What the above does, is if the PICOTOOL_OVERRIDE_DIR system env var is set, it uses the picotool executable in there, tests if it is the correct version, and if so, then simply uses that.

I have tested by doing a build, and can see that the .uf2 file was successfully created. I have attached the output showing that.

In case it is acceptable, I'll create a PR and reference this issue.

nmake_output.txt cmake_g_nmake_makefile_output.txt

bhass1 commented 1 month ago

I have this issue in Ubuntu 22.04 (Running in WSL2).

I have added picotool version 2.0.0 to my path, but cmake isn't grabbing it.

CMake Warning at /root/source/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
Call Stack (most recent call first):
  /root/source/pico-sdk/tools/CMakeLists.txt:138 (find_package)
  /root/source/pico-sdk/src/cmake/on_device.cmake:33 (pico_init_picotool)
  /root/source/pico-sdk/src/rp2350/boot_stage2/CMakeLists.txt:57 (pico_add_dis_output)
  /root/source/pico-sdk/src/rp2350/boot_stage2/CMakeLists.txt:100 (pico_define_boot_stage2)

How else can I tell cmake where it is?

shabaz123 commented 1 month ago

Hi! Your issue looks very similar to what I experienced on Windows. I think the fix described above may well work on Linux too. If you wish to give it a go (apologies in advance in case it doesn't work : ( in brief, the steps are:

(1) Obtain and build picotool manually, using the steps written at the picotool github page. Create a folder called (say) /home/bhass1/development/pico/tools/picotool and place the picotool binary in that picotool folder.

(2) Add an environment variable in Linux (e.g. in .bashrc) something like: export PICOTOOL_OVERRIDE_DIR="/home/bhass1/development/pico/tools/picotool"

(3) In your pico-sdk/tools folder, locate the file called Findpicotool.cmake and edit it, and insert the following near the top, after the line containing cmake_minimum_required(VERSION 3.17) :

# if PICOTOOL_OVERRIDE_DIR system environment variable is set,
# then use that as the folder for the picotool executable
if (DEFINED ENV{PICOTOOL_OVERRIDE_DIR})
    message("PICOTOOL_OVERRIDE_DIR env var is set to '$ENV{PICOTOOL_OVERRIDE_DIR}'")
    add_executable(picotool IMPORTED GLOBAL)
    set_property(TARGET picotool PROPERTY IMPORTED_LOCATION $ENV{PICOTOOL_OVERRIDE_DIR}/picotool)
    # check the picotool version:
    execute_process(COMMAND $ENV{PICOTOOL_OVERRIDE_DIR}/picotool version
                    OUTPUT_VARIABLE PICOTOOL_VERSION
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REGEX MATCH "^picotool v${picotool_VERSION_REQUIRED}" PICOTOOL_VERSION_MATCH ${PICOTOOL_VERSION})
    if (NOT PICOTOOL_VERSION_MATCH)
        message("picotool version response was: ${PICOTOOL_VERSION}")
        message(FATAL_ERROR "PICOTOOL_OVERRIDE_DIR is set to '$ENV{PICOTOOL_OVERRIDE_DIR}', but the version of picotool found is not ${picotool_VERSION_REQUIRED}")
    endif()
endif ()

Now if you close and re-open your shell prompt (so that the environment variable is read) and then delete your project build directory, and then create the build directory and re-start from your cmake -G ..etc command, hopefully your new environment variable will be detected by that Findpicotool.cmake file and use the built picotool, instead of downloading and building within the project.

If it works or doesn't please report back! I might not know the answer, but can take a look in case I spot anything in your output.

bhass1 commented 1 month ago

Hi @shabaz123, thank you for the detailed help! I decided to try the recommended approach by @will-v-pi in PR #1820, and that worked for me.

Running cmake --install . in my picotool project's build folder (I had only built it before, not "installed" it) put everything in the right places so that Findpicotool.cmake could find it!

Here's my output from cmake --install .

(base) root@Nomad-1:~/source/picotool/build# cmake --install .
-- Install configuration: "Release"
-- Installing: /usr/local/picotool/picotool
-- Installing: /usr/local/picotool/picotoolTargets.cmake
-- Installing: /usr/local/picotool/picotoolTargets-release.cmake
-- Installing: /usr/local/picotool/picotoolConfig.cmake
-- Installing: /usr/local/picotool/picotoolConfigVersion.cmake
-- Installing: /usr/local/picotool/rp2350_otp_contents.json
-- Installing: /usr/local/picotool/xip_ram_perms.elf

I hope this helps you!

shabaz123 commented 1 month ago

Thanks for the response! Awesome, great to hear the recommended method is confirmed functioning.

ryanguilherme commented 1 week ago

Hi @shabaz123, thank you for the detailed help! I decided to try the recommended approach by @will-v-pi in PR #1820, and that worked for me.

Running cmake --install . in my picotool project's build folder (I had only built it before, not "installed" it) put everything in the right places so that Findpicotool.cmake could find it!

Here's my output from cmake --install .

(base) root@Nomad-1:~/source/picotool/build# cmake --install .
-- Install configuration: "Release"
-- Installing: /usr/local/picotool/picotool
-- Installing: /usr/local/picotool/picotoolTargets.cmake
-- Installing: /usr/local/picotool/picotoolTargets-release.cmake
-- Installing: /usr/local/picotool/picotoolConfig.cmake
-- Installing: /usr/local/picotool/picotoolConfigVersion.cmake
-- Installing: /usr/local/picotool/rp2350_otp_contents.json
-- Installing: /usr/local/picotool/xip_ram_perms.elf

I hope this helps you!

This solution solved my problem too, quickly and easily, thanks mate 🤝