dusty-nv / jetson-utils

C++/CUDA/Python multimedia utilities for NVIDIA Jetson

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unknown CMake command "cuda_add_library" while building as a submodule

onurbingol opened this issue · comments

Hello,

I am coming Jetson Hacks' CSI-Camera repository, as they stated that jetson-utils would be a better and more complete C++ solution. After investigating jetson-utils, I've decided to build jetson-utils package as a submodule to my project, but I am getting the following error.

[cmake] -- The CXX compiler identification is GNU 9.4.0
[cmake] -- Check for working CXX compiler: /usr/bin/aarch64-linux-gnu-g++
[cmake] -- Check for working CXX compiler: /usr/bin/aarch64-linux-gnu-g++ -- works
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- jetson-utils:  building as submodule, /home/user/projects/my_project/thirdparty
[cmake] -- nvbuf_utils:  /usr/lib/aarch64-linux-gnu/tegra/libnvbuf_utils.so
[cmake] -- NVMM zero-copy memory:  ENABLE_NVMM=ON
[cmake] CMake Error at thirdparty/jetson-utils/CMakeLists.txt:102 (cuda_add_library):
[cmake]   Unknown CMake command "cuda_add_library".
[cmake] 
[cmake] 
[cmake] -- Configuring incomplete, errors occurred!

My setup is as follows:

  • I have cloned jetson-utils as a submodule to my project, shown as my-project above.
  • The directory I cloned jetson-utils is <project_root>/thirdparty/jetson-utils
  • I have a CMakeLists.txt file in the <project_root>/thirdparty/ directory, containing add_subdirectory(jetson-utils)
  • Similarly, the CMakeLists.txt file in the <project_root> directory has add_subdirectory(thirdparty). As you can see, there are no problems shown regarding the CMakeLists.txt structure on the error shown above.

The L4T version and details are as follows:

~$ cat /etc/nv_tegra_release
# R35 (release), REVISION: 3.1, GCID: 32827747, BOARD: t186ref, EABI: aarch64, DATE: Sun Mar 19 15:19:21 UTC 2023

My project doesn't have a CUDA dependency (for now), so I don't need find_package(CUDA) in my CMakeLists.txt file. The README file mentions jetson-inference package, but as far as I can see, jetson-inference finds the CUDA libraries in its CMakeLists.txt file, and it should be fine in general.

The solution is very easy for me: Just add find_package(CUDA) (and maybe a bit more lines to improve compatibility). Although this is not a super critical issue, I wanted to report the it for a proper solution.

Thanks,

Hi @onurbingol, try changing this line to if(FALSE) so that it performs the needed configuration for CUDA:

if(hasParent)

jetson-utils is commonly built as either a submodule of jetson-inference (which also does the above configuration in it's own CMakeLists, because it needs it itself too) or as standalone. You seem to have hit a corner-case where it's a submodule, but not of jetson-inference. I should probably add a cmake option so that you can trigger that conditional without needing to manually edit it.

@dusty-nv, thanks for the quick response. The solution you suggested would definitely work fine.

As I mentioned, this repository is suggested on the Jetson Hacks' CSI-Camera example repository. Most of the time, python code would work fine, especially for testing and prototyping. On the other hand, I'd need to use C++ for my custom module due to performance reasons and don't want to reinvent the wheel. Everyone would appreciate a nice library, and it would be always possible to extend it where necessary.

As you may understand, I only would like to use the parts related to the camera image retrieval. I know this might take time, but it would be great if it is possible to improve CMakeLists.txt file to make jetson-utils more modular. The rationale of this suggestion comes from the idea that I don't really like to change the dependent repositories. For sure, I can patch it during the CMake configure step, but that adds another item to maintain as the dependent project (in this case, jetson-utils)changes.

As an example to improve modularity, the following lines could allow users to choose if they want to build/install Python bindings.

set(JU_ENABLE_PYTHON_BINDINGS ON CACHE BOOL "Enable jetson-utils python bindings")
if(${JU_ENABLE_PYTHON_BINDINGS})
  add_subdirectory(python)
endif()

Similarly, there might be more CMake-native ways, for instance, to find and link libraries, like GStreamer example. I haven't tested this solution yet, but wanted to share it as an example.

Eventually, I'd need to make some changes on the CMakeLists.txt file a bit to improve its modularity and make it more CMake-native. If you prefer, I would be happy to create a PR and include some changes, like the CUDA find issue discussed above. However, I only have access to Jetson Orin Nano at this time, and I might not be able to test it against all the supported platforms. I could also share the CMakeLists.txt file here when it is completed, so that other users could use it in their own liking.

Hello again,

Here is the first draft of the updated CMakeLists.txt file. make and make install work, but I haven't tested it thoroughly. Please feel free to use and/or edit it.

# jetson-utils -- CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0048 NEW)
project(jetson-utils LANGUAGES CXX VERSION 1.0.0)

# Include CMake modules
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

# Set install directory
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
  set(JU_INSTALL_DIR ${PROJECT_BINARY_DIR}/install/${CMAKE_SYSTEM_PROCESSOR} CACHE PATH "jetson-utils install directory")
  set(CMAKE_INSTALL_PREFIX ${JU_INSTALL_DIR})
endif()
message(STATUS "jetson-utils: install directory  ${CMAKE_INSTALL_PREFIX}")

# Detect distro version
find_program(LSB_RELEASE_EXEC lsb_release /usr/bin)

if(NOT DEFINED LSB_RELEASE_EXEC)
  message(FATAL_ERROR "-- jetson-utils: Cannot find 'lsb_release' executable. Please install it via 'apt install lsb_release'.")
endif()

execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_RELEASE_ID OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --codename OUTPUT_VARIABLE LSB_RELEASE_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE)

message(STATUS "jetson-utils: distro ID       ${LSB_RELEASE_ID}")
message(STATUS "jetson-utils: distro version  ${LSB_RELEASE_VERSION}")
message(STATUS "jetson-utils: distro codename ${LSB_RELEASE_CODENAME}")

if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
    include_directories(/usr/src/jetson_multimedia_api/include)
    link_directories(/usr/lib/aarch64-linux-gnu/tegra)
endif()

# Use C++11 standard if no standard defined
if(NOT DEFINED CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 11)
  set(CMAKE_CXX_STANDARD_REQUIRED ON)
  set(CMAKE_CXX_EXTENSIONS OFF)
endif()
message(STATUS "jetson-utils: using C++ standard ${CMAKE_CXX_STANDARD}")

# Setup CUDA
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cuda")
find_package(CUDA)
message(STATUS "jetson-utils: CUDA version  ${CUDA_VERSION}")

set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; -O3)

if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
    message(STATUS "jetson-utils: CUDA ${CUDA_VERSION} detected (${CMAKE_SYSTEM_PROCESSOR}), enabling SM_53 SM_62")
    set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; -gencode arch=compute_53,code=sm_53 -gencode arch=compute_62,code=sm_62)

    if(CUDA_VERSION_MAJOR GREATER 9)
        message(STATUS "jetson-utils: CUDA ${CUDA_VERSION} detected (${CMAKE_SYSTEM_PROCESSOR}), enabling SM_72")
        set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; -gencode arch=compute_72,code=sm_72)
    endif()

    if(CUDA_VERSION_MAJOR GREATER 10)
        message(STATUS "jetson-utils: CUDA ${CUDA_VERSION} detected (${CMAKE_SYSTEM_PROCESSOR}), enabling SM_87")
        set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; -gencode arch=compute_87,code=sm_87)
    endif()
endif()

# Option for enabling/disabling NVMM memory in multimedia stack
find_library(NVBUF_UTILS NAMES nvbuf_utils PATHS /usr/lib/aarch64-linux-gnu/tegra)
message(STATUS "jetson-utils: nvbuf_utils  ${NVBUF_UTILS}")

if(NVBUF_UTILS)
    set(ENABLE_NVMM_DEFAULT ON)
else()
    set(ENABLE_NVMM_DEFAULT OFF)
endif()

option(ENABLE_NVMM "Enable use of NVMM zero-copy memory in video and camera streaming" ${ENABLE_NVMM_DEFAULT})
message(STATUS "jetson-utils: NVMM zero-copy memory:  ENABLE_NVMM=${ENABLE_NVMM}")

if(ENABLE_NVMM)
    add_definitions(-DENABLE_NVMM)
endif()

# Find dependent packages
cmake_policy(SET CMP0072 OLD)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GSTREAMER REQUIRED IMPORTED_TARGET gstreamer-1.0)
pkg_check_modules(GSTREAMER_APP REQUIRED IMPORTED_TARGET gstreamer-app-1.0)
pkg_check_modules(GSTREAMER_VIDEO REQUIRED IMPORTED_TARGET gstreamer-video-1.0)
pkg_check_modules(GSTREAMER_PBUTILS REQUIRED IMPORTED_TARGET gstreamer-pbutils-1.0)
pkg_check_modules(GSTREAMER_WEBRTC REQUIRED IMPORTED_TARGET gstreamer-webrtc-1.0)
pkg_check_modules(GSTREAMER_SDP REQUIRED IMPORTED_TARGET gstreamer-sdp-1.0)
pkg_check_modules(GSTREAMER_RTSP_SERVER REQUIRED IMPORTED_TARGET gstreamer-rtsp-server-1.0)
pkg_check_modules(JSON_GLIB REQUIRED IMPORTED_TARGET json-glib-1.0)
pkg_check_modules(SOUP REQUIRED IMPORTED_TARGET libsoup-2.4)

# Build library
file(GLOB jetsonUtilitySources *.cpp camera/*.cpp codec/*.cpp cuda/*.cu cuda/*.cpp display/*.cpp image/*.cpp input/*.cpp network/*.cpp threads/*.cpp video/*.cpp)
file(GLOB jetsonUtilityIncludes *.h *.hpp camera/*.h codec/*.h cuda/*.h cuda/*.cuh display/*.h image/*.h image/*.inl input/*.h network/*.h threads/*.h threads/*.inl video/*.h)

cuda_add_library(${PROJECT_NAME} SHARED ${jetsonUtilitySources})
target_link_libraries(${PROJECT_NAME}
  GLEW::GLEW
  OpenGL::GL
  OpenGL::GLU
  PkgConfig::GLIB
  PkgConfig::GSTREAMER
  PkgConfig::GSTREAMER_APP
  PkgConfig::GSTREAMER_PBUTILS
  PkgConfig::GSTREAMER_WEBRTC
  PkgConfig::GSTREAMER_SDP
  PkgConfig::GSTREAMER_RTSP_SERVER
  PkgConfig::JSON_GLIB
  PkgConfig::SOUP
  ${CUDA_nppicc_LIBRARY}
)

#if(NVBUF_UTILS)
#    target_link_libraries(${PROJECT_NAME} nvbuf_utils)
#endif()
# had an issue linking nvbuf_utils, the following seems to be working fine
if(DEFINED NVBUF_UTILS)
    add_library(nvbufutils SHARED IMPORTED)
    set_target_properties(nvbufutils PROPERTIES IMPORTED_LOCATION ${NVBUF_UTILS})
    target_link_libraries(${PROJECT_NAME} nvbufutils)
endif()

target_include_directories(${PROJECT_NAME}
  PUBLIC
    $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/${PROJECT_NAME}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}>
)
set_target_properties(${PROJECT_NAME}
  PROPERTIES
    PUBLIC_HEADER "${jetsonUtilityIncludes}"
)

# Transfer all headers to the include directory
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include/${PROJECT_NAME})
foreach(include ${jetsonUtilityIncludes})
    message(STATUS "Copying ${include}")
    configure_file(${include} ${PROJECT_BINARY_DIR}/include/jetson-utils COPYONLY)
endforeach()

# Install the library
install(TARGETS ${PROJECT_NAME}
  EXPORT ${PROJECT_NAME}Targets
  PUBLIC_HEADER
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
)

# Export targets with a namespace
install(EXPORT ${PROJECT_NAME}Targets
  FILE ${PROJECT_NAME}Targets.cmake
  NAMESPACE "JetsonUtils::"
  DESTINATION
    ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
)

# Configure package config files using a template
configure_package_config_file(
  ${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}Config.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
  INSTALL_DESTINATION
    ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
)

# Generate the config files
write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
  VERSION ${PROJECT_VERSION}
  COMPATIBILITY SameMajorVersion
)

# Install config files
install(
  FILES
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
  DESTINATION
    ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
)

# build python bindings + samples
#add_subdirectory(python)
#add_subdirectory(video/video-viewer)

#add_subdirectory(camera/camera-viewer)
#add_subdirectory(display/gl-display-test)
#add_subdirectory(network/webrtc-server)
#add_subdirectory(network/rtsp-server)

The CMakeLists.txt file above would look for jetson-utilsConfig.cmake.in file.

# jetson-utils -- jetson-utilsConfig.cmake.in
@PACKAGE_INIT@

# Find dependencies
include(CMakeFindDependencyMacro)
#find_dependency(XYZ)

# Include targets
include(${CMAKE_CURRENT_LIST_DIR}/jetson-utilsTargets.cmake)

# Check required components
check_required_components(jetson-utils)

Thanks @onurbingol ! I will make a note to try your CMakeLists and see if it builds with jetson-inference too 👍

@dusty-nv it might not be ready to test as I still observe some minor issues. I've created a PR #163 to keep track of the changes (still draft as of now). The python bindings and the other components are disabled for now. I'll take a look and make sure everything works before testing with jetson-inference.