Skip to content

Commit

Permalink
Merge branch 'yarp_add_idl'
Browse files Browse the repository at this point in the history
Closes #376
  • Loading branch information
drdanz committed Jan 4, 2016
2 parents 65847b4 + bbf55c5 commit 63eb5b8
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 4 deletions.
217 changes: 213 additions & 4 deletions conf/YarpIDL.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright: (C) 2012 IITRBCS
# Authors: Elena Ceseracciu, Paul Fitzpatrick
# Copyright (C) 2012 Robotics Brain and Cognitive Sciences, Istituto Italiano di Tecnologia
# Copyright (C) 2014 iCub Facility, Istituto Italiano di Tecnologia
# Authors: Elena Ceseracciu, Paul Fitzpatrick, Daniele E. Domenichelli
# CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT

# yarp_idl_to_dir
Expand All @@ -12,14 +13,32 @@
# yarp_idl_to_dir(foo.thrift foo)
# yarp_idl_to_dir(foo.thrift foo SOURCES HEADERS)
# yarp_idl_to_dir(foo.thrift foo SOURCES HEADERS INCLUDE_PATHS)
#
#
# yarp_add_idl
# ------------
#
# Take one or more IDL files and generate code at build time.
# Files will be regenerated whenever the IDL file changes.
#
# yarp_add_idl(<var> <file> [file [...]])
#
# The <var> variable, will contain the generated files, and can be
# added to the an add_executable or add_library call. For example:
#
# set(THRIFT_FILES file1.thrift
# file2.msg
# file3.srv)
# yarp_add_idl(THRIFT_GEN_FILES ${THRIFT_FILES})
# add_executable(foo main.cpp ${THRIFT_GEN_FILES})



# Avoid multiple inclusions of this file
if(COMMAND yarp_idl_to_dir)
if(COMMAND yarp_add_idl)
return()
endif()


function(YARP_IDL_TO_DIR yarpidl_file_base output_dir)
# Store optional output variable(s).
set(out_vars ${ARGN})
Expand Down Expand Up @@ -151,3 +170,193 @@ function(YARP_IDL_TO_DIR yarpidl_file_base output_dir)
set(${target_paths} ${output_dir} ${output_dir}/include PARENT_SCOPE)
endif()
endfunction()


# Internal function.
# Calculate a list of sources generated from a .thrift file
function(_YARP_IDL_THRIFT_TO_FILE_LIST file path basename ext gen_srcs_var gen_hdrs_var)
set(gen_srcs)
set(gen_hdrs)

# Read thrift file
file(READ ${file} file_content)

# Remove comments
string(REGEX REPLACE "/\\*[^*]?[^/]+\\*/" "" file_content ${file_content})
string(REGEX REPLACE "#[^\n]+" "" file_content ${file_content})
string(REGEX REPLACE "//[^\n]+" "" file_content ${file_content})

# Match "enum"s, "struct"s and "service"s defined in the file
string(REGEX MATCHALL "(enum|struct|service)[ \t\n]+([^ \t\n]+)[ \t\n]*{[^}]+}([ \t\n]*\\([^\\)]+\\))?" objects ${file_content})

# Find object name and append generated files
foreach(object ${objects})
string(REGEX MATCH "^(enum|struct|service)[ \t\n]+([^ \t\n{]+)" unused ${object})
set(objectname ${CMAKE_MATCH_2})
if(NOT "${object}" MATCHES "{[^}]+}[ \t\n]*(\\([^\\)]*yarp.name[^\\)]+\\))")
# No files are generated for YARP types.
list(APPEND gen_srcs ${objectname}.cpp)
list(APPEND gen_hdrs ${objectname}.h)
endif()
endforeach()

# Remove "enum"s, "struct"s and "service"s
string (REGEX REPLACE "(enum|struct|service)[ \t\n]+([^ \t\n]+)[ \t\n]*{[^}]+}([ \t\n]*\\([^\\)]+\\))?" "" file_content ${file_content})

# Find if at least one "const" or "typedef" is defined
if("${file_content}" MATCHES "(const|typedef)[ \t]+([^ \t\n]+)[ \t]*([^ \t\n]+)")
list(APPEND gen_hdrs ${basename}_common.h)
endif()

