From 050ce9ee512fe8a42ea26934bdb80f64200ef057 Mon Sep 17 00:00:00 2001 From: Jeremy Nimmer Date: Fri, 21 Feb 2025 15:23:04 -0800 Subject: [PATCH] Add support for Bazel Add examples/bazel with a sample downstream use, licensed as MIT-0. Other fixes: - Adjust lcm_eventlog.py test to not require copying the example log. - Fix a small typo in the go example. --- .bazelignore | 2 + .github/workflows/test_bazel.yml | 25 +++ .gitignore | 2 + BUILD.bazel | 16 ++ MODULE.bazel | 39 ++++ docs/content/build-instructions.md | 24 +++ examples/.gitignore | 3 + examples/bazel/.gitignore | 4 + examples/bazel/BUILD.bazel | 132 +++++++++++++ examples/bazel/LICENSE.TXT | 12 ++ examples/bazel/MODULE.bazel | 15 ++ examples/bazel/exlcm/example_list_t.lcm | 1 + examples/bazel/exlcm/example_t.lcm | 1 + examples/bazel/exlcm/exampleconst_t.lcm | 1 + examples/bazel/exlcm/multidim_array_t.lcm | 1 + examples/bazel/exlcm/node_t.lcm | 1 + examples/bazel/test_c.c | 32 +++ examples/bazel/test_cc.cc | 24 +++ examples/bazel/test_py.py | 26 +++ examples/go/gen.go | 2 +- ...ultidim_array_t.lcm => muldim_array_t.lcm} | 0 lcm-bazel/BUILD.bazel | 4 + lcm-bazel/lcm_c_library_srcs.bzl | 30 +++ lcm-bazel/lcm_cc_library_srcs.bzl | 30 +++ lcm-bazel/lcm_info.bzl | 12 ++ lcm-bazel/lcm_java_library_srcs.bzl | 29 +++ lcm-bazel/lcm_library.bzl | 38 ++++ lcm-bazel/lcm_py_library_srcs.bzl | 29 +++ lcm-bazel/private/BUILD.bazel | 4 + lcm-bazel/private/copts.bzl | 10 + lcm-bazel/private/lcm_c_library_srcs.bzl | 53 +++++ lcm-bazel/private/lcm_cc_library_srcs.bzl | 51 +++++ lcm-bazel/private/lcm_info.bzl | 10 + lcm-bazel/private/lcm_java_library_srcs.bzl | 51 +++++ lcm-bazel/private/lcm_library.bzl | 42 ++++ lcm-bazel/private/lcm_py_library_srcs.bzl | 53 +++++ lcm-java/BUILD.bazel | 67 +++++++ lcm-logger/BUILD.bazel | 30 +++ lcm-python/BUILD.bazel | 34 ++++ lcm/BUILD.bazel | 182 ++++++++++++++++++ lcmgen/BUILD.bazel | 33 ++++ lcmgen/main.c | 2 +- test/BUILD.bazel | 9 + test/c/BUILD.bazel | 125 ++++++++++++ test/cpp/BUILD.bazel | 89 +++++++++ test/java/BUILD.bazel | 84 ++++++++ test/python/BUILD.bazel | 134 +++++++++++++ test/python/CMakeLists.txt | 2 - test/python/lcm_eventlog.py | 3 +- test/types/BUILD.bazel | 45 +++++ 50 files changed, 1643 insertions(+), 5 deletions(-) create mode 100644 .bazelignore create mode 100644 .github/workflows/test_bazel.yml create mode 100644 BUILD.bazel create mode 100644 MODULE.bazel create mode 100644 examples/bazel/.gitignore create mode 100644 examples/bazel/BUILD.bazel create mode 100644 examples/bazel/LICENSE.TXT create mode 100644 examples/bazel/MODULE.bazel create mode 120000 examples/bazel/exlcm/example_list_t.lcm create mode 120000 examples/bazel/exlcm/example_t.lcm create mode 120000 examples/bazel/exlcm/exampleconst_t.lcm create mode 120000 examples/bazel/exlcm/multidim_array_t.lcm create mode 120000 examples/bazel/exlcm/node_t.lcm create mode 100644 examples/bazel/test_c.c create mode 100644 examples/bazel/test_cc.cc create mode 100644 examples/bazel/test_py.py rename examples/types/{multidim_array_t.lcm => muldim_array_t.lcm} (100%) create mode 100644 lcm-bazel/BUILD.bazel create mode 100644 lcm-bazel/lcm_c_library_srcs.bzl create mode 100644 lcm-bazel/lcm_cc_library_srcs.bzl create mode 100644 lcm-bazel/lcm_info.bzl create mode 100644 lcm-bazel/lcm_java_library_srcs.bzl create mode 100644 lcm-bazel/lcm_library.bzl create mode 100644 lcm-bazel/lcm_py_library_srcs.bzl create mode 100644 lcm-bazel/private/BUILD.bazel create mode 100644 lcm-bazel/private/copts.bzl create mode 100644 lcm-bazel/private/lcm_c_library_srcs.bzl create mode 100644 lcm-bazel/private/lcm_cc_library_srcs.bzl create mode 100644 lcm-bazel/private/lcm_info.bzl create mode 100644 lcm-bazel/private/lcm_java_library_srcs.bzl create mode 100644 lcm-bazel/private/lcm_library.bzl create mode 100644 lcm-bazel/private/lcm_py_library_srcs.bzl create mode 100644 lcm-java/BUILD.bazel create mode 100644 lcm-logger/BUILD.bazel create mode 100644 lcm-python/BUILD.bazel create mode 100644 lcm/BUILD.bazel create mode 100644 lcmgen/BUILD.bazel create mode 100644 test/BUILD.bazel create mode 100644 test/c/BUILD.bazel create mode 100644 test/cpp/BUILD.bazel create mode 100644 test/java/BUILD.bazel create mode 100644 test/python/BUILD.bazel create mode 100644 test/types/BUILD.bazel diff --git a/.bazelignore b/.bazelignore new file mode 100644 index 000000000..158ec4093 --- /dev/null +++ b/.bazelignore @@ -0,0 +1,2 @@ +# When traversing //... don't incorporate the example. +examples/bazel diff --git a/.github/workflows/test_bazel.yml b/.github/workflows/test_bazel.yml new file mode 100644 index 000000000..0ac261df5 --- /dev/null +++ b/.github/workflows/test_bazel.yml @@ -0,0 +1,25 @@ +name: test_bazel + +on: [push, pull_request] + +jobs: + bazel: + strategy: + matrix: + os: [ubuntu-24.04, macos-14] + bazel: ['8.0.1', '8.1.0'] + runs-on: ${{ matrix.os }} + env: + USE_BAZEL_VERSION: ${{ matrix.bazel }} + steps: + - uses: actions/checkout@v4 + - uses: bazel-contrib/setup-bazel@0.13.0 + with: + bazelisk-cache: true + disk-cache: ${{ github.workflow }} + repository-cache: true + - name: Test Main + run: 'bazel test //...' + - name: Test Example + working-directory: examples/bazel + run: 'bazel test //...' diff --git a/.gitignore b/.gitignore index 98ce1b229..4248218e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ build*/ __pycache__ docs/_build/ +bazel-* +MODULE.bazel.lock .vscode/ .idea/ diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 000000000..945964035 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_license//rules:license.bzl", "license") + +package( + default_applicable_licenses = [":license"], + default_visibility = ["//visibility:public"], +) + +exports_files([ + "COPYING", +]) + +license( + name = "license", + license_kinds = ["@rules_license//licenses/spdx:LGPL-2.1"], + license_text = "COPYING", +) diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 000000000..1ac2d433b --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,39 @@ +# This file specifies a Bazel workspace (see https://bazel.build/). +# +# For now, LCM's Bazel build only supports C, C++, Java, and Python. +# We invite users to submit pull requests for other languages if needed. + +module( + name = "lcm", + bazel_compatibility = [">=8.0.1"], +) + +# Load bazel rules. + +bazel_dep(name = "apple_support", version = "1.17.1", repo_name = "build_bazel_apple_support") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "rules_cc", version = "0.0.17") +bazel_dep(name = "rules_java", version = "8.6.1") +bazel_dep(name = "rules_jvm_external", version = "6.6") +bazel_dep(name = "rules_license", version = "1.0.0") +bazel_dep(name = "rules_python", version = "0.40.0") + +# Load runtime dependencies. + +bazel_dep(name = "pcre2", version = "10.45") +bazel_dep(name = "glib", version = "2.82.2.bcr.1") + +maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") +maven.install( + name = "lcm_maven", + artifacts = [ + "junit:junit:4.11", + "net.sf.jchart2d:jchart2d:3.3.2", + ], +) +use_repo(maven, "lcm_maven") + +# Load dev dependencies. + +bazel_dep(name = "googletest", version = "1.15.2", dev_dependency = True) diff --git a/docs/content/build-instructions.md b/docs/content/build-instructions.md index 076ce14a6..e8d0907c0 100644 --- a/docs/content/build-instructions.md +++ b/docs/content/build-instructions.md @@ -192,3 +192,27 @@ In addition, `pkgconfig` can be configured to find lcm.pc: ```shell export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$LCM_LIBRARY_DIR/pkgconfig ``` + +## Bazel + +LCM also supports [Bazel](https://bazel.build/) for a subset of languages +(C, C++, Java, Python). The Bazel build only provides libraries and command +line tools; it doesn't support building wheels or documentation. + +If you are already a Bazel user this is a good option, but if not you will +perhaps be happier sticking with the CMake or Meson build, explained above. + +The Bazel build uses very few system packages, so most of the text above about +required packages does not apply. The only required tool is a C/C++ compiler, +e.g., `apt install build-essential` on Ubuntu and Debian. If Java will +be used, a local JDK is also recommended, e.g., `apt install default-jdk`. +See the [example](https://github.com/lcm-proj/lcm/tree/master/examples/bazel) +for details. + +The Bazel build is not currently tested on Windows and is probably incomplete. +We welcome contributions of build fixes (for Windows or any other problems). + +To try out the Bazel build, first install +[bazelisk](https://github.com/bazelbuild/bazelisk) to provide `bazel` on your +PATH and then run, e.g., `bazel run //lcm-java:lcm-spy`. See also the +sample projct at `examples/bazel` for how to use LCM as a Bazel dependency. diff --git a/examples/.gitignore b/examples/.gitignore index bcaa26295..57a84361d 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -20,3 +20,6 @@ /cpp/lcm_log_writer/pronto/ /java/temperature_demo_java/lcmtypes/ !/go/listener/ + +# Don't ignore the bazel/exlcm source file symlinks. +!bazel/exlcm/ diff --git a/examples/bazel/.gitignore b/examples/bazel/.gitignore new file mode 100644 index 000000000..10a8b9101 --- /dev/null +++ b/examples/bazel/.gitignore @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: MIT-0 + +bazel-* +MODULE.bazel.lock diff --git a/examples/bazel/BUILD.bazel b/examples/bazel/BUILD.bazel new file mode 100644 index 000000000..974cbf7a9 --- /dev/null +++ b/examples/bazel/BUILD.bazel @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: MIT-0 +# +# Using LGPL-2.1 for examples leads to unnecessary hassle for users, so this +# example is licensed under the https://spdx.org/licenses/MIT-0.html license, +# except for the exlcm/*.lcm message definitions. + +load("@lcm//lcm-bazel:lcm_c_library_srcs.bzl", "lcm_c_library_srcs") +load("@lcm//lcm-bazel:lcm_cc_library_srcs.bzl", "lcm_cc_library_srcs") +load("@lcm//lcm-bazel:lcm_java_library_srcs.bzl", "lcm_java_library_srcs") +load("@lcm//lcm-bazel:lcm_library.bzl", "lcm_library") +load("@lcm//lcm-bazel:lcm_py_library_srcs.bzl", "lcm_py_library_srcs") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") +load("@rules_java//java:java_binary.bzl", "java_binary") +load("@rules_java//java:java_library.bzl", "java_library") +load("@rules_license//rules:license.bzl", "license") +load("@rules_python//python:py_library.bzl", "py_library") +load("@rules_python//python:py_test.bzl", "py_test") + +package( + default_applicable_licenses = [":license"], + default_visibility = ["//visibility:public"], +) + +exports_files([ + "LICENSE.TXT", +]) + +license( + name = "license", + license_kinds = ["@rules_license//licenses/spdx:MIT-0"], + license_text = "LICENSE.TXT", +) + +# Run lcm-gen on 'exlcm' for C, C++, Java, and Python. + +lcm_library( + name = "exlcm", + srcs = glob(["exlcm/*.lcm"]), + lcm_package = "exlcm", +) + +lcm_c_library_srcs( + name = "exlcm_c_srcs", + src = ":exlcm", +) + +cc_library( + name = "exlcm_c", + srcs = [":exlcm_c_srcs"], + deps = ["@lcm//lcm:lcm-static"], +) + +lcm_cc_library_srcs( + name = "exlcm_cc_srcs", + src = ":exlcm", +) + +cc_library( + name = "exlcm_cc", + srcs = [":exlcm_cc_srcs"], + deps = ["@lcm//lcm:lcm-coretypes"], +) + +lcm_java_library_srcs( + name = "exlcm_java_srcs", + src = ":exlcm", +) + +java_library( + name = "exlcm_java", + srcs = [":exlcm_java_srcs"], + deps = ["@lcm//lcm-java"], +) + +lcm_py_library_srcs( + name = "exlcm_py_srcs", + src = ":exlcm", +) + +py_library( + name = "exlcm_py", + srcs = [":exlcm_py_srcs"], + imports = ["."], +) + +# Perform some basic testing on the generated messages. + +cc_test( + name = "test_c", + srcs = ["test_c.c"], + deps = [ + ":exlcm_c", + "@lcm//lcm:lcm-static", + ], +) + +cc_test( + name = "test_cc", + srcs = ["test_cc.cc"], + deps = [ + ":exlcm_cc", + "@lcm//lcm:lcm-static", + ], +) + +py_test( + name = "test_py", + srcs = ["test_py.py"], + deps = [ + ":exlcm_py", + "@lcm//lcm-python", + ], +) + +# Create aliases for the Java tools, adding our messages to the classpath. + +java_binary( + name = "lcm-spy", + main_class = "lcm.spy.Spy", + runtime_deps = [ + ":exlcm_java", + ], +) + +java_binary( + name = "lcm-logplayer-gui", + main_class = "lcm.logging.LogPlayer", + runtime_deps = [ + ":exlcm_java", + ], +) diff --git a/examples/bazel/LICENSE.TXT b/examples/bazel/LICENSE.TXT new file mode 100644 index 000000000..d97b05508 --- /dev/null +++ b/examples/bazel/LICENSE.TXT @@ -0,0 +1,12 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/examples/bazel/MODULE.bazel b/examples/bazel/MODULE.bazel new file mode 100644 index 000000000..03cf09d89 --- /dev/null +++ b/examples/bazel/MODULE.bazel @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: MIT-0 + +bazel_dep(name = "lcm", version = "1.5.1") + +# This example uses lcm from our same git checkout. In most cases, you'll want +# to remove this override in your own projects. +local_path_override( + module_name = "lcm", + path = "../..", +) + +bazel_dep(name = "rules_cc", version = "0.0.17") +bazel_dep(name = "rules_java", version = "8.6.1") +bazel_dep(name = "rules_license", version = "1.0.0") +bazel_dep(name = "rules_python", version = "0.40.0") diff --git a/examples/bazel/exlcm/example_list_t.lcm b/examples/bazel/exlcm/example_list_t.lcm new file mode 120000 index 000000000..860639b91 --- /dev/null +++ b/examples/bazel/exlcm/example_list_t.lcm @@ -0,0 +1 @@ +../../types/example_list_t.lcm \ No newline at end of file diff --git a/examples/bazel/exlcm/example_t.lcm b/examples/bazel/exlcm/example_t.lcm new file mode 120000 index 000000000..bff5f9804 --- /dev/null +++ b/examples/bazel/exlcm/example_t.lcm @@ -0,0 +1 @@ +../../types/example_t.lcm \ No newline at end of file diff --git a/examples/bazel/exlcm/exampleconst_t.lcm b/examples/bazel/exlcm/exampleconst_t.lcm new file mode 120000 index 000000000..b291d8e39 --- /dev/null +++ b/examples/bazel/exlcm/exampleconst_t.lcm @@ -0,0 +1 @@ +../../types/exampleconst_t.lcm \ No newline at end of file diff --git a/examples/bazel/exlcm/multidim_array_t.lcm b/examples/bazel/exlcm/multidim_array_t.lcm new file mode 120000 index 000000000..7360de550 --- /dev/null +++ b/examples/bazel/exlcm/multidim_array_t.lcm @@ -0,0 +1 @@ +../../types/multidim_array_t.lcm \ No newline at end of file diff --git a/examples/bazel/exlcm/node_t.lcm b/examples/bazel/exlcm/node_t.lcm new file mode 120000 index 000000000..c7fb3f582 --- /dev/null +++ b/examples/bazel/exlcm/node_t.lcm @@ -0,0 +1 @@ +../../types/node_t.lcm \ No newline at end of file diff --git a/examples/bazel/test_c.c b/examples/bazel/test_c.c new file mode 100644 index 000000000..f94b3b378 --- /dev/null +++ b/examples/bazel/test_c.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: MIT-0 */ + +#include +#include + +#include "exlcm_example_t.h" + +int main() +{ + exlcm_example_t message = {}; + message.name = ""; + const int size = exlcm_example_t_encoded_size(&message); + if (size != 82) { + fprintf(stderr, "size = %d\n", size); + fflush(stderr); + return 1; + } + + lcm_t *memq = lcm_create("memq://"); + int handled = -1; + if (memq != NULL) { + handled = lcm_handle_timeout(memq, 0); + lcm_destroy(memq); + } + if (handled != 0) { + fprintf(stderr, "memq failure\n"); + fflush(stderr); + return 1; + } + + return 0; +} diff --git a/examples/bazel/test_cc.cc b/examples/bazel/test_cc.cc new file mode 100644 index 000000000..0edd4ca03 --- /dev/null +++ b/examples/bazel/test_cc.cc @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT-0 */ + +#include + +#include + +#include "exlcm/example_t.hpp" + +int main() { + exlcm::example_t message = {}; + const auto size = message.getEncodedSize(); + if (size != 82) { + std::cerr << "size = " << size << "\n"; + return 1; + } + + lcm::LCM memq("memq://"); + if (memq.handleTimeout(0) != 0) { + std::cerr << "memq failure\n"; + return 1; + } + + return 0; +} diff --git a/examples/bazel/test_py.py b/examples/bazel/test_py.py new file mode 100644 index 000000000..886bf7fd3 --- /dev/null +++ b/examples/bazel/test_py.py @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: MIT-0 + +import unittest + +import lcm + +from exlcm import example_t + + +class TestPy(unittest.TestCase): + def test_size(self): + message = example_t() + size = len(message.encode()) + self.assertEqual(size, 82) + + def test_memq(self): + memq = lcm.LCM("memq://") + self.assertEqual(memq.handle_timeout(0), 0) + + +def main(): + unittest.main() + + +assert __name__ == '__main__' +main() diff --git a/examples/go/gen.go b/examples/go/gen.go index 2df772aaf..0737eba1a 100644 --- a/examples/go/gen.go +++ b/examples/go/gen.go @@ -6,5 +6,5 @@ package exlcm //go:generate lcm-gen -g ../types/exampleconst_t.lcm //go:generate lcm-gen -g ../types/example_list_t.lcm //go:generate lcm-gen -g ../types/example_t.lcm -//go:generate lcm-gen -g ../types/multidim_array_t.lcm +//go:generate lcm-gen -g ../types/muldim_array_t.lcm //go:generate lcm-gen -g ../types/node_t.lcm diff --git a/examples/types/multidim_array_t.lcm b/examples/types/muldim_array_t.lcm similarity index 100% rename from examples/types/multidim_array_t.lcm rename to examples/types/muldim_array_t.lcm diff --git a/lcm-bazel/BUILD.bazel b/lcm-bazel/BUILD.bazel new file mode 100644 index 000000000..256963db7 --- /dev/null +++ b/lcm-bazel/BUILD.bazel @@ -0,0 +1,4 @@ +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) diff --git a/lcm-bazel/lcm_c_library_srcs.bzl b/lcm-bazel/lcm_c_library_srcs.bzl new file mode 100644 index 000000000..362771159 --- /dev/null +++ b/lcm-bazel/lcm_c_library_srcs.bzl @@ -0,0 +1,30 @@ +"""Rule that runs lcm-gen to convert `*.lcm` files to `*.h` and `*.c` files. +The rules only creates the files; it does not create a cc_library. + +Example use: + +lcm_library( + name = "foo_bar", + lcm_package = "foo.bar", + srcs = [ + "foo/bar/baz_t.lcm", + "foo/bar/quux_t.lcm", + ], +) + +lcm_c_library_srcs( + name = "foo_bar_c_srcs", + src = ":foo_bar", +) + +cc_library( + name = "foo_bar_c", + srcs = [":foo_bar_c_srcs"], + includes = ["."], + deps = ["@lcm//lcm:lcm-static"], +) +""" + +load("//lcm-bazel/private:lcm_c_library_srcs.bzl", _lcm_c_library_srcs = "lcm_c_library_srcs") + +lcm_c_library_srcs = _lcm_c_library_srcs diff --git a/lcm-bazel/lcm_cc_library_srcs.bzl b/lcm-bazel/lcm_cc_library_srcs.bzl new file mode 100644 index 000000000..5a7ab48bf --- /dev/null +++ b/lcm-bazel/lcm_cc_library_srcs.bzl @@ -0,0 +1,30 @@ +"""Rule that runs lcm-gen to convert `*.lcm` files to `*.hpp` files. +The rule only creates the files; it does not create a cc_library. + +Example use: + +lcm_library( + name = "foo_bar", + lcm_package = "foo.bar", + srcs = [ + "foo/bar/baz_t.lcm", + "foo/bar/quux_t.lcm", + ], +) + +lcm_cc_library_srcs( + name = "foo_bar_cc_srcs", + src = ":foo_bar", +) + +cc_library( + name = "foo_bar_cc", + srcs = [":foo_bar_cc_srcs"], + includes = ["."], + deps = ["@lcm//lcm:lcm-coretypes"], +) +""" + +load("//lcm-bazel/private:lcm_cc_library_srcs.bzl", _lcm_cc_library_srcs = "lcm_cc_library_srcs") + +lcm_cc_library_srcs = _lcm_cc_library_srcs diff --git a/lcm-bazel/lcm_info.bzl b/lcm-bazel/lcm_info.bzl new file mode 100644 index 000000000..248e66fca --- /dev/null +++ b/lcm-bazel/lcm_info.bzl @@ -0,0 +1,12 @@ +"""Provider for LCM message information. + +Fields: +- lcm_package: (string) The 'foo.bar' in `package foo.bar`. +- lcm_package_split: (list-of-string) e.g. `['foo', 'bar']` for `package foo.bar`. +- lcm_srcs: (depset) The '*.lcm' files. +- lcm_message_names: (list-of-string) The names like 'quux_t' in `struct quux_t` for all of the lcm_srcs. +""" + +load("//lcm-bazel/private:lcm_info.bzl", _LcmInfo = "LcmInfo") + +LcmInfo = _LcmInfo diff --git a/lcm-bazel/lcm_java_library_srcs.bzl b/lcm-bazel/lcm_java_library_srcs.bzl new file mode 100644 index 000000000..082ee0d17 --- /dev/null +++ b/lcm-bazel/lcm_java_library_srcs.bzl @@ -0,0 +1,29 @@ +"""Rule that runs lcm-gen to convert `*.lcm` files to `*.java` files. +The rule only creates the files; it does not create a java_library. + +Example use: + +lcm_library( + name = "foo_bar", + lcm_package = "foo.bar", + srcs = [ + "foo/bar/baz_t.lcm", + "foo/bar/quux_t.lcm", + ], +) + +lcm_java_library_srcs( + name = "foo_bar_java_srcs", + src = ":foo_bar", +) + +java_library( + name = "foo_bar_java", + srcs = [":foo_bar_java_srcs"], + deps = ["@lcm//lcm-java"], +) +""" + +load("//lcm-bazel/private:lcm_java_library_srcs.bzl", _lcm_java_library_srcs = "lcm_java_library_srcs") + +lcm_java_library_srcs = _lcm_java_library_srcs diff --git a/lcm-bazel/lcm_library.bzl b/lcm-bazel/lcm_library.bzl new file mode 100644 index 000000000..40b230e7e --- /dev/null +++ b/lcm-bazel/lcm_library.bzl @@ -0,0 +1,38 @@ +"""Rule that declares a package of `*.lcm` source files, which can then later +be used as an input to lcm-gen. + +When specifying a sources library you must list the `*.lcm` files as `srcs` and +also specify the `lcm_package` which is common to all of them. The `lcm_package` +is the string part 'YY.ZZ' of the `package YY.ZZ;` statement atop each file, +i.e., each word is separated by dots. + +Example use: + +# Declare the library of source files. +lcm_library( + name = "foo_bar", + lcm_package = "foo.bar", + srcs = [ + "foo/bar/baz_t.lcm", + "foo/bar/quux_t.lcm", + ], +) + +# Run lcm-gen to convert lcm sources files to C source files. +lcm_c_library_srcs( + name = "foo_bar_c_srcs", + src = ":foo_bar", +) + +# Compile the C source files into a library. +cc_library( + name = "foo_bar_c", + srcs = [":foo_bar_c_srcs"], + # Depend on the LCM library to provide `#include ` etc. + deps = ["@lcm//lcm:lcm-static"], +) +""" + +load("//lcm-bazel/private:lcm_library.bzl", _lcm_library = "lcm_library") + +lcm_library = _lcm_library diff --git a/lcm-bazel/lcm_py_library_srcs.bzl b/lcm-bazel/lcm_py_library_srcs.bzl new file mode 100644 index 000000000..27790d02e --- /dev/null +++ b/lcm-bazel/lcm_py_library_srcs.bzl @@ -0,0 +1,29 @@ +"""Rule that runs lcm-gen to convert `*.lcm` files to `*.py` files. +The rule only creates the files; it does not create a py_library. + +Example use: + +lcm_library( + name = "foo_bar", + lcm_package = "foo.bar", + srcs = [ + "foo/bar/baz_t.lcm", + "foo/bar/quux_t.lcm", + ], +) + +lcm_py_library_srcs( + name = "foo_bar_py_srcs", + src = ":foo_bar", +) + +py_library( + name = "foo_bar_py", + srcs = [":foo_bar_py_srcs"], + imports = ["."], +) +""" + +load("//lcm-bazel/private:lcm_py_library_srcs.bzl", _lcm_py_library_srcs = "lcm_py_library_srcs") + +lcm_py_library_srcs = _lcm_py_library_srcs diff --git a/lcm-bazel/private/BUILD.bazel b/lcm-bazel/private/BUILD.bazel new file mode 100644 index 000000000..256963db7 --- /dev/null +++ b/lcm-bazel/private/BUILD.bazel @@ -0,0 +1,4 @@ +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) diff --git a/lcm-bazel/private/copts.bzl b/lcm-bazel/private/copts.bzl new file mode 100644 index 000000000..99cbbc354 --- /dev/null +++ b/lcm-bazel/private/copts.bzl @@ -0,0 +1,10 @@ +# Match the default warning suppressions from lcm-cmake/config.cmake. + +WARNINGS_COPTS = select({ + "//lcm:windows": [], + "//conditions:default": [ + "-Wno-unused-parameter", + "-Wno-format-zero-length", + "-Wno-stringop-truncation", + ], +}) diff --git a/lcm-bazel/private/lcm_c_library_srcs.bzl b/lcm-bazel/private/lcm_c_library_srcs.bzl new file mode 100644 index 000000000..1ccd2bd09 --- /dev/null +++ b/lcm-bazel/private/lcm_c_library_srcs.bzl @@ -0,0 +1,53 @@ +# For documentation, refer to the public alias in our parent directory. + +load(":lcm_info.bzl", "LcmInfo") + +def _impl(ctx): + info = ctx.attr.src[LcmInfo] + + # Declare the output files. + output_files = [ + ctx.actions.declare_file("_".join(info.lcm_package_split + [x + ".c"])) + for x in info.lcm_message_names + ] + [ + ctx.actions.declare_file("_".join(info.lcm_package_split + [x + ".h"])) + for x in info.lcm_message_names + ] + + # Choose the base dir to output into. + output_dir = output_files[0].dirname + "/" + arguments = [ + "--c", + "--c-cpath=" + output_dir, + "--c-hpath=" + output_dir, + ] + + # Run lcm-gen. + ctx.actions.run( + inputs = info.lcm_srcs, + outputs = output_files, + arguments = arguments + [ + lcm_src.path + for lcm_src in info.lcm_srcs.to_list() + ], + executable = ctx.executable.lcmgen, + ) + + # Return the '*.c' and '*.h' files. + return [ + DefaultInfo(files = depset(output_files)), + ] + +lcm_c_library_srcs = rule( + implementation = _impl, + attrs = { + "src": attr.label( + providers = [LcmInfo], + ), + "lcmgen": attr.label( + cfg = "host", + executable = True, + default = Label("//lcmgen:lcm-gen"), + ), + }, +) diff --git a/lcm-bazel/private/lcm_cc_library_srcs.bzl b/lcm-bazel/private/lcm_cc_library_srcs.bzl new file mode 100644 index 000000000..565f749a3 --- /dev/null +++ b/lcm-bazel/private/lcm_cc_library_srcs.bzl @@ -0,0 +1,51 @@ +# For documentation, refer to the public alias in our parent directory. + +load(":lcm_info.bzl", "LcmInfo") + +def _impl(ctx): + info = ctx.attr.src[LcmInfo] + + # Declare the output files. + output_files = [ + ctx.actions.declare_file("/".join(info.lcm_package_split + [x + ".hpp"])) + for x in info.lcm_message_names + ] + + # Choose the base dir to output into. + output_dir = output_files[0].dirname + "/" + for _ in info.lcm_package_split: + output_dir = output_dir + "../" + arguments = [ + "--cpp", + "--cpp-hpath=" + output_dir, + ] + + # Run lcm-gen. + ctx.actions.run( + inputs = info.lcm_srcs, + outputs = output_files, + arguments = arguments + [ + lcm_src.path + for lcm_src in info.lcm_srcs.to_list() + ], + executable = ctx.executable.lcmgen, + ) + + # Return the '*.hpp' files. + return [ + DefaultInfo(files = depset(output_files)), + ] + +lcm_cc_library_srcs = rule( + implementation = _impl, + attrs = { + "src": attr.label( + providers = [LcmInfo], + ), + "lcmgen": attr.label( + cfg = "host", + executable = True, + default = Label("//lcmgen:lcm-gen"), + ), + }, +) diff --git a/lcm-bazel/private/lcm_info.bzl b/lcm-bazel/private/lcm_info.bzl new file mode 100644 index 000000000..d7a4fde9a --- /dev/null +++ b/lcm-bazel/private/lcm_info.bzl @@ -0,0 +1,10 @@ +# For documentation, refer to the public alias in our parent directory. + +LcmInfo = provider( + fields = [ + "lcm_package", + "lcm_package_split", + "lcm_srcs", + "lcm_message_names", + ], +) diff --git a/lcm-bazel/private/lcm_java_library_srcs.bzl b/lcm-bazel/private/lcm_java_library_srcs.bzl new file mode 100644 index 000000000..6381bb513 --- /dev/null +++ b/lcm-bazel/private/lcm_java_library_srcs.bzl @@ -0,0 +1,51 @@ +# For documentation, refer to the public alias in our parent directory. + +load(":lcm_info.bzl", "LcmInfo") + +def _impl(ctx): + info = ctx.attr.src[LcmInfo] + + # Declare the output files. + output_files = [ + ctx.actions.declare_file("/".join(info.lcm_package_split + [x + ".java"])) + for x in info.lcm_message_names + ] + + # Choose the base dir to output into. + output_dir = output_files[0].dirname + "/" + for _ in info.lcm_package_split: + output_dir = output_dir + "../" + arguments = [ + "--java", + "--jpath=" + output_dir, + ] + + # Run lcm-gen. + ctx.actions.run( + inputs = info.lcm_srcs, + outputs = output_files, + arguments = arguments + [ + lcm_src.path + for lcm_src in info.lcm_srcs.to_list() + ], + executable = ctx.executable.lcmgen, + ) + + # Return the '*.java' files. + return [ + DefaultInfo(files = depset(output_files)), + ] + +lcm_java_library_srcs = rule( + implementation = _impl, + attrs = { + "src": attr.label( + providers = [LcmInfo], + ), + "lcmgen": attr.label( + cfg = "host", + executable = True, + default = Label("//lcmgen:lcm-gen"), + ), + }, +) diff --git a/lcm-bazel/private/lcm_library.bzl b/lcm-bazel/private/lcm_library.bzl new file mode 100644 index 000000000..d43477a0f --- /dev/null +++ b/lcm-bazel/private/lcm_library.bzl @@ -0,0 +1,42 @@ +# For documentation, refer to the public alias in our parent directory. + +load(":lcm_info.bzl", "LcmInfo") + +def _impl(ctx): + lcm_package = ctx.attr.lcm_package + if not lcm_package: + lcm_package_split = [] + else: + lcm_package_split = lcm_package.split(".") + lcm_srcs = depset(ctx.files.srcs) + lcm_message_names = [] + for lcm_src in ctx.files.srcs: + lcm_message_names.append(lcm_src.basename[:-len(".lcm")]) + return [ + DefaultInfo(files = lcm_srcs), + LcmInfo( + lcm_package = lcm_package, + lcm_package_split = lcm_package_split, + lcm_srcs = lcm_srcs, + lcm_message_names = lcm_message_names, + ), + ] + +lcm_library = rule( + implementation = _impl, + provides = [LcmInfo], + attrs = { + "lcm_package": attr.string( + mandatory = True, + ), + "srcs": attr.label_list( + allow_files = [".lcm"], + mandatory = True, + ), + # TODO(jwnimmer-tri) This isn't actually used for anything yet ... + # still, it seems worthwhile to let people write it down. + "deps": attr.label_list( + providers = [LcmInfo], + ), + }, +) diff --git a/lcm-bazel/private/lcm_py_library_srcs.bzl b/lcm-bazel/private/lcm_py_library_srcs.bzl new file mode 100644 index 000000000..03e26a7b1 --- /dev/null +++ b/lcm-bazel/private/lcm_py_library_srcs.bzl @@ -0,0 +1,53 @@ +# For documentation, refer to the public alias in our parent directory. + +load(":lcm_info.bzl", "LcmInfo") + +def _impl(ctx): + info = ctx.attr.src[LcmInfo] + + # Declare the output files. + output_files = [ + ctx.actions.declare_file("/".join(info.lcm_package_split + ["__init__.py"])), + ] + [ + ctx.actions.declare_file("/".join(info.lcm_package_split + [x + ".py"])) + for x in info.lcm_message_names + ] + + # Choose the base dir to output into. + output_dir = output_files[0].dirname + "/" + for _ in info.lcm_package_split: + output_dir = output_dir + "../" + arguments = [ + "--python", + "--ppath=" + output_dir, + ] + + # Run lcm-gen. + ctx.actions.run( + inputs = info.lcm_srcs, + outputs = output_files, + arguments = arguments + [ + lcm_src.path + for lcm_src in info.lcm_srcs.to_list() + ], + executable = ctx.executable.lcmgen, + ) + + # Return the '*.py' files. + return [ + DefaultInfo(files = depset(output_files)), + ] + +lcm_py_library_srcs = rule( + implementation = _impl, + attrs = { + "src": attr.label( + providers = [LcmInfo], + ), + "lcmgen": attr.label( + cfg = "host", + executable = True, + default = Label("//lcmgen:lcm-gen"), + ), + }, +) diff --git a/lcm-java/BUILD.bazel b/lcm-java/BUILD.bazel new file mode 100644 index 000000000..e9363203a --- /dev/null +++ b/lcm-java/BUILD.bazel @@ -0,0 +1,67 @@ +load("@rules_java//java:java_binary.bzl", "java_binary") +load("@rules_java//java:java_library.bzl", "java_library") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +java_library( + name = "lcm-java", + srcs = [ + "lcm/lcm/LCM.java", + "lcm/lcm/LCMDataInputStream.java", + "lcm/lcm/LCMDataOutputStream.java", + "lcm/lcm/LCMEncodable.java", + "lcm/lcm/LCMSubscriber.java", + "lcm/lcm/LogFileProvider.java", + "lcm/lcm/MemqProvider.java", + "lcm/lcm/MessageAggregator.java", + "lcm/lcm/Provider.java", + "lcm/lcm/TCPProvider.java", + "lcm/lcm/TCPService.java", + "lcm/lcm/UDPMulticastProvider.java", + "lcm/lcm/URLParser.java", + "lcm/logging/JScrubber.java", + "lcm/logging/JScrubberListener.java", + "lcm/logging/Log.java", + "lcm/logging/LogDiagnostic.java", + "lcm/logging/LogPlayer.java", + "lcm/spy/ChannelData.java", + "lcm/spy/ChartData.java", + "lcm/spy/LCMTypeDatabase.java", + "lcm/spy/ObjectPanel.java", + "lcm/spy/Spy.java", + "lcm/spy/SpyPlugin.java", + "lcm/spy/ZoomableChartScrollWheel.java", + "lcm/util/BufferedRandomAccessFile.java", + "lcm/util/ClassDiscoverer.java", + "lcm/util/ColorMapper.java", + "lcm/util/JImage.java", + "lcm/util/ParameterGUI.java", + "lcm/util/ParameterListener.java", + "lcm/util/TableSorter.java", + ], + javacopts = [ + # Suppressed until lcm-proj/lcm#159 is fixed. + "-XepDisableAllChecks", + ], + visibility = ["//visibility:public"], + deps = [ + "@lcm_maven//:net_sf_jchart2d_jchart2d", + ], +) + +java_binary( + name = "lcm-spy", + main_class = "lcm.spy.Spy", + visibility = ["//visibility:public"], + runtime_deps = [":lcm-java"], +) + +java_binary( + name = "lcm-logplayer-gui", + main_class = "lcm.logging.LogPlayer", + visibility = ["//visibility:public"], + runtime_deps = [":lcm-java"], +) diff --git a/lcm-logger/BUILD.bazel b/lcm-logger/BUILD.bazel new file mode 100644 index 000000000..dfdf23530 --- /dev/null +++ b/lcm-logger/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +cc_binary( + name = "lcm-logger", + srcs = [ + "glib_util.c", + "glib_util.h", + "lcm_logger.c", + ], + visibility = ["//visibility:public"], + deps = [ + "//lcm:lcm-static", + ], +) + +cc_binary( + name = "lcm-logplayer", + srcs = [ + "lcm_logplayer.c", + ], + visibility = ["//visibility:public"], + deps = [ + "//lcm:lcm-static", + ], +) diff --git a/lcm-python/BUILD.bazel b/lcm-python/BUILD.bazel new file mode 100644 index 000000000..be3f0f96c --- /dev/null +++ b/lcm-python/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_python//python:py_library.bzl", "py_library") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +cc_binary( + name = "lcm/_lcm.so", + srcs = [ + "module.c", + "pyeventlog.c", + "pylcm.c", + "pylcm.h", + "pylcm_subscription.c", + "pylcm_subscription.h", + ], + linkshared = True, + visibility = ["//visibility:private"], + deps = [ + "//lcm:lcm-shared", + "@rules_python//python/cc:current_py_cc_headers", + "@rules_python//python/cc:current_py_cc_libs", + ], +) + +py_library( + name = "lcm-python", + srcs = ["lcm/__init__.py"], + data = [":lcm/_lcm.so"], + imports = ["."], + visibility = ["//visibility:public"], +) diff --git a/lcm/BUILD.bazel b/lcm/BUILD.bazel new file mode 100644 index 000000000..17047845f --- /dev/null +++ b/lcm/BUILD.bazel @@ -0,0 +1,182 @@ +load("@bazel_skylib//lib:paths.bzl", "paths") +load("@bazel_skylib//rules:copy_file.bzl", "copy_file") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_shared_library.bzl", "cc_shared_library") +load("//lcm-bazel/private:copts.bzl", "WARNINGS_COPTS") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +# The following constants are congruent with the CMakeLists.txt. + +LCM_SOURCES = [ + "eventlog.c", + "lcm.c", + "lcm_file.c", + "lcm_memq.c", + "lcm_mpudpm.c", + "lcm_tcpq.c", + "lcm_udpm.c", + "ringbuffer.c", + "udpm_util.c", + "lcmtypes/channel_port_map_update_t.c", + "lcmtypes/channel_to_port_t.c", +] + +LCM_INSTALL_HEADERS = [ + "eventlog.h", + "lcm.h", + "lcm_coretypes.h", + "lcm_version.h", + "lcm-cpp.hpp", + "lcm-cpp-impl.hpp", + "lcm_export.h", +] + +LCM_SOURCES_WIN32 = [ + "windows/WinLCM.cpp", + "windows/WinPorting.cpp", +] + +LCM_INSTALL_HEADERS_WIN32 = [ + "windows/WinPorting.h", +] + +LCM_LINKOPTS_WIN32 = [ + # TODO(jwnimmer-tri) Not sure yet how to do this in Bazel. + # target_link_libraries(${lcm_lib} PRIVATE wsock32 ws2_32) +] + +LCM_LINKOPTS_LINUX = [ + "-pthread", +] + +LCM_COMPILE_DEFINITIONS_PRIVATE = [ + "_FILE_OFFSET_BITS=64", + "_LARGEFILE_SOURCE", + "_REENTRANT", +] + +# Declare the libraries. + +LCM_PRIVATE_HEADERS = [ + "dbg.h", + "ioutils.h", + "lcm_internal.h", + "ringbuffer.h", + "udpm_util.h", + "lcmtypes/channel_port_map_update_t.h", + "lcmtypes/channel_to_port_t.h", +] + +[ + # To obtain the correct include paths ``, we need to copy public + # headers to a subdir now and then set `strip_include_prefix` later. + copy_file( + name = "_add_hdrs_" + paths.basename(x), + src = x, + out = "hdrs/lcm/" + x, + ) + for x in LCM_INSTALL_HEADERS + LCM_INSTALL_HEADERS_WIN32 +] + +cc_library( + name = "lcm-coretypes", + hdrs = ["hdrs/lcm/lcm_coretypes.h"], + strip_include_prefix = "/lcm/hdrs", + visibility = ["//visibility:public"], +) + +cc_library( + name = "lcm-version", + hdrs = ["hdrs/lcm/lcm_version.h"], + strip_include_prefix = "/lcm/hdrs", + visibility = ["//lcmgen:__pkg__"], +) + +config_setting( + name = "linux", + constraint_values = ["@platforms//os:linux"], +) + +config_setting( + name = "windows", + constraint_values = ["@platforms//os:windows"], +) + +SRCS = LCM_SOURCES + LCM_PRIVATE_HEADERS + select({ + ":windows": LCM_SOURCES_WIN32, + "//conditions:default": [], +}) + +HDRS = LCM_INSTALL_HEADERS + select({ + ":windows": LCM_INSTALL_HEADERS_WIN32, + "//conditions:default": [], +}) + +cc_library( + name = "_public_hdrs", + hdrs = [ + "hdrs/lcm/" + x + for x in LCM_INSTALL_HEADERS + ] + select({ + ":windows": [ + "hdrs/lcm/" + x + for x in LCM_INSTALL_HEADERS_WIN32 + ], + "//conditions:default": [], + }), + strip_include_prefix = "/lcm/hdrs", +) + +COPTS = [ + "-D" + x + for x in LCM_COMPILE_DEFINITIONS_PRIVATE +] + WARNINGS_COPTS + +LINKOPTS = select({ + ":linux": LCM_LINKOPTS_LINUX, + "//conditions:default": [], +}) + +DEPS = [ + ":_public_hdrs", + "@glib//glib", +] + +cc_library( + name = "lcm-shared", + srcs = SRCS, + hdrs = HDRS, + copts = COPTS, + linkopts = LINKOPTS, + visibility = ["//visibility:public"], + deps = DEPS, +) + +cc_library( + name = "lcm-static", + srcs = SRCS, + hdrs = HDRS, + copts = COPTS, + defines = ["LCM_STATIC"], + linkopts = LINKOPTS, + linkstatic = True, + visibility = ["//visibility:public"], + deps = DEPS, +) + +cc_shared_library( + name = "glib-2.0", + visibility = ["//visibility:public"], + deps = DEPS, +) + +cc_shared_library( + name = "lcm", + dynamic_deps = [":glib-2.0"], + visibility = ["//visibility:public"], + deps = ["lcm-shared"], +) diff --git a/lcmgen/BUILD.bazel b/lcmgen/BUILD.bazel new file mode 100644 index 000000000..300917240 --- /dev/null +++ b/lcmgen/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("//lcm-bazel/private:copts.bzl", "WARNINGS_COPTS") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +cc_binary( + name = "lcm-gen", + srcs = [ + "emit_c.c", + "emit_cpp.c", + "emit_csharp.c", + "emit_go.c", + "emit_java.c", + "emit_lua.c", + "emit_python.c", + "getopt.c", + "getopt.h", + "lcmgen.c", + "lcmgen.h", + "main.c", + "tokenize.c", + "tokenize.h", + ], + copts = WARNINGS_COPTS, + visibility = ["//visibility:public"], + deps = [ + "//lcm:lcm-version", + "@glib//glib", + ], +) diff --git a/lcmgen/main.c b/lcmgen/main.c index 041694493..b8df29a7d 100644 --- a/lcmgen/main.c +++ b/lcmgen/main.c @@ -7,12 +7,12 @@ #endif #include #include +#include #include #include #include #include -#include "../lcm/lcm_version.h" #include "getopt.h" #include "lcmgen.h" #include "tokenize.h" diff --git a/test/BUILD.bazel b/test/BUILD.bazel new file mode 100644 index 000000000..1c93be17a --- /dev/null +++ b/test/BUILD.bazel @@ -0,0 +1,9 @@ +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +exports_files( + ["run_client_server_test.py"], + visibility = ["//test:__subpackages__"], +) diff --git a/test/c/BUILD.bazel b/test/c/BUILD.bazel new file mode 100644 index 000000000..df001198d --- /dev/null +++ b/test/c/BUILD.bazel @@ -0,0 +1,125 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") +load("@rules_python//python:py_test.bzl", "py_test") +load("//lcm-bazel:lcm_c_library_srcs.bzl", "lcm_c_library_srcs") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +lcm_c_library_srcs( + name = "lcmtest", + testonly = True, + src = "//test/types:lcmtest", +) + +lcm_c_library_srcs( + name = "lcmtest2", + testonly = True, + src = "//test/types:lcmtest2", +) + +lcm_c_library_srcs( + name = "lcmtest3", + testonly = True, + src = "//test/types:lcmtest3", +) + +cc_library( + name = "messages", + testonly = True, + srcs = [ + ":lcmtest", + ":lcmtest2", + ":lcmtest3", + ], + includes = ["."], + deps = [ + "//lcm:lcm-static", + ], +) + +TEST_C_LIBS = [ + ":messages", + "//lcm:lcm-static", + "@googletest//:gtest", + "@googletest//:gtest_main", +] + +cc_test( + name = "memq_test", + srcs = [ + "common.c", + "common.h", + "memq_test.cpp", + ], + deps = TEST_C_LIBS, +) + +cc_test( + name = "eventlog_test", + srcs = [ + "common.c", + "common.h", + "eventlog_test.cpp", + ], + deps = TEST_C_LIBS, +) + +cc_test( + name = "udpm_test", + srcs = [ + "common.c", + "common.h", + "udpm_test.cpp", + ], + deps = TEST_C_LIBS, +) + +cc_binary( + name = "server", + testonly = True, + srcs = [ + "common.c", + "common.h", + "server.c", + ], + linkstatic = True, + visibility = ["//test:__subpackages__"], + deps = [ + ":messages", + "//lcm:lcm-static", + ], +) + +cc_binary( + name = "client", + testonly = True, + srcs = [ + "client.cpp", + "common.c", + "common.h", + ], + deps = TEST_C_LIBS, +) + +py_test( + name = "client_server_test", + srcs = ["//test:run_client_server_test.py"], + args = [ + "$(rootpath :server)", + "$(rootpath :client)", + ], + data = [ + ":client", + ":server", + ], + env = { + # Use a different port number for each language to avoid conflicts. + "LCM_DEFAULT_URL": "udpm://239.255.76.67:7601?ttl=0", + }, + flaky = True, + main = "//test:run_client_server_test.py", +) diff --git a/test/cpp/BUILD.bazel b/test/cpp/BUILD.bazel new file mode 100644 index 000000000..24f75f3a5 --- /dev/null +++ b/test/cpp/BUILD.bazel @@ -0,0 +1,89 @@ +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") +load("@rules_python//python:py_test.bzl", "py_test") +load("//lcm-bazel:lcm_cc_library_srcs.bzl", "lcm_cc_library_srcs") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +lcm_cc_library_srcs( + name = "lcmtest", + testonly = True, + src = "//test/types:lcmtest", +) + +lcm_cc_library_srcs( + name = "lcmtest2", + testonly = True, + src = "//test/types:lcmtest2", +) + +lcm_cc_library_srcs( + name = "lcmtest3", + testonly = True, + src = "//test/types:lcmtest3", +) + +cc_library( + name = "messages", + testonly = True, + srcs = [ + ":lcmtest", + ":lcmtest2", + ":lcmtest3", + ], + includes = ["."], + deps = [ + "//lcm:lcm-coretypes", + ], +) + +TEST_CPP_LIBS = [ + ":messages", + "//lcm:lcm-static", + "@googletest//:gtest", + "@googletest//:gtest_main", +] + +cc_test( + name = "memq_test", + srcs = [ + "common.cpp", + "common.hpp", + "memq_test.cpp", + ], + deps = TEST_CPP_LIBS, +) + +cc_binary( + name = "client", + testonly = True, + srcs = [ + "client.cpp", + "common.cpp", + "common.hpp", + ], + deps = TEST_CPP_LIBS, +) + +py_test( + name = "client_server_test", + srcs = ["//test:run_client_server_test.py"], + args = [ + "$(rootpath //test/c:server)", + "$(rootpath :client)", + ], + data = [ + ":client", + "//test/c:server", + ], + env = { + # Use a different port number for each language to avoid conflicts. + "LCM_DEFAULT_URL": "udpm://239.255.76.67:7602?ttl=0", + }, + flaky = True, + main = "//test:run_client_server_test.py", +) diff --git a/test/java/BUILD.bazel b/test/java/BUILD.bazel new file mode 100644 index 000000000..71e015cd3 --- /dev/null +++ b/test/java/BUILD.bazel @@ -0,0 +1,84 @@ +load("@rules_java//java:java_binary.bzl", "java_binary") +load("@rules_java//java:java_library.bzl", "java_library") +load("@rules_java//java:java_test.bzl", "java_test") +load("@rules_python//python:py_test.bzl", "py_test") +load("//lcm-bazel:lcm_java_library_srcs.bzl", "lcm_java_library_srcs") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +lcm_java_library_srcs( + name = "lcmtest", + testonly = True, + src = "//test/types:lcmtest", +) + +lcm_java_library_srcs( + name = "lcmtest2", + testonly = True, + src = "//test/types:lcmtest2", +) + +lcm_java_library_srcs( + name = "lcmtest3", + testonly = True, + src = "//test/types:lcmtest3", +) + +java_library( + name = "messages", + testonly = True, + srcs = [ + ":lcmtest", + ":lcmtest2", + ":lcmtest3", + ], + deps = [ + "//lcm-java", + ], +) + +java_test( + name = "junit", + srcs = [ + "lcmtest/TestUDPMulticastProvider.java", + ], + test_class = "TestUDPMulticastProvider", + deps = [ + ":messages", + "//lcm-java", + "@lcm_maven//:junit_junit", + ], +) + +java_binary( + name = "client", + testonly = True, + srcs = ["lcmtest/LcmTestClient.java"], + main_class = "LcmTestClient", + deps = [ + ":messages", + "//lcm-java", + ], +) + +py_test( + name = "client_server_test", + srcs = ["//test:run_client_server_test.py"], + args = [ + "$(rootpath //test/c:server)", + "$(rootpath :client)", + ], + data = [ + ":client", + "//test/c:server", + ], + env = { + # Use a different port number for each language to avoid conflicts. + "LCM_DEFAULT_URL": "udpm://239.255.76.67:7604?ttl=0", + }, + flaky = True, + main = "//test:run_client_server_test.py", +) diff --git a/test/python/BUILD.bazel b/test/python/BUILD.bazel new file mode 100644 index 000000000..bfb6cc5f3 --- /dev/null +++ b/test/python/BUILD.bazel @@ -0,0 +1,134 @@ +load("@rules_python//python:py_binary.bzl", "py_binary") +load("@rules_python//python:py_library.bzl", "py_library") +load("@rules_python//python:py_test.bzl", "py_test") +load("//lcm-bazel:lcm_py_library_srcs.bzl", "lcm_py_library_srcs") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +lcm_py_library_srcs( + name = "lcmtest", + testonly = True, + src = "//test/types:lcmtest", +) + +lcm_py_library_srcs( + name = "lcmtest2", + testonly = True, + src = "//test/types:lcmtest2", +) + +lcm_py_library_srcs( + name = "lcmtest3", + testonly = True, + src = "//test/types:lcmtest3", +) + +py_library( + name = "messages", + testonly = True, + srcs = [ + ":lcmtest", + ":lcmtest2", + ":lcmtest3", + ], + imports = ["."], +) + +py_test( + name = "bool_test", + srcs = ["bool_test.py"], + deps = [ + ":messages", + ], +) + +py_test( + name = "byte_array_test", + srcs = ["byte_array_test.py"], + deps = [ + ":messages", + ], +) + +py_test( + name = "lcm_file_test", + srcs = [ + "client.py", + "lcm_file_test.py", + ], + deps = [ + ":messages", + "//lcm-python", + ], +) + +py_test( + name = "lcm_memq_test", + srcs = ["lcm_memq_test.py"], + deps = [ + ":messages", + "//lcm-python", + ], +) + +py_test( + name = "lcm_thread_test", + srcs = ["lcm_thread_test.py"], + deps = [ + ":messages", + "//lcm-python", + ], +) + +py_test( + name = "lcm_udpm_queue_issue_test", + srcs = ["lcm_udpm_queue_issue_test.py"], + deps = [ + ":messages", + "//lcm-python", + ], +) + +py_test( + name = "lcm_eventlog", + srcs = ["lcm_eventlog.py"], + data = [ + "example.lcmlog", + ], + deps = [ + ":messages", + "//lcm-python", + ], +) + +py_binary( + name = "client", + testonly = True, + srcs = ["client.py"], + deps = [ + ":messages", + "//lcm-python", + ], +) + +py_test( + name = "client_server_test", + srcs = ["//test:run_client_server_test.py"], + args = [ + "$(rootpath //test/c:server)", + "$(rootpath :client)", + ], + data = [ + ":client", + "//test/c:server", + ], + env = { + # Use a different port number for each language to avoid conflicts. + "LCM_DEFAULT_URL": "udpm://239.255.76.67:7606?ttl=0", + }, + flaky = True, + main = "//test:run_client_server_test.py", +) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 3f8a21860..d7061eebd 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -12,8 +12,6 @@ function(add_python_test NAME SCRIPT) ${Python_EXECUTABLE} ${SCRIPT} ${ARGN}) endfunction() -file(COPY example.lcmlog DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - add_python_test(Python::bool_test bool_test.py) add_python_test(Python::byte_array_test byte_array_test.py) add_python_test(Python::lcm_file_test lcm_file_test.py) diff --git a/test/python/lcm_eventlog.py b/test/python/lcm_eventlog.py index 5aa66017e..3c0189d40 100644 --- a/test/python/lcm_eventlog.py +++ b/test/python/lcm_eventlog.py @@ -7,7 +7,8 @@ class TestLcmEventLog(unittest.TestCase): def test_read_eventlog(self): - log = lcm.EventLog('example.lcmlog') + mydir = os.path.dirname(__file__) + log = lcm.EventLog(os.path.join(mydir, 'example.lcmlog')) event = log.read_next_event() def main(): diff --git a/test/types/BUILD.bazel b/test/types/BUILD.bazel new file mode 100644 index 000000000..ae6ac1962 --- /dev/null +++ b/test/types/BUILD.bazel @@ -0,0 +1,45 @@ +load("//lcm-bazel:lcm_library.bzl", "lcm_library") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:private"], +) + +lcm_library( + name = "lcmtest", + testonly = True, + srcs = [ + "lcmtest/bools_t.lcm", + "lcmtest/byte_array_t.lcm", + "lcmtest/comments_t.lcm", + "lcmtest/exampleconst_t.lcm", + "lcmtest/multidim_array_t.lcm", + "lcmtest/node_t.lcm", + "lcmtest/primitives_list_t.lcm", + "lcmtest/primitives_t.lcm", + ], + lcm_package = "lcmtest", + visibility = ["//test:__subpackages__"], +) + +lcm_library( + name = "lcmtest2", + testonly = True, + srcs = [ + "lcmtest2/another_type_t.lcm", + "lcmtest2/cross_package_t.lcm", + ], + lcm_package = "lcmtest2", + visibility = ["//test:__subpackages__"], + deps = [":lcmtest"], +) + +lcm_library( + name = "lcmtest3", + testonly = True, + srcs = [ + "lcmtest3/arrays_t.lcm", + ], + lcm_package = "lcmtest3", + visibility = ["//test:__subpackages__"], +)