diff --git a/.github/workflows/build_nilrt.yml b/.github/workflows/build_nilrt.yml index d8a085a2e..21d720906 100644 --- a/.github/workflows/build_nilrt.yml +++ b/.github/workflows/build_nilrt.yml @@ -96,7 +96,7 @@ jobs: -S . -B build -D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE} - -D CMAKE_TOOLCHAIN_FILE=$ENV{GITHUB_WORKSPACE}/cmake/nilrt-x86_64.cmake + -D grpc_device_USE_NILRT_LEGACY_TOOLCHAIN=on RESULT_VARIABLE result ) if (NOT result EQUAL 0) diff --git a/CMakeLists.txt b/CMakeLists.txt index 40b74e51e..434b13d5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,62 +5,105 @@ project(ni_grpc_device_server VERSION 2.5.0) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -include(CreateVirtualEnvironment) + # Workaround for: https://bugs.chromium.org/p/boringssl/issues/detail?id=423 if (CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") set(CMAKE_SYSTEM_PROCESSOR "amd64") endif() + +#--- +# Conifguration options +#--- +option(grpc_device_USE_NILRT_LEGACY_TOOLCHAIN "Enable to use tools and libraries from a NILRT compile toolchain." OFF) +option(grpc_device_USE_PYTHON_VENV "Enable to use the automatically-generated python venv, local to this project source." ON) +option(grpc_device_USE_SUBMODULE_DEPS "Enable to link against the submodule libraries, rather than their native-OS equivalents." ON) + #---------------------------------------------------------------------- -# Use the grpc targets directly from this build, only when not cross-compiling. +# Setup build dependencies, according to the toolchain options. #---------------------------------------------------------------------- -if(CMAKE_CROSSCOMPILING) - find_program(_PROTOBUF_PROTOC protoc) - find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) - if(NOT _GRPC_DEVICE_NILRT_LEGACY_TOOLCHAIN) - find_package(gRPC REQUIRED) - find_library(_REFLECTION grpc++_reflection) - find_library(_GRPC_GRPCPP grpc++) - find_library(_PROTOBUF_LIBPROTOBUF protobuf) - else() +if(grpc_device_USE_SUBMODULE_DEPS) + # The archetypical WIN32 build case + # protobuf_INSTALL must be turned OFF whenever building it as a cmake subdir. + set(protobuf_INSTALL OFF) + + add_subdirectory(third_party/grpc ${CMAKE_CURRENT_BINARY_DIR}/grpc) + add_subdirectory(third_party/gtest ${CMAKE_CURRENT_BINARY_DIR}/gtest) + add_subdirectory(third_party/json ${CMAKE_CURRENT_BINARY_DIR}/json) + add_subdirectory(third_party/utfcpp ${CMAKE_CURRENT_BINARY_DIR}/utfcpp) + + set(_REFLECTION grpc++_reflection) + set(_GRPC grpc) + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + set(_GRPC_GRPCPP grpc++) + set(_PROTOBUF_LIBPROTOBUF libprotobuf) + set(_PROTOBUF_PROTOC $) + set(_UTF8CPP utf8cpp) +else() + find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED) + + find_library(_GRPC_GPR gpr REQUIRED) + find_library(_ABSEIL_SYNC absl_synchronization REQUIRED) + + if(grpc_device_USE_NILRT_LEGACY_TOOLCHAIN) + include(nilrt-x86_64) + # The archetypical NILRT SDK toolchain build case add_subdirectory(third_party/grpc ${CMAKE_CURRENT_BINARY_DIR}/grpc EXCLUDE_FROM_ALL) set(_REFLECTION grpc++_reflection) set(_GRPC_GRPCPP grpc++) set(_PROTOBUF_LIBPROTOBUF libprotobuf) + set(_PROTOBUF_PROTOC protoc) + else() + # The archetypical linux build case (including OpenEmbedded) + find_library(_GRPC_GRPCPP grpc++) + find_library(_PROTOBUF_LIBPROTOBUF protobuf) + find_library(_REFLECTION grpc++_reflection) + + find_package(gRPC REQUIRED) + find_package(GTest REQUIRED) + find_package(nlohmann_json REQUIRED) + find_package(utf8cpp REQUIRED) + + find_program(_PROTOBUF_PROTOC protoc REQUIRED) + + set(_GRPC gRPC::grpc) + set(_UTF8CPP utf8cpp::utf8cpp) endif() +endif() +# Python3 Virtual Environment +if(grpc_device_USE_PYTHON_VENV) + include(CreateVirtualEnvironment) + CreateVirtualEnvironment(virtual_environment + REQUIREMENTS_TXT + ${CMAKE_SOURCE_DIR}/python_build_requirements.txt + ENV_NAME + venv + OUT_PYTHON_EXE + PYTHON_EXE + ) else() - add_subdirectory(third_party/grpc ${CMAKE_CURRENT_BINARY_DIR}/grpc EXCLUDE_FROM_ALL) - set(_PROTOBUF_PROTOC $) - set(_REFLECTION grpc++_reflection) - set(_GRPC_CPP_PLUGIN_EXECUTABLE $) - set(_GRPC_GRPCPP grpc++) - set(_PROTOBUF_LIBPROTOBUF libprotobuf) + find_package(Python3 REQUIRED) + set(PYTHON_EXE ${Python3_EXECUTABLE}) endif() -#---------------------------------------------------------------------- -CreateVirtualEnvironment(virtual_environment - REQUIREMENTS_TXT - ${CMAKE_SOURCE_DIR}/python_build_requirements.txt - ENV_NAME - venv - OUT_PYTHON_EXE - PYTHON_EXE -) -#---------------------------------------------------------------------- -# Use the utfcpp targets directly from this build, only when not cross-compiling. -#---------------------------------------------------------------------- -if(CMAKE_CROSSCOMPILING AND NOT _GRPC_DEVICE_NILRT_LEGACY_TOOLCHAIN) - find_package(utf8cpp REQUIRED) -else() - add_subdirectory(third_party/utfcpp ${CMAKE_CURRENT_BINARY_DIR}/utfcpp EXCLUDE_FROM_ALL) +# Dynamically link all libraries when using MSVC. +if(CMAKE_LINKER MATCHES "MSVC") + add_compile_options( + $<$:/MTd> + $<$:/MTd> + $<$:/MT> + ) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") + message("Set MSVC flags.") endif() -include_directories( - "./third_party/utfcpp/source" -) + +enable_testing() +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) #---------------------------------------------------------------------- # Use C++17 (needed for shared_mutex support on Linux) @@ -141,6 +184,10 @@ endif() set(all_codegen_dependencies "") +if(grpc_device_USE_PYTHON_VENV) + list(APPEND all_codegen_dependencies virtual_environment) +endif() + foreach(api ${nidrivers}) set(codegen_dependencies "${metadata_dir}/${api}/attributes.py" @@ -191,7 +238,10 @@ foreach(api ${nidrivers}) ${nidriver_client_srcs} "${service_output_dir}/${api}/${api}_client.cpp") endif() - set(proto_dependencies ${codegen_dependencies} ${codegen_scripts} virtual_environment) + set(proto_dependencies ${codegen_dependencies} ${codegen_scripts}) + if (grpc_device_USE_PYTHON_VENV) + list(APPEND proto_dependencies virtual_environment) + endif() add_custom_command(OUTPUT ${output_files} ${gen_command} COMMENT "Generating proto file and service for ${api}" @@ -211,7 +261,6 @@ add_custom_command( DEPENDS ${all_codegen_dependencies} ${codegen_scripts} - virtual_environment ) set(nidriver_service_srcs @@ -240,6 +289,9 @@ function(GenerateGrpcSources) cmake_parse_arguments(GENERATE_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(output_files "${GENERATE_ARGS_OUTPUT}") set(proto_file "${GENERATE_ARGS_PROTO}") + if(grpc_device_USE_SUBMODULE_DEPS) + set(protobuf_includes_arg -I ${CMAKE_SOURCE_DIR}/third_party/grpc/third_party/protobuf/src/) + endif() get_filename_component(proto_path "${proto_file}" PATH) # Asssumption: all outputs are in the same directory: use the zero-th. list(GET output_files 0 proto_srcs) @@ -250,7 +302,7 @@ function(GenerateGrpcSources) ARGS --grpc_out "${proto_out_path}" --cpp_out "${proto_out_path}" -I "${proto_path}" - -I ${CMAKE_SOURCE_DIR}/third_party/grpc/third_party/protobuf/src/ + ${protobuf_includes_arg} -I ${CMAKE_SOURCE_DIR}/imports/protobuf --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" "${proto_file}" @@ -472,14 +524,21 @@ if(CMAKE_SYSTEM_NAME STREQUAL Windows) PRIVATE "source/server/windows/console_ctrl_handler.cpp") endif() +set(server_lib_deps + ${_ABSEIL_SYNC} + ${_GRPC_GPR} + ${_GRPC_GRPCPP} + ${_GRPC} + ${_PROTOBUF_LIBPROTOBUF} + ${_REFLECTION} + ${_UTF8CPP} + ${CMAKE_DL_LIBS} + nlohmann_json::nlohmann_json +) + target_link_libraries(ni_grpc_device_server - ${_REFLECTION} - ${_GRPC_GRPCPP} - ${_PROTOBUF_LIBPROTOBUF} - ${CMAKE_DL_LIBS} - nlohmann_json::nlohmann_json - utf8cpp - ) + ${server_lib_deps} +) set_target_properties(ni_grpc_device_server PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE) @@ -500,20 +559,6 @@ add_custom_command( COMMAND ${PYTHON_EXE} ${codegen_dir}/generate_server_capabilities.py ${metadata_dir}/ -o $/) - -#---------------------------------------------------------------------- -# Add JSON parser and configure google tests -#---------------------------------------------------------------------- -if(CMAKE_CROSSCOMPILING AND NOT _GRPC_DEVICE_NILRT_LEGACY_TOOLCHAIN) - find_package(nlohmann_json REQUIRED) - find_package(GTest REQUIRED) -else() - add_subdirectory(third_party/json ${CMAKE_CURRENT_BINARY_DIR}/json EXCLUDE_FROM_ALL) - enable_testing() - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - add_subdirectory(third_party/gtest ${CMAKE_CURRENT_BINARY_DIR}/gtest EXCLUDE_FROM_ALL) -endif() - # Link test executable against gtest add_executable(IntegrationTestsRunner "imports/include/nierr_Status.cpp" @@ -568,12 +613,12 @@ add_executable(IntegrationTestsRunner find_package(Threads REQUIRED) target_link_libraries(IntegrationTestsRunner - gtest + ${server_lib_deps} gmock - ${_GRPC_GRPCPP} - ${CMAKE_DL_LIBS} + grpc + gtest Threads::Threads - nlohmann_json::nlohmann_json) +) # Ignore the use of deprecated functions in test code target_compile_definitions(IntegrationTestsRunner @@ -673,12 +718,13 @@ target_include_directories(UnitTestsRunner PRIVATE "source/server") target_link_libraries(UnitTestsRunner - gtest - gmock - ${_GRPC_GRPCPP} ${CMAKE_DL_LIBS} + ${server_lib_deps} + gmock + grpc + gtest Threads::Threads - nlohmann_json::nlohmann_json) +) #---------------------------------------------------------------------- # Copy test asset certificates to binary output certs sub-directory @@ -695,8 +741,10 @@ foreach(api ${nidrivers_to_build}) "${service_output_dir}/${api}/${api}_compilation_test.cpp") endforeach() add_library(CompilationTests STATIC ${compilation_test_sources}) + target_link_libraries(CompilationTests ${_GRPC_GRPCPP} + ${_UTF8CPP} ) add_custom_target(generated_nidriver_service_library_hdrs DEPENDS ${nidriver_service_library_hdrs}) add_dependencies(CompilationTests generated_nidriver_service_library_hdrs) @@ -801,11 +849,10 @@ endif() add_executable(SystemTestsRunner ${system_test_runner_sources}) target_link_libraries(SystemTestsRunner - gtest - gmock - ${_GRPC_GRPCPP} ${CMAKE_DL_LIBS} - nlohmann_json::nlohmann_json + ${server_lib_deps} + gmock + gtest ) # Ignore the use of deprecated functions in test code @@ -818,7 +865,7 @@ add_custom_command( ${CMAKE_SOURCE_DIR}/source/tests/assets/data/ $/) -if(_GRPC_DEVICE_NILRT_LEGACY_TOOLCHAIN) +if(grpc_device_USE_NILRT_LEGACY_TOOLCHAIN) target_link_libraries(SystemTestsRunner stdc++fs) target_compile_definitions(SystemTestsRunner PRIVATE FS_EXPERIMENTAL) endif() diff --git a/cmake/nilrt-x86_64.cmake b/cmake/nilrt-x86_64.cmake index c007f6966..7f00969f5 100644 --- a/cmake/nilrt-x86_64.cmake +++ b/cmake/nilrt-x86_64.cmake @@ -3,7 +3,6 @@ #---------------------------------------------------------------------- set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR x86_64) -set(_GRPC_DEVICE_NILRT_LEGACY_TOOLCHAIN TRUE) #---------------------------------------------------------------------- # Path variables for toolchains