set(${gen_srcs_var} ${gen_srcs} PARENT_SCOPE)
set(${gen_hdrs_var} ${gen_hdrs} PARENT_SCOPE)
endfunction()


# Internal function.
# Calculate a list of sources generated from a .msg or a .srv file
function(_YARP_IDL_ROSMSG_TO_FILE_LIST file path pkg basename ext gen_srcs_var gen_hdrs_var)
set(gen_srcs )
set(gen_hdrs )

get_filename_component(ext ${file} EXT)

if(NOT "${pkg}" STREQUAL "")
set(gen_hdrs "${pkg}/${basename}.h"
"${pkg}_${basename}.h")
else()
set(gen_hdrs "${basename}.h")
endif()
if("${ext}" STREQUAL ".srv")
list(APPEND gen_hdrs ${basename}Reply.h)
if(NOT "${path}" STREQUAL "")
list(APPEND gen_hdrs ${clean_path}_${basename}Reply.h)
endif()
endif()

# Read rosmsg file
file(READ ${file} file_content)

# Check if std_msgs/Header.h or TickTime.h will be created
if("${file_content}" MATCHES "(^|\n)Header[ \t]")
list(APPEND gen_hdrs std_msgs/Header.h std_msgs_Header.h TickTime.h)
elseif("${file_content}" MATCHES "(^|\n)time[ \t]")
list(APPEND gen_hdrs TickTime.h)
endif()

set(${gen_srcs_var} ${gen_srcs} PARENT_SCOPE)
set(${gen_hdrs_var} ${gen_hdrs} PARENT_SCOPE)
endfunction()


function(YARP_ADD_IDL var first_file)

# Ensure that the output variable is empty
unset(${var})
unset(include_dirs)

foreach(file "${first_file}" ${ARGN})

# Ensure that the filename is relative to the current source directory
if (IS_ABSOLUTE "${file}")
file(RELATIVE_PATH file "${CMAKE_CURRENT_SOURCE_DIR}" "${file}")
endif()

# Extract a name and extension.
get_filename_component(path ${file} PATH)
get_filename_component(basename ${file} NAME_WE)
get_filename_component(ext ${file} EXT)
string(TOLOWER ${ext} ext)

# Figure out format we are working with and determine which files
# will be generated
if("${ext}" STREQUAL ".thrift")
set(family thrift)
_yarp_idl_thrift_to_file_list("${file}" "${path}" "${basename}" ${ext} gen_srcs gen_hdrs)
elseif("${ext}" MATCHES "^\\.(msg|srv)$")
set(family rosmsg)
get_filename_component(pkg "${path}" NAME)
get_filename_component(path "${path}" PATH)
_yarp_idl_rosmsg_to_file_list("${file}" "${path}" "${pkg}" "${basename}" ${ext} gen_srcs gen_hdrs)
else()
message(FATAL_ERROR "Unknown extension ${ext}. Supported extensiona are .thrift, .msg, and .srv")
endif()


# Choose target depending on family and on whether we are building
# or using YARP
# FIXME CMake 2.8.12 Use ALIAS and always YARP::yarpidl_${family}
if(TARGET YARP::yarpidl_${family})
# Outside YARP
set(YARPIDL_${family}_COMMAND YARP::yarpidl_${family})
else()
# Building YARP
set(YARPIDL_${family}_COMMAND yarpidl_${family})
endif()

