Skip to content

Commit

Permalink
RSDK-8822: Whole archive linking (#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
lia-viam authored Oct 18, 2024
1 parent d8bee17 commit f78507f
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 34 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ jobs:
runs-on: ubuntu-latest
container:
image: ghcr.io/viamrobotics/canon:amd64
strategy:
matrix:
include:
- BUILD_SHARED: ON
- BUILD_SHARED: OFF
steps:
- uses: actions/checkout@v4
###########################################
Expand All @@ -18,4 +23,4 @@ jobs:
- name: build-docker-test
run: |
docker build -t cpp . -f etc/docker/tests/Dockerfile.debian.bullseye
docker run --rm -i -w /tmp cpp /bin/bash
docker run -e BUILD_SHARED=${{ matrix.BUILD_SHARED }} --rm -i -w /tmp cpp /bin/bash
14 changes: 5 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ project(viam-cpp-sdk
#
# Enabled by default so that we produce a
# modern SDK, this option can be set to `OFF` to build a static
# library. Note that this may result in non-functional examples.
# library.
# Note that the pkg-config files installed by the project do not work
# for a static build; please use Conan for more robust pkg-config support.
#
option(BUILD_SHARED_LIBS "If enabled, build shared libraries" ON)

Expand Down Expand Up @@ -129,14 +131,8 @@ option(VIAMCPPSDK_CLANG_TIDY "Run the clang-tidy linter" OFF)

# The following options are only defined if this project is not being included as a subproject
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
include(CMakeDependentOption)
option(VIAMCPPSDK_BUILD_EXAMPLES "Build the example executables (requires building tests too)" ON)

# Note that the complex module example requires the testing library and adds its tests to the unit
# test suite. Thus you can only disable tests if examples are also disabled.
# The call below says don't give the user the option to disable tests unless examples are already
# disabled, and default to building the tests in either case.
cmake_dependent_option(VIAMCPPSDK_BUILD_TESTS "Build the unit test suite" ON "NOT VIAMCPPSDK_BUILD_EXAMPLES" ON)
option(VIAMCPPSDK_BUILD_EXAMPLES "Build the example executables" ON)
option(VIAMCPPSDK_BUILD_TESTS "Build the example executables" ON)
endif()


Expand Down
17 changes: 16 additions & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
from conan.tools.files import load
from conan.tools.apple import is_apple_os
import os
import re

class ViamCppSdkRecipe(ConanFile):
Expand Down Expand Up @@ -81,9 +83,10 @@ def package(self):

def package_info(self):
self.cpp_info.components["viam_rust_utils"].libs = ["viam_rust_utils"]

self.cpp_info.components["viamsdk"].libs = ["viamsdk"]

for component in ["viamsdk", "viamapi"]:
self.cpp_info.components[component].libs = [component]
self.cpp_info.components[component].set_property("cmake_target_name", "viam-cpp-sdk::{}".format(component))
self.cpp_info.components[component].set_property("pkg_config_name", "viam-cpp-sdk-lib{}".format(component))
self.cpp_info.components[component].requires = ["grpc::grpc++", "protobuf::libprotobuf"]
Expand All @@ -95,6 +98,18 @@ def package_info(self):

self.cpp_info.components["viamapi"].includedirs.append("include/viam/api")

if self.options.shared:
self.cpp_info.components["viamapi"].libs = ["viamapi"]
else:
lib_folder = os.path.join(self.package_folder, "lib")
lib_fullpath = os.path.join(lib_folder, "libviamapi.a")
if is_apple_os(self):
whole_archive = f"-Wl,-force_load,{lib_fullpath}"
else:
whole_archive = f"-Wl,--push-state,--whole-archive,{lib_fullpath},--pop-state"
self.cpp_info.components["viamapi"].exelinkflags.append(whole_archive)
self.cpp_info.components["viamapi"].sharedlinkflags.append(whole_archive)

self.cpp_info.components["viamsdk"].requires.extend([
"viamapi",
"boost::headers",
Expand Down
31 changes: 23 additions & 8 deletions etc/docker/tests/run_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ mkdir build
cd build
cmake .. -G Ninja -DVIAMCPPSDK_USE_DYNAMIC_PROTOS=ON \
-DVIAMCPPSDK_OFFLINE_PROTO_GENERATION=ON \
-DVIAMCPPSDK_SANITIZED_BUILD=ON \
-DVIAMCPPSDK_CLANG_TIDY=ON
-DVIAMCPPSDK_SANITIZED_BUILD=$BUILD_SHARED \
-DVIAMCPPSDK_CLANG_TIDY=ON \
-DBUILD_SHARED_LIBS=$BUILD_SHARED

ninja all
ninja install
INSTALL_DIR="$(pwd)/install"
Expand All @@ -20,15 +22,28 @@ popd

# Test that example_module builds and runs with the SDK install from above.
# Check with both CMake and make/pkg-config that we can build the example
# and have it exit with the expected error message.
# and have it start listening.

run_module() {
./example_module fake-socket-path > module-out-temp.txt &
MODULE_PID=$!
sleep 2
kill ${MODULE_PID}
grep 'Module listening' module-out-temp.txt
return $?
}

cd ../src/viam/examples/project
pushd cmake
cmake . -G Ninja # Just do an in-source build to save path fiddling
ninja all
[ $(./example_module 2>&1 | grep 'main failed with exception:' -c) = 1 ]
popd
pushd pkg-config
PKG_CONFIG_PATH=${INSTALL_DIR}/lib/pkgconfig make all
[ $(./example_module 2>&1 | grep 'main failed with exception:' -c) = 1 ]
run_module
popd

if [ ${BUILD_SHARED} = "ON" ]
then
pushd pkg-config
PKG_CONFIG_PATH=${INSTALL_DIR}/lib/pkgconfig make all
run_module
popd
fi
18 changes: 10 additions & 8 deletions src/viam/examples/modules/complex/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,13 @@ install(
# writing their own modules. We are simply integrating tests from
# `test_complex_module.cpp` into the Viam C++ SDK testing suite.

enable_testing()
viamcppsdk_add_boost_test(test_complex_module.cpp)
target_sources(test_complex_module
PRIVATE
gizmo/impl.cpp
summation/impl.cpp
)
target_link_libraries(test_complex_module complex_module_sources)
if (VIAMCPPSDK_BUILD_TESTS)
enable_testing()
viamcppsdk_add_boost_test(test_complex_module.cpp)
target_sources(test_complex_module
PRIVATE
gizmo/impl.cpp
summation/impl.cpp
)
target_link_libraries(test_complex_module complex_module_sources)
endif()
7 changes: 6 additions & 1 deletion src/viam/sdk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,13 @@ target_link_directories(viamsdk
"$<INSTALL_INTERFACE:${VIAMCPPSDK_PROTOBUF_LIBRARY_DIRS}>"
)

if (BUILD_SHARED_LIBS)
target_link_libraries(viamsdk PUBLIC viam-cpp-sdk::viamapi)
else()
target_link_libraries(viamsdk PUBLIC "$<LINK_LIBRARY:WHOLE_ARCHIVE,viam-cpp-sdk::viamapi>")
endif()

target_link_libraries(viamsdk
PUBLIC viam-cpp-sdk::viamapi
PUBLIC ${VIAMCPPSDK_GRPCXX_LIBRARIES}
PUBLIC ${VIAMCPPSDK_GRPC_LIBRARIES}
PUBLIC ${VIAMCPPSDK_PROTOBUF_LIBRARIES}
Expand Down
26 changes: 20 additions & 6 deletions test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import subprocess
import os
from io import StringIO

from conan import ConanFile
from conan.errors import ConanException
Expand All @@ -23,8 +23,22 @@ def layout(self):

def test(self):
if can_run(self):
cmd = os.path.join(self.cpp.build.bindir, "example_module")
stderr = StringIO()
self.run(cmd, env='conanrun', stderr=stderr, ignore_errors=True)
if "main failed with exception:" not in stderr.getvalue():
raise ConanException("Unexpected error output from test")
sock = "fake-socket-path"

cmd = os.path.join(self.cpp.build.bindir, f"example_module {sock}")

# the ConanFile run method is a wrapper around Popen, but it only returns the retcode.
# A properly intialized module waits indefinitely on a signal, so we have to use Popen manually.
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, text=True)

out = None

try:
out = proc.communicate(timeout=2)[0]
except subprocess.TimeoutExpired:
proc.terminate()
out = proc.communicate()[0]
pass

if f"Module listening on {sock}" not in out:
raise ConanException(f"Simple example failed to start module listening")

0 comments on commit f78507f

Please sign in to comment.