diff options
author | Christopher Hughes <67643395+chughes-pika@users.noreply.github.com> | 2022-11-26 09:33:48 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-26 09:33:48 +0300 |
commit | f4bc415fa9d0042523c93f5d47728199dc2cb39d (patch) | |
tree | 1e33610d61dfd1b50cfd55e09fe2f17378d3cfc3 | |
parent | bb5b4d90cb372288f157eb9c3c2b9cc6c6ad2df4 (diff) |
Adding a simple Conan+CMake example (#837)
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | examples/conan_dependency/.gitignore | 1 | ||||
-rw-r--r-- | examples/conan_dependency/CMakeLists.txt | 13 | ||||
-rw-r--r-- | examples/conan_dependency/README.md | 28 | ||||
-rw-r--r-- | examples/conan_dependency/conanfile.py | 42 | ||||
-rw-r--r-- | examples/conan_dependency/protos/simple.proto | 9 | ||||
-rw-r--r-- | examples/conan_dependency/src/simple.c | 71 |
7 files changed, 166 insertions, 0 deletions
@@ -9,6 +9,7 @@ *_pb2.py *~ *.tar.gz +*.swp .sconsign.dblite config.log .sconf_temp @@ -29,3 +30,4 @@ generator/nanopb_pb2.pyc !generator-bin/**/* bazel-* extra/poetry/build +build/ diff --git a/examples/conan_dependency/.gitignore b/examples/conan_dependency/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/examples/conan_dependency/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/examples/conan_dependency/CMakeLists.txt b/examples/conan_dependency/CMakeLists.txt new file mode 100644 index 0000000..f5df573 --- /dev/null +++ b/examples/conan_dependency/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.20) +project(simple C) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +add_library(simple-protos STATIC + ${CMAKE_BINARY_DIR}/src/simple.pb.c +) + +add_executable(simple ${CMAKE_BINARY_DIR}/src/simple.c) + +target_link_libraries(simple ${CONAN_LIBS} simple-protos) diff --git a/examples/conan_dependency/README.md b/examples/conan_dependency/README.md new file mode 100644 index 0000000..00b86c4 --- /dev/null +++ b/examples/conan_dependency/README.md @@ -0,0 +1,28 @@ +# About +This example shows how to use Conan to pull in the header files and static libraries +for `nanopb` and incorporate them into a very simple CMake application. + +## How To Run + +### Before using this example +The `conanfile.py` here imports `0.4.6` for `nanopb` and uses the packaged artifacts +to build a simple application. You'll likely need to build this yourself, so +checkout the tagged version and run `conan create .` in the base of this repository + +### Running line by line +To run though the build one step at a time, use the following commands. +```sh +mkdir build +cd build +conan install .. +conan source .. +conan build .. +conan package .. +``` +The `conanfile.py` has been commented to explain the workflow + +### Installing to cache +To have everything build at once and install to your local Conan cache +```sh +conan create . +``` diff --git a/examples/conan_dependency/conanfile.py b/examples/conan_dependency/conanfile.py new file mode 100644 index 0000000..e762bd5 --- /dev/null +++ b/examples/conan_dependency/conanfile.py @@ -0,0 +1,42 @@ +from conans import ConanFile, CMake + +class SimpleProtosConan(ConanFile): + name = "simple_protos" + version = "1.0.0" + description = "An example of importing nanopb as a conan artifact" + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + exports = "*" + + def requirements(self): + self.requires("nanopb/0.4.6") + + def imports(self): + # Includes the nanopb headers + self.copy("*.h") + # Includes the compiled nanopb libraries + self.copy("*", src="lib", dst="lib") + # Includes the protoc plugin + self.copy("*", src="bin", dst="bin") + # Includes the python libraries that `bin` reaches out to + self.copy("*", src="local", dst="local") + + def source(self): + # To include the packages from nanopb, we need to get their path in cache + nanopb_package_root = self.deps_cpp_info["nanopb"].rootpath + python_path=f"PYTHONPATH={nanopb_package_root}/local/lib/python3.10/dist-packages" + plugin=f"--plugin={nanopb_package_root}/bin/protoc-gen-nanopb" + # These next values grab this environments source and proto directories + output=f"--nanopb_out={self.source_folder}/src" + proto_flags=f"-I {self.source_folder}/protos simple.proto" + + self.run(f"{python_path} protoc {plugin} {output} {proto_flags}") + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + self.copy("simple", dst="bin", src="bin") + diff --git a/examples/conan_dependency/protos/simple.proto b/examples/conan_dependency/protos/simple.proto new file mode 100644 index 0000000..5c73a3b --- /dev/null +++ b/examples/conan_dependency/protos/simple.proto @@ -0,0 +1,9 @@ +// A very simple protocol definition, consisting of only +// one message. + +syntax = "proto2"; + +message SimpleMessage { + required int32 lucky_number = 1; +} + diff --git a/examples/conan_dependency/src/simple.c b/examples/conan_dependency/src/simple.c new file mode 100644 index 0000000..1f6b137 --- /dev/null +++ b/examples/conan_dependency/src/simple.c @@ -0,0 +1,71 @@ +#include <stdio.h> +#include <pb_encode.h> +#include <pb_decode.h> +#include "simple.pb.h" + +int main() +{ + /* This is the buffer where we will store our message. */ + uint8_t buffer[128]; + size_t message_length; + bool status; + + /* Encode our message */ + { + /* Allocate space on the stack to store the message data. + * + * Nanopb generates simple struct definitions for all the messages. + * - check out the contents of simple.pb.h! + * It is a good idea to always initialize your structures + * so that you do not have garbage data from RAM in there. + */ + SimpleMessage message = SimpleMessage_init_zero; + + /* Create a stream that will write to our buffer. */ + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + /* Fill in the lucky number */ + message.lucky_number = 13; + + /* Now we are ready to encode the message! */ + status = pb_encode(&stream, SimpleMessage_fields, &message); + message_length = stream.bytes_written; + + /* Then just check for any errors.. */ + if (!status) + { + printf("Encoding failed: %s\n", PB_GET_ERROR(&stream)); + return 1; + } + } + + /* Now we could transmit the message over network, store it in a file or + * wrap it to a pigeon's leg. + */ + + /* But because we are lazy, we will just decode it immediately. */ + + { + /* Allocate space for the decoded message. */ + SimpleMessage message = SimpleMessage_init_zero; + + /* Create a stream that reads from the buffer. */ + pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); + + /* Now we are ready to decode the message. */ + status = pb_decode(&stream, SimpleMessage_fields, &message); + + /* Check for errors... */ + if (!status) + { + printf("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + return 1; + } + + /* Print the data contained in the message. */ + printf("Your lucky number was %d!\n", message.lucky_number); + } + + return 0; +} + |