Skip to content

Commit 1a4ab65

Browse files
committed
engine: Make server an optional component
1 parent ac3a7fc commit 1a4ab65

File tree

7 files changed

+215
-19
lines changed

7 files changed

+215
-19
lines changed

Makefile.all

+11
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ CONAN_OPTIONS :=
8787
WITH_ENGINE := 1
8888
$(call assert_numeric_bool, WITH_ENGINE)
8989

90+
## WITH_SERVER
91+
## Usage: make WITH_SERVER=0 <targets>
92+
## Default: 1
93+
##
94+
WITH_SERVER := 1
95+
9096
## WITH_VTD
9197
## Usage: make WITH_VTD=1 <targets>
9298
## Default: 0
@@ -152,6 +158,11 @@ ALL_PKGS := $(filter-out engine, ${ALL_PKGS})
152158
override CONAN_OPTIONS += -o cloe:with_engine=False
153159
endif
154160

161+
ifeq (${WITH_SERVER},0)
162+
ALL_PKGS := $(filter-out oak, ${ALL_PKGS})
163+
override CONAN_OPTIONS += -o cloe-engine:server=False
164+
endif
165+
155166
ifeq (${WITH_VTD},1)
156167
override CONAN_OPTIONS += -o cloe:with_vtd=True
157168
else

conantest.py

+3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ class CloeTest(ConanFile):
77
settings = "os", "compiler", "build_type", "arch"
88
options = {
99
"with_vtd": [True, False],
10+
"with_server": [True, False],
1011
}
1112
default_options = {
1213
"with_vtd": False,
14+
"with_server": True,
1315
}
1416
no_copy_source = True
1517

@@ -29,3 +31,4 @@ def requirements(self):
2931

3032
def configure(self):
3133
self.options["cloe"].with_vtd = self.options.with_vtd
34+
self.options["cloe"].with_server = self.options.with_server

engine/CMakeLists.txt

+31-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(output cloe-engine)
77
set(libstack cloe-stack)
88

99
option(BuildTests "Build tests?" ON)
10+
option(WithServer "Enable integrated server component?" ON)
1011

