Skip to content

Commit

Permalink
add installation support for pkg-config dependency detection
Browse files Browse the repository at this point in the history
pkg-config is a buildsystem-agnostic alternative to
`pybind11Config.cmake` that can be used from build systems other than
cmake.

Fixes pybind#230
  • Loading branch information
eli-schwartz authored and henryiii committed Aug 8, 2022
1 parent 29f4940 commit c933d9b
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#
# See https://github.com/pre-commit/pre-commit

# third-party content
exclude: ^tools/JoinPaths.cmake$

repos:
# Standard hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
Expand Down
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ else()
endif()

include("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11Common.cmake")
# https://github.com/jtojnar/cmake-snips/#concatenating-paths-when-building-pkg-config-files
# TODO: cmake 3.20 adds the cmake_path() function, which obsoletes this snippet
include("${CMAKE_CURRENT_SOURCE_DIR}/tools/JoinPaths.cmake")

# Relative directory setting
if(USE_PYTHON_INCLUDE_DIR AND DEFINED Python_INCLUDE_DIRS)
Expand Down Expand Up @@ -262,6 +265,16 @@ if(PYBIND11_INSTALL)
NAMESPACE "pybind11::"
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})

# pkg-config support
if(NOT prefix_for_pc_file)
set(prefix_for_pc_file "${CMAKE_INSTALL_PREFIX}")
endif()
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")

# Uninstall target
if(PYBIND11_MASTER_PROJECT)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake_uninstall.cmake.in"
Expand Down
3 changes: 2 additions & 1 deletion pybind11/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@


from ._version import __version__, version_info
from .commands import get_cmake_dir, get_include
from .commands import get_cmake_dir, get_include, get_pkgconfig_dir

__all__ = (
"version_info",
"__version__",
"get_include",
"get_cmake_dir",
"get_pkgconfig_dir",
)
9 changes: 8 additions & 1 deletion pybind11/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys
import sysconfig

from .commands import get_cmake_dir, get_include
from .commands import get_cmake_dir, get_include, get_pkgconfig_dir


def print_includes() -> None:
Expand Down Expand Up @@ -36,13 +36,20 @@ def main() -> None:
action="store_true",
help="Print the CMake module directory, ideal for setting -Dpybind11_ROOT in CMake.",
)
parser.add_argument(
"--pkgconfigdir",
action="store_true",
help="Print the pkgconfig directory, ideal for setting $PKG_CONFIG_PATH.",
)
args = parser.parse_args()
if not sys.argv[1:]:
parser.print_help()
if args.includes:
print_includes()
if args.cmakedir:
print(get_cmake_dir())
if args.pkgconfigdir:
print(get_pkgconfig_dir())


if __name__ == "__main__":
Expand Down
12 changes: 12 additions & 0 deletions pybind11/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,15 @@ def get_cmake_dir() -> str:

msg = "pybind11 not installed, installation required to access the CMake files"
raise ImportError(msg)


def get_pkgconfig_dir() -> str:
"""
Return the path to the pybind11 pkgconfig directory.
"""
pkgconfig_installed_path = os.path.join(DIR, "share", "pkgconfig")
if os.path.exists(pkgconfig_installed_path):
return pkgconfig_installed_path

msg = "pybind11 not installed, installation required to access the pkgconfig files"
raise ImportError(msg)
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ def remove_output(*sources: str) -> Iterator[None]:
"-DCMAKE_INSTALL_PREFIX=pybind11",
"-DBUILD_TESTING=OFF",
"-DPYBIND11_NOPYTHON=ON",
"-Dprefix_for_pc_file=${pcfiledir}/../../",
]
if "CMAKE_ARGS" in os.environ:
fcommand = [
Expand Down
7 changes: 6 additions & 1 deletion tests/extra_python_package/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
"share/cmake/pybind11/pybind11Tools.cmake",
}

pkgconfig_files = {
"share/pkgconfig/pybind11.pc",
}

py_files = {
"__init__.py",
"__main__.py",
Expand All @@ -69,7 +73,7 @@
}

headers = main_headers | detail_headers | stl_headers
src_files = headers | cmake_files
src_files = headers | cmake_files | pkgconfig_files
all_files = src_files | py_files


Expand All @@ -82,6 +86,7 @@
"pybind11/share",
"pybind11/share/cmake",
"pybind11/share/cmake/pybind11",
"pybind11/share/pkgconfig",
"pyproject.toml",
"setup.cfg",
"setup.py",
Expand Down
23 changes: 23 additions & 0 deletions tools/JoinPaths.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This module provides function for joining paths
# known from most languages
#
# SPDX-License-Identifier: (MIT OR CC0-1.0)
# Copyright 2020 Jan Tojnar
# https://github.com/jtojnar/cmake-snips
#
# Modelled after Python’s os.path.join
# https://docs.python.org/3.7/library/os.path.html#os.path.join
# Windows not supported
function(join_paths joined_path first_path_segment)
set(temp_path "${first_path_segment}")
foreach(current_segment IN LISTS ARGN)
if(NOT ("${current_segment}" STREQUAL ""))
if(IS_ABSOLUTE "${current_segment}")
set(temp_path "${current_segment}")
else()
set(temp_path "${temp_path}/${current_segment}")
endif()
endif()
endforeach()
set(${joined_path} "${temp_path}" PARENT_SCOPE)
endfunction()
7 changes: 7 additions & 0 deletions tools/pybind11.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
prefix=@prefix_for_pc_file@
includedir=@includedir_for_pc_file@

Name: @PROJECT_NAME@
Description: Seamless operability between C++11 and Python
Version: @PROJECT_VERSION@
Cflags: -I${includedir}
2 changes: 2 additions & 0 deletions tools/setup_global.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ main_headers = glob.glob("pybind11/include/pybind11/*.h")
detail_headers = glob.glob("pybind11/include/pybind11/detail/*.h")
stl_headers = glob.glob("pybind11/include/pybind11/stl/*.h")
cmake_files = glob.glob("pybind11/share/cmake/pybind11/*.cmake")
pkgconfig_files = glob.glob("pybind11/share/pkgconfig/*.pc")
headers = main_headers + detail_headers + stl_headers

cmdclass = {"install_headers": InstallHeadersNested}
Expand All @@ -51,6 +52,7 @@ setup(
headers=headers,
data_files=[
(base + "share/cmake/pybind11", cmake_files),
(base + "share/pkgconfig", pkgconfig_files),
(base + "include/pybind11", main_headers),
(base + "include/pybind11/detail", detail_headers),
(base + "include/pybind11/stl", stl_headers),
Expand Down
2 changes: 2 additions & 0 deletions tools/setup_main.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ setup(
"pybind11.include.pybind11.detail",
"pybind11.include.pybind11.stl",
"pybind11.share.cmake.pybind11",
"pybind11.share.pkgconfig",
],
package_data={
"pybind11": ["py.typed"],
"pybind11.include.pybind11": ["*.h"],
"pybind11.include.pybind11.detail": ["*.h"],
"pybind11.include.pybind11.stl": ["*.h"],
"pybind11.share.cmake.pybind11": ["*.cmake"],
"pybind11.share.pkgconfig": ["*.pc"],
},
extras_require={
"global": ["pybind11_global==$version"]
Expand Down

0 comments on commit c933d9b

Please sign in to comment.