diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 5f735016..af41020c 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -1,6 +1,4 @@ -# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform. -# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml -name: CMake on multiple platforms +name: CMake on: push: @@ -13,19 +11,11 @@ jobs: runs-on: ${{ matrix.os }} strategy: - # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. - fail-fast: false - - # Set up a matrix to run the following 3 configurations: - # 1. - # 2. - # 3. - # - # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: os: [ubuntu-latest, windows-latest, macos-latest] build_type: [Release] c_compiler: [gcc, clang, cl] + shared_libs: ['ON', 'OFF'] include: - os: windows-latest c_compiler: cl @@ -45,20 +35,18 @@ jobs: - os: macos-latest c_compiler: clang cpp_compiler: clang++ - - os: macos-latest - c_compiler: gcc - cpp_compiler: g++ exclude: - os: ubuntu-latest c_compiler: cl - os: macos-latest c_compiler: cl + - os: macos-latest + c_compiler: gcc steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set reusable strings - # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. id: strings shell: bash run: | @@ -68,23 +56,33 @@ jobs: - uses: ilammy/msvc-dev-cmd@v1 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - run: pip install numpy + - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type run: > cmake -B ${{ steps.strings.outputs.build-output-dir }} -G Ninja - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -D CMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -D CMAKE_C_COMPILER=${{ matrix.c_compiler }} + -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} + -D BUILD_SHARED_LIBS=${{ matrix.shared_libs }} -S ${{ github.workspace }} - name: Build - # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + - name: Install (Windows) + if: matrix.os == 'windows-latest' + run: Start-Process -Verb RunAs -FilePath cmake "--build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} --target install" + + - name: Install (sudo) + if: matrix.os != 'windows-latest' + run: sudo cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} --target install + - name: Test working-directory: ${{ steps.strings.outputs.build-output-dir }} - # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest --build-config ${{ matrix.build_type }} diff --git a/.github/workflows/colcon-workspace.yml b/.github/workflows/colcon-workspace.yml index ca37f4b3..c9f6d56f 100644 --- a/.github/workflows/colcon-workspace.yml +++ b/.github/workflows/colcon-workspace.yml @@ -62,7 +62,7 @@ jobs: strategy: matrix: ros_distribution: [noetic, humble] - cmake_shared_libs: ['OFF'] + cmake_shared_libs: ['ON', 'OFF'] include: - ros_distribution: noetic ros_version: 1 @@ -103,7 +103,7 @@ jobs: strategy: matrix: ros_distribution: [humble] - cmake_shared_libs: ['OFF'] + cmake_shared_libs: ['ON', 'OFF'] steps: - uses: actions/checkout@v4 diff --git a/CMake/vtkEncodeString.cmake b/CMake/vtkEncodeString.cmake new file mode 100644 index 00000000..25a332d2 --- /dev/null +++ b/CMake/vtkEncodeString.cmake @@ -0,0 +1,279 @@ +#[==[ + +Copyright (c) 1993-2015 Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names + of any contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#]==] + +#[==[ +@file vtkEncodeString.cmake + +This module contains the @ref vtk_encode_string function which may be used to +turn a file into a C string. This is primarily used within a program so that +the content does not need to be retrieved from the filesystem at runtime, but +can still be developed as a standalone file. +#]==] + +set(_vtkEncodeString_script_file "${CMAKE_CURRENT_LIST_FILE}") + +#[==[ +@brief Encode a file as a C string at build time + +Adds a rule to turn a file into a C string. Note that any Unicode characters +will not be replaced with escaping, so it is recommended to avoid their usage +in the input. + +~~~ +vtk_encode_string( + INPUT + [NAME ] + [EXPORT_SYMBOL ] + [EXPORT_HEADER
] + [HEADER_OUTPUT ] + [SOURCE_OUTPUT ] + + [ABI_MANGLE_SYMBOL_BEGIN ] + [ABI_MANGLE_SYMBOL_END ] + [ABI_MANGLE_HEADER
] + + [BINARY] [NUL_TERMINATE]) +~~~ + +The only required variable is `INPUT`, however, it is likely that at least one +of `HEADER_OUTPUT` or `SOURCE_OUTPUT` will be required to add them to a +library. + + * `INPUT`: (Required) The path to the file to be embedded. If a relative path + is given, it will be interpreted as being relative to + `CMAKE_CURRENT_SOURCE_DIR`. + * `NAME`: This is the base name of the files that will be generated as well + as the variable name for the C string. It defaults to the basename of the + input without extensions. + * `EXPORT_SYMBOL`: The symbol to use for exporting the variable. By default, + it will not be exported. If set, `EXPORT_HEADER` must also be set. + * `EXPORT_HEADER`: The header to include for providing the given export + symbol. If set, `EXPORT_SYMBOL` should also be set. + * `HEADER_OUTPUT`: The variable to store the generated header path. + * `SOURCE_OUTPUT`: The variable to store the generated source path. + * `BINARY`: If given, the data will be written as an array of `unsigned char` + bytes. + * `NUL_TERMINATE`: If given, the binary data will be `NUL`-terminated. Only + makes sense with the `BINARY` flag. This is intended to be used if + embedding a file as a C string exceeds compiler limits on string literals + in various compilers. + * `ABI_MANGLE_SYMBOL_BEGIN`: Open a mangling namespace with the given symbol. + If given, `ABI_MANGLE_SYMBOL_END` and `ABI_MANGLE_HEADER` must also be set. + * `ABI_MANGLE_SYMBOL_END`: Close a mangling namespace with the given symbol. + If given, `ABI_MANGLE_SYMBOL_BEGIN` and `ABI_MANGLE_HEADER` must also be set. + * `ABI_MANGLE_HEADER`: The header which provides the ABI mangling symbols. + If given, `ABI_MANGLE_SYMBOL_BEGIN` and `ABI_MANGLE_SYMBOL_END` must also + be set. +#]==] +function (vtk_encode_string) + cmake_parse_arguments(PARSE_ARGV 0 _vtk_encode_string + "BINARY;NUL_TERMINATE" + "INPUT;NAME;EXPORT_SYMBOL;EXPORT_HEADER;HEADER_OUTPUT;SOURCE_OUTPUT;ABI_MANGLE_SYMBOL_BEGIN;ABI_MANGLE_SYMBOL_END;ABI_MANGLE_HEADER" + "") + + if (_vtk_encode_string_UNPARSED_ARGUMENTS) + message(FATAL_ERROR + "Unrecognized arguments to vtk_encode_string: " + "${_vtk_encode_string_UNPARSED_ARGUMENTS}") + endif () + + if (NOT DEFINED _vtk_encode_string_INPUT) + message(FATAL_ERROR + "Missing `INPUT` for vtk_encode_string.") + endif () + + if (NOT DEFINED _vtk_encode_string_NAME) + get_filename_component(_vtk_encode_string_NAME + "${_vtk_encode_string_INPUT}" NAME_WE) + endif () + + if (DEFINED _vtk_encode_string_EXPORT_SYMBOL AND + NOT DEFINED _vtk_encode_string_EXPORT_HEADER) + message(FATAL_ERROR + "Missing `EXPORT_HEADER` when using `EXPORT_SYMBOL`.") + endif () + + if (DEFINED _vtk_encode_string_EXPORT_HEADER AND + NOT DEFINED _vtk_encode_string_EXPORT_SYMBOL) + message(WARNING + "Missing `EXPORT_SYMBOL` when using `EXPORT_HEADER`.") + endif () + + if (DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN AND + (NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_END OR + NOT DEFINED _vtk_encode_string_ABI_MANGLE_HEADER)) + message(WARNING + "Missing `ABI_MANGLE_SYMBOL_END` or `ABI_MANGLE_HEADER` when using " + "`ABI_MANGLE_SYMBOL_BEGIN`.") + endif () + + if (DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_END AND + (NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN OR + NOT DEFINED _vtk_encode_string_ABI_MANGLE_HEADER)) + message(WARNING + "Missing `ABI_MANGLE_SYMBOL_BEGIN` or `ABI_MANGLE_HEADER` when using " + "`ABI_MANGLE_SYMBOL_END`.") + endif () + + if (DEFINED _vtk_encode_string_ABI_MANGLE_HEADER AND + (NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN OR + NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_END)) + message(WARNING + "Missing `ABI_MANGLE_SYMBOL_BEGIN` or `ABI_MANGLE_SYMBOL_END` when " + "using `ABI_MANGLE_HEADER`.") + endif () + + if (NOT _vtk_encode_string_BINARY AND _vtk_encode_string_NUL_TERMINATE) + message(FATAL_ERROR + "The `NUL_TERMINATE` flag only makes sense with the `BINARY` flag.") + endif () + + set(_vtk_encode_string_header + "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.h") + set(_vtk_encode_string_source + "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.cxx") + + if (IS_ABSOLUTE "${_vtk_encode_string_INPUT}") + set(_vtk_encode_string_input + "${_vtk_encode_string_INPUT}") + else () + set(_vtk_encode_string_input + "${CMAKE_CURRENT_SOURCE_DIR}/${_vtk_encode_string_INPUT}") + endif () + + set(_vtk_encode_string_depends_args) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.27") + list(APPEND _vtk_encode_string_depends_args + DEPENDS_EXPLICIT_ONLY) + endif () + + add_custom_command( + OUTPUT ${_vtk_encode_string_header} + ${_vtk_encode_string_source} + DEPENDS "${_vtkEncodeString_script_file}" + "${_vtk_encode_string_input}" + COMMAND "${CMAKE_COMMAND}" + "-Dsource_dir=${CMAKE_CURRENT_SOURCE_DIR}" + "-Dbinary_dir=${CMAKE_CURRENT_BINARY_DIR}" + "-Dsource_file=${_vtk_encode_string_input}" + "-Doutput_name=${_vtk_encode_string_NAME}" + "-Dexport_symbol=${_vtk_encode_string_EXPORT_SYMBOL}" + "-Dexport_header=${_vtk_encode_string_EXPORT_HEADER}" + "-Dabi_mangle_symbol_begin=${_vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN}" + "-Dabi_mangle_symbol_end=${_vtk_encode_string_ABI_MANGLE_SYMBOL_END}" + "-Dabi_mangle_header=${_vtk_encode_string_ABI_MANGLE_HEADER}" + "-Dbinary=${_vtk_encode_string_BINARY}" + "-Dnul_terminate=${_vtk_encode_string_NUL_TERMINATE}" + "-D_vtk_encode_string_run=ON" + -P "${_vtkEncodeString_script_file}" + ${_vtk_encode_string_depends_args}) + + if (DEFINED _vtk_encode_string_SOURCE_OUTPUT) + set("${_vtk_encode_string_SOURCE_OUTPUT}" + "${_vtk_encode_string_source}" + PARENT_SCOPE) + endif () + + if (DEFINED _vtk_encode_string_HEADER_OUTPUT) + set("${_vtk_encode_string_HEADER_OUTPUT}" + "${_vtk_encode_string_header}" + PARENT_SCOPE) + endif () +endfunction () + +if (_vtk_encode_string_run AND CMAKE_SCRIPT_MODE_FILE) + set(output_source "${binary_dir}/${output_name}.h") + + set(license_topfile "// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n// SPDX-License-Identifier: BSD-3-Clause\n") + file(WRITE "${output_source}" ${license_topfile}) + + if (IS_ABSOLUTE "${source_file}") + set(source_file_full "${source_file}") + else () + set(source_file_full "${source_dir}/${source_file}") + endif () + set(hex_arg) + if (binary) + set(hex_arg HEX) + endif () + file(READ "${source_file_full}" original_content ${hex_arg}) + + if (binary) + if (nul_terminate) + string(APPEND original_content "00") + endif () + string(LENGTH "${original_content}" output_size) + math(EXPR output_size "${output_size} / 2") + + file(APPEND "${output_source}" + "#include \"${output_name}.h\"\n\n") + if (abi_mangle_symbol_begin) + file(APPEND "${output_source}" + "${abi_mangle_symbol_begin}\n\n") + endif () + file(APPEND "${output_source}" + "const unsigned char ${output_name}[${output_size}] = {\n") + string(REGEX REPLACE "\([0-9a-f][0-9a-f]\)" ",0x\\1" escaped_content "${original_content}") + # Hard line wrap the file. + string(REGEX REPLACE "\(..........................................................................,\)" "\\1\n" escaped_content "${escaped_content}") + # Remove the leading comma. + string(REGEX REPLACE "^," "" escaped_content "${escaped_content}") + file(APPEND "${output_source}" + "${escaped_content}\n") + file(APPEND "${output_source}" + "};\n") + if (abi_mangle_symbol_end) + file(APPEND "${output_source}" + "${abi_mangle_symbol_end}\n") + endif () + else () + # Escape literal backslashes. + string(REPLACE "\\" "\\\\" escaped_content "${original_content}") + # Escape literal double quotes. + string(REPLACE "\"" "\\\"" escaped_content "${escaped_content}") + # Turn newlines into newlines in the C string. + string(REPLACE "\n" "\\n\"\n\"" escaped_content "${escaped_content}") + + if (abi_mangle_symbol_begin) + file(APPEND "${output_source}" + "${abi_mangle_symbol_begin}\n\n") + endif () + file(APPEND "${output_source}" + "const char ${output_name}[] =\n") + file(APPEND "${output_source}" + "\"${escaped_content}\";\n") + if (abi_mangle_symbol_end) + file(APPEND "${output_source}" + "\n${abi_mangle_symbol_end}\n") + endif () + endif () +endif () diff --git a/CMakeLists.txt b/CMakeLists.txt index a42d460e..bc6ec06f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") add_compile_options(-Wno-shift-negative-value) endif() -if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_C_COMPILER_ID MATCHES "AppleClang" AND NOT CMAKE_C_SIMULATE_ID MATCHES "MSVC") +if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT APPLE AND NOT CMAKE_C_SIMULATE_ID MATCHES "MSVC") add_link_options("-Wl,-z,relro,-z,now,-z,defs") endif() @@ -56,7 +56,6 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_C_SIMULATE_ID MATCHES "MSVC") # "strdup" is standard since C23 add_definitions(-D _CRT_NONSTDC_NO_DEPRECATE) # ignore "'fopen' is deprecated" and "'strncpy' is deprecated" warnings - # TODO: replace by fopen_s and strncpy_s in C11 add_definitions(-D _CRT_SECURE_NO_WARNINGS) endif() @@ -66,6 +65,7 @@ set(APRILTAG_SRCS apriltag.c apriltag_pose.c apriltag_quad_thresh.c) # Library file(GLOB TAG_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tag*.c) add_library(${PROJECT_NAME} ${APRILTAG_SRCS} ${COMMON_SRC} ${TAG_FILES}) +set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) if (MSVC) add_compile_definitions("_CRT_SECURE_NO_WARNINGS") @@ -147,47 +147,40 @@ install(FILES "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc" # Python wrapper -include(CMakeDependentOption) -cmake_dependent_option(BUILD_PYTHON_WRAPPER "Builds Python wrapper" ON BUILD_SHARED_LIBS OFF) - -if(BUILD_PYTHON_WRAPPER) - SET(Python_ADDITIONAL_VERSIONS 3) - find_package(PythonLibs) - execute_process(COMMAND which python3 OUTPUT_QUIET RESULT_VARIABLE Python3_NOT_FOUND) - execute_process(COMMAND python3 -c "import numpy" RESULT_VARIABLE Numpy_NOT_FOUND) -endif(BUILD_PYTHON_WRAPPER) - -if (NOT Python3_NOT_FOUND AND NOT Numpy_NOT_FOUND AND PYTHONLIBS_FOUND AND BUILD_PYTHON_WRAPPER) - # TODO deal with both python2/3 - execute_process(COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/python_build_flags.py OUTPUT_VARIABLE PY_OUT) - set(PY_VARS CFLAGS LDFLAGS LINKER EXT_SUFFIX) - cmake_parse_arguments(PY "" "${PY_VARS}" "" ${PY_OUT}) - separate_arguments(PY_CFLAGS) - list(REMOVE_ITEM PY_CFLAGS -flto) - separate_arguments(PY_LDFLAGS) - - foreach(X detect py_type) - add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/apriltag_${X}.docstring.h - COMMAND < ${CMAKE_CURRENT_SOURCE_DIR}/apriltag_${X}.docstring sed 's/\"/\\\\\"/g\; s/^/\"/\; s/$$/\\\\n\"/\;' > apriltag_${X}.docstring.h - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) - endforeach() +option(BUILD_PYTHON_WRAPPER "Builds Python wrapper" ON) - add_custom_command(OUTPUT apriltag_pywrap.o - COMMAND ${CMAKE_C_COMPILER} ${PY_CFLAGS} -I${PROJECT_BINARY_DIR} -c -o apriltag_pywrap.o ${CMAKE_CURRENT_SOURCE_DIR}/apriltag_pywrap.c - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/apriltag_pywrap.c ${PROJECT_BINARY_DIR}/apriltag_detect.docstring.h ${PROJECT_BINARY_DIR}/apriltag_py_type.docstring.h) +find_package(Python3 QUIET COMPONENTS Development NumPy) - add_custom_target(apriltag${PY_EXT_SUFFIX} - ${PY_LINKER} ${PY_LDFLAGS} -Wl,-rpath,$ORIGIN apriltag_pywrap.o $ -o apriltag${PY_EXT_SUFFIX} - DEPENDS ${PROJECT_NAME} apriltag_pywrap.o - VERBATIM) +if(BUILD_PYTHON_WRAPPER AND Python3_Development_FOUND AND Python3_NumPy_FOUND) - add_custom_target(apriltag_python ALL - DEPENDS apriltag${PY_EXT_SUFFIX}) + include(CMake/vtkEncodeString.cmake) -execute_process(COMMAND python3 -m site --user-site OUTPUT_VARIABLE PY_DEST) -string(STRIP ${PY_DEST} PY_DEST) -install(FILES ${PROJECT_BINARY_DIR}/apriltag${PY_EXT_SUFFIX} DESTINATION ${PY_DEST}) -endif (NOT Python3_NOT_FOUND AND NOT Numpy_NOT_FOUND AND PYTHONLIBS_FOUND AND BUILD_PYTHON_WRAPPER) + foreach(X IN ITEMS detect py_type) + vtk_encode_string( + INPUT ${CMAKE_CURRENT_SOURCE_DIR}/apriltag_${X}.docstring + NAME apriltag_${X}_docstring + ) + endforeach() + add_custom_target(apriltag_py_docstrings DEPENDS + ${PROJECT_BINARY_DIR}/apriltag_detect_docstring.h + ${PROJECT_BINARY_DIR}/apriltag_py_type_docstring.h + ) + + # set the SOABI manually since renaming the library via OUTPUT_NAME does not work on MSVC + set(apriltag_py_target "apriltag.${Python3_SOABI}") + Python3_add_library(${apriltag_py_target} MODULE ${CMAKE_CURRENT_SOURCE_DIR}/apriltag_pywrap.c) + add_dependencies(${apriltag_py_target} apriltag_py_docstrings) + target_link_libraries(${apriltag_py_target} PRIVATE apriltag Python3::Python Python3::NumPy) + target_include_directories(${apriltag_py_target} PRIVATE ${PROJECT_BINARY_DIR}) + + set(PY_DEST ${CMAKE_INSTALL_PREFIX}/lib/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages/) + install(TARGETS ${apriltag_py_target} LIBRARY DESTINATION ${PY_DEST}) +elseif(BUILD_PYTHON_WRAPPER) + message(WARNING + "Python bindings requested (BUILD_PYTHON_WRAPPER=ON) but Development and NumPy not found. " + "Python bindings will not be built. Set BUILD_PYTHON_WRAPPER=OFF to silent this warnings." + ) +endif() # Examples if (BUILD_EXAMPLES) diff --git a/apriltag_pywrap.c b/apriltag_pywrap.c index cb991bb4..a8964fbf 100644 --- a/apriltag_pywrap.c +++ b/apriltag_pywrap.c @@ -206,7 +206,9 @@ static PyObject* apriltag_detect(apriltag_py_t* self, PyArrayObject* image = NULL; PyObject* detections_tuple = NULL; +#ifdef _POSIX_C_SOURCE SET_SIGINT(); +#endif if(!PyArg_ParseTuple( args, "O&", PyArray_Converter, &image )) goto done; @@ -251,7 +253,7 @@ static PyObject* apriltag_detect(apriltag_py_t* self, PyErr_Format(PyExc_RuntimeError, "Error creating output tuple of size %d", N); goto done; } - + for (int i=0; i < N; i++) { xy_c = (PyArrayObject*)PyArray_SimpleNew(1, ((npy_intp[]){2}), NPY_FLOAT64); @@ -300,21 +302,19 @@ static PyObject* apriltag_detect(apriltag_py_t* self, Py_XDECREF(image); Py_XDECREF(detections_tuple); +#ifdef _POSIX_C_SOURCE RESET_SIGINT(); +#endif return result; } -static const char apriltag_detect_docstring[] = -#include "apriltag_detect.docstring.h" - ; -static const char apriltag_type_docstring[] = -#include "apriltag_py_type.docstring.h" - ; +#include "apriltag_detect_docstring.h" +#include "apriltag_py_type_docstring.h" static PyMethodDef apriltag_methods[] = { PYMETHODDEF_ENTRY(apriltag_, detect, METH_VARARGS), - {} + {NULL, NULL, 0, NULL} }; static PyTypeObject apriltagType = @@ -326,11 +326,11 @@ static PyTypeObject apriltagType = .tp_dealloc = (destructor)apriltag_dealloc, .tp_methods = apriltag_methods, .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = apriltag_type_docstring + .tp_doc = apriltag_py_type_docstring }; static PyMethodDef methods[] = - { {} + { {NULL, NULL, 0, NULL} }; @@ -358,7 +358,11 @@ static struct PyModuleDef module_def = "apriltag", "AprilTags visual fiducial system detector", -1, - methods + methods, + 0, + 0, + 0, + 0 }; PyMODINIT_FUNC PyInit_apriltag(void) @@ -378,4 +382,3 @@ PyMODINIT_FUNC PyInit_apriltag(void) } #endif - diff --git a/common/g2d.c b/common/g2d.c index 91bbcabc..4d5502fc 100644 --- a/common/g2d.c +++ b/common/g2d.c @@ -120,7 +120,7 @@ int g2d_polygon_contains_point_ref(const zarray_t *poly, double q[2]) double acc_theta = 0; - double last_theta; + double last_theta = 0; for (int i = 0; i <= psz; i++) { double p[2]; diff --git a/package.xml b/package.xml index f235a1af..449c790d 100644 --- a/package.xml +++ b/package.xml @@ -16,6 +16,7 @@ Max Krogius cmake + python3-dev python3-numpy diff --git a/python_build_flags.py b/python_build_flags.py deleted file mode 100644 index f3f0e79a..00000000 --- a/python_build_flags.py +++ /dev/null @@ -1,34 +0,0 @@ -from __future__ import print_function -import sysconfig -import re -import numpy as np -conf = sysconfig.get_config_vars() - -print('CFLAGS', end=';') -c_flags = [] -# Grab compiler flags minus the compiler itself. -c_flags.extend(conf.get('CC', '').split()[2:]) -c_flags.extend(conf.get('CFLAGS', '').split()) -c_flags.extend(conf.get('CCSHARED', '').split()) -c_flags.append('-I{}'.format(conf.get('INCLUDEPY', ''))) -c_flags.append('-I{}'.format(np.get_include())) -c_flags.append('-Wno-strict-prototypes') -c_flags = [x for x in c_flags if not x.startswith('-O')] -print(' '.join(c_flags), end=';') - - -print('LINKER', end=';') -print(conf.get('BLDSHARED', '').split()[0], end=';') - -print('LDFLAGS', end=';') -print(' '.join(conf.get('BLDSHARED', '').split()[1:]) + ' ' + conf.get('BLDLIBRARY', '') + ' ' + conf.get('LDFLAGS', ''), end=';') - -print('EXT_SUFFIX', end=';') -ext_suffix = '.so' -if 'EXT_SUFFIX' in conf: - ext_suffix = conf['EXT_SUFFIX'] -elif 'MULTIARCH' in conf: - ext_suffix = '.' + conf['MULTIARCH'] + '.so' - -print(ext_suffix, end=';') -