# Set intermediate output directory, remove extra '/' and ensure that
# the directory exists.
set(tmp_dir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/yarpidl_${family}/${path}")
string(REGEX REPLACE "/(/|$)" "\\1" tmp_dir "${tmp_dir}")
make_directory(${tmp_dir})

# Set output directories and remove extra "/"
set(srcs_out_dir "${CMAKE_CURRENT_BINARY_DIR}/src")
set(hdrs_out_dir "${CMAKE_CURRENT_BINARY_DIR}/include")
string(REGEX REPLACE "/(/|$)" "\\1" srcs_out_dir "${srcs_out_dir}")
string(REGEX REPLACE "/(/|$)" "\\1" hdrs_out_dir "${hdrs_out_dir}")


# Prepare main command
if("${family}" STREQUAL "thrift")
set(cmd ${YARPIDL_thrift_COMMAND} --gen yarp:include_prefix --I "${CMAKE_CURRENT_SOURCE_DIR}" --out "${tmp_dir}" "${file}")
else()
set(cmd ${YARPIDL_rosmsg_COMMAND} --no-ros true --out "${CMAKE_CURRENT_BINARY_DIR}/include" "${file}")
endif()

# Prepare copy command (thrift only) and populate output variable
unset(output)
foreach(gen_file ${gen_srcs})
set(out "${srcs_out_dir}/${gen_file}")
list(FIND ${var} ${out} x)
if(x EQUAL -1)
list(APPEND output "${out}")
if("${family}" STREQUAL "thrift")
set(in "${tmp_dir}/${gen_file}")
list(APPEND cmd COMMAND ${CMAKE_COMMAND} -E copy "${in}" "${out}")
endif()
endif()
endforeach()
foreach(gen_file ${gen_hdrs})
set(out "${hdrs_out_dir}/${gen_file}")
list(FIND ${var} ${out} x)
if(x EQUAL -1)
list(APPEND output "${out}")
if("${family}" STREQUAL "thrift")
set(in "${tmp_dir}/${gen_file}")
list(APPEND cmd COMMAND ${CMAKE_COMMAND} -E copy "${in}" "${out}")
endif()
endif()
endforeach()

if(NOT "${output}" STREQUAL "")
add_custom_command(OUTPUT ${output}
DEPENDS ${file}
${extra_deps}
COMMAND ${cmd}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating code from ${file}")

# Append output to return variable
list(APPEND ${var} ${output})

# Force CMake to run again if the file is modified
configure_file("${file}" "${tmp_dir}/${basename}${ext}" COPYONLY)
endif()

endforeach()

set(${var} ${${var}} PARENT_SCOPE)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include/")

endfunction()
16 changes: 16 additions & 0 deletions src/idls/rosmsg/tests/demo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ find_package(YARP REQUIRED)
list(APPEND CMAKE_MODULE_PATH ${YARP_MODULE_PATH})
include(YarpIDL)

# Test using yarp_idl_to_dir
set(generated_libs_dir "${CMAKE_CURRENT_BINARY_DIR}/bits")
yarp_idl_to_dir(SharedData.msg ${generated_libs_dir} S1 H1)
yarp_idl_to_dir(Demo.msg ${generated_libs_dir} S2 H2)
Expand All @@ -26,3 +27,18 @@ target_link_libraries(demo_test ${YARP_LIBRARIES})
add_test(demo_basic demo_test --help)


# Test using yarp_add_idl
set(IDL_FILES SharedData.msg
Demo.msg
Tennis.srv
Rpc.srv
HeaderTest.msg
HeaderTest2.srv)
yarp_add_idl(IDL_GEN_FILES ${IDL_FILES})

include_directories(${YARP_INCLUDE_DIRS})
add_executable(demo_test2 main.cpp ${IDL_GEN_FILES})
target_link_libraries(demo_test2 ${YARP_LIBRARIES})

add_test(demo_basic2 demo_test2 --help)

14 changes: 14 additions & 0 deletions src/idls/thrift/tests/demo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ find_package(YARP REQUIRED)
list(APPEND CMAKE_MODULE_PATH ${YARP_MODULE_PATH})
include(YarpIDL)

# Test using yarp_idl_to_dir
set(generated_libs_dir "${CMAKE_CURRENT_BINARY_DIR}")
yarp_idl_to_dir(demo.thrift ${generated_libs_dir} S1 H1 I1)
yarp_idl_to_dir(namespaced.thrift ${generated_libs_dir} S2 H2 I2)
Expand All @@ -26,3 +27,16 @@ target_link_libraries(demo_test ${YARP_LIBRARIES})
add_test(demo_basic demo_test)


# Test using yarp_add_idl
set(IDL_FILES demo.thrift
namespaced.thrift
objects3D.thrift
wrapping.thrift
sub/directory/clock_rpc.thrift
settings.thrift)
yarp_add_idl(IDL_GEN_FILES ${IDL_FILES})
include_directories(${YARP_INCLUDE_DIRS})
add_executable(demo_test2 main.cpp ${IDL_GEN_FILES})
target_link_libraries(demo_test2 ${YARP_LIBRARIES})

add_test(demo_basic2 demo_test2)

0 comments on commit 63eb5b8

Please sign in to comment.