From 6bbb70af1a7dc47e737957e1ad469581dcbf99f6 Mon Sep 17 00:00:00 2001 From: Petteri Aimonen Date: Thu, 26 Oct 2023 12:26:15 +0300 Subject: CMake: Installation improvements. - Allow installed nanopb_generator.py wrapper script find the module by relative path. - Install include files under `nanopb` subdirectory. --- .github/workflows/cmake.yml | 6 +- CMakeLists.txt | 83 +++++++++++++++------------- docs/migration.md | 16 ++++++ extra/script_wrappers/nanopb_generator.py | 6 -- extra/script_wrappers/nanopb_generator.py.in | 24 ++++++++ 5 files changed, 88 insertions(+), 47 deletions(-) delete mode 100755 extra/script_wrappers/nanopb_generator.py create mode 100755 extra/script_wrappers/nanopb_generator.py.in diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ac0e641..f8f3838 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -35,7 +35,7 @@ jobs: run: | cd examples/simple nanopb_generator simple.proto - gcc -Wall -Werror -osimple simple.pb.c simple.c -lprotobuf-nanopb + gcc -Wall -Werror -osimple simple.pb.c simple.c -lprotobuf-nanopb -I/usr/local/include/nanopb ./simple build_cmake_windows: @@ -65,7 +65,7 @@ jobs: run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" cd examples/simple - C:\nanopb-test\bin\nanopb_generator simple.proto - cl /out:simple.exe simple.pb.c simple.c C:\nanopb-test\nanopb\lib\protobuf-nanopb.lib + call C:\nanopb-test\bin\nanopb_generator simple.proto + cl simple.pb.c simple.c /IC:\nanopb-test\include\nanopb C:\nanopb-test\lib\protobuf-nanopb.lib /link /out:simple.exe simple.exe diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a2c3d0..473a77c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,52 +44,59 @@ endif() # Determine Python module installation path if (NOT nanopb_PYTHON_INSTDIR_OVERRIDE) find_package(Python REQUIRED COMPONENTS Interpreter) - execute_process( - COMMAND ${Python_EXECUTABLE} -c - "import os.path, sys, sysconfig; print(sysconfig.get_path('purelib'))" - OUTPUT_VARIABLE PYTHON_INSTDIR - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + file(TO_CMAKE_PATH "${Python_SITELIB}" PYTHON_INSTDIR) else() set(PYTHON_INSTDIR ${nanopb_PYTHON_INSTDIR_OVERRIDE}) endif() message(STATUS "Python install dir: ${PYTHON_INSTDIR}") -# Install nanopb generator as Python module 'nanopb' +# Package nanopb generator as Python module 'nanopb' if(nanopb_BUILD_GENERATOR) - set(generator_protos nanopb) - - foreach(generator_proto IN LISTS generator_protos) - string(REGEX REPLACE "([^;]+)" "${PROJECT_SOURCE_DIR}/generator/proto/\\1.proto" generator_proto_file "${generator_proto}") - string(REGEX REPLACE "([^;]+)" "\\1_pb2.py" generator_proto_py_file "${generator_proto}") - add_custom_command( - OUTPUT ${generator_proto_py_file} - COMMAND ${nanopb_PROTOC_PATH} --python_out=${PROJECT_BINARY_DIR} -I${PROJECT_SOURCE_DIR}/generator/proto ${generator_proto_file} - DEPENDS ${generator_proto_file} - ) - add_custom_target("generate_${generator_proto_py_file}" ALL DEPENDS ${generator_proto_py_file}) - install( - FILES ${PROJECT_BINARY_DIR}/${generator_proto_py_file} - ${generator_proto_file} - DESTINATION ${PYTHON_INSTDIR}/nanopb/generator/proto/ - ) - endforeach() + # Copy Python code files related to the generator + add_custom_target(nanopb_generator ALL + COMMAND ${CMAKE_COMMAND} -E make_directory + ${PROJECT_BINARY_DIR}/nanopb/generator/proto + + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${PROJECT_SOURCE_DIR}/generator/proto/_utils.py + ${PROJECT_SOURCE_DIR}/generator/proto/__init__.py + ${PROJECT_SOURCE_DIR}/generator/proto/nanopb.proto + ${PROJECT_BINARY_DIR}/nanopb/generator/proto + + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${PROJECT_SOURCE_DIR}/generator/nanopb_generator.py + ${PROJECT_SOURCE_DIR}/generator/__init__.py + ${PROJECT_BINARY_DIR}/nanopb/generator + + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${PROJECT_SOURCE_DIR}/generator/__init__.py + ${PROJECT_BINARY_DIR}/nanopb + + COMMAND ${nanopb_PROTOC_PATH} + --python_out=${PROJECT_BINARY_DIR}/nanopb/generator/proto + -I${PROJECT_SOURCE_DIR}/generator/proto + ${PROJECT_SOURCE_DIR}/generator/proto/nanopb.proto + ) - install( FILES generator/proto/_utils.py - generator/proto/__init__.py - DESTINATION ${PYTHON_INSTDIR}/nanopb/generator/proto/ ) - install( FILES generator/nanopb_generator.py - generator/__init__.py - DESTINATION ${PYTHON_INSTDIR}/nanopb/generator/ ) - install( FILES generator/__init__.py - DESTINATION ${PYTHON_INSTDIR}/nanopb/ ) + # Install Python module files + install( + DIRECTORY ${PROJECT_BINARY_DIR}/nanopb + DESTINATION ${PYTHON_INSTDIR} + FILES_MATCHING + PATTERN *.py + PATTERN *.proto + PATTERN __pycache__ EXCLUDE + ) - # Install a script that calls nanopb.generator Python module when invoked + # Generate a wrapper script that calls nanopb.generator Python module when invoked + configure_file( + extra/script_wrappers/nanopb_generator.py.in + ${PROJECT_BINARY_DIR}/nanopb_generator.py + ) install( - PROGRAMS - extra/script_wrappers/nanopb_generator.py + PROGRAMS ${PROJECT_BINARY_DIR}/nanopb_generator.py DESTINATION ${CMAKE_INSTALL_BINDIR} ) @@ -139,7 +146,7 @@ if(nanopb_BUILD_RUNTIME) LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) target_include_directories(protobuf-nanopb INTERFACE - $ + $ $ ) endif() @@ -158,7 +165,7 @@ if(nanopb_BUILD_RUNTIME) install(TARGETS protobuf-nanopb-static EXPORT nanopb-targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) target_include_directories(protobuf-nanopb-static INTERFACE - $ + $ $ ) endif() @@ -175,5 +182,5 @@ if(nanopb_BUILD_RUNTIME) DESTINATION ${CMAKE_INSTALL_CMAKEDIR}) install(FILES pb.h pb_common.h pb_encode.h pb_decode.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/nanopb) endif() diff --git a/docs/migration.md b/docs/migration.md index 646f84b..ddcc363 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -6,6 +6,22 @@ required modifications of user applications are explained. Also any error indications are included, in order to make it easier to find this document. +Nanopb-0.4.8 (2023-xx-xx) +------------------------- + +### Fix naming conflicts with CMake installation + +**Rationale:** Previously `CMakeLists.txt` installed nanopb Python module under name `proto` and include file directly as `/usr/include/pb.h`. These names have potential to conflict with other libraries. + +**Changes:** Python module is installed as `nanopb` and include files under `/usr/include/nanopb`. + +**Required actions:** Only affects users who install nanopb using the `cmake` build system. +Does not affect use of `FindNanopb.cmake`. +Calling nanopb generator should work as before. +Include path may need adjustment if not using `nanopb-targets.cmake` to determine it. + +**Error indications:** Include file `pb.h` not found when compiling against a system-wide installation done with CMake. + Nanopb-0.4.7 (2022-xx-xx) ------------------------- diff --git a/extra/script_wrappers/nanopb_generator.py b/extra/script_wrappers/nanopb_generator.py deleted file mode 100755 index 493a91f..0000000 --- a/extra/script_wrappers/nanopb_generator.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 -# This script is a wrapper to invoke nanopb_generator from an installed Python module. -import sys -from nanopb.generator.nanopb_generator import main_cli, main_plugin -if __name__ == '__main__': - sys.exit(main_cli()) diff --git a/extra/script_wrappers/nanopb_generator.py.in b/extra/script_wrappers/nanopb_generator.py.in new file mode 100755 index 0000000..d44a9db --- /dev/null +++ b/extra/script_wrappers/nanopb_generator.py.in @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# This script is a wrapper to invoke nanopb_generator from an installed Python module. +import sys +import os.path + +# CMakeLists.txt can provide this file the path to Python module installation +# location. It is used as a relative path. By default only system path is used. +python_instdir = r"@PYTHON_INSTDIR@" +cmake_bindir = r"@CMAKE_INSTALL_BINDIR@" +cmake_install_prefix = r"@CMAKE_INSTALL_PREFIX@" +if python_instdir[0] != '@': + python_instdir = os.path.join(cmake_install_prefix, python_instdir) + cmake_bindir = os.path.join(cmake_install_prefix, cmake_bindir) + relpath = os.path.relpath(python_instdir, cmake_bindir) + bindir = os.path.dirname(os.path.realpath(__file__)) + libdir = os.path.abspath(os.path.join(bindir, relpath)) + if os.path.isdir(libdir): + sys.path.insert(0, libdir) # Path after make install + else: + sys.path.insert(0, bindir) # Path before make install + +from nanopb.generator.nanopb_generator import main_cli, main_plugin +if __name__ == '__main__': + sys.exit(main_cli()) -- cgit v1.2.3