troubles with find_package and CMAKE_PREFIX_PATH

Hello,

i have the problem that i’ve build cpython on my own in /home/stuv/build/cpython and i set CMAKE_PREFIX_PATH to this path but when i try

find_package(
Python3
REQUIRED VERSION 3.13
COMPONENTS Development
)

he tells me he can only find the version 3.11 which is the system installed one. is there a way i can tell cmake which version i wold prefer or why he doesn’t he find my version from the build dir ?

Maybe you have to install your build (make install) to have a correct layout to be searchable…

i’ve done so now with --prefix and put the builded version into /home/user/build/python3.13 and my code looks like:
cmake_minimum_required(VERSION 3.5)
project(TestPython)

set(EXTERNAL_BUILD_PATH /home/user/build/python3.13)
list(APPEND CMAKE_PREFIX_PATH ${EXTERNAL_BUILD_PATH})
find_package(
Python
version 3.13
REQUIRED
PATHS ${EXTERNAL_BUILD_PATH}
)

if(Python_FOUND)
message(“python was found”)
elseif()
message(“python was not found”)
endif()

and it gives me the error message find_package called with invalid argument “version” …

As the error message said, version is not a valid argument to find_package() command. The version can be specified but without keyword:

find_package(Python 
3.13
REQUIRED
PATHS ${EXTERNAL_BUILD_PATH}
)

i now get the output:
CMake Error at /usr/local/share/cmake-3.28/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find Python3 (missing: PATH /home/stuv/build/python3.13) (found
suitable version “3.13.0”, minimum required is “3.13.0”)
Call Stack (most recent call first):
/usr/local/share/cmake-3.28/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
/usr/local/share/cmake-3.28/Modules/FindPython/Support.cmake:3867 (find_package_handle_standard_args)
/usr/local/share/cmake-3.28/Modules/FindPython3.cmake:545 (include)
CMakeLists.txt:56 (find_package)

so it looks like he can find the version but has some othe trouble, i set Python_DIR to /home/user/build/python3.13

Configuring with the --debug-find may help figure out why that PATH bit is considered missing.

Thank you for the parameter but the directory is not listed but i pass it to MCMAKE_PREFIX_PATH:

function(bs_set_cmake_prefix_path)
    set(CMAKE_PREFIX_QT6 "/home/stuv/Qt/6.6.1/gcc_64/lib/cmake/Qt6")
    set(CMAKE_PREFIX_PYTHON3 "/home/stuv/projects/build/python3.13")
    set(QT6_RPATH "/home/stuv/Qt/6.6.1/gcc_64/lib")

    list(APPEND CMAKE_PREFIX_PATH ${CMAKE_PREFIX_QT6} ${CMAKE_PREFIX_PYTHON3})
endfunction()

CMake functions establish a variable scope. When you modify CMAKE_PREFIX_PATH inside a function, the modification will not propagate outside the function. See Introduction to list() command for details and possible solutions.

list(APPEND PARENT_SCOPE CMAKE_PREFIX_PATH ${CMAKE_PREFIX_QT6} ${CMAKE_PREFIX_PYTHON3}) does not work

And nothing in the docs suggests that it should. Quoting the docs I linked:

To propagate the results of these operations upwards, use set() with PARENT_SCOPE, set() with CACHE INTERNAL, or some other means of value propagation.

Have you tried one of these?

when i copy the text from the .cmake file to the main CMakeLists.txt file it doe work!!

gut when i remove it from the CMakeLists.txt and use:

function(bs_set_cmake_prefix_path)
    set(CMAKE_PREFIX_QT6 "/home/stuv/Qt/6.6.1/gcc_64/lib/cmake/Qt6" PARENT_SCOPE)
    set(CMAKE_PREFIX_PYTHON3 "/home/stuv/projects/build/python3.13" PARENT_SCOPE)
    set(QT6_RPATH "/home/stuv/Qt/6.6.1/gcc_64/lib" PARENT_SCOPE)

    list(APPEND CMAKE_PREFIX_PATH ${CMAKE_PREFIX_QT6} ${CMAKE_PREFIX_PYTHON3} PARENT_SCOPE)
endfunction()

The directory is not listet with --find-debug

list() doesn’t support PARENT_SCOPE. Please try reading through the linked docs a bit.

ups, thank you

i now tried it with block() but this also doesn’t work like expected:

function(bs_set_cmake_prefix_path)
  block(PROPAGATE CMAKE_PREFIX_PATH CMAKE_PREFIX_QT6 CMAKE_PREFIX_PYTHON3 QT6_RPATH)
    set(CMAKE_PREFIX_PYTHON3 "/home/stuv/projects/build/python3.13")
    set(CMAKE_PREFIX_QT6 "/home/stuv/Qt/6.6.1/gcc_64/lib/cmake/Qt6")
    set(QT6_RPATH "/home/stuv/Qt/6.6.1/gcc_64/lib")
    set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_QT6} ${CMAKE_PREFIX_PYTHON3})
  endblock()

endfunction()

Indeed. block() introduces its own scope, as does the function. So your code propagates the variables out of the block into the enclosing scope, which is the function. You need to do the modifications such that they propagate outside of the function.

i’ve tried now the block() command like:

I changed the list() to set() and used block() like:

It’s strange, i’ve a function where i set my variables with PARENT_SCOPE like this:

function(bs_set_cmake_prefix_path)
  set(CMAKE_PREFIX_PYTHON3 "/home/stuv/projects/build/python3.13" PARENT_SCOPE)
  set(CMAKE_PREFIX_QT6 "/home/stuv/Qt/6.6.1/gcc_64/lib/cmake/Qt6" PARENT_SCOPE)
  set(QT6_RPATH "/home/stuv/Qt/6.6.1/gcc_64/lib" PARENT_SCOPE)
  set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_QT6} ${CMAKE_PREFIX_PYTHON3} PARENT_SCOPE)
endfunction()

When i put a message() after the function all variables are in the parent scope, only CMAKE_PREFIX_PATH is empty!

PARENT_SCOPE is weird[1]. For a function like that, I would recommend removing PARENT_SCOPE and just using a macro instead.

[1] The detail that you’re missing (and it’s a silly behavior, but it’s what we have) is that the local variable of the same name is pulled from the parent scope. So you set your variable there, but here the value is still “undefined”, so when you try to set up CMAKE_PREFIX_PATH, the element variables you’re using are empty.