Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install gcovr
run: pip install gcovr==7.0
- name: Setup venv
run: python setup.py
- name: Build test
run: ./build_test.sh
- name: Code coverage
Expand Down
88 changes: 74 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,84 @@
# the Netherlands
#

cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.21)

project(test_EmbeddedProto)
project(EmbeddedProto
HOMEPAGE_URL "https://EmbeddedProto.com"
)

set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
set(EMBEDDED_PROTO_GEN_PATH ${CMAKE_CURRENT_LIST_DIR} CACHE STRING "Root path for EmbeddedProto code generator")
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/venv" AND EMBEDDED_PROTO_GEN_PATH STREQUAL CMAKE_CURRENT_LIST_DIR)
find_package(Python 3 REQUIRED)
execute_process(
COMMAND ${Python_EXECUTABLE} setup.py --ignore_version_diff
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif()

add_subdirectory(external/googletest)
include(cmake/GenerateEmbeddedProto.cmake)

file(GLOB src_files
"src/*.cpp"
"test/*.cpp"
"build/EAMS/*.cpp"
add_library(${PROJECT_NAME} STATIC)
target_sources(${PROJECT_NAME} PRIVATE
src/Fields.cpp
src/MessageInterface.cpp
src/ReadBufferSection.cpp
)
target_include_directories(${PROJECT_NAME} PUBLIC
src
)

include_directories(test test/mock src build/EAMS)
include_directories(external/googletest/googletest external/googletest/googletest/include
external/googletest/googlemock external/googletest/googlemock/include)
if(PROJECT_IS_TOP_LEVEL)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)

add_subdirectory(external/googletest)

file(GLOB src_files
"test/*.cpp"
)
add_executable(test_${PROJECT_NAME} ${src_files})

add_executable(test_EmbeddedProto ${src_files})
target_link_libraries(test_EmbeddedProto gtest gmock)
target_include_directories(test_${PROJECT_NAME}
PRIVATE
test
test/mock
${CMAKE_CURRENT_BINARY_DIR}/EAMS
)
target_link_libraries(test_${PROJECT_NAME}
PRIVATE
${PROJECT_NAME}
gtest
gmock
)
generate_embedded_proto(PROTO_HEADERS_1
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/EAMS
INCLUDE_DIRS
test/proto
PROTO_FILES
test/proto/simple_types.proto
test/proto/nested_message.proto
test/proto/repeated_fields.proto
test/proto/oneof_fields.proto
# Deliberately do not manually generate file_to_include.proto and subfolder/file_to_include_from_subfolder.proto
# to test the automatic generation of files from including them in include_other_files.proto.
test/proto/include_other_files.proto
test/proto/empty_message.proto
test/proto/optional_fields.proto
)
generate_embedded_proto(PROTO_HEADERS_2
OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/EAMS
INCLUDE_DIRS
test/proto
generator
PROTO_FILES
test/proto/string_bytes.proto
test/proto/field_options.proto
)
add_custom_target(generate_protos
DEPENDS
${PROTO_HEADERS_1}
${PROTO_HEADERS_2}
)
add_dependencies(test_${PROJECT_NAME} generate_protos)
endif()
14 changes: 0 additions & 14 deletions build_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,6 @@
# Fail on first non-zero return code
set -exuo pipefail

# Generate sources using the EAMS plugin.
mkdir -p ./build/EAMS
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/simple_types.proto
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/nested_message.proto
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/repeated_fields.proto
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/oneof_fields.proto
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/include_other_files.proto
# Delibertly do not manually generate file_to_include.proto and subfolder/file_to_include_from_subfolder.proto
# to test the automatic generation of files from including them in include_other_files.proto.
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto -I./generator --eams_out=./build/EAMS ./test/proto/string_bytes.proto
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/empty_message.proto
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto --eams_out=./build/EAMS ./test/proto/optional_fields.proto
protoc --plugin=protoc-gen-eams=protoc-gen-eams -I./test/proto -I./generator --eams_out=./build/EAMS ./test/proto/field_options.proto

# For validation and testing generate the same message using python
mkdir -p ./build/python
mkdir -p ./build/python/subfolder
Expand Down
69 changes: 69 additions & 0 deletions cmake/GenerateEmbeddedProto.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
function(generate_embedded_proto OUTPUT_VARIABLE)
# Define the expected named parameters
set(options) # No options/flags
# Single value arguments
# OUTPUT_DIR: where to place generated files
set(oneValueArgs OUTPUT_DIR)
# Multi-value arguments: multiple include directories + list of proto files
set(multiValueArgs INCLUDE_DIRS PROTO_FILES)

# Parse the named parameters
cmake_parse_arguments(PROTO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

# Validate required parameters
if(NOT PROTO_INCLUDE_DIRS)
message(FATAL_ERROR "INCLUDE_DIRS is required (use INCLUDE_DIRS <dir1> <dir2> ...)")
endif()
if(NOT PROTO_OUTPUT_DIR)
message(FATAL_ERROR "OUTPUT_DIR is required")
endif()
if(NOT PROTO_PROTO_FILES)
message(FATAL_ERROR "PROTO_FILES is required")
endif()
if(PROTO_PROTO_FILES STREQUAL "")
message(WARNING "PROTO_FILES is empty")
endif()
# If caller did not provide an output variable name (first positional arg), use a default
if(NOT OUTPUT_VARIABLE)
set(OUTPUT_VARIABLE "GENERATED_PROTO_FILES")
endif()

file(MAKE_DIRECTORY ${PROTO_OUTPUT_DIR})
get_filename_component(ABS_GENERATED_SRC_DIR ${PROTO_OUTPUT_DIR} ABSOLUTE)

# Build include arguments (-I ...) from INCLUDE_DIRS
set(INCLUDE_ARGS)
foreach(INC_DIR ${PROTO_INCLUDE_DIRS})
get_filename_component(ABS_INC_DIR ${INC_DIR} ABSOLUTE)
list(APPEND INCLUDE_ARGS -I${ABS_INC_DIR})
endforeach()

set(GENERATED_FILES)
# Process each protobuf file
foreach(PROTO_FILE ${PROTO_PROTO_FILES})
# Get absolute path
get_filename_component(ABS_PROTO_FILE ${PROTO_FILE} ABSOLUTE)
# Get the filename without the .proto extension
get_filename_component(PROTO_NAME ${PROTO_FILE} NAME_WE)

# Add the custom command to generate code for each proto file
add_custom_command(
OUTPUT "${ABS_GENERATED_SRC_DIR}/${PROTO_NAME}.h"
WORKING_DIRECTORY ${EMBEDDED_PROTO_GEN_PATH}
COMMAND protoc
ARGS
--plugin=protoc-gen-eams=protoc-gen-eams
${INCLUDE_ARGS}
--eams_out=${ABS_GENERATED_SRC_DIR}
${ABS_PROTO_FILE}
DEPENDS ${ABS_PROTO_FILE} ${EMBEDDED_PROTO_GEN_PATH}/protoc-gen-eams
COMMENT "Generating EmbeddedProto code for ${PROTO_FILE}"
VERBATIM
)
# Record the generated file path so the caller can consume it
list(APPEND GENERATED_FILES "${ABS_GENERATED_SRC_DIR}/${PROTO_NAME}.h")
endforeach()

# Export the list of generated files to the caller (parent scope)
set(${OUTPUT_VARIABLE} ${GENERATED_FILES} PARENT_SCOPE)
endfunction()