1112
# Conan / Editor -----------------------------------------------------
1213
include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake)
@@ -69,7 +70,6 @@ add_executable(${target}
6970
src/coordinator.cpp
7071
src/plugins/nop_controller.cpp
7172
src/plugins/nop_simulator.cpp
72-
src/server.cpp
7373
src/simulation.cpp
7474
src/simulation_context.cpp
7575
src/utility/command.cpp
@@ -80,9 +80,10 @@ set_target_properties(${target} PROPERTIES
8080
OUTPUT_NAME ${output}
8181
)
8282
target_compile_definitions(${target}
83-
PRIVATE
84-
CLOE_ENGINE_VERSION="${CLOE_ENGINE_VERSION}"
85-
CLOE_ENGINE_TIMESTAMP="${CLOE_ENGINE_TIMESTAMP}"
83+
PRIVATE
84+
CLOE_ENGINE_VERSION="${CLOE_ENGINE_VERSION}"
85+
CLOE_ENGINE_TIMESTAMP="${CLOE_ENGINE_TIMESTAMP}"
86+
PROJECT_SOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"
8687
)
8788
set_target_linting(${target})
8889
target_include_directories(${target}
@@ -92,14 +93,35 @@ target_include_directories(${target}
9293
target_link_libraries(${target}
9394
PRIVATE
9495
CONAN_PKG::cli11
95-
CONAN_PKG::cloe-oak
9696
CONAN_PKG::cloe-models
9797
${libstack}
9898
)
99-
target_compile_definitions(${target}
100-
PRIVATE
101-
PROJECT_SOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"
102-
)
99+
100+
if(${WithServer})
101+
message(STATUS "-> Enable server component")
102+
target_sources(${target}
103+
PRIVATE
104+
src/server.cpp
105+
)
106+
target_link_libraries(${target}
107+
PRIVATE
108+
CONAN_PKG::cloe-oak
109+
)
110+
target_compile_definitions(${target}
111+
PRIVATE
112+
CLOE_ENGINE_WITH_SERVER=1
113+
)
114+
else()
115+
message(STATUS "-> Disable server component")
116+
target_sources(${target}
117+
PRIVATE
118+
src/server_mock.cpp
119+
)
120+
target_compile_definitions(${target}
121+
PRIVATE
122+
CLOE_ENGINE_WITH_SERVER=0
123+
)
124+
endif()
103125

104126
# Installation -------------------------------------------------------
105127
include(GNUInstallDirs)

engine/conanfile.py

+22-6
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,25 @@ class CloeEngine(ConanFile):
1010
description = "Cloe engine to execute simulations"
1111
settings = "os", "compiler", "build_type", "arch"
1212
options = {
13+
# Whether the server feature is compiled and built into the Cloe engine.
14+
# Not building this may make compiling the engine possible if the web
15+
# server dependencies are incompatible with your target system.
16+
"server": [True, False],
17+
18+
# Build and run unit tests.
1319
"test": [True, False],
20+
21+
# Make the compiler be strict and pedantic.
22+
# Disable if you upgrade compilers and run into new warnings preventing
23+
# the build from completing. May be removed in the future.
1424
"pedantic": [True, False],
1525
}
1626
default_options = {
17-
"fable:allow_comments": True,
18-
19-
# These don't change the output.
27+
"server": True,
2028
"test": True,
2129
"pedantic": True,
30+
31+
"fable:allow_comments": True,
2232
}
2333
generators = "cmake"
2434
no_copy_source = True
@@ -39,11 +49,16 @@ def set_version(self):
3949
self.version = git.run("describe --dirty=-dirty")[1:]
4050

4151
def requirements(self):
42-
self.requires("boost/[>=1.65.1]"),
4352
self.requires(f"cloe-runtime/{self.version}@cloe/develop")
4453
self.requires(f"cloe-models/{self.version}@cloe/develop")
45-
self.requires(f"cloe-oak/{self.version}@cloe/develop", private=True)
46-
self.requires("cli11/[~=2.1.2]", private=True),
54+
self.requires("cli11/[~=2.1.2]", private=True)
55+
if self.options.server:
56+
self.requires(f"cloe-oak/{self.version}@cloe/develop", private=True)
57+
self.requires("boost/[>=1.65.1,<1.70.0]")
58+
else:
59+
self.requires("boost/[>=1.65.1]")
60+
self.requires("fmt/8.0.1", override=True)
61+
self.requires("nlohmann_json/3.10.5", override=True)
4762

4863
def build_requirements(self):
4964
if self.options.test:
@@ -55,6 +70,7 @@ def _configure_cmake(self):
5570
self._cmake = CMake(self)
5671
self._cmake.definitions["CMAKE_EXPORT_COMPILE_COMMANDS"] = True
5772
self._cmake.definitions["BuildTests"] = self.options.test
73+
self._cmake.definitions["WithServer"] = self.options.server
5874
self._cmake.definitions["TargetLintingExtended"] = self.options.pedantic
5975
self._cmake.definitions["CLOE_PROJECT_VERSION"] = self.version
6076
self._cmake.configure()

engine/src/main_version.hpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ struct VersionOptions {
4343

4444
inline int version(const VersionOptions& opt) {
4545
cloe::Json v{
46-
{"engine", CLOE_ENGINE_VERSION},
47-
{"build_date", CLOE_ENGINE_TIMESTAMP},
48-
{"stack", CLOE_STACK_VERSION},
49-
{"plugin_manifest", CLOE_PLUGIN_MANIFEST_VERSION},
46+
{"engine", CLOE_ENGINE_VERSION}, // from CMakeLists.txt
47+
{"build_date", CLOE_ENGINE_TIMESTAMP}, // from CMakeLists.txt
48+
{"stack", CLOE_STACK_VERSION}, // from "stack.hpp"
49+
{"plugin_manifest", CLOE_PLUGIN_MANIFEST_VERSION}, // from <cloe/plugin.hpp>
50+
{"feature_server", CLOE_ENGINE_WITH_SERVER ? true : false}, // from CMakeLists.txt
5051
};
5152

5253
if (opt.output_json) {
@@ -59,6 +60,8 @@ Engine Version: [[engine]]
5960
Build Date: [[build_date]]
6061
Stack: [[stack]]
6162
Plugin Manifest: [[plugin_manifest]]
63+
Features:
64+
server: [[feature_server]]
6265
)",
6366
v);
6467
}

engine/src/server.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
/**
1919
* \file server.cpp
2020
* \see server.hpp
21+
*
22+
* This file is included in the build when the server component is enabled.
2123
*/
2224

2325
#include "server.hpp"

engine/src/server_mock.cpp

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright 2022 Robert Bosch GmbH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
*/
18+
/**
19+
* \file server_mock.cpp
20+
* \see server.hpp
21+
* \see server.cpp
22+
*
23+
* This file is included in the build when the server component is disabled.
24+
* This allows us to decouple the engine from the oak dependency with all
25+
* it entails in one place.
26+
*
27+
* We still need to implement the interfaces defined in server.hpp though.
28+
*
29+
* Having a separate file makes it easier to diff the two implmentation files.
30+
*/
31+
32+
#include "server.hpp"
33+
34+
#include <memory> // for unique_ptr<>, make_unique
35+
36+
#include <cloe/registrar.hpp> // for HandlerType
37+
38+
namespace engine {
39+
40+
class ServerRegistrarImpl : public ServerRegistrar {
41+
public:
42+
ServerRegistrarImpl(const std::string& static_prefix, const std::string& api_prefix)
43+
: static_prefix_(static_prefix), api_prefix_(api_prefix) {}
44+
45+
std::unique_ptr<ServerRegistrar> clone() const override {
46+
return std::make_unique<ServerRegistrarImpl>(static_prefix_, api_prefix_);
47+
}
48+
49+
std::unique_ptr<ServerRegistrar> with_prefix(const std::string& static_prefix,
50+
const std::string& api_prefix) const override {
51+
assert(static_prefix.empty() || static_prefix[0] == '/');
52+
assert(api_prefix.empty() || api_prefix[0] == '/');
53+
return std::make_unique<ServerRegistrarImpl>(static_prefix_ + static_prefix,
54+
api_prefix_ + api_prefix);
55+
}
56+
57+
void register_static_handler(const std::string& endpoint, cloe::Handler) override {
58+
logger()->warn("Unregistered static endpoint: {}", endpoint);
59+
}
60+
61+
void register_api_handler(const std::string& endpoint, cloe::HandlerType t,
62+
cloe::Handler) override {
63+
switch (t) {
64+
case cloe::HandlerType::STATIC:
65+
logger()->warn("Unregistered static endpoint: {}", endpoint);
66+
break;
67+
case cloe::HandlerType::DYNAMIC:
68+
logger()->warn("Unregistered dynamic endpoint: {}", endpoint);
69+
break;
70+
case cloe::HandlerType::BUFFERED:
71+
logger()->warn("Unregistered buffered endpoint: {}", endpoint);
72+
break;
73+
default:
74+
throw std::runtime_error("unknown handler type");
75+
}
76+
}
77+
78+
cloe::Logger logger() const {
79+
return cloe::logger::get("cloe");
80+
}
81+
82+
private:
83+
std::string static_prefix_{"/"};
84+
std::string api_prefix_{"/"};
85+
};
86+
87+
class ServerImpl : public Server {
88+
public:
89+
ServerImpl(const cloe::ServerConf& config) : Server(config) {
90+
if (config.listen) {
91+
logger()->error("Server unavailable, but configuration value /server/listen = true");
92+
logger()->error("Server unavailable, feature is not compiled into engine.");
93+
}
94+
}
95+
96+
~ServerImpl() {}
97+
98+
public:
99+
bool is_listening() const override { return false; }
100+
101+
bool is_streaming() const override { return false; }
102+
103+
void start() override {
104+
logger()->error("Server unavailable, cannot start.");
105+
}
106+
107+
void init_stream(const std::string& ) override {
108+
logger()->error("Server unavailable, cannot initialize stream.");
109+
}
110+
111+
void stop() override {
112+
}
113+
114+
void enroll(cloe::Registrar& ) override {
115+
}
116+
117+
std::unique_ptr<ServerRegistrar> server_registrar() override {
118+
return server_registrar_.clone();
119+
}
120+
121+
void refresh_buffer_start_stream() override {
122+
}
123+
124+
void refresh_buffer() override {
125+
}
126+
127+
Defer lock() override {
128+
return Defer([]() {});
129+
}
130+
131+
private:
132+
ServerRegistrarImpl server_registrar_{ "", "" };
133+
};
134+
135+
std::unique_ptr<Server> make_server(const cloe::ServerConf& c) {
136+
return std::make_unique<ServerImpl>(c);
137+
}
138+
139+
} // namespace engine

0 commit comments

Comments
 (0)