Commit 0626e714 authored by Dominik Charousset's avatar Dominik Charousset

Add to_strings for enum back to the repository

Using a code generator that requires compiling a C++ tool breaks when
crosscompiling CAF. It can also interact badly with projects that
include CAF as a submodule.

As a compromise between easy consumption / integration of CAF and
maintainability of the `to_string` implementations, this set of changes
adds two new targets to CMake:
- `check-consistency` runs the code generator and checks whether all
  files in the repository are still up-to-date. We can run this target
  automatically in our CI to fail builds that introduce inconsistencies.
- `update-enum-strings` runs the code generator to replace the files in
  the source tree. This is meant for CAF developers to update `.cpp`
  files after changing enum headers.

Both new targets are excluded from `ALL` in CMake and thus do not run
automatically.
parent b05a4b7b
......@@ -97,14 +97,39 @@ function(pretty_yes var)
endif()
endfunction(pretty_yes)
add_executable(caf-generate-enum-strings cmake/caf-generate-enum-strings.cpp)
add_executable(caf-generate-enum-strings
EXCLUDE_FROM_ALL
cmake/caf-generate-enum-strings.cpp)
function(enum_to_string relative_input_file relative_output_file)
set(input "${CMAKE_CURRENT_SOURCE_DIR}/${relative_input_file}")
set(output "${CMAKE_CURRENT_BINARY_DIR}/${relative_output_file}")
add_custom_target(consistency-check)
add_custom_target(update-enum-strings)
# adds a consistency check that verifies that `cpp_file` is still valid by
# re-generating the file and comparing it to the existing file
function(add_enum_consistency_check hpp_file cpp_file)
set(input "${CMAKE_CURRENT_SOURCE_DIR}/${hpp_file}")
set(file_under_test "${CMAKE_CURRENT_SOURCE_DIR}/${cpp_file}")
set(output "${CMAKE_CURRENT_BINARY_DIR}/check/${cpp_file}")
add_custom_command(OUTPUT "${output}"
COMMAND caf-generate-enum-strings "${input}" "${output}"
DEPENDS caf-generate-enum-strings "${input}")
get_filename_component(target_name "${input}" NAME_WE)
add_custom_target("${target_name}"
COMMAND
"${CMAKE_COMMAND}"
"-Dfile_under_test=${file_under_test}"
"-Dgenerated_file=${output}"
-P "${PROJECT_SOURCE_DIR}/cmake/check-consistency.cmake"
DEPENDS "${output}")
add_dependencies(consistency-check "${target_name}")
add_custom_target("${target_name}-update"
COMMAND
caf-generate-enum-strings
"${input}"
"${file_under_test}"
DEPENDS caf-generate-enum-strings "${input}")
add_dependencies(update-enum-strings "${target_name}-update")
endfunction()
################################################################################
......
......@@ -36,7 +36,7 @@ void keep_alnum(string& str) {
int main(int argc, char** argv) {
if (argc != 3) {
cerr << "wrong number of arguments.\n"
<< "usage: " << argv[0] << "input-file output-file\n";
<< "usage: " << argv[0] << " input-file output-file\n";
return EXIT_FAILURE;
}
std::ifstream in{argv[1]};
......@@ -89,7 +89,11 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
// Print file header.
out << "#include \"" << namespaces[0];
out << "// clang-format off\n"
<< "// DO NOT EDIT: "
"this file is auto-generated by caf-generate-enum-strings.\n"
"// Run the target update-enum-strings if this file is out of sync.\n"
<< "#include \"" << namespaces[0];
for (size_t i = 1; i < namespaces.size(); ++i)
out << '/' << namespaces[i];
out << '/' << enum_name << ".hpp\"\n\n"
......
execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files
"${file_under_test}" "${generated_file}"
RESULT_VARIABLE result)
if(result EQUAL 0)
# files still in sync
else()
message(SEND_ERROR "${file_under_test} is out of sync! Run target "
"'update-enum-strings' to update automatically")
endif()
project(caf_core C CXX)
# get header files; only needed by CMake generators,
# e.g., for creating proper Xcode projects
file(GLOB_RECURSE LIBCAF_CORE_HDRS "caf/*.hpp")
enum_to_string("caf/exit_reason.hpp" "exit_reason_strings.cpp")
enum_to_string("caf/intrusive/inbox_result.hpp" "inbox_result_strings.cpp")
enum_to_string("caf/intrusive/task_result.hpp" "task_result_strings.cpp")
enum_to_string("caf/invoke_message_result.hpp" "invoke_msg_result_strings.cpp")
enum_to_string("caf/message_priority.hpp" "message_priority_strings.cpp")
enum_to_string("caf/pec.hpp" "pec_strings.cpp")
enum_to_string("caf/sec.hpp" "sec_strings.cpp")
enum_to_string("caf/stream_priority.hpp" "stream_priority_strings.cpp")
# extend the consistency-check target for enum to_string implementations
add_enum_consistency_check("caf/sec.hpp" "src/sec_strings.cpp")
add_enum_consistency_check("caf/pec.hpp" "src/pec_strings.cpp")
add_enum_consistency_check("caf/stream_priority.hpp"
"src/stream_priority_strings.cpp")
add_enum_consistency_check("caf/exit_reason.hpp"
"src/exit_reason_strings.cpp")
add_enum_consistency_check("caf/invoke_message_result.hpp"
"src/invoke_msg_result_strings.cpp")
add_enum_consistency_check("caf/message_priority.hpp"
"src/message_priority_strings.cpp")
add_enum_consistency_check("caf/intrusive/inbox_result.hpp"
"src/intrusive/inbox_result_strings.cpp")
add_enum_consistency_check("caf/intrusive/task_result.hpp"
"src/intrusive/task_result_strings.cpp")
# list cpp files excluding platform-dependent files
set(LIBCAF_CORE_SRCS
"${CMAKE_CURRENT_BINARY_DIR}/exit_reason_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/inbox_result_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/invoke_msg_result_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/message_priority_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/pec_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/sec_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/stream_priority_strings.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/task_result_strings.cpp"
src/abstract_actor.cpp
src/abstract_channel.cpp
src/abstract_composable_behavior.cpp
......@@ -95,11 +92,15 @@ set(LIBCAF_CORE_SRCS
src/event_based_actor.cpp
src/execution_unit.cpp
src/exit_reason.cpp
src/exit_reason_strings.cpp
src/forwarding_actor_proxy.cpp
src/group.cpp
src/group_manager.cpp
src/group_module.cpp
src/inbound_path.cpp
src/intrusive/inbox_result_strings.cpp
src/intrusive/task_result_strings.cpp
src/invoke_msg_result_strings.cpp
src/ipv4_address.cpp
src/ipv4_endpoint.cpp
src/ipv4_subnet.cpp
......@@ -115,11 +116,13 @@ set(LIBCAF_CORE_SRCS
src/message.cpp
src/message_builder.cpp
src/message_handler.cpp
src/message_priority_strings.cpp
src/message_view.cpp
src/monitorable_actor.cpp
src/node_id.cpp
src/outbound_path.cpp
src/pec.cpp
src/pec_strings.cpp
src/policy/downstream_messages.cpp
src/policy/unprofiled.cpp
src/policy/work_sharing.cpp
......@@ -139,11 +142,13 @@ set(LIBCAF_CORE_SRCS
src/scoped_actor.cpp
src/scoped_execution_unit.cpp
src/sec.cpp
src/sec_strings.cpp
src/serializer.cpp
src/settings.cpp
src/skip.cpp
src/stream_aborter.cpp
src/stream_manager.cpp
src/stream_priority_strings.cpp
src/string_algorithms.cpp
src/string_view.cpp
src/term.cpp
......
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/exit_reason.hpp"
#include <string>
namespace caf {
std::string to_string(exit_reason x) {
switch(x) {
default:
return "???";
case exit_reason::normal:
return "normal";
case exit_reason::unhandled_exception:
return "unhandled_exception";
case exit_reason::unknown:
return "unknown";
case exit_reason::out_of_workers:
return "out_of_workers";
case exit_reason::user_shutdown:
return "user_shutdown";
case exit_reason::kill:
return "kill";
case exit_reason::remote_link_unreachable:
return "remote_link_unreachable";
case exit_reason::unreachable:
return "unreachable";
};
}
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/intrusive/inbox_result.hpp"
#include <string>
namespace caf {
namespace intrusive {
std::string to_string(inbox_result x) {
switch(x) {
default:
return "???";
case inbox_result::success:
return "success";
case inbox_result::unblocked_reader:
return "unblocked_reader";
case inbox_result::queue_closed:
return "queue_closed";
};
}
} // namespace intrusive
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/intrusive/task_result.hpp"
#include <string>
namespace caf {
namespace intrusive {
std::string to_string(task_result x) {
switch(x) {
default:
return "???";
case task_result::resume:
return "resume";
case task_result::skip:
return "skip";
case task_result::stop:
return "stop";
case task_result::stop_all:
return "stop_all";
};
}
} // namespace intrusive
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/invoke_message_result.hpp"
#include <string>
namespace caf {
std::string to_string(invoke_message_result x) {
switch(x) {
default:
return "???";
case invoke_message_result::consumed:
return "consumed";
case invoke_message_result::skipped:
return "skipped";
case invoke_message_result::dropped:
return "dropped";
};
}
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/message_priority.hpp"
#include <string>
namespace caf {
std::string to_string(message_priority x) {
switch(x) {
default:
return "???";
case message_priority::high:
return "high";
case message_priority::normal:
return "normal";
};
}
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/pec.hpp"
#include <string>
namespace caf {
std::string to_string(pec x) {
switch(x) {
default:
return "???";
case pec::success:
return "success";
case pec::trailing_character:
return "trailing_character";
case pec::unexpected_eof:
return "unexpected_eof";
case pec::unexpected_character:
return "unexpected_character";
case pec::timespan_overflow:
return "timespan_overflow";
case pec::fractional_timespan:
return "fractional_timespan";
case pec::too_many_characters:
return "too_many_characters";
case pec::illegal_escape_sequence:
return "illegal_escape_sequence";
case pec::unexpected_newline:
return "unexpected_newline";
case pec::integer_overflow:
return "integer_overflow";
case pec::integer_underflow:
return "integer_underflow";
case pec::exponent_underflow:
return "exponent_underflow";
case pec::exponent_overflow:
return "exponent_overflow";
case pec::type_mismatch:
return "type_mismatch";
case pec::not_an_option:
return "not_an_option";
case pec::illegal_argument:
return "illegal_argument";
case pec::missing_argument:
return "missing_argument";
case pec::illegal_category:
return "illegal_category";
case pec::invalid_field_name:
return "invalid_field_name";
case pec::repeated_field_name:
return "repeated_field_name";
case pec::missing_field:
return "missing_field";
};
}
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/sec.hpp"
#include <string>
namespace caf {
std::string to_string(sec x) {
switch(x) {
default:
return "???";
case sec::none:
return "none";
case sec::unexpected_message:
return "unexpected_message";
case sec::unexpected_response:
return "unexpected_response";
case sec::request_receiver_down:
return "request_receiver_down";
case sec::request_timeout:
return "request_timeout";
case sec::no_such_group_module:
return "no_such_group_module";
case sec::no_actor_published_at_port:
return "no_actor_published_at_port";
case sec::unexpected_actor_messaging_interface:
return "unexpected_actor_messaging_interface";
case sec::state_not_serializable:
return "state_not_serializable";
case sec::unsupported_sys_key:
return "unsupported_sys_key";
case sec::unsupported_sys_message:
return "unsupported_sys_message";
case sec::disconnect_during_handshake:
return "disconnect_during_handshake";
case sec::cannot_forward_to_invalid_actor:
return "cannot_forward_to_invalid_actor";
case sec::no_route_to_receiving_node:
return "no_route_to_receiving_node";
case sec::failed_to_assign_scribe_from_handle:
return "failed_to_assign_scribe_from_handle";
case sec::failed_to_assign_doorman_from_handle:
return "failed_to_assign_doorman_from_handle";
case sec::cannot_close_invalid_port:
return "cannot_close_invalid_port";
case sec::cannot_connect_to_node:
return "cannot_connect_to_node";
case sec::cannot_open_port:
return "cannot_open_port";
case sec::network_syscall_failed:
return "network_syscall_failed";
case sec::invalid_argument:
return "invalid_argument";
case sec::invalid_protocol_family:
return "invalid_protocol_family";
case sec::cannot_publish_invalid_actor:
return "cannot_publish_invalid_actor";
case sec::cannot_spawn_actor_from_arguments:
return "cannot_spawn_actor_from_arguments";
case sec::end_of_stream:
return "end_of_stream";
case sec::no_context:
return "no_context";
case sec::unknown_type:
return "unknown_type";
case sec::no_proxy_registry:
return "no_proxy_registry";
case sec::runtime_error:
return "runtime_error";
case sec::remote_linking_failed:
return "remote_linking_failed";
case sec::cannot_add_upstream:
return "cannot_add_upstream";
case sec::upstream_already_exists:
return "upstream_already_exists";
case sec::invalid_upstream:
return "invalid_upstream";
case sec::cannot_add_downstream:
return "cannot_add_downstream";
case sec::downstream_already_exists:
return "downstream_already_exists";
case sec::invalid_downstream:
return "invalid_downstream";
case sec::no_downstream_stages_defined:
return "no_downstream_stages_defined";
case sec::stream_init_failed:
return "stream_init_failed";
case sec::invalid_stream_state:
return "invalid_stream_state";
case sec::unhandled_stream_error:
return "unhandled_stream_error";
case sec::bad_function_call:
return "bad_function_call";
case sec::feature_disabled:
return "feature_disabled";
case sec::cannot_open_file:
return "cannot_open_file";
case sec::socket_invalid:
return "socket_invalid";
case sec::socket_disconnected:
return "socket_disconnected";
case sec::socket_operation_failed:
return "socket_operation_failed";
case sec::unavailable_or_would_block:
return "unavailable_or_would_block";
case sec::remote_lookup_failed:
return "remote_lookup_failed";
};
}
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/stream_priority.hpp"
#include <string>
namespace caf {
std::string to_string(stream_priority x) {
switch(x) {
default:
return "???";
case stream_priority::very_high:
return "very_high";
case stream_priority::high:
return "high";
case stream_priority::normal:
return "normal";
case stream_priority::low:
return "low";
case stream_priority::very_low:
return "very_low";
};
}
} // namespace caf
project(caf_io C CXX)
# get header files; only needed by CMake generators,
# e.g., for creating proper Xcode projects
file(GLOB_RECURSE LIBCAF_IO_HDRS "caf/*.hpp")
enum_to_string("caf/io/basp/message_type.hpp" "message_type_to_string.cpp")
enum_to_string("caf/io/network/operation.hpp" "operation_to_string.cpp")
add_enum_consistency_check("caf/io/basp/message_type.hpp"
"src/io/basp/message_type_strings.cpp")
add_enum_consistency_check("caf/io/network/operation.hpp"
"src/io/network/operation_strings.cpp")
# list cpp files excluding platform-dependent files
set(LIBCAF_IO_SRCS
"${CMAKE_CURRENT_BINARY_DIR}/message_type_to_string.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/operation_to_string.cpp"
src/detail/socket_guard.cpp
src/io/abstract_broker.cpp
src/io/basp/header.cpp
src/io/basp/instance.cpp
src/io/basp/message_queue.cpp
src/io/basp/message_type_strings.cpp
src/io/basp/routing_table.cpp
src/io/basp/worker.cpp
src/io/basp_broker.cpp
......@@ -39,6 +39,7 @@ set(LIBCAF_IO_SRCS
src/io/network/manager.cpp
src/io/network/multiplexer.cpp
src/io/network/native_socket.cpp
src/io/network/operation_strings.cpp
src/io/network/pipe_reader.cpp
src/io/network/protocol.cpp
src/io/network/receive_buffer.cpp
......
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/io/basp/message_type.hpp"
#include <string>
namespace caf {
namespace io {
namespace basp {
std::string to_string(message_type x) {
switch(x) {
default:
return "???";
case message_type::server_handshake:
return "server_handshake";
case message_type::client_handshake:
return "client_handshake";
case message_type::direct_message:
return "direct_message";
case message_type::routed_message:
return "routed_message";
case message_type::monitor_message:
return "monitor_message";
case message_type::down_message:
return "down_message";
case message_type::heartbeat:
return "heartbeat";
};
}
} // namespace basp
} // namespace io
} // namespace caf
// clang-format off
// DO NOT EDIT: this file is auto-generated by caf-generate-enum-strings.
// Run the target update-enum-strings if this file is out of sync.
#include "caf/io/network/operation.hpp"
#include <string>
namespace caf {
namespace io {
namespace network {
std::string to_string(operation x) {
switch(x) {
default:
return "???";
case operation::read:
return "read";
case operation::write:
return "write";
case operation::propagate_error:
return "propagate_error";
};
}
} // namespace network
} // namespace io
} // namespace caf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment