diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml index dd37a985d..78431f553 100644 --- a/.github/workflows/conan.yml +++ b/.github/workflows/conan.yml @@ -1,10 +1,16 @@ name: Test conan packages on: - # Run weekdays at 11:15pm UTC, and specify below to only run if there's been new commits + # Runs for PRs that directly change conan code, and weekdays at 11:15pm UTC. + # Additional logic in the prepare job below makes it so scheduled builds only run + # on new commits. schedule: - cron: "15 11 * * 1-5" workflow_dispatch: + pull_request: + paths: + - conanfile.py + - test_package/conanfile.py jobs: prepare: @@ -13,17 +19,24 @@ jobs: steps: - name: Checkout Code uses: actions/checkout@v4 - - - name: Get new commit count - id: new_commit_count - shell: bash - run: echo "commit_count=$(git log --oneline --since '24 hours ago' | wc -l)" >> $GITHUB_OUTPUT - - - name: Cancelling scheduled build with no new commits - uses: andymckay/cancel-action@0.2 + - name: Get current git info + if: github.event_name == 'schedule' + id: git_info + run: | + echo "current_commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + echo "current_branch=$(git branch --show-current)" >> $GITHUB_OUTPUT + - name: Get last successful commit + if: github.event_name == 'schedule' + id: last_successful_commit + uses: nrwl/last-successful-commit-action@v1 + with: + branch: ${{ steps.git_info.outputs.current_branch }} + workflow_id: conan.yml + - name: Cancel scheduled build with no new commits + uses: nrwl/last-successful-commit-action@v1 if: | - steps.new_commit_count.outputs.commit_count == '0' && - github.event_name == 'schedule' + github.event_name == 'schedule' && + steps.git_info.outputs.current_commit == steps.last_successful_commit.outputs.commit_hash build_macos: if: github.repository_owner == 'viamrobotics' diff --git a/conanfile.py b/conanfile.py index 98fe462cc..b388f67db 100644 --- a/conanfile.py +++ b/conanfile.py @@ -32,14 +32,15 @@ def set_version(self): self.version = re.search("set\(CMAKE_PROJECT_VERSION (.+)\)", content).group(1).strip() def configure(self): - # If we're building static then build the world as static, otherwise - # stuff will probably break. - # If you want your shared build to also build the world as shared, you - # can invoke conan with -o "&:shared=False" -o "*:shared=False", - # possibly with --build=missing or --build=cascade as desired, - # but this is probably not necessary. - if not self.options.shared: - self.options["*"].shared = False + if self.options.shared: + # See https://github.com/conan-io/conan-center-index/issues/25107 + self.options["grpc"].secure = True + + # From some experiments it seems that the shared-ness of these packages + # should match that of the SDK recipe. Failure to do so can cause linker + # errors while compiling, or static initialization errors at runtime for modules. + for lib in ["grpc", "protobuf", "abseil"]: + self.options[lib].shared = True def requirements(self): self.requires('boost/[>=1.74.0]', transitive_headers=True) @@ -49,8 +50,8 @@ def requirements(self): self.requires('grpc/[>=1.48.4]', transitive_headers=True) self.requires('protobuf/[>=3.17.1]', transitive_headers=True) - self.requires('xtensor/[>=0.24.3]', transitive_headers=True) - self.requires('abseil/[>=20230125.3]') + self.requires('xtensor/[>=0.24.3]') + self.requires('abseil/[>=20230125.3]', transitive_libs=True) def build_requirements(self): if self.options.offline_proto_generation: @@ -83,13 +84,13 @@ 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].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"] + self.cpp_info.components[component].requires = ["grpc::grpc++"] if self.settings.os in ["Linux", "FreeBSD"]: self.cpp_info.components[component].system_libs = ["pthread"] @@ -114,11 +115,12 @@ def package_info(self): "viamapi", "boost::headers", "boost::log", + "grpc::grpc++_reflection", + "protobuf::libprotobuf", "xtensor::xtensor", "viam_rust_utils", "abseil::absl_strings", - "grpc::grpc++_reflection" ]) self.cpp_info.components["viamsdk"].frameworks = ["Security"] diff --git a/test_package/conanfile.py b/test_package/conanfile.py index d3627813a..ef3274f7f 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -5,6 +5,7 @@ from conan.errors import ConanException from conan.tools.cmake import CMake, cmake_layout from conan.tools.build import can_run +from conan.tools.env import VirtualRunEnv class viamCppSdkTest(ConanFile): settings = "os", "compiler", "build_type", "arch" @@ -25,11 +26,14 @@ def test(self): if can_run(self): sock = "fake-socket-path" - cmd = os.path.join(self.cpp.build.bindir, f"example_module {sock}") + cmd = os.path.join(self.cpp.build.bindir, "example_module") # 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) + # Use VirtualRunEnv to perform the equivalent of passing env="conanrun" to self.run, so that + # shared builds have a properly set LD_LIBRARY_PATH among other things. + env = VirtualRunEnv(self).vars() + proc = subprocess.Popen([cmd, sock], stdout=subprocess.PIPE, text=True, env=env) out = None