Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMakeLists: refactor to optionally use native libs #1045

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion .github/workflows/build_nilrt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
193 changes: 120 additions & 73 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 $<TARGET_FILE:grpc_cpp_plugin>)
set(_GRPC_GRPCPP grpc++)
set(_PROTOBUF_LIBPROTOBUF libprotobuf)
set(_PROTOBUF_PROTOC $<TARGET_FILE: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 $<TARGET_FILE:protobuf::protoc>)
set(_REFLECTION grpc++_reflection)
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:grpc_cpp_plugin>)
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(
$<$<CONFIG:>:/MTd>
$<$<CONFIG:Debug>:/MTd>
$<$<CONFIG:Release>:/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)
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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}"
Expand All @@ -211,7 +261,6 @@ add_custom_command(
DEPENDS
${all_codegen_dependencies}
${codegen_scripts}
virtual_environment
)

set(nidriver_service_srcs
Expand Down Expand Up @@ -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)
Expand All @@ -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}"
Expand Down Expand Up @@ -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)

Expand All @@ -500,20 +559,6 @@ add_custom_command(
COMMAND ${PYTHON_EXE} ${codegen_dir}/generate_server_capabilities.py ${metadata_dir}/
-o $<TARGET_FILE_DIR:ni_grpc_device_server>/)


#----------------------------------------------------------------------
# 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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -818,7 +865,7 @@ add_custom_command(
${CMAKE_SOURCE_DIR}/source/tests/assets/data/
$<TARGET_FILE_DIR:SystemTestsRunner>/)

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()
Expand Down
1 change: 0 additions & 1 deletion cmake/nilrt-x86_64.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading