Skip to content

[BUG]: CMake, repeated calls to find_package(pybind11 CONFIG REQUIRED) can fail #5686

@petersteneteg

Description

@petersteneteg

Required prerequisites

What version (or hash if on master) of pybind11 are you using?

98bd78f

Problem description

I get this error:

add_library cannot create imported target "pybind11::headers" because
another target with the same name already exists.
Call Stack (most recent call first):
.../pybind11/pybind11Config.cmake:253 (add_library)
CMakeLists.txt:9 (find_package)

This happens if I first call find_package(pybind11) in a subdirectory.
This will do everything as intended and notably it will include
https://github.com/pybind/pybind11/blob/master/tools/pybind11Common.cmake

this will add a some targets like pybind11::python_link_helper

add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global})

This will be added with directory scope since we are using "is_config" mode. This mean that the target will not be visible when we leave the subdirectory

The important thing to note here is that this file will never be included again since we have a
include_guard(GLOBAL)

include_guard(GLOBAL)

This means that if I now at the toplevel run find_package(pybind11) twice the "guard" in

if(TARGET pybind11::python_link_helper)
# This has already been setup elsewhere, such as with a previous call or
# add_subdirectory
return()
endif()

will not work since we will never define the pybind11::python_link_helper targets.

Hence we I'll try to add the pybind11::headersmultiple times.

This is a regression that was introduced here:
28dbce4#diff-b1088d71d1d5f7fe8b6f2c6f8a8b4e3437c4e653344c445d0bf077615c2f8457

My solution is to use: include_guard(DIRECTORY) instead.
But I'm not 100% sure that this will not run into other problems, when not using config mode for example.

I think it might also be a good idea to move the definition of pybind11::headers from pybind11Config.cmake.in to pybind11Common.cmake to ensure that all targets are added one go...

Reproducible example code

CMakeLists.txt:
cmake_minimum_required(VERSION 3.30...4.0)
project(pybind11-find-package LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Python3 COMPONENTS Interpreter Development)
add_subdirectory(a)
find_package(pybind11 CONFIG REQUIRED)
find_package(pybind11 CONFIG REQUIRED)

a/CmakeLists.txt:
cmake_minimum_required(VERSION 3.30...4.0)
find_package(pybind11 CONFIG REQUIRED)

Is this a regression? Put the last known working version here if it is.

28dbce4 introduced the problem

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions