diff --git a/CMakeLists.txt b/CMakeLists.txt index c6cf3ab65..912ae83e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,6 @@ LIST( GET RTT_VERSIONS 0 RTT_VERSION_MAJOR) LIST( GET RTT_VERSIONS 1 RTT_VERSION_MINOR) LIST( GET RTT_VERSIONS 2 RTT_VERSION_PATCH) -SET(ROS_ROOT $ENV{ROS_ROOT}) - MESSAGE( "Orocos RTT version ${VERSION} (${RTT_VERSION_MAJOR}.${RTT_VERSION_MINOR}.${RTT_VERSION_PATCH})" ) SET( PROJ_SOURCE_DIR ${orocos-rtt_SOURCE_DIR} ) @@ -52,41 +50,9 @@ IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) ENDIF(MSVC) ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) -# We force it in case of ROS builds because the UseOrocos.cmake scripts will always look -# in this path, also during an autoproj/bootstrap build. -IF(ROS_ROOT) - SET(CMAKE_INSTALL_PREFIX - ${PROJECT_SOURCE_DIR}/../install CACHE PATH "Orocos install prefix for ROS builds" FORCE - ) - # Necessary when building Debian packages: - set(ROS_STACK_DIR_FINAL $ENV{ROS_STACK_DIR_FINAL}) - if (ROS_STACK_DIR_FINAL) - set(DEFAULT_PLUGIN_PATH "${ROS_STACK_DIR_FINAL}/orocos_toolchain/install/lib/orocos") - endif(ROS_STACK_DIR_FINAL) - # Necessary for backwards compatibility such that packages find RTT's cmake macros: - if (NOT IS_SYMLINK ${CMAKE_CURRENT_SOURCE_DIR}/install ) - # Note: we use WORKING_DIRECTORY - execute_process ( - COMMAND ${CMAKE_COMMAND} -E remove_directory install - COMMAND ${CMAKE_COMMAND} -E create_symlink ../install install - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_QUIET ERROR_QUIET - ) - endif() - # We had to split the if statement above in two parts because cmake 2.8.0 would choke on a single-liner: - if ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/install ) - # Note: we use WORKING_DIRECTORY - execute_process ( - COMMAND ${CMAKE_COMMAND} -E create_symlink ../install install - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_QUIET ERROR_QUIET - ) - endif() - - # Tell deployer to use ROSlib support. - set(ROSLIB_SUPPORT TRUE) - include(config/FindRoslib.cmake) -ENDIF(ROS_ROOT) +# Tell deployer to use ROSlib support. +set(ROSLIB_SUPPORT TRUE) +include(config/FindRoslib.cmake) #Use these variables to store build-local flags. #They are used when the targets are configured. diff --git a/Makefile b/Makefile index d7fb4ee03..3136adbd9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ifdef ROS_ROOT -EXTRA_CMAKE_FLAGS=-DENABLE_CORBA=ON -DCORBA_IMPLEMENTATION=OMNIORB +EXTRA_CMAKE_FLAGS=-DENABLE_CORBA=ON -DCORBA_IMPLEMENTATION=OMNIORB -DCMAKE_INSTALL_PREFIX=$(shell rospack find rtt)/../install default: install_rtt include $(shell rospack find mk)/cmake.mk install_rtt: all diff --git a/UseOROCOS-RTT-helpers.cmake b/UseOROCOS-RTT-helpers.cmake index 16c9afdcc..19307b06b 100644 --- a/UseOROCOS-RTT-helpers.cmake +++ b/UseOROCOS-RTT-helpers.cmake @@ -1,3 +1,55 @@ + +# +# Parses arguments or options +# +# From: http://www.cmake.org/Wiki/CMakeMacroParseArguments +# +# For each item in options, PARSE_ARGUMENTS will create a variable +# with that name, prefixed with prefix_. So, for example, if prefix is +# MY_MACRO and options is OPTION1;OPTION2, then PARSE_ARGUMENTS will +# create the variables MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These +# variables will be set to true if the option exists in the command +# line or false otherwise. +# +# For each item in arg_names, PARSE_ARGUMENTS will create a variable +# with that name, prefixed with prefix_. Each variable will be filled +# with the arguments that occur after the given arg_name is encountered +# up to the next arg_name or the end of the arguments. All options are +# removed from these lists. PARSE_ARGUMENTS also creates a +# prefix_DEFAULT_ARGS variable containing the list of all arguments up +# to the first arg_name encountered. +# +MACRO(ORO_PARSE_ARGUMENTS prefix arg_names option_names) + SET(DEFAULT_ARGS) + FOREACH(arg_name ${arg_names}) + SET(${prefix}_${arg_name}) + ENDFOREACH(arg_name) + FOREACH(option ${option_names}) + SET(${prefix}_${option} FALSE) + ENDFOREACH(option) + + SET(current_arg_name DEFAULT_ARGS) + SET(current_arg_list) + FOREACH(arg ${ARGN}) + SET(larg_names ${arg_names}) + LIST(FIND larg_names "${arg}" is_arg_name) + IF (is_arg_name GREATER -1) + SET(${prefix}_${current_arg_name} ${current_arg_list}) + SET(current_arg_name ${arg}) + SET(current_arg_list) + ELSE (is_arg_name GREATER -1) + SET(loption_names ${option_names}) + LIST(FIND loption_names "${arg}" is_option) + IF (is_option GREATER -1) + SET(${prefix}_${arg} TRUE) + ELSE (is_option GREATER -1) + SET(current_arg_list ${current_arg_list} ${arg}) + ENDIF (is_option GREATER -1) + ENDIF (is_arg_name GREATER -1) + ENDFOREACH(arg) + SET(${prefix}_${current_arg_name} ${current_arg_list}) +ENDMACRO(ORO_PARSE_ARGUMENTS) + # # Parses the manifest.xml file and stores the dependencies in RESULT. # Relies on xpath. If no manifest is found, returns an empty RESULT. @@ -28,8 +80,8 @@ function( orocos_get_manifest_deps RESULT) string(REGEX REPLACE "${REGEX_STR}" "\\1;" RR_RESULT ${DEPS}) #message("Deps are: '${DEPS}'") - #message("Dependencies are: '${RR_RESULT}'") - set(${RESULT} ${RR_RESULT}) + set(${RESULT} ${RR_RESULT} PARENT_SCOPE) + #message("Dependencies are: '${${RESULT}}'") endif (NOT XPATH_EXE) endfunction( orocos_get_manifest_deps RESULT) @@ -37,7 +89,7 @@ endfunction( orocos_get_manifest_deps RESULT) # # Find a package, pick up its include dirs and link with its libraries. # It does this by locating and reading the .pc file generated by that package. -# In case no such .pc file exists (or is not found), tt is assumed that no +# In case no such .pc file exists (or is not found), it is assumed that no # flags are necessary. # # This macro is called for you by UseOrocos-RTT.cmake @@ -58,9 +110,8 @@ endfunction( orocos_get_manifest_deps RESULT) # Usage: orocos_use_package( myrobot ) # macro( orocos_use_package PACKAGE ) - if (PACKAGE STREQUAL "rtt") - return() - endif (PACKAGE STREQUAL "rtt") + if ( "${PACKAGE}" STREQUAL "rtt") + else() if (IS_ROS_PACKAGE) if (NOT USE_FOUND_${PACKAGE}_PACKAGE_PATH) # use rospack to find package directories of *all* dependencies. @@ -101,24 +152,39 @@ macro( orocos_use_package PACKAGE ) # Use find_libraries to find each library: unset(${PACKAGE}_LIBRARIES CACHE) foreach(COMP_LIB ${${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARIES}) - find_library(${PACKAGE}_${COMP_LIB}_LIBRARY NAMES ${COMP_LIB} HINTS ${${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARY_DIRS}) + # Two options: COMP_LIB is an absolute path-to-lib (must start with ':') or just a libname: + if ( ${COMP_LIB} MATCHES "^:(.+)" OR EXISTS ${COMP_LIB}) + if (EXISTS "${CMAKE_MATCH_1}" ) + # absolute path (shared lib): + set( ${PACKAGE}_${COMP_LIB}_LIBRARY "${CMAKE_MATCH_1}" ) + endif() + if (EXISTS "${COMP_LIB}" ) + # absolute path (static lib): + set( ${PACKAGE}_${COMP_LIB}_LIBRARY "${COMP_LIB}" ) + endif() + else() + # libname: + find_library(${PACKAGE}_${COMP_LIB}_LIBRARY NAMES ${COMP_LIB} HINTS ${${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARY_DIRS}) + endif() if(${PACKAGE}_${COMP_LIB}_LIBRARY) else(${PACKAGE}_${COMP_LIB}_LIBRARY) message(SEND_ERROR "In package >>>${PACKAGE}<<< : could not find library ${COMP_LIB} in directory ${${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARY_DIRS}, although its .pc file says it should be there.\n\n Try to do 'make clean; rm -rf lib' and then 'make' in the package >>>${PACKAGE}<<<.\n\n") endif(${PACKAGE}_${COMP_LIB}_LIBRARY) - list(APPEND ${PACKAGE}_LIBRARIES ${${PACKAGE}_${COMP_LIB}_LIBRARY}) + list(APPEND ${PACKAGE}_LIBRARIES "${${PACKAGE}_${COMP_LIB}_LIBRARY}") endforeach(COMP_LIB ${${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARIES}) # Add some output variables to the cache to make them accessible from outside this scope - set(${PACKAGE}_INCLUDE_DIRS ${${PACKAGE}_COMP_${OROCOS_TARGET}_INCLUDE_DIRS} CACHE INTERNAL "") - set(${PACKAGE}_LIBRARY_DIRS ${${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARY_DIRS} CACHE INTERNAL "") - set(${PACKAGE}_LIBRARIES ${${PACKAGE}_LIBRARIES} CACHE INTERNAL "") + set(${PACKAGE}_INCLUDE_DIRS "${${PACKAGE}_COMP_${OROCOS_TARGET}_INCLUDE_DIRS}" CACHE INTERNAL "") + set(${PACKAGE}_LIBRARY_DIRS "${${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARY_DIRS}" CACHE INTERNAL "") + set(${PACKAGE}_LIBRARIES "${${PACKAGE}_LIBRARIES}" CACHE INTERNAL "") + # The flags are space separated, so no need to quote here: set(${PACKAGE}_CFLAGS_OTHER ${${PACKAGE}_COMP_${OROCOS_TARGET}_CFLAGS_OTHER} CACHE INTERNAL "") set(${PACKAGE}_LDFLAGS_OTHER ${${PACKAGE}_COMP_${OROCOS_TARGET}_LDFLAGS_OTHER} CACHE INTERNAL "") # Add compiler and linker flags to the USE_OROCOS_XXX_FLAGS variables used in the orocos_add_x macros set(USE_OROCOS_COMPILE_FLAGS ${USE_OROCOS_COMPILE_FLAGS} ${${PACKAGE}_COMP_${OROCOS_TARGET}_CFLAGS_OTHER}) set(USE_OROCOS_LINK_FLAGS ${USE_OROCOS_LINK_FLAGS} ${${PACKAGE}_COMP_${OROCOS_TARGET}_LDFLAGS_OTHER}) + # This probably does not work since lists are ';' separated and not ' ' separated: list(REMOVE_DUPLICATES USE_OROCOS_COMPILE_FLAGS) list(REMOVE_DUPLICATES USE_OROCOS_LINK_FLAGS) @@ -130,11 +196,9 @@ macro( orocos_use_package PACKAGE ) endif (NOT OROCOS_NO_AUTO_LINKING AND ${PACKAGE}_COMP_${OROCOS_TARGET}_LIBRARIES) else (${PACKAGE}_COMP_${OROCOS_TARGET}_FOUND) - if (VERBOSE) message("[UseOrocos] ${PACKAGE} does not provide a .pc file for exporting its build/link flags (or one of it 'Requires' dependencies was not found).") - endif (VERBOSE) endif (${PACKAGE}_COMP_${OROCOS_TARGET}_FOUND) - + endif() endmacro( orocos_use_package PACKAGE ) macro(_orocos_list_to_string _string _list) diff --git a/UseOROCOS-RTT.cmake b/UseOROCOS-RTT.cmake index 846ce88c1..2a210fe39 100644 --- a/UseOROCOS-RTT.cmake +++ b/UseOROCOS-RTT.cmake @@ -20,25 +20,38 @@ if(OROCOS-RTT_FOUND) add_definitions(${OROCOS-RTT_DEFINITIONS}) set(ROS_ROOT $ENV{ROS_ROOT}) - if (ROS_ROOT AND NOT NO_ROS_PACKAGE ) - set(ROS_PACKAGE_PATH $ENV{ROS_PACKAGE_PATH}) - #In bash: for i in $(echo "$ROS_PACKAGE_PATH" | sed -e's/:/ /g'); do if expr match "`pwd`" "$i"; then is_ros_package=1; fi; done > /dev/null - string(REPLACE ":" ";" ROS_PACKAGE_PATH ${ROS_PACKAGE_PATH}) - foreach( rpath IN LISTS ROS_PACKAGE_PATH ) - # This is a bit tricky since overlapping directory names may give false positives: - file(TO_CMAKE_PATH ${rpath} path) # removes trailing '/' - #message(" ${rpath} -> ${path}") - if ( "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${path}" OR "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "${path}/" ) - set(IS_ROS_PACKAGE TRUE) - message("This package is in your ROS_PACKAGE_PATH, so I'm using rosbuild-style package building.") - + if (ROS_ROOT AND NOT NO_ROS_PACKAGE AND NOT NO_ROS_BUILD) + # If pre-groovy, we're using rosbuild + # Otherwise, we skip this whole rosbuild mess. + find_package(ROS QUIET) + if(NOT ROS_FOUND OR NOT catkin_FOUND) # pre-Groovy, use rosbuild + set(ROS_PACKAGE_PATH $ENV{ROS_PACKAGE_PATH}) + #In bash: for i in $(echo "$ROS_PACKAGE_PATH" | sed -e's/:/ /g'); do if expr match "`pwd`" "$i"; then is_ros_package=1; fi; done > /dev/null + string(REPLACE ":" ";" ROS_PACKAGE_PATH ${ROS_PACKAGE_PATH}) + foreach( rpath IN LISTS ROS_PACKAGE_PATH ) + # This is a bit tricky since overlapping directory names may give false positives: + file(TO_CMAKE_PATH ${rpath} path) # removes trailing '/' + #message(" ${rpath} -> ${path}") + if ( "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${path}" OR "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "${path}/" ) + set(IS_ROS_PACKAGE TRUE) + message("This package is in your ROS_PACKAGE_PATH, so I'm using rosbuild-style package building.") + endif() + endforeach() + if(NOT IS_ROS_PACKAGE) + message("ROS_ROOT was detected but this package is NOT in your ROS_PACKAGE_PATH. I'm not using any rosbuild-style building.") + # These were set by roscpp cmake macros: + unset( EXECUTABLE_OUTPUT_PATH ) + unset( LIBRARY_OUTPUT_PATH ) + endif() + else() + set (ROS_DISTRO $ENV{ROS_DISTRO}) + if ( ROS_DISTRO STREQUAL groovy ) + message("ROS_ROOT was detected, and Groovy was detected, assuming rosbuild-style (dry) building (no make install required). Set NO_ROS_BUILD to TRUE to use plain cmake or catkin 'wet' style building.") + set(IS_ROS_PACKAGE TRUE) + else() + #Hydro and later... + message("ROS_ROOT was detected, and catkin_FOUND was set, assuming catkin-style building (you'll need to make install).") endif() - endforeach() - if(NOT IS_ROS_PACKAGE) - message("ROS_ROOT was detected but this package is NOT in your ROS_PACKAGE_PATH. I'm not using any rosbuild-style building.") - # These were set by roscpp cmake macros: - unset( EXECUTABLE_OUTPUT_PATH ) - unset( LIBRARY_OUTPUT_PATH ) endif() endif() @@ -90,8 +103,10 @@ if(OROCOS-RTT_FOUND) endif(DEFINED ORO_DEFAULT_INSTALL_PREFIX) # Infer package name from directory name. - get_filename_component(orocos_package ${CMAKE_SOURCE_DIR} NAME) + get_filename_component(orocos_package ${PROJECT_SOURCE_DIR} NAME) message("[UseOrocos] Building package ${orocos_package}") + # Set to true to indicate that these macros are available. + set(USE_OROCOS_RTT 1) # By default, install libs in /target/ subdir in order to allow # multi-target installs. @@ -107,6 +122,14 @@ if(OROCOS-RTT_FOUND) rosbuild_init() endif() + if (CMAKE_EXTRA_GENERATOR STREQUAL "Eclipse CDT4") + message("Eclipse Generator detected. I'm setting EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH") + #set the default path for built executables to the "bin" directory + set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) + #set the default path for built libraries to the "lib" directory + set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) + endif() + # In ros builds, we need to set the pkg-config path such that RTT is found by # the typekit/typegen/pc files logic: set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${rtt_PACKAGE_PATH}/install/lib/pkgconfig") @@ -122,7 +145,7 @@ if(OROCOS-RTT_FOUND) else (IS_ROS_PACKAGE) # Fall back to 'manually' processing the manifest.xml file. orocos_get_manifest_deps( DEPS ) - #message("Dependencies are: ${DEPS}") + #message("orocos_get_manifest_deps are: ${DEPS}") foreach(DEP ${DEPS}) orocos_use_package( ${DEP} ) endforeach(DEP ${DEPS}) @@ -140,41 +163,6 @@ if(OROCOS-RTT_FOUND) endif(OROCOS_TARGET STREQUAL "win32") -# -# Include and link against required stuff -# -#From: http://www.cmake.org/Wiki/CMakeMacroParseArguments -MACRO(ORO_PARSE_ARGUMENTS prefix arg_names option_names) - SET(DEFAULT_ARGS) - FOREACH(arg_name ${arg_names}) - SET(${prefix}_${arg_name}) - ENDFOREACH(arg_name) - FOREACH(option ${option_names}) - SET(${prefix}_${option} FALSE) - ENDFOREACH(option) - - SET(current_arg_name DEFAULT_ARGS) - SET(current_arg_list) - FOREACH(arg ${ARGN}) - SET(larg_names ${arg_names}) - LIST(FIND larg_names "${arg}" is_arg_name) - IF (is_arg_name GREATER -1) - SET(${prefix}_${current_arg_name} ${current_arg_list}) - SET(current_arg_name ${arg}) - SET(current_arg_list) - ELSE (is_arg_name GREATER -1) - SET(loption_names ${option_names}) - LIST(FIND loption_names "${arg}" is_option) - IF (is_option GREATER -1) - SET(${prefix}_${arg} TRUE) - ELSE (is_option GREATER -1) - SET(current_arg_list ${current_arg_list} ${arg}) - ENDIF (is_option GREATER -1) - ENDIF (is_arg_name GREATER -1) - ENDFOREACH(arg) - SET(${prefix}_${current_arg_name} ${current_arg_list}) -ENDMACRO(ORO_PARSE_ARGUMENTS) - # Components should add themselves by calling 'OROCOS_COMPONENT' # instead of 'ADD_LIBRARY' in CMakeLists.txt. # You can set a variable COMPONENT_VERSION x.y.z to set a version or @@ -202,7 +190,7 @@ macro( orocos_component COMPONENT_NAME ) endif() # Set library name: - if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32") + if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32" OR ${OROCOS_TARGET} STREQUAL "macosx") set( COMPONENT_LIB_NAME ${COMPONENT_NAME}-${OROCOS_TARGET}) else() set( COMPONENT_LIB_NAME ${COMPONENT_NAME}) @@ -238,6 +226,12 @@ macro( orocos_component COMPONENT_NAME ) INSTALL_RPATH_USE_LINK_PATH 1 INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib/orocos${OROCOS_SUFFIX};${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" ) + if(APPLE) + SET_TARGET_PROPERTIES( ${COMPONENT_NAME} PROPERTIES + INSTALL_NAME_DIR "@rpath" + LINK_FLAGS "-Wl,-rpath,${CMAKE_INSTALL_PREFIX}/lib/orocos${OROCOS_SUFFIX},-rpath,${CMAKE_INSTALL_PREFIX}/lib,-rpath,${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" + ) + endif() orocos_add_compile_flags(${COMPONENT_NAME} ${USE_OROCOS_COMPILE_FLAGS}) orocos_add_link_flags(${COMPONENT_NAME} ${USE_OROCOS_LINK_FLAGS}) TARGET_LINK_LIBRARIES( ${COMPONENT_NAME} ${OROCOS-RTT_LIBRARIES} ) #${OROCOS-RTT_TYPEKIT_LIBRARIES} ) @@ -282,7 +276,7 @@ macro( orocos_library LIB_TARGET_NAME ) set(AC_INSTALL_RT_DIR bin) endif() - if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32") + if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32" OR ${OROCOS_TARGET} STREQUAL "macosx") set( LIB_NAME ${LIB_TARGET_NAME}-${OROCOS_TARGET}) else() set( LIB_NAME ${LIB_TARGET_NAME}) @@ -311,6 +305,12 @@ macro( orocos_library LIB_TARGET_NAME ) INSTALL_RPATH_USE_LINK_PATH 1 INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" ) + if(APPLE) + SET_TARGET_PROPERTIES( ${LIB_TARGET_NAME} PROPERTIES + INSTALL_NAME_DIR "@rpath" + LINK_FLAGS "-Wl,-rpath,${CMAKE_INSTALL_PREFIX}/lib,-rpath,${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" + ) + endif() orocos_add_compile_flags(${LIB_TARGET_NAME} ${USE_OROCOS_COMPILE_FLAGS}) orocos_add_link_flags(${LIB_TARGET_NAME} ${USE_OROCOS_LINK_FLAGS}) TARGET_LINK_LIBRARIES( ${LIB_TARGET_NAME} ${OROCOS-RTT_LIBRARIES} ) #${OROCOS-RTT_TYPEKIT_LIBRARIES} ) @@ -344,7 +344,7 @@ macro( orocos_executable EXE_TARGET_NAME ) set(AC_INSTALL_RT_DIR bin) endif() - if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32") + if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32" OR ${OROCOS_TARGET} STREQUAL "macosx") set( EXE_NAME ${EXE_TARGET_NAME}-${OROCOS_TARGET}) else() set( EXE_NAME ${EXE_TARGET_NAME}) @@ -361,9 +361,16 @@ macro( orocos_executable EXE_TARGET_NAME ) INSTALL_RPATH_USE_LINK_PATH 1 INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/bin;${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" ) - if(CMAKE_DEBUG_POSTFIX) - set_target_properties( ${EXE_TARGET_NAME} PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) - endif(CMAKE_DEBUG_POSTFIX) + if(APPLE) + SET_TARGET_PROPERTIES( ${EXE_TARGET_NAME} PROPERTIES + INSTALL_NAME_DIR "@rpath" + LINK_FLAGS "-Wl,-rpath,${CMAKE_INSTALL_PREFIX}/bin,-rpath,${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" + ) + endif() + + if(CMAKE_DEBUG_POSTFIX) + set_target_properties( ${EXE_TARGET_NAME} PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) + endif(CMAKE_DEBUG_POSTFIX) orocos_add_compile_flags(${EXE_TARGET_NAME} ${USE_OROCOS_COMPILE_FLAGS}) orocos_add_link_flags(${EXE_TARGET_NAME} ${USE_OROCOS_LINK_FLAGS}) @@ -378,13 +385,31 @@ endmacro( orocos_executable ) # Type headers should add themselves by calling 'orocos_typegen_headers()' # They will be processed by typegen to generate a typekit from it, with the -# name of the current project. +# name of the current project. You may also pass additional options to typegen +# before listing your header files. +# +# Use 'DEPENDS ...' to add dependencies on other (typegen) packages. +# This macro passes the -x OROCOS_TARGET flag to typegen automatically, so there +# is no need to include the -OROCOS_TARGET suffix in the +# +# NOTE: if you use a subdir for your headers, e.g. include/robotdata.hpp, it +# will install this header into pkgname/include/robotdata.hpp ! Most likely +# not what you want. So call this macro from the include dir itself. # -# Usage: orocos_typegen_headers( robotdata.hpp sensordata.hpp ) +# Usage: orocos_typegen_headers( robotdata.hpp sensordata.hpp DEPENDS orocos_kdl ) # macro( orocos_typegen_headers ) - MESSAGE( "[UseOrocos] Generating typekit for ${PROJECT_NAME}..." ) + ORO_PARSE_ARGUMENTS(ORO_TYPEGEN_HEADERS + "DEPENDS" + "" + ${ARGN} + ) + + if ( ORO_TYPEGEN_HEADERS_DEPENDS ) + set (ORO_TYPEGEN_HEADERS_DEP_INFO_MSG "using: ${ORO_TYPEGEN_HEADERS_DEP_INFO_MSG}") + endif() + MESSAGE( "[UseOrocos] Generating typekit for ${PROJECT_NAME} ${ORO_TYPEGEN_HEADERS_DEP_INFO_MSG}..." ) # Works in top level source dir: find_program(TYPEGEN_EXE typegen) @@ -392,12 +417,18 @@ macro( orocos_typegen_headers ) message(FATAL_ERROR "'typegen' not found in path. Can't build typekit. Did you 'source env.sh' ?") else (NOT TYPEGEN_EXE) - execute_process( COMMAND ${TYPEGEN_EXE} --output typekit ${PROJECT_NAME} ${ARGN} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + foreach( IMP ${ORO_TYPEGEN_HEADERS_DEPENDS} ) + set(ORO_TYPEGEN_HEADERS_IMPORTS "${ORO_TYPEGEN_HEADERS_IMPORTS} -i ${IMP}" ) + endforeach() + # Working directory is necessary to be able to find the source files. + execute_process( COMMAND ${TYPEGEN_EXE} --output ${PROJECT_SOURCE_DIR}/typekit ${PROJECT_NAME} ${ORO_TYPEGEN_HEADERS_IMPORTS} ${ORO_TYPEGEN_HEADERS_DEFAULT_ARGS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) + # work around generated manifest.xml file: - execute_process( COMMAND ${CMAKE} remove -f typekit/manifest.xml ) - add_subdirectory( typekit ) + execute_process( COMMAND ${CMAKE_COMMAND} -E remove -f ${PROJECT_SOURCE_DIR}/typekit/manifest.xml ) + add_subdirectory( ${PROJECT_SOURCE_DIR}/typekit ${PROJECT_BINARY_DIR}/typekit) + list(APPEND OROCOS_DEFINED_TYPES " -l${PROJECT_NAME}-typekit-${OROCOS_TARGET}") endif (NOT TYPEGEN_EXE) endmacro( orocos_typegen_headers ) @@ -432,7 +463,7 @@ macro( orocos_typekit LIB_TARGET_NAME ) set( LIB_COMPONENT_VERSION VERSION ${ORO_TYPEKIT_VERSION}) endif(ORO_TYPEKIT_VERSION) - if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32") + if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32" OR ${OROCOS_TARGET} STREQUAL "macosx") set( LIB_NAME ${LIB_TARGET_NAME}-${OROCOS_TARGET}) else() set( LIB_NAME ${LIB_TARGET_NAME}) @@ -456,6 +487,13 @@ macro( orocos_typekit LIB_TARGET_NAME ) INSTALL_RPATH_USE_LINK_PATH 1 INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/lib/orocos${OROCOS_SUFFIX}/types;${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" ) + if(APPLE) + SET_TARGET_PROPERTIES( ${LIB_TARGET_NAME} PROPERTIES + INSTALL_NAME_DIR "@rpath" + LINK_FLAGS "-Wl,-rpath,${CMAKE_INSTALL_PREFIX}/lib,-rpath,${CMAKE_INSTALL_PREFIX}/lib/orocos${OROCOS_SUFFIX}/types,-rpath,${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" + ) + endif() + TARGET_LINK_LIBRARIES( ${LIB_TARGET_NAME} ${OROCOS-RTT_LIBRARIES} ) # On win32, typekit runtime (.dll) should go in orocos/types folder @@ -501,7 +539,7 @@ macro( orocos_plugin LIB_TARGET_NAME ) set( LIB_COMPONENT_VERSION VERSION ${ORO_PLUGIN_VERSION}) endif(ORO_PLUGIN_VERSION) - if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32") + if ( ${OROCOS_TARGET} STREQUAL "gnulinux" OR ${OROCOS_TARGET} STREQUAL "lxrt" OR ${OROCOS_TARGET} STREQUAL "xenomai" OR ${OROCOS_TARGET} STREQUAL "win32" OR ${OROCOS_TARGET} STREQUAL "macosx") set( LIB_NAME ${LIB_TARGET_NAME}-${OROCOS_TARGET}) else() set( LIB_NAME ${LIB_TARGET_NAME}) @@ -526,6 +564,12 @@ macro( orocos_plugin LIB_TARGET_NAME ) INSTALL_RPATH_USE_LINK_PATH 1 INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/lib/orocos${OROCOS_SUFFIX}/plugins;${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" ) + if(APPLE) + SET_TARGET_PROPERTIES( ${LIB_TARGET_NAME} PROPERTIES + INSTALL_NAME_DIR "@rpath" + LINK_FLAGS "-Wl,-rpath,${CMAKE_INSTALL_PREFIX}/lib,-rpath,${CMAKE_INSTALL_PREFIX}/lib/orocos${OROCOS_SUFFIX}/plugins,-rpath,${CMAKE_INSTALL_PREFIX}/${AC_INSTALL_DIR}" + ) + endif() orocos_add_compile_flags(${LIB_TARGET_NAME} ${USE_OROCOS_COMPILE_FLAGS}) orocos_add_link_flags(${LIB_TARGET_NAME} ${USE_OROCOS_LINK_FLAGS}) TARGET_LINK_LIBRARIES( ${LIB_TARGET_NAME} ${OROCOS-RTT_LIBRARIES} ) #${OROCOS-RTT_TYPEKIT_LIBRARIES} ) diff --git a/config/FindRoslib.cmake b/config/FindRoslib.cmake index 9ce6145bc..f76f87442 100644 --- a/config/FindRoslib.cmake +++ b/config/FindRoslib.cmake @@ -2,21 +2,8 @@ IF ( ROSLIB_SUPPORT ) # Catkin style of fetching ROS deps - FIND_PACKAGE( ROS QUIET COMPONENTS roslib ) + FIND_PACKAGE( ROS QUIET COMPONENTS rospack) - IF(NOT ROS_FOUND) # pre-Fuerte - # TODO: This block to get roslib is deprecated as of ROS Fuerte, but is left in for pre-Fuerte compatibility - set(roslib_PACKAGE_PATH ${ROS_ROOT}/core/roslib) ### XXX hardcoded - message("Falling back to roslib in: ${roslib_PACKAGE_PATH}") - find_library(ROS_LIBRARIES roslib ${roslib_PACKAGE_PATH}/lib ) - if ( NOT ROS_LIBRARIES ) - find_package( ROS COMPONENTS roslib ) # Yells at user (non-QUIET !) - else() - set(ROS_FOUND TRUE) - set(ROS_INCLUDE_DIRS ${roslib_PACKAGE_PATH}/include) - endif() - ENDIF(NOT ROS_FOUND) - IF(ROS_FOUND) include_directories( ${ROS_INCLUDE_DIRS} ) add_definitions( -DHAS_ROSLIB ) diff --git a/config/FindXenomai.cmake b/config/FindXenomai.cmake index 34d7c7ee2..8ea44c951 100644 --- a/config/FindXenomai.cmake +++ b/config/FindXenomai.cmake @@ -1,6 +1,6 @@ ################################################################################ # -# CMake script for finding XENOMAI. +# CMake script for finding the XENOMAI native skin. # If the optional XENOMAI_ROOT_DIR environment variable exists, header files and # libraries will be searched in the XENOMAI_ROOT_DIR/include and XENOMAI_ROOT_DIR/lib # directories, respectively. Otherwise the default CMake search process will be @@ -21,6 +21,14 @@ if(NOT $ENV{XENOMAI_ROOT_DIR} STREQUAL "") mark_as_advanced(XENOMAI_ROOT_DIR) endif() +if ( Xenomai_FIND_QUIETLY ) + set( XENOMAI_FIND_QUIETLY "QUIET") +endif() + +if ( Xenomai_FIND_REQUIRED ) + set( XENOMAI_FIND_REQUIRED "REQUIRED") +endif() + # Header files to find set(header_NAME native/task.h) @@ -31,16 +39,26 @@ set(XENOMAI_NATIVE_NAME native) # Find headers and libraries if(XENOMAI_ROOT_DIR) # Use location specified by environment variable + find_program(XENOMAI_XENO_CONFIG NAMES xeno-config PATHS ${XENOMAI_ROOT_DIR}/bin NO_DEFAULT_PATH) find_path(XENOMAI_INCLUDE_DIR NAMES ${header_NAME} PATHS ${XENOMAI_ROOT_DIR}/include PATH_SUFFIXES xenomai NO_DEFAULT_PATH) find_library(XENOMAI_LIBRARY NAMES ${XENOMAI_NAME} PATHS ${XENOMAI_ROOT_DIR}/lib NO_DEFAULT_PATH) find_library(XENOMAI_NATIVE_LIBRARY NAMES ${XENOMAI_NATIVE_NAME} PATHS ${XENOMAI_ROOT_DIR}/lib NO_DEFAULT_PATH) else() # Use default CMake search process + find_program(XENOMAI_XENO_CONFIG NAMES xeno-config ) find_path(XENOMAI_INCLUDE_DIR NAMES ${header_NAME} PATH_SUFFIXES xenomai ) find_library(XENOMAI_LIBRARY NAMES ${XENOMAI_NAME}) find_library(XENOMAI_NATIVE_LIBRARY NAMES ${XENOMAI_NATIVE_NAME}) endif() +if( XENOMAI_LIBRARY AND XENOMAI_INCLUDE_DIR AND NOT XENOMAI_XENO_CONFIG ) + message(SEND_ERROR "Your Xenomai installation is broken: I can not determine Xenomai Native cflags/ldflags without xeno-config.") +else() + execute_process(COMMAND ${XENOMAI_XENO_CONFIG} --skin=native --ldflags OUTPUT_VARIABLE XENOMAI_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${XENOMAI_XENO_CONFIG} --skin=native --cflags OUTPUT_VARIABLE XENOMAI_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + + # Set the include dir variables and the libraries and let libfind_process do the rest. # NOTE: Singular variables for this library, plural for libraries this this lib depends on. set(XENOMAI_PROCESS_INCLUDES XENOMAI_INCLUDE_DIR) diff --git a/config/FindXenomaiPosix.cmake b/config/FindXenomaiPosix.cmake index 1b6e49b88..942208584 100644 --- a/config/FindXenomaiPosix.cmake +++ b/config/FindXenomaiPosix.cmake @@ -1,6 +1,6 @@ ################################################################################ # -# CMake script for finding XENOMAI. +# CMake script for finding the XENOMAI Posix skin. # If the optional XENOMAI_ROOT_DIR environment variable exists, header files and # libraries will be searched in the XENOMAI_ROOT_DIR/include and XENOMAI_ROOT_DIR/lib # directories, respectively. Otherwise the default CMake search process will be @@ -16,9 +16,17 @@ include(LibFindMacros) # Get hint from environment variable (if any) -if(NOT $ENV{XENOMAI_POSIX_ROOT_DIR} STREQUAL "") - set(XENOMAI_POSIX_ROOT_DIR $ENV{XENOMAI_POSIX_ROOT_DIR} CACHE PATH "Xenomai Posix base directory location (optional, used for nonstandard installation paths)" FORCE) - mark_as_advanced(XENOMAI_POSIX_ROOT_DIR) +if(NOT $ENV{XENOMAI_ROOT_DIR} STREQUAL "") + set(XENOMAI_ROOT_DIR $ENV{XENOMAI_ROOT_DIR} CACHE PATH "Xenomai Posix base directory location (optional, used for nonstandard installation paths)" FORCE) + mark_as_advanced(XENOMAI_ROOT_DIR) +endif() + +if ( XenomaiPosix_FIND_QUIETLY ) + set( XENOMAI_POSIX_FIND_QUIETLY "QUIET") +endif() + +if ( XenomaiPosix_FIND_REQUIRED ) + set( XENOMAI_POSIX_FIND_REQUIRED "REQUIRED") endif() # Header files to find @@ -28,11 +36,11 @@ set(header_NAME pthread.h) set(XENOMAI_POSIX_NAME pthread_rt) # Find headers and libraries -if(XENOMAI_POSIX_ROOT_DIR) +if(XENOMAI_ROOT_DIR) # Use location specified by environment variable - find_program(XENOMAI_XENO_CONFIG NAMES xeno-config PATHS ${XENOMAI_POSIX_ROOT_DIR}/bin NO_DEFAULT_PATH) - find_path(XENOMAI_POSIX_INCLUDE_DIR NAMES ${header_NAME} PATHS ${XENOMAI_POSIX_ROOT_DIR}/include PATH_SUFFIXES xenomai/posix NO_DEFAULT_PATH) - find_library(XENOMAI_POSIX_LIBRARY NAMES ${XENOMAI_POSIX_NAME} PATHS ${XENOMAI_POSIX_ROOT_DIR}/lib NO_DEFAULT_PATH) + find_program(XENOMAI_XENO_CONFIG NAMES xeno-config PATHS ${XENOMAI_ROOT_DIR}/bin NO_DEFAULT_PATH) + find_path(XENOMAI_POSIX_INCLUDE_DIR NAMES ${header_NAME} PATHS ${XENOMAI_ROOT_DIR}/include PATH_SUFFIXES xenomai/posix NO_DEFAULT_PATH) + find_library(XENOMAI_POSIX_LIBRARY NAMES ${XENOMAI_POSIX_NAME} PATHS ${XENOMAI_ROOT_DIR}/lib NO_DEFAULT_PATH) else() # Use default CMake search process find_program(XENOMAI_XENO_CONFIG NAMES xeno-config ) @@ -43,8 +51,8 @@ endif() if( XENOMAI_POSIX_LIBRARY AND XENOMAI_POSIX_INCLUDE_DIR AND NOT XENOMAI_XENO_CONFIG ) message(SEND_ERROR "Your Xenomai installation is broken: I can not determine Xenomai POSIX cflags/ldflags without xeno-config.") else() - execute_process(COMMAND ${XENOMAI_XENO_CONFIG} --posix-ldflags OUTPUT_VARIABLE XENOMAI_POSIX_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND ${XENOMAI_XENO_CONFIG} --posix-cflags OUTPUT_VARIABLE XENOMAI_POSIX_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${XENOMAI_XENO_CONFIG} --skin=posix --ldflags OUTPUT_VARIABLE XENOMAI_POSIX_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${XENOMAI_XENO_CONFIG} --skin=posix --cflags OUTPUT_VARIABLE XENOMAI_POSIX_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE) endif() # Set the include dir variables and the libraries and let libfind_process do the rest. diff --git a/config/LibFindMacros.cmake b/config/LibFindMacros.cmake index db880c19b..5c648ff6e 100644 --- a/config/LibFindMacros.cmake +++ b/config/LibFindMacros.cmake @@ -71,7 +71,7 @@ macro (libfind_process PREFIX) foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS}) message("${i}=${${i}}") endforeach (i) - message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use the ${PREFIX}_ROOT_DIR environment variable or ccmake to set the missing variables manually.") + message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, set the ${PREFIX}_ROOT_DIR environment variable or use cmake to set the missing variables manually.") else (${PREFIX}_FIND_REQUIRED) # NOTE: else case not included in original file message (STATUS "Optional library ${PREFIX} NOT FOUND. If the library is already installed, use the ${PREFIX}_ROOT_DIR environment variable or ccmake to set the missing variables manually.") endif (${PREFIX}_FIND_REQUIRED) diff --git a/config/check_depend.cmake b/config/check_depend.cmake index f3a9a4b0a..ee8ea5dc3 100644 --- a/config/check_depend.cmake +++ b/config/check_depend.cmake @@ -69,6 +69,7 @@ if(Boost_INCLUDE_DIR) if(OROCOS_TARGET STREQUAL "win32") add_definitions(-DBOOST_ALL_NO_LIB) endif() + # We don't link with boost here. It depends on the options set by the user. #list(APPEND OROCOS-RTT_LIBRARIES ${Boost_LIBRARIES} ) else(Boost_INCLUDE_DIR) @@ -111,6 +112,10 @@ endif(XERCES_FOUND) message("Orocos target is ${OROCOS_TARGET}") string(TOUPPER ${OROCOS_TARGET} OROCOS_TARGET_CAP) +if ( NOT ";lxrt;gnulinux;xenomai;macosx;win32;" MATCHES ".*;${OROCOS_TARGET};.*") + message( FATAL_ERROR "OROCOS_TARGET=${OROCOS_TARGET} is an unkown target. Please use one of lxrt;gnulinux;xenomai;macosx;win32.") +endif() + # Setup flags for RTAI/LXRT if(OROCOS_TARGET STREQUAL "lxrt") set(OROPKG_OS_LXRT TRUE CACHE INTERNAL "This variable is exported to the rtt-config.h file to expose our target choice to the code." FORCE) @@ -144,10 +149,13 @@ if(OROCOS_TARGET STREQUAL "xenomai") add_definitions( -Wall ) if(XENOMAI_FOUND) - list(APPEND OROCOS-RTT_USER_LINK_LIBS ${XENOMAI_LIBRARIES} ) # For libraries used in inline (fosi/template) code. + # Input for .pc and .cmake generated files: list(APPEND OROCOS-RTT_INCLUDE_DIRS ${XENOMAI_INCLUDE_DIRS} ${PTHREAD_INCLUDE_DIRS}) list(APPEND OROCOS-RTT_LIBRARIES ${XENOMAI_LIBRARIES} ${PTHREAD_LIBRARIES} dl) list(APPEND OROCOS-RTT_DEFINITIONS "OROCOS_TARGET=${OROCOS_TARGET}") + # Direct input only for .pc file: + list(APPEND RTT_USER_LDFLAGS ${XENOMAI_LDFLAGS} ) + list(APPEND RTT_USER_CFLAGS ${XENOMAI_CFLAGS} ) if (XENOMAI_POSIX_FOUND) set(MQ_LDFLAGS ${XENOMAI_POSIX_LDFLAGS} ) set(MQ_CFLAGS ${XENOMAI_POSIX_CFLAGS} ) @@ -187,11 +195,14 @@ if(OROCOS_TARGET STREQUAL "macosx") message(SEND_ERROR "Boost thread library not found but required on macosx.") endif () - list(APPEND OROCOS-RTT_INCLUDE_DIRS ${Boost_THREAD_INCLUDE_DIRS} ) + list(APPEND OROCOS-RTT_INCLUDE_DIRS ${Boost_THREAD_INCLUDE_DIRS} ${Boost_SYSTEM_INCLUDE_DIRS} ) SELECT_ONE_LIBRARY("Boost_THREAD_LIBRARY" BOOST_THREAD_LIB) LIST(APPEND OROCOS-RTT_USER_LINK_LIBS ${BOOST_THREAD_LIB}) + SELECT_ONE_LIBRARY("Boost_SYSTEM_LIBRARY" BOOST_SYSTEM_LIB) + LIST(APPEND OROCOS-RTT_USER_LINK_LIBS ${BOOST_SYSTEM_LIB}) + message( "Forcing ORO_OS_USE_BOOST_THREAD to ON") set( ORO_OS_USE_BOOST_THREAD ON CACHE BOOL "Forced enable use of Boost.thread on macosx." FORCE) @@ -202,6 +213,7 @@ if(OROCOS_TARGET STREQUAL "macosx") # see also src/CMakeLists.txt as it adds the boost_thread library to OROCOS_RTT_LIBRARIES list(APPEND OROCOS-RTT_LIBRARIES ${PTHREAD_LIBRARIES} dl) list(APPEND OROCOS-RTT_DEFINITIONS "OROCOS_TARGET=${OROCOS_TARGET}") + else() set(OROPKG_OS_MACOSX FALSE CACHE INTERNAL "" FORCE) endif() @@ -261,7 +273,7 @@ else(OROCOS_TARGET STREQUAL "win32") endif(OROCOS_TARGET STREQUAL "win32") if( NOT OROCOS-RTT_DEFINITIONS ) - message(FATAL_ERROR "No suitable OROCOS_TARGET selected. Use one of 'lxrt,xenomai,gnulinux,macosx,win32'") + message(FATAL_ERROR "No suitable OROCOS_TARGET found. Please check your setup or provide additional search paths to cmake.") endif() # The machine type is tested using compiler macros in rtt-config.h.in diff --git a/debian/changelog b/debian/changelog index b44fea534..ab60eb704 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +orocos-rtt (2.6.0-0) precise; urgency=low + + * New upstream release + + -- Peter Soetens Thu, 29 Nov 2012 23:27:00 +0100 + orocos-rtt (2.5.0-1) natty; urgency=low * New upstream release diff --git a/debian/liborocos-rtt-common-dev.install b/debian/liborocos-rtt-common-dev.install index ff14e65dd..5e036ff9f 100644 --- a/debian/liborocos-rtt-common-dev.install +++ b/debian/liborocos-rtt-common-dev.install @@ -51,6 +51,7 @@ usr/include/rtt/transports/mqueue/MQSendRecv.hpp usr/include/rtt/transports/mqueue/MQLib.hpp usr/include/rtt/transports/mqueue/binary_data_archive.hpp usr/include/rtt/transports/mqueue/Dispatcher.hpp +usr/include/rtt/deployment/ComponentLoader.hpp usr/include/rtt/marsh usr/include/rtt/types usr/include/rtt/typekit @@ -58,6 +59,7 @@ usr/include/rtt/extras usr/include/rtt/plugin usr/include/rtt/scripting usr/include/rtt/internal +usr/include/rtt/deployment usr/include/rtt/Activity.hpp usr/include/rtt/ArgumentDescription.hpp usr/include/rtt/Attribute.hpp diff --git a/doc/xml/images/DeploymentLevels.svg b/doc/xml/images/DeploymentLevels.svg index 7c298a2e5..418912402 100644 --- a/doc/xml/images/DeploymentLevels.svg +++ b/doc/xml/images/DeploymentLevels.svg @@ -13,7 +13,7 @@ height="210mm" id="svg3778" sodipodi:version="0.32" - inkscape:version="0.47pre4 r22446" + inkscape:version="0.48.2 r9819" sodipodi:docname="DeploymentLevels.svg" inkscape:export-filename="/home/sspr/Projecten/OpenRTC/vdw-distributie/CoreVsContext.png" inkscape:export-xdpi="200" @@ -116,17 +116,22 @@ inkscape:pageshadow="2" inkscape:zoom="0.70529234" inkscape:cx="546.53442" - inkscape:cy="317.52938" + inkscape:cy="414.65223" inkscape:current-layer="layer1" id="namedview3782" - inkscape:window-width="1680" - inkscape:window-height="1000" - inkscape:window-x="-4" - inkscape:window-y="-3" + inkscape:window-width="1024" + inkscape:window-height="576" + inkscape:window-x="0" + inkscape:window-y="24" showguides="true" inkscape:guide-bbox="true" showgrid="false" - inkscape:window-maximized="1" /> + inkscape:window-maximized="1"> + + @@ -379,7 +384,9 @@ y="619.89178" x="70.517464" id="tspan3320" - sodipodi:role="line">TaskCores are non-distributable,TaskCores are non-distributable,A TaskContext is a distributableA TaskContext is a distributableaddLocalOperation(op) + y="30.512833">addLocalOperation(op) @@ -606,7 +617,9 @@ sodipodi:role="line" id="tspan4370" x="697.54706" - y="30.512833">addOperation(op) + y="30.512833">addOperation(op) Orocos Remoting Library:Orocos Transport: - Automatic proxy generation- User writes Orocos Transport- Automatic proxy generation- Remote interface browsing- Remote interface browsing- Scripting support- Scripting support- User defined types- User defined types- One library for all components- One library for all components and all data types + Operation<R(Arg)> op diff --git a/doc/xml/orocos-rtt-changes.xml b/doc/xml/orocos-rtt-changes.xml index fce94a2bf..2ce27cf74 100644 --- a/doc/xml/orocos-rtt-changes.xml +++ b/doc/xml/orocos-rtt-changes.xml @@ -3,8 +3,8 @@ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ Orocos"> - - + + ] > @@ -36,30 +36,63 @@ Toolchain 2.2 Changes Toolchain 2.3 Changes Toolchain 2.4 Changes + Toolchain 2.5 Changes
- Caveats + Important Caveats This release is binary incompatible with RTT &oldversion;.x. You need to recompile the whole toolchain and all your applications in order to use this release. - - Take care that all previously built components and plugins in the <install>/lib/orocos directory and subdirectories - are removed, since the plugin loader may not find older versions. Especially on 'ROS' systems, which have - such files in their <packagename>/lib/ directory. + Take care that all previously built components and plugins in the + <install>/lib/orocos directory and subdirectories are removed, since the component + and plugin loaders may get confused if older versions are found. - You can only attach one callback to an EvenPort, during the addEventPort() function call. - If you need multiple call-backs, you need to call these yourself from the function you've - provided to addEventPort(). In this regard, the port->getNewDataOnPortEvent() call has - been removed. You can enable it by defining ORO_SIGNALLING_PORTS in the cmake - configuration step, but this feature will be removed eventually. + The rttlua DeploymentComponent's name has been changed from "deployer" to "Deployer" in + order to be compatible with the existing deployer application. This change only influences + Lua users and requires each occurence of getPeer("deployer") to be changed by getPeer("Deployer"). + + + You can do the renaming in your existing source trees with this Shell command: + find . ! -path "*.git*" -name "*.lua" -print0 | xargs -0 sed -i "s/\"deployer\"/\"Deployer\"/g;s/\'deployer\'/\'Deployer\'/g" + + + + + + There was an API change in the (RTT internal) RTT::types::TypeInfo + class. If you inherited directly or indirectly from this class, you'll probably need to + inherit from RTT::types::TypeInfoGenerator instead and fabricate a + installTypeInfoObject() function. There is generally no change needed on your + side if you inherited from RTT::types::TemplateTypeInfo, + RTT::types::StructTypeInfo or similar classes, since these classes + have implemented installTypeInfoObject() function for you and inherit + from RTT::types::TypeInfoGenerator. + + + + + There was an API change in the (RTT internal) + RTT::marsh::PropertyLoader class. It requires now a TaskContext or + Service in the constructor and no longer as argument to the rest of the API. + + + + + We no longer load component libraries with the RTLD_GLOBAL flag. + + + + This means you must link + with all required libraries at link time, and not rely on symbol resolution during the + loading by the deployer. @@ -68,16 +101,14 @@ ROS Users - The Orocos Toolchain 2.5.x will only be released in ROS Electric. This comes with a - major overhaul of the Electric ROS integration packages of RTT. The ROS Wiki contains - the necessary upgrade steps you need to take to migrate existing code to the new ROS - package structure. ROS Wiki on rtt_ros_integration. + The Orocos Toolchain 2.6.x will only be released in ROS Fuerte and later. + - The Orocos-ROS integration and the Orocos Toolchain are available as Ubuntu packages - from http://packages.ros.org/ros/ubuntu distroname main. - See ROS Wiki on installing ROS. + We fixed issues of conflicting typekits (see more on that below). This means that its + allowed now to load typekits from ROS and non-ROS packages, describing the same + structs. @@ -87,43 +118,29 @@
Building - - - Switching between OROCOS_TARGET configurations is now more robust. - In environments where multiple OROCOS_TARGET are possible (for example xenomai/gnulinux), - the OROCOS_TARGET environment variable can be set and will be picked up by the UseOrocos.cmake - macros. - - ROS_ROOT is no longer influencing your build, unless you're in a ROS_PACKAGE_PATH - In &oldversion;, the build system would switch to ROS-style if the user had defined the - ROS_ROOT environment variable. In &version;, the build system will only switch if the - package being built is a ROS package, ie, it is underneath the ROS_PACKAGE_PATH. + The last cornercases of ROS_ROOT influencing our build behavior have been ironed out in this release. - This allows better integration with AutoProj. + This fixes integration issues with AutoProj. - ROS package builds no longer install in a <package>/install subdirectory - All Orocos Toolchain ROS packages now install in the <orocos-toolchain>/install directory. - As such both ROS and non-ROS builds have the same directory layout. You can still use 'rosrun' - to run an OCL program, since these are still available in the package as well. + RTT and OCL builds with clang++ 3.0 - This allows better integration with AutoProj. + This allows you to speed up RTT builds significantly. When you enabled CORBA, only the OMNIORB transport compiles fine + in clang. - RTT builds with clang++ 2.9 - This allows you to speed up RTT builds significantly. - - - This allows better integration with AutoProj. + It's now possible to create applications that setup a CORBA proxy, without + linking to TAO/OMNIORB directly, but only to the RTT corba transport. See the + RTT::corba::TaskContextFactory class. @@ -133,76 +150,70 @@ - An important fix was applied when two or more output ports were connected to one - input port, which led to dropping data samples from time to time. + A new connection type has been introduced, CIRCULAR_BUFFER + + + This new type can be used in the ConnPolicy.type field in order to have circular + buffers instead of the classical non-circular buffer. - -
-
- Data Types, Toolkits and Typekits - - The Typekits now support fixed size arrays better. Especially, there is no need anymore for having - one typekit for each size of an array. The ROS fixed-size array implementation in Electric makes use of - this feature. - For this, there was some class-reordering in the TypeInfo hierarchy, but it should remain transparant - for existing users. + Exceptions thrown in operations are now detected and handled. + + When an operation threw an exception, this resulted in undefined behavior. The exception is + now caught by RTT and the caller side receives an std::runtime_exception exception. + Passing exceptions is not supported, so this is a last-resort solution to cope with + misbehaving operations. + The ComponentLoader is from now on part of RTT instead of OCL. + + + This means you no longer need a DeploymentComponent to import typekits or component + packages.
- Operating Systems + Data Types, Toolkits and Typekits + We restructured typekits such that it is now allowed to load multiple typekits for the same type. - There were the usual fixes for new compilers or header locations for - all Operating Systems: Linux, Mac OS-X and Win32. + If these typekits name the type differently, the names will function as an alias. Also, + TypeInfo object pointers are now constant and can no longer become invalid in a running + application. The restructuring allows one to install a TypeInfo object and later-on + add features such as type decomposition or transports. The classical TypeInfo subclasses + all have been adapted, but if you created your own TypeInfo variant, you will need to + update your code minimally. - - - The CPU affinity Thread function for Xenomai is implemented but not yet stable. We - are delving into this but already provide it to allow more testing. + See the Caveats section above in case you wrote a custom typekit. - Xenomai threads now run with a default stack size of 128kb, instead of 32kb. This may still - be too little if you have scripts which load scripts or have heavy stack use. In that case, - use the RTT::os::Thread::setStackSize function before creating a new Thread/Activity. + The internal function getMember is now much more efficient and faster. - - - The Xenomai main() thread now runs with priority 0 instead of 10. Since this is the - thread which is doing all the setup work, it shouldn't have defaulted - to a real-time priority. - - - - - There have been a bunch of patches for Mac OS-X, but more testing is still necessary. + There's now also + a real-time version of getMember, if you provide it a ReferenceDataSource such that a + reference to the member can be given without allocating a DataSource for it.
- Orocos scripting + Operating Systems - RTT script functions can now be decorated with 'global', 'local' and 'export'. 'local' is the - default and keeps a function local to the scripting service. 'export' attaches the script - function to the interface of the component it belongs to. 'global' puts the function in - the GlobalService, such that other scripts in other components can use it directly, without - the need to refer to a component. + Creating a Linux thread now prints the TID or PID instead of the POSIX id, such that + RTT threads can be correlated to normal Unix tools such as top or ps. @@ -215,37 +226,32 @@ - Consult the LuaCookbook - for the latest changes + rttlua and tlsf-rttlua now support CORBA and Log4cpp logging as well. - The TLSF branch of Lua has been merged, which will allow hard real-time script execution in the near - future. Further minor releases will pollish this feature more. + tlsf-rttlua is now capable of executing RTT operations in hard real-time, as long + as they are assigned to an operation variable in a non-critical-time section. - Your scripts have now access to the RTT globals using the rtt.globals - table. These are the scheduler types, data flow & operations return codes and constants for initializing - ConnectionPolicy objects. + Consult the LuaCookbook + for the latest changes
- TimerComponent + Reporting - The TimerComponent was changed to have one port for each timer ID as well in addition to one port - for all timer ID's. This avoid spurious wake-ups (triggers and calls of updateHook() ) - of components waiting for timer events on event ports. - - - You are advised to update your deployment to make use of the new timer ports. + The reporting component has been rewritten (again) boosting its performance sometimes a + 1000-fold (but at least a 100-fold), especially when using the NetCDF reporting component. We can now reliably log + a dozen ports at 1kHz, using only 10% cpu on an Intel i7 system. @@ -255,25 +261,14 @@ - The Deployment XML format now also accepts an 'Affinity' field which allows to specify a - CPU mask on which the thread may run. - There is a new operation called 'setActivityOnCPU' which takes an affinity parameter - as well. - - - NOTE: this function is still experimental and not yet stable on Xenomai. + A -d or --daemon flag has been added to the deployer to let it + run in the background. You can use the new signal catching functions in the deployer + API to catch shutdown/restart signals. - -
-
- Reporting - - The reporting component has been rewritten such that it behaves consistently. When - being periodic, it will sample all input ports at the frequency it runs. When being - triggered, it will log the ports which have new data. + Two new operations were added: setFileDescriptorActivity and connectOperations. diff --git a/orocos-rtt-config.cmake b/orocos-rtt-config.cmake index 4fd69a500..0b6cbc108 100644 --- a/orocos-rtt-config.cmake +++ b/orocos-rtt-config.cmake @@ -107,10 +107,8 @@ if(NOT OROCOS-RTT_FOUND) # Import targets set(OROCOS-RTT_IMPORT_FILE "${SELF_DIR}/orocos-rtt-${OROCOS_TARGET}-libraries.cmake") -if (NOT EXISTS "${OROCOS-RTT_IMPORT_FILE}") - message(FATAL_ERROR "Could not find an OROCOS-RTT installation for the ${OROCOS_TARGET} target. Missing file: ${OROCOS-RTT_IMPORT_FILE}") -endif() -include("${OROCOS-RTT_IMPORT_FILE}") +if (EXISTS "${OROCOS-RTT_IMPORT_FILE}") + include("${OROCOS-RTT_IMPORT_FILE}") # Core RTT libraries set(OROCOS-RTT_TARGET "${PREFIX}orocos-rtt-${OROCOS_TARGET}_dynamic") @@ -142,6 +140,8 @@ if(TARGET ${OROCOS-RTT-MQUEUE_TARGET}) set(FOUND_TRANSPORTS "${FOUND_TRANSPORTS} mqueue") set(OROCOS-RTT_MQUEUE_LIBRARIES ${OROCOS-RTT-MQUEUE_TARGET}) endif() +endif() + # Definitions set(OROCOS-RTT_DEFINITIONS "-DOROCOS_TARGET=${OROCOS_TARGET}") diff --git a/orocos-rtt.default.cmake b/orocos-rtt.default.cmake index c3a9041cb..1373243d6 100644 --- a/orocos-rtt.default.cmake +++ b/orocos-rtt.default.cmake @@ -69,7 +69,7 @@ else() set(OROCOS_TARGET gnulinux CACHE STRING "${DOC_STRING}") endif() endif() - message( "No OROCOS_TARGET environment variable detected. Using: ${OROCOS_TARGET}") + message( "No OROCOS_TARGET environment variable set. Using: ${OROCOS_TARGET}") endif() # Useful for Windows/MSVC builds, sets all libraries and executables in one place. diff --git a/package.xml b/package.xml new file mode 100644 index 000000000..7532674f2 --- /dev/null +++ b/package.xml @@ -0,0 +1,29 @@ + + rtt + 2.6.0 + + Orocos/RTT component framework + + GPL v2 with linking exception + RTT Developers + RTT Developers + http://www.orocos.org/rtt + + cmake + + boost + omniorb + rospack + + boost + omniorb + rospack + + + + cmake + + + + + diff --git a/rtt/ConnPolicy.hpp b/rtt/ConnPolicy.hpp index cab1cbc10..764b997e8 100644 --- a/rtt/ConnPolicy.hpp +++ b/rtt/ConnPolicy.hpp @@ -49,10 +49,10 @@ namespace RTT { * behave. Various parameters are available: * *
    - *
  • the connection type: DATA or BUFFER. On a data connection, the reader will have + *
  • the connection type: DATA, BUFFER or CIRCULAR_BUFFER. On a data connection, the reader will have * only access to the last written value. On a buffered connection, a * \a size number of elements can be stored until the reader reads - * them. + * them. BUFFER drops newer samples on full, CIRCULAR_BUFFER drops older samples on full. *
  • the locking policy: LOCKED, LOCK_FREE or UNSYNC. This defines how locking is done in the * connection. For now, only three policies are available. LOCKED uses * mutexes, LOCK_FREE uses a lock free method and UNSYNC means there's no @@ -137,7 +137,7 @@ namespace RTT { */ explicit ConnPolicy(int type = DATA, int lock_policy = LOCK_FREE); - /** This is the type for the data holding element in the connection */ + /** DATA, BUFFER or CIRCULAR_BUFFER */ int type; /** If true, one should initialize the connection's value with the last * value written on the writer port. This is only possible if the writer diff --git a/rtt/ExecutionEngine.cpp b/rtt/ExecutionEngine.cpp index fa3f20913..4bde246b1 100644 --- a/rtt/ExecutionEngine.cpp +++ b/rtt/ExecutionEngine.cpp @@ -43,6 +43,7 @@ #include "rtt-fwd.hpp" #include "os/MutexLock.hpp" #include "internal/MWSRQueue.hpp" +#include "TaskContext.hpp" #include #include @@ -406,6 +407,15 @@ namespace RTT } void ExecutionEngine::setExceptionTask() { + std::string name; + TaskContext* tc = dynamic_cast(taskc); + if (tc) + name = tc->getName(); + else if (taskc) + name = "TaskCore"; + else + name = "GlobalEngine"; + log(Error) << "in "<exception(); } diff --git a/rtt/InputPort.hpp b/rtt/InputPort.hpp index 56bb6b418..d10c2ba4f 100644 --- a/rtt/InputPort.hpp +++ b/rtt/InputPort.hpp @@ -63,7 +63,6 @@ namespace RTT class InputPort : public base::InputPortInterface { friend class internal::ConnOutputEndpoint; - typename internal::InputPortSource::shared_ptr data_source; virtual bool connectionAdded( base::ChannelElementBase::shared_ptr channel_input, ConnPolicy const& policy ) { return true; } @@ -96,9 +95,9 @@ namespace RTT public: InputPort(std::string const& name = "unnamed", ConnPolicy const& default_policy = ConnPolicy()) : base::InputPortInterface(name, default_policy) - , data_source(0) {} + {} - virtual ~InputPort() { disconnect(); if (data_source) data_source->dropPort(); } + virtual ~InputPort() { disconnect(); } /** \overload */ FlowStatus read(base::DataSourceBase::shared_ptr source) @@ -174,6 +173,22 @@ namespace RTT return RTT::NewData; } + /** + * Get a sample of the data on this port, without actually reading the port's data. + * It's the complement of OutputPort::setDataSample() and serves to retrieve the size + * of a variable sized data type T. Returns default T if !connected() or if the + * OutputPort did not use setDataSample(). Returns an example T otherwise. + * In case multiple inputs are connected to this port a sample from the currently read + * connection will be returned. + */ + void getDataSample(T& sample) + { + typename base::ChannelElement::shared_ptr input = static_cast< base::ChannelElement* >( cmanager.getCurrentChannel() ); + if ( input ) { + sample = input->data_sample(); + } + } + /** Returns the types::TypeInfo object for the port's type */ virtual const types::TypeInfo* getTypeInfo() const { return internal::DataSourceTypeInfo::getTypeInfo(); } @@ -193,14 +208,11 @@ namespace RTT { return new OutputPort(this->getName()); } /** Returns a base::DataSourceBase interface to read this port. The returned - * data source is always the same object and will be destroyed when the - * port is destroyed. + * data source is always a new object. */ base::DataSourceBase* getDataSource() { - if (data_source) return data_source.get(); - data_source = new internal::InputPortSource(*this); - return data_source.get(); + return new internal::InputPortSource(*this); } virtual bool createStream(ConnPolicy const& policy) diff --git a/rtt/base/BufferInterface.hpp b/rtt/base/BufferInterface.hpp index fe666a781..ead17ba3c 100644 --- a/rtt/base/BufferInterface.hpp +++ b/rtt/base/BufferInterface.hpp @@ -131,6 +131,11 @@ namespace RTT * @nrt */ virtual void data_sample( const T& sample ) = 0; + + /** + * Reads back a data sample. + */ + virtual T data_sample() const = 0; }; }} diff --git a/rtt/base/BufferLockFree.hpp b/rtt/base/BufferLockFree.hpp index fbc4abcaa..8ad75b54e 100644 --- a/rtt/base/BufferLockFree.hpp +++ b/rtt/base/BufferLockFree.hpp @@ -100,6 +100,17 @@ namespace RTT mpool.data_sample(sample); } + virtual T data_sample() const + { + T result = T(); + Item* mitem = mpool.allocate(); + if (mitem != 0) { + result = *mitem; + mpool.deallocate( mitem ); + } + return result; + } + size_type capacity() const { diff --git a/rtt/base/BufferLocked.hpp b/rtt/base/BufferLocked.hpp index c14207be9..3e4a56ccf 100644 --- a/rtt/base/BufferLocked.hpp +++ b/rtt/base/BufferLocked.hpp @@ -84,6 +84,12 @@ namespace RTT { buf.resize(cap, sample); buf.resize(0); + lastSample = sample; + } + + virtual T data_sample() const + { + return lastSample; } /** diff --git a/rtt/base/BufferUnSync.hpp b/rtt/base/BufferUnSync.hpp index c006df5d2..741eb37e3 100644 --- a/rtt/base/BufferUnSync.hpp +++ b/rtt/base/BufferUnSync.hpp @@ -79,6 +79,11 @@ namespace RTT buf.resize(0); } + virtual T data_sample() const + { + return lastSample; + } + /** * Destructor */ diff --git a/rtt/base/ChannelElement.hpp b/rtt/base/ChannelElement.hpp index f03e856f4..20cd7faf0 100644 --- a/rtt/base/ChannelElement.hpp +++ b/rtt/base/ChannelElement.hpp @@ -87,6 +87,14 @@ namespace RTT { namespace base { return false; } + virtual value_t data_sample() + { + typename ChannelElement::shared_ptr input = boost::static_pointer_cast< ChannelElement >(getInput()); + if (input) + return input->data_sample(); + return value_t(); + } + /** Writes a new sample on this connection. \a sample is the sample to * write. * diff --git a/rtt/base/DataObjectUnSync.hpp b/rtt/base/DataObjectUnSync.hpp index 9f3d8dbe2..a235033c8 100644 --- a/rtt/base/DataObjectUnSync.hpp +++ b/rtt/base/DataObjectUnSync.hpp @@ -82,6 +82,12 @@ namespace RTT virtual void data_sample( const DataType& sample ) { Set(sample); } + + virtual T data_sample() const + { + return data; + } + }; }} diff --git a/rtt/base/DisposableInterface.hpp b/rtt/base/DisposableInterface.hpp index fb8a6a6e3..117048dd3 100644 --- a/rtt/base/DisposableInterface.hpp +++ b/rtt/base/DisposableInterface.hpp @@ -40,6 +40,7 @@ #define ORO_DISPOSABLEINTERFACE_HPP #include +#include "../rtt-config.h" namespace RTT { @@ -49,7 +50,7 @@ namespace RTT * @brief An object that is executable and * is freed after execution. */ - class DisposableInterface + class RTT_API DisposableInterface { public: /** diff --git a/rtt/base/InputPortInterface.cpp b/rtt/base/InputPortInterface.cpp index f5cc2bb60..dc11fe4a2 100644 --- a/rtt/base/InputPortInterface.cpp +++ b/rtt/base/InputPortInterface.cpp @@ -45,7 +45,7 @@ #include using namespace RTT; -using namespace detail; +using namespace RTT::detail; using namespace std; diff --git a/rtt/base/InputPortInterface.hpp b/rtt/base/InputPortInterface.hpp index 0ce671df4..b08fce40c 100644 --- a/rtt/base/InputPortInterface.hpp +++ b/rtt/base/InputPortInterface.hpp @@ -105,8 +105,7 @@ namespace RTT virtual bool removeConnection(internal::ConnID* cid); /** Returns a DataSourceBase interface to read this port. The returned - * data source is always the same object and will be destroyed when the - * port is destroyed. + * data source is always a new object. */ virtual DataSourceBase* getDataSource() = 0; diff --git a/rtt/base/OperationCallerBase.hpp b/rtt/base/OperationCallerBase.hpp index 98f3f15b8..eb5876048 100644 --- a/rtt/base/OperationCallerBase.hpp +++ b/rtt/base/OperationCallerBase.hpp @@ -69,7 +69,6 @@ namespace RTT */ virtual OperationCallerBase* cloneI(ExecutionEngine* caller) const = 0; - virtual void reportError() = 0; }; } } diff --git a/rtt/base/OperationCallerInterface.cpp b/rtt/base/OperationCallerInterface.cpp new file mode 100644 index 000000000..5f89f7729 --- /dev/null +++ b/rtt/base/OperationCallerInterface.cpp @@ -0,0 +1,55 @@ +#include "OperationCallerInterface.hpp" +#include "../internal/GlobalEngine.hpp" + +using namespace RTT; +using namespace base; +using namespace internal; + +OperationCallerInterface::OperationCallerInterface() + : myengine(0), caller(0), ownerEngine(0), met(OwnThread) +{} + +OperationCallerInterface::OperationCallerInterface(OperationCallerInterface const& orig) + : myengine(orig.myengine), caller(orig.caller), ownerEngine(orig.ownerEngine), met(orig.met) +{} + +OperationCallerInterface::~OperationCallerInterface() +{ +} + +void OperationCallerInterface::setOwner(ExecutionEngine* ee) { + ownerEngine = ee; +} + +void OperationCallerInterface::setExecutor(ExecutionEngine* ee) { + if (met == OwnThread) + myengine = ee; + else + myengine = GlobalEngine::Instance(); +} + +void OperationCallerInterface::setCaller(ExecutionEngine* ee) { + if (ee) + caller = ee; + else + caller = GlobalEngine::Instance(); +} + +bool OperationCallerInterface::setThread(ExecutionThread et, ExecutionEngine* executor) { + if ( !myengine && !caller && !ownerEngine ) + return false; // detect uninitialized object. This is actually a hack for RemoteOperationCaller. + met = et; + setExecutor(executor); + return true; +} + +// report an error if an exception was thrown while calling exec() +void OperationCallerInterface::reportError() { + // This localOperation was added to a TaskContext or to a Service owned by a TaskContext + if (this->ownerEngine != 0) + this->ownerEngine->setExceptionTask(); + // This operation is called through OperationCaller directly + else if (this->met == OwnThread) + this->myengine->setExceptionTask(); +} + diff --git a/rtt/base/OperationCallerInterface.hpp b/rtt/base/OperationCallerInterface.hpp index b00366498..395c6c151 100644 --- a/rtt/base/OperationCallerInterface.hpp +++ b/rtt/base/OperationCallerInterface.hpp @@ -12,7 +12,7 @@ namespace RTT /** * The interface class for operation callers. */ - struct OperationCallerInterface: public DisposableInterface + struct RTT_API OperationCallerInterface: public DisposableInterface { /** * Use this type for shared pointer storage of an @@ -20,9 +20,11 @@ namespace RTT */ typedef boost::shared_ptr shared_ptr; - virtual ~OperationCallerInterface() - { - } + OperationCallerInterface(); + + OperationCallerInterface(OperationCallerInterface const& orig); + + virtual ~OperationCallerInterface(); /** * Available such that implementations have a way to @@ -30,6 +32,13 @@ namespace RTT */ virtual bool ready() const = 0; + /** + * Set the ExecutionEngine of the task which owns this method. + * @param ee The ExecutionEngine of the component that + * owns this operation. + */ + void setOwner(ExecutionEngine* ee); + /** * Set an executor which will execute this method * when it is called or sent. If ee is set to 0, @@ -38,7 +47,7 @@ namespace RTT * @param ee The ExecutionEngine of the component that * is executing this operation. */ - virtual void setExecutor(ExecutionEngine* ee) = 0; + void setExecutor(ExecutionEngine* ee); /** * Sets the caller's engine of this operation. @@ -47,7 +56,7 @@ namespace RTT * @param ee The ExecutionEngine of the component that * is calling this operation. */ - virtual void setCaller(ExecutionEngine* ee) = 0; + void setCaller(ExecutionEngine* ee); /** * Sets the Thread execution policy of this object. @@ -57,8 +66,25 @@ namespace RTT * executor may be null. * @return false if it may not be modified. */ - virtual bool setThread(ExecutionThread et, - ExecutionEngine* executor) = 0; + bool setThread(ExecutionThread et, + ExecutionEngine* executor); + + /** + * Executed when the operation execution resulted in a + * C++ exception. Must report the error to the ExecutionEngine + * of the owner of this operation. + */ + void reportError(); + + /** + * Helpful function to tell us if this operations is to be sent or not. + */ + bool isSend() { return met == OwnThread && myengine != caller; } + protected: + ExecutionEngine* myengine; + ExecutionEngine* caller; + ExecutionEngine* ownerEngine; + ExecutionThread met; }; } } diff --git a/rtt/base/OutputPortInterface.cpp b/rtt/base/OutputPortInterface.cpp index 4db576d33..04a2334b2 100644 --- a/rtt/base/OutputPortInterface.cpp +++ b/rtt/base/OutputPortInterface.cpp @@ -43,7 +43,7 @@ #include using namespace RTT; -using namespace detail; +using namespace RTT::detail; using namespace std; diff --git a/rtt/deployment/CMakeLists.txt b/rtt/deployment/CMakeLists.txt index e35811e0d..cbdcc5ba7 100644 --- a/rtt/deployment/CMakeLists.txt +++ b/rtt/deployment/CMakeLists.txt @@ -1,20 +1,10 @@ if ( PLUGINS_ENABLE ) - # Do this first. + # See also plugin/CMakeLists.txt if (NOT DEFAULT_PLUGIN_PATH) - IF ( ROSLIB_SUPPORT ) - # Necessary when building Debian packages: - set(ROS_STACK_DIR_FINAL $ENV{ROS_STACK_DIR_FINAL}) - if (ROS_STACK_DIR_FINAL) - set(DEFAULT_COMPONENT_PATH "${ROS_STACK_DIR_FINAL}/orocos_toolchain/install/lib/orocos") - else(ROS_STACK_DIR_FINAL) - set(DEFAULT_COMPONENT_PATH "${PROJECT_SOURCE_DIR}/../install/lib/orocos" CACHE STRING "Default component lookup path when none given. (semi-)colon separated list." FORCE) - endif(ROS_STACK_DIR_FINAL) - ENDIF( ROSLIB_SUPPORT ) - - message("No default component path given, setting it to ${CMAKE_INSTALL_PREFIX}/lib/orocos.") - message("Define the DEFAULT_COMPONENT_PATH cmake variable to override this.") - set(DEFAULT_COMPONENT_PATH "${CMAKE_INSTALL_PREFIX}/lib/orocos") + set(DEFAULT_COMPONENT_PATH "${CMAKE_INSTALL_PREFIX}/lib/orocos") + else() + set(DEFAULT_COMPONENT_PATH "${DEFAULT_PLUGIN_PATH}") endif() configure_file( comppath.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/comppath.cpp @ONLY ) diff --git a/rtt/deployment/ComponentLoader.cpp b/rtt/deployment/ComponentLoader.cpp index 0171bf418..1341a1354 100644 --- a/rtt/deployment/ComponentLoader.cpp +++ b/rtt/deployment/ComponentLoader.cpp @@ -8,7 +8,7 @@ #include #ifdef HAS_ROSLIB -#include +#include #endif #ifndef _WIN32 @@ -353,7 +353,7 @@ bool ComponentLoader::import( std::string const& package, std::string const& pat { // check first for exact match to *file*: path arg( package ); - if (is_regular_file(arg)) { + if (is_regular_file(arg) && isLoadableLibrary(arg)) { #if BOOST_VERSION >= 104600 return loadInProcess(arg.string(), makeShortFilename( arg.filename().string() ), true); #else @@ -395,22 +395,37 @@ bool ComponentLoader::importRosPackage(std::string const& package) { // check for rospack #ifdef HAS_ROSLIB - using namespace ros::package; + using namespace rospack; try { bool found = false; - string ppath = getPath( package ); + Rospack rpack; + rpack.setQuiet(true); + char* rpp = getenv("ROS_PACKAGE_PATH"); + vector paths; + if (rpp) + paths = splitPaths(rpp); + string ppath; + rpack.crawl(paths,false); + rpack.find(package, ppath); if ( !ppath.empty() ) { path rospath = path(ppath) / "lib" / "orocos"; path rospath_target = rospath / OROCOS_TARGET_NAME; // + add all dependencies to paths: - V_string rospackresult; - command("depends " + package, rospackresult); - for(V_string::iterator it = rospackresult.begin(); it != rospackresult.end(); ++it) { + vector rospackresult; + rpack.setQuiet(false); + bool valid = rpack.deps(package, false, rospackresult); // false: also indirect deps. + if (!valid) { + log(Error) <<"The ROS package '"<< package <<"' in '"<< ppath << "' caused trouble. Bailing out."<::iterator it = rospackresult.begin(); it != rospackresult.end(); ++it) { if ( isImported(*it) ) { log(Debug) <<"Package dependency '"<< *it <<"' already imported." <value == ptr) + return; { os::MutexLock do_lock(safe->lock); if (safe->readers == 2) // we are sole owner diff --git a/rtt/internal/BindStorage.hpp b/rtt/internal/BindStorage.hpp index de7775a91..791d25126 100644 --- a/rtt/internal/BindStorage.hpp +++ b/rtt/internal/BindStorage.hpp @@ -70,7 +70,6 @@ namespace RTT T& get() { return arg; } void operator()(T a) { arg = a; } - operator T() { return arg;} }; @@ -84,26 +83,17 @@ namespace RTT T& get() { return *arg; } void operator()(T& a) { arg = &a; } - operator T&() { return *arg;} }; template std::ostream& operator<<(std::ostream& o, AStore& a) { o << "aarg:"< - struct RStore { - T arg; + template<> + struct RStore { bool executed; bool error; - RStore() : arg(), executed(false), error(false) {} + RStore() : executed(false), error(false) {} void checkError() const { if(error) throw std::runtime_error("Unable to complete the operation call. The called operation has thrown an exception"); @@ -117,10 +107,39 @@ namespace RTT return executed; } - //bool operator()() { return executed; } + template + void exec(F f) { + error = false; + try{ + f(); + } catch (std::exception& e) { + log(Error) << "Exception raised while executing an operation : " << e.what() << endlog(); + error = true; + } catch (...) { + log(Error) << "Unknown exception raised while executing an operation." << endlog(); + error = true; + } + executed = true; + } + + void result() { checkError(); return; } + }; + + + /** + * Store a return value which may be a void, reference, const reference or + * any other type. We need these specialisations because the collection + * of the results will be different if R is non-void or poid (appears as + * first arg of collect() or not respectively). So RStore is the only + * instance that knows if a return value was stored or not. + */ + template + struct RStore : public RStore { + T arg; + RStore() : arg() {} T& result() { checkError(); return arg; } - operator T&() { checkError(); return arg;} + operator T&() { return arg;} /** * Stores the result of a function. @@ -133,7 +152,11 @@ namespace RTT error = false; try{ arg = f(); + } catch (std::exception& e) { + log(Error) << "Exception raised while executing an operation : " << e.what() << endlog(); + error = true; } catch (...) { + log(Error) << "Unknown exception raised while executing an operation." << endlog(); error = true; } executed = true; @@ -141,31 +164,21 @@ namespace RTT }; template - struct RStore + struct RStore : public RStore { T* arg; - bool executed; - bool error; - RStore() : arg(), executed(false), error(false) {} - - void checkError() const { - if(error) throw std::runtime_error("Unable to complete the operation call. The called operation has thrown an exception"); - } - - bool isError() const { - return error; - } - - bool isExecuted() const { - return executed; - } + RStore() : arg() {} template void exec(F f) { error = false; try{ arg = &f(); - } catch(...) { + } catch (std::exception& e) { + log(Error) << "Exception raised while executing an operation : " << e.what() << endlog(); + error = true; + } catch (...) { + log(Error) << "Unknown exception raised while executing an operation." << endlog(); error = true; } executed = true; @@ -178,28 +191,12 @@ namespace RTT }; template - struct RStore { + struct RStore : public RStore { T arg; - bool executed; - bool error; - RStore() : arg(), executed(false), error(false) {} - - void checkError() const { - if(error) throw std::runtime_error("Unable to complete the operation call. The called operation has thrown an exception"); - } - - bool isError() const { - return error; - } - - bool isExecuted() const { - return executed; - } - - //bool operator()() { return executed; } + RStore() : arg() {} T& result() { checkError(); return arg; } - operator T&() { return arg;} + operator T&() { checkError(); return arg;} /** * Stores the result of a function. @@ -212,46 +209,16 @@ namespace RTT error = false; try{ arg = f(); - } catch(...) { + } catch (std::exception& e) { + log(Error) << "Exception raised while executing an operation : " << e.what() << endlog(); error = true; - } - executed = true; - } - - }; - - template<> - struct RStore { - bool executed; - bool error; - RStore() : executed(false), error(false) {} - - void checkError() const { - if(error) throw std::runtime_error("Unable to complete the operation call. The called operation has thrown an exception"); - } - - bool isError() const { - return error; - } - - bool isExecuted() const { - return executed; - } - - template - void exec(F f) { - error = false; - try{ - f(); } catch(...) { + log(Error) << "Unknown exception raised while executing an operation." << endlog(); error = true; } executed = true; } - //bool operator()() { return executed; } - - void result() { checkError(); return; } }; template diff --git a/rtt/internal/ChannelBufferElement.hpp b/rtt/internal/ChannelBufferElement.hpp index 4e143bdf6..c38a00704 100644 --- a/rtt/internal/ChannelBufferElement.hpp +++ b/rtt/internal/ChannelBufferElement.hpp @@ -118,6 +118,10 @@ namespace RTT { namespace internal { return base::ChannelElement::data_sample(sample); } + virtual T data_sample() + { + return buffer->data_sample(); + } }; }} diff --git a/rtt/internal/ChannelDataElement.hpp b/rtt/internal/ChannelDataElement.hpp index 6559f5d68..a6958de39 100644 --- a/rtt/internal/ChannelDataElement.hpp +++ b/rtt/internal/ChannelDataElement.hpp @@ -107,6 +107,11 @@ namespace RTT { namespace internal { return base::ChannelElement::data_sample(sample); } + virtual T data_sample() + { + return data->Get(); + } + }; }} diff --git a/rtt/internal/Collect.hpp b/rtt/internal/Collect.hpp index 516a54c94..99ed2e7d4 100644 --- a/rtt/internal/Collect.hpp +++ b/rtt/internal/Collect.hpp @@ -248,43 +248,6 @@ namespace RTT } }; - template - struct CollectImpl<7,Ft,BaseImpl> - : public BaseImpl - { - typedef typename boost::function::arg1_type arg1_type; - typedef typename boost::function::arg2_type arg2_type; - typedef typename boost::function::arg3_type arg3_type; - typedef typename boost::function::arg4_type arg4_type; - typedef typename boost::function::arg5_type arg5_type; - typedef typename boost::function::arg6_type arg6_type; - typedef typename boost::function::arg7_type arg7_type; - virtual ~CollectImpl() {} - - /** - * Collect F without returning the results. - * @return - */ - virtual SendStatus collect() - { - return BaseImpl::collect_impl(); - } - /** - * Collect a void(arg1_type) F or - * arg1_type(void) F - * @return - */ - virtual SendStatus collect(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7) - { - return BaseImpl::collect_impl(a1,a2,a3,a4,a5,a6,a7); - } - virtual SendStatus collectIfDone(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7) - { - return BaseImpl::collectIfDone_impl(a1,a2,a3,a4,a5,a6,a7); - } - }; - - template struct CollectImpl<5,Ft,BaseImpl> : public BaseImpl diff --git a/rtt/internal/CollectBase.hpp b/rtt/internal/CollectBase.hpp index 7be4dacd1..74ee0226d 100644 --- a/rtt/internal/CollectBase.hpp +++ b/rtt/internal/CollectBase.hpp @@ -152,6 +152,78 @@ namespace RTT virtual SendStatus collect(arg1_type a1, arg2_type a2, arg3_type a3) = 0; virtual SendStatus collectIfDone(arg1_type a1, arg2_type a2, arg3_type a3) = 0; }; + + template + struct CollectBaseImpl<4,Ft> + { + typedef typename boost::function::arg1_type arg1_type; + typedef typename boost::function::arg2_type arg2_type; + typedef typename boost::function::arg3_type arg3_type; + typedef typename boost::function::arg4_type arg4_type; + virtual ~CollectBaseImpl() {} + + /** + * Collect F without returning the results. + * @return + */ + virtual SendStatus collect() = 0; + /** + * Collect a void(arg1_type) F or + * arg1_type(void) F + * @return + */ + virtual SendStatus collect(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) = 0; + virtual SendStatus collectIfDone(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) = 0; + }; + + template + struct CollectBaseImpl<5,Ft> + { + typedef typename boost::function::arg1_type arg1_type; + typedef typename boost::function::arg2_type arg2_type; + typedef typename boost::function::arg3_type arg3_type; + typedef typename boost::function::arg4_type arg4_type; + typedef typename boost::function::arg5_type arg5_type; + virtual ~CollectBaseImpl() {} + + /** + * Collect F without returning the results. + * @return + */ + virtual SendStatus collect() = 0; + /** + * Collect a void(arg1_type) F or + * arg1_type(void) F + * @return + */ + virtual SendStatus collect(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5) = 0; + virtual SendStatus collectIfDone(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5) = 0; + }; + + template + struct CollectBaseImpl<6,Ft> + { + typedef typename boost::function::arg1_type arg1_type; + typedef typename boost::function::arg2_type arg2_type; + typedef typename boost::function::arg3_type arg3_type; + typedef typename boost::function::arg4_type arg4_type; + typedef typename boost::function::arg5_type arg5_type; + typedef typename boost::function::arg6_type arg6_type; + virtual ~CollectBaseImpl() {} + + /** + * Collect F without returning the results. + * @return + */ + virtual SendStatus collect() = 0; + /** + * Collect a void(arg1_type) F or + * arg1_type(void) F + * @return + */ + virtual SendStatus collect(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6) = 0; + virtual SendStatus collectIfDone(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6) = 0; + }; } } #endif diff --git a/rtt/internal/CollectSignature.hpp b/rtt/internal/CollectSignature.hpp index f89aed20b..7ea17b931 100644 --- a/rtt/internal/CollectSignature.hpp +++ b/rtt/internal/CollectSignature.hpp @@ -331,41 +331,6 @@ namespace RTT ToCollect cimpl; }; - template - struct CollectSignature<7,F,ToCollect> - { - typedef typename boost::function_traits::arg1_type arg1_type; - typedef typename boost::function_traits::arg2_type arg2_type; - typedef typename boost::function_traits::arg3_type arg3_type; - typedef typename boost::function_traits::arg4_type arg4_type; - typedef typename boost::function_traits::arg5_type arg5_type; - typedef typename boost::function_traits::arg6_type arg6_type; - typedef typename boost::function_traits::arg7_type arg7_type; - - CollectSignature() : cimpl() {} - CollectSignature(ToCollect implementation) : cimpl(implementation) {} - ~CollectSignature() { } - - /** - * Collect this operator if the method has four arguments. - */ - SendStatus collect(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4, arg5_type t5, arg6_type t6, arg7_type t7) - { - if (cimpl) - return cimpl->collect(t1, t2, t3, t4, t5, t6, t7); - return SendFailure; - } - - SendStatus collectIfDone(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4, arg5_type t5, arg6_type t6, arg7_type t7) - { - if (cimpl) - return cimpl->collect(t1, t2, t3, t4, t5, t6, t7); - return SendFailure; - } - protected: - ToCollect cimpl; - }; - } } #endif diff --git a/rtt/internal/FusedFunctorDataSource.hpp b/rtt/internal/FusedFunctorDataSource.hpp index f920c28a8..14690d829 100644 --- a/rtt/internal/FusedFunctorDataSource.hpp +++ b/rtt/internal/FusedFunctorDataSource.hpp @@ -306,8 +306,7 @@ namespace RTT value_t get() const { - FusedMCallDataSource::evaluate(); - ret.checkError(); + evaluate(); return ret.result(); } diff --git a/rtt/internal/InputPortSource.hpp b/rtt/internal/InputPortSource.hpp index bcd074c23..e0738012d 100644 --- a/rtt/internal/InputPortSource.hpp +++ b/rtt/internal/InputPortSource.hpp @@ -57,9 +57,14 @@ namespace RTT * call base::InputPortInterface::getDataSource() to get the corresponding data * source. This is your duty to destroy the port when it is not needed * anymore. + * + * @note Although this DataSource is assignable, writing to it is not causing + * any change in the port. You should not use the set() functions of this object. + * We provide this interface in order to allow other + * code to take a non-const reference to the read data. */ template - class InputPortSource : public DataSource + class InputPortSource : public AssignableDataSource { InputPort* port; mutable T mvalue; @@ -68,22 +73,14 @@ namespace RTT typedef typename boost::intrusive_ptr > shared_ptr; InputPortSource(InputPort& port) - : port(&port), mvalue() { } - - /** - * Called by owner port to notify that it is being - * destructed. Since this InputPortSource is refcounted, - * we need a way to tell it that the port no longer - * exists. - */ - void dropPort() { - port = 0; + : port(&port), mvalue() { + port.getDataSample( mvalue ); } void reset() { port->clear(); } bool evaluate() const { - return port->read(mvalue) == NewData; + return port->read(mvalue, false) == NewData; } typename DataSource::result_t value() const @@ -97,9 +94,17 @@ namespace RTT else return T(); } - DataSource* clone() const + virtual void set( typename AssignableDataSource::param_t t ) { + mvalue = t; + } + + virtual typename AssignableDataSource::reference_t set() { + return mvalue; + } + + AssignableDataSource* clone() const { return new InputPortSource(*port); } - DataSource* copy( std::map& alreadyCloned ) const + AssignableDataSource* copy( std::map& alreadyCloned ) const { return const_cast*>(this); } }; }} diff --git a/rtt/internal/LocalOperationCaller.hpp b/rtt/internal/LocalOperationCaller.hpp index c81a17f0e..6fd04db76 100644 --- a/rtt/internal/LocalOperationCaller.hpp +++ b/rtt/internal/LocalOperationCaller.hpp @@ -51,7 +51,6 @@ #include "../SendHandle.hpp" #include "../ExecutionEngine.hpp" #include "OperationCallerBinder.hpp" -#include "GlobalEngine.hpp" #include #include "../os/oro_allocator.hpp" @@ -81,7 +80,7 @@ namespace RTT protected BindStorage { public: - LocalOperationCallerImpl() : myengine(GlobalEngine::Instance()), caller(GlobalEngine::Instance()) {} + LocalOperationCallerImpl() {} typedef FunctionT Signature; typedef typename boost::function_traits::result_type result_type; typedef typename boost::function_traits::result_type result_reference; @@ -97,26 +96,6 @@ namespace RTT return this->retv.isError(); } - virtual void setExecutor(ExecutionEngine* ee) { - if (met == OwnThread) - myengine = ee; - else - myengine = GlobalEngine::Instance(); - } - - virtual void setCaller(ExecutionEngine* ee) { - if (ee) - caller = ee; - else - caller = GlobalEngine::Instance(); - } - - virtual bool setThread(ExecutionThread et, ExecutionEngine* executor) { - met = et; - setExecutor(executor); - return true; - } - void executeAndDispose() { if (!this->retv.isExecuted()) { this->exec(); // calls BindStorage. @@ -124,8 +103,8 @@ namespace RTT if(this->retv.isError()) this->reportError(); bool result = false; - if (caller){ - result = caller->process(this); + if ( this->caller){ + result = this->caller->process(this); } if (!result) dispose(); @@ -151,22 +130,12 @@ namespace RTT } - // report an error if an exception was thrown while calling exec() - virtual void reportError() { - // This localOperation was added to a TaskContext or to a Service owned by a TaskContext - if (this->ownerEngine != NULL) - this->ownerEngine->setExceptionTask(); - // This operation is called through OperationCaller directly - else if (this->met == OwnThread) - this->myengine->setExceptionTask(); - } - - ExecutionEngine* getMessageProcessor() const { return myengine; } + ExecutionEngine* getMessageProcessor() const { return this->myengine; } SendHandle do_send(shared_ptr cl) { - assert(myengine); // myengine must be either the caller's engine or GlobalEngine::Instance(). + assert(this->myengine); // myengine must be either the caller's engine or GlobalEngine::Instance(). //std::cout << "Sending clone..."<process( cl.get() ) ) { + if ( this->myengine->process( cl.get() ) ) { cl->self = cl; return SendHandle( cl ); } else { @@ -319,24 +288,24 @@ namespace RTT } SendStatus collect_impl() { - caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); + this->caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); return this->collectIfDone_impl(); } template SendStatus collect_impl( T1& a1 ) { - caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); + this->caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); return this->collectIfDone_impl(a1); } template SendStatus collect_impl( T1& a1, T2& a2 ) { - caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); + this->caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); return this->collectIfDone_impl(a1,a2); } template SendStatus collect_impl( T1& a1, T2& a2, T3& a3 ) { - caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); + this->caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) ); return this->collectIfDone_impl(a1,a2,a3); } @@ -346,7 +315,7 @@ namespace RTT result_type call_impl() { - if (met == OwnThread && myengine != caller) { + if ( this->isSend() ) { SendHandle h = send_impl(); if ( h.collect() == SendSuccess ) return h.ret(); @@ -371,7 +340,7 @@ namespace RTT result_type call_impl(T1 a1) { SendHandle h; - if (met == OwnThread && myengine != caller) { + if ( this->isSend() ) { h = send_impl(a1); // collect_impl may take diff number of arguments than // call_impl/ret_impl(), so we use generic collect() + ret_impl() @@ -395,7 +364,7 @@ namespace RTT result_type call_impl(T1 a1, T2 a2) { SendHandle h; - if (met == OwnThread && myengine != caller) { + if ( this->isSend() ) { h = send_impl(a1,a2); if ( h.collect() == SendSuccess ) return h.ret(a1,a2); @@ -417,7 +386,7 @@ namespace RTT result_type call_impl(T1 a1, T2 a2, T3 a3) { SendHandle h; - if (met == OwnThread && myengine != caller) { + if ( this->isSend() ) { h = send_impl(a1,a2,a3); if ( h.collect() == SendSuccess ) return h.ret(a1,a2,a3); @@ -439,7 +408,7 @@ namespace RTT result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4) { SendHandle h; - if (met == OwnThread && myengine != caller) { + if ( this->isSend() ) { h = send_impl(a1,a2,a3,a4); if ( h.collect() == SendSuccess ) return h.ret(a1,a2,a3,a4); @@ -461,7 +430,7 @@ namespace RTT result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { SendHandle h; - if (met == OwnThread && myengine != caller) { + if (this->isSend()) { h = send_impl(a1,a2,a3,a4,a5); if ( h.collect() == SendSuccess ) return h.ret(a1,a2,a3,a4,a5); @@ -483,7 +452,7 @@ namespace RTT result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) { SendHandle h; - if (met == OwnThread && myengine != caller) { + if (this->isSend()) { h = send_impl(a1,a2,a3,a4,a5,a6); if ( h.collect() == SendSuccess ) return h.ret(a1,a2,a3,a4,a5,a6); @@ -505,7 +474,7 @@ namespace RTT result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) { SendHandle h; - if (met == OwnThread && myengine != caller) { + if (this->isSend()) { h = send_impl(a1,a2,a3,a4,a5,a6,a7); if ( h.collect() == SendSuccess ) return h.ret(a1,a2,a3,a4,a5,a6,a7); @@ -613,11 +582,7 @@ namespace RTT virtual shared_ptr cloneRT() const = 0; protected: - ExecutionEngine* myengine; - ExecutionEngine* caller; - ExecutionEngine* ownerEngine; typedef BindStorage Store; - ExecutionThread met; /** * Used to refcount self as long as dispose() is not called. * This refcount is real-time since both shared_ptr and object @@ -657,38 +622,35 @@ namespace RTT * Construct a LocalOperationCaller from a class member pointer and an * object of that class. * - * @param name The name of this method * @param meth A pointer to a class member function * @param object An object of the class which has \a meth as member function. + * @param ee The executing engine. This is the owner engine or the GlobalEngine. If null, will be the GlobalEngine. + * @param caller The caller engine. From which component we call this Operation. + * @param oe The owner engine. In which component this Operation lives */ template LocalOperationCaller(M meth, ObjectType object, ExecutionEngine* ee, ExecutionEngine* caller, ExecutionThread et = ClientThread, ExecutionEngine* oe = NULL ) { - if (!ee) - ee = GlobalEngine::Instance(); + this->setExecutor( ee ); + this->setCaller( caller ); + this->setOwner(oe); + this->setThread( et, ee ); this->mmeth = OperationCallerBinder()(meth, object); - this->myengine = ee; - this->caller = caller; - this->ownerEngine = oe; - this->met = et; } /** * Construct a LocalOperationCaller from a function pointer or function object. * - * @param name the name of this method * @param meth an pointer to a function or function object. */ template LocalOperationCaller(M meth, ExecutionEngine* ee, ExecutionEngine* caller, ExecutionThread et = ClientThread, ExecutionEngine* oe = NULL ) { - if (!ee) - ee = GlobalEngine::Instance(); + this->setExecutor( ee ); + this->setCaller( caller ); + this->setOwner(oe); + this->setThread( et, ee ); this->mmeth = meth; - this->myengine = ee; - this->caller = caller; - this->ownerEngine = oe; - this->met = et; } boost::function getOperationCallerFunction() const diff --git a/rtt/internal/RemoteOperationCaller.hpp b/rtt/internal/RemoteOperationCaller.hpp index 13d902fbd..edf8be0dd 100644 --- a/rtt/internal/RemoteOperationCaller.hpp +++ b/rtt/internal/RemoteOperationCaller.hpp @@ -99,14 +99,6 @@ namespace RTT virtual bool isError() const { return false; } virtual void dispose() { assert(false); } - virtual void setExecutor(ExecutionEngine* ee) { - } - - virtual void setCaller(ExecutionEngine* ee) { - } - - virtual void reportError() {} - /** * Call this operator if the RemoteOperationCaller takes no arguments. * @@ -437,20 +429,10 @@ namespace RTT this->mhandle.setAutoCollect(false); } - virtual void readArguments() {} - virtual bool ready() const { return this->mmeth.ready(); } - virtual bool execute() { - return this->mmeth.call(); - } - - virtual bool setThread(ExecutionThread, ExecutionEngine* ) { - return false; - } - virtual base::OperationCallerBase* cloneI(ExecutionEngine* caller) const { RemoteOperationCaller* rm = new RemoteOperationCaller( this->mmeth.getOrp(), this->mmeth.getName(), caller); return rm; diff --git a/rtt/orocos-rtt.pc.in b/rtt/orocos-rtt.pc.in index 1cf19f7c3..d071408e2 100644 --- a/rtt/orocos-rtt.pc.in +++ b/rtt/orocos-rtt.pc.in @@ -6,6 +6,6 @@ includedir=${prefix}/include Name: Orocos-RTT # human-readable name Description: Open Robot Control Software: Real-Time Tookit # human-readable description Version: @RTT_VERSION@ -Libs: -L${libdir} -lorocos-rtt-@OROCOS_TARGET@ @RTT_USER_LINK_LIBS@ # If some RTT headers include inline calls to other libraries, we need to specify these here too. +Libs: -L${libdir} -lorocos-rtt-@OROCOS_TARGET@ @RTT_USER_LINK_LIBS@ @RTT_USER_LDFLAGS@ # If some RTT headers include inline calls to other libraries, we need to specify these here too. Libs.private: @RTT_LINKFLAGS@ -Cflags: -I${includedir} @RTT_DEFINES@ @RTT_CFLAGS@ +Cflags: -I${includedir} @RTT_DEFINES@ @RTT_CFLAGS@ @RTT_USER_CFLAGS@ diff --git a/rtt/os/macosx/fosi.h b/rtt/os/macosx/fosi.h index 72e70ba32..935b92165 100644 --- a/rtt/os/macosx/fosi.h +++ b/rtt/os/macosx/fosi.h @@ -15,9 +15,7 @@ #ifndef __FOSI_H #define __FOSI_H -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 600 // use all Posix features. -#endif +#define _DARWIN_C_SOURCE #define HAVE_FOSI_API diff --git a/rtt/os/oro_allocator.hpp b/rtt/os/oro_allocator.hpp index 5dc5eebae..56faa1c32 100644 --- a/rtt/os/oro_allocator.hpp +++ b/rtt/os/oro_allocator.hpp @@ -239,6 +239,7 @@ namespace RTT { namespace os { template<> class local_allocator { + public: typedef void value_type; typedef void* pointer; typedef const void* const_pointer; @@ -320,6 +321,7 @@ namespace RTT { namespace os { template<> class rt_allocator { + public: typedef void value_type; typedef void* pointer; typedef const void* const_pointer; diff --git a/rtt/os/startstop.cpp b/rtt/os/startstop.cpp index 486f52732..a515e68ae 100644 --- a/rtt/os/startstop.cpp +++ b/rtt/os/startstop.cpp @@ -68,7 +68,6 @@ using namespace std; using namespace RTT; using namespace RTT::os; -static os::StartStopManager* initM; static int os_argc_arg; static char** os_argv_arg; @@ -86,8 +85,7 @@ int __os_init(int argc, char** argv ) Logger::log() << Logger::Debug << "MainThread started." << Logger::endl; Logger::log() << Logger::Debug << "Starting StartStopManager." << Logger::endl; - initM = os::StartStopManager::Instance(); - int ret = initM->start() ? 0 : 1; + int ret = os::StartStopManager::Instance()->start() ? 0 : 1; #ifdef OROPKG_OS_THREAD_SCOPE unsigned int bit = 0; @@ -175,7 +173,7 @@ void __os_exit(void) types::TypekitRepository::Release(); Logger::log() << Logger::Debug << "Stopping StartStopManager." << Logger::endl; - initM->stop(); + os::StartStopManager::Instance()->stop(); os::StartStopManager::Release(); // This should be the (one but) last message to be logged : diff --git a/rtt/plugin/PluginLoader.cpp b/rtt/plugin/PluginLoader.cpp index fc2619772..d5c86cfb9 100644 --- a/rtt/plugin/PluginLoader.cpp +++ b/rtt/plugin/PluginLoader.cpp @@ -100,7 +100,7 @@ static const std::string default_delimiter(":"); returns true for ".1", ".12", ".123" returns false for ".a", "1", "123", ".123 ", "a", "", ".1.a", ".1a2" */ -bool isExtensionVersion(const std::string& ext) +RTT_API bool isExtensionVersion(const std::string& ext) { bool isExtensionVersion = false; @@ -138,7 +138,7 @@ bool isExtensionVersion(const std::string& ext) All the above also apply without the "lib" prefix. */ -bool isLoadableLibrary(const path& filename) +RTT_API bool isLoadableLibrary(const path& filename) { bool isLoadable = false; @@ -757,8 +757,8 @@ bool PluginLoader::isCompatiblePlugin(std::string const& filepath) #ifdef OROCOS_TARGET_WIN32 // On WIN32 target: - // - look if the library name ends with "win32.dll" on release mode - // - look if the library name ends with "win32d.dll" on debug mode + // - look if the library name ends with "-win32.dll" on release mode + // - look if the library name ends with "-win32d.dll" on debug mode if(!hasEnding(libname, FULL_PLUGINS_SUFFIX)) { //log(Debug) << "Plugin file '" + libname + "' is incompatible because it doesn't have the suffix " << FULL_PLUGINS_SUFFIX << endlog(); diff --git a/rtt/plugin/PluginLoader.hpp b/rtt/plugin/PluginLoader.hpp index 744422c4e..494d16bf0 100644 --- a/rtt/plugin/PluginLoader.hpp +++ b/rtt/plugin/PluginLoader.hpp @@ -179,7 +179,7 @@ namespace RTT { * Load any typekit found in the 'types/' subdirectory of each path in path_list in the process. * This is not a 'smart' function. It will only look into that directory and will not try * to guess a target specific subdir or any other means for locating typekits. - * @return false if some typekit caused an error, or some path was not found. + * @return false if some typekit caused an error, or some path was not found or if path_list was empty. * @param path_list A colon or semi-colon seperated list of paths * to look for typekits. No other paths will be searched. * @throw std::runtime_exception if one of the found typekits refused to load. @@ -187,9 +187,11 @@ namespace RTT { bool loadTypekits(std::string const& path_list); /** - * Load a typekit found in the 'types/' subdirectory of each path in path_list in the process. + * Load a typekit found in the 'types/' subdirectory of a package present in path_list. + * @param name The name of the package (a directory name) which contains the typekit you wish to load. * @param path_list A colon or semi-colon seperated list of paths - * to look for typekits. May be empty the empty string. + * to look for the \a name subdirectory. If this list is empty, the current plugin path is searched and + * the current working directory. * @throw std::runtime_exception if the found typekit refused to load. */ bool loadTypekit(std::string const& name, std::string const& path_list); diff --git a/rtt/scripting/CommonParser.cpp b/rtt/scripting/CommonParser.cpp index 95f059bee..a5f27530b 100644 --- a/rtt/scripting/CommonParser.cpp +++ b/rtt/scripting/CommonParser.cpp @@ -106,6 +106,7 @@ namespace RTT { BOOST_SPIRIT_DEBUG_RULE( lexeme_identifier ); BOOST_SPIRIT_DEBUG_RULE( lexeme_notassertingidentifier ); BOOST_SPIRIT_DEBUG_RULE( type_name ); + BOOST_SPIRIT_DEBUG_RULE( skipper ); // an identifier is a word which can be used to identify a // label, or be the name of an object or method. it is required diff --git a/rtt/scripting/FunctionGraph.cpp b/rtt/scripting/FunctionGraph.cpp index 2c86ff0bd..f7af24ee3 100644 --- a/rtt/scripting/FunctionGraph.cpp +++ b/rtt/scripting/FunctionGraph.cpp @@ -205,8 +205,7 @@ namespace RTT { } switch (pStatus) { case Status::running: - this->executeUntil(); - return true; + return this->executeUntil(); break; case Status::paused: if (mstep) { @@ -281,8 +280,10 @@ namespace RTT { } while ( previous != current && pStatus == Status::running && !pausing); // keep going if we found a new node // check finished state - if (current == exitv) + if (current == exitv) { this->stop(); + return !munload_on_stop; + } return true; // we need to wait. } diff --git a/rtt/scripting/ScriptParser.cpp b/rtt/scripting/ScriptParser.cpp index 3bff0e465..5fb3d1836 100644 --- a/rtt/scripting/ScriptParser.cpp +++ b/rtt/scripting/ScriptParser.cpp @@ -17,6 +17,7 @@ #include #include #include "../internal/mystd.hpp" +#include "../internal/GlobalEngine.hpp" #include "ParsedStateMachine.hpp" namespace RTT @@ -161,8 +162,12 @@ namespace RTT //skip_parser_t skip_parser = SKIP_PARSER; //iter_pol_t iter_policy( skip_parser ); //#define SKIP_PARSER - iter_pol_t iter_policy((comment_p("#") | comment_p("//") | comment_p( - "/*", "*/") | (space_p - eol_p) | commonparser->skipper)); + skip_parser_t skippers = (comment_p("#") | comment_p("//") + | comment_p("/*", "*/") + | (space_p - eol_p) + | (commonparser->skipper)); + + iter_pol_t iter_policy(skippers); scanner_pol_t policies(iter_policy); scanner_t scanner(begin, end, policies); diff --git a/rtt/scripting/ValueParser.cpp b/rtt/scripting/ValueParser.cpp index 8699babce..d720c8095 100644 --- a/rtt/scripting/ValueParser.cpp +++ b/rtt/scripting/ValueParser.cpp @@ -114,9 +114,9 @@ namespace RTT void ValueParser::seenpeer() { // inform propparser of new peer : - //std::cerr << "ValueParser: seenpeer : "<< peerparser.peer()->getName() - // <<" has props :" << (peerparser.peer()->properties() != 0) << std::endl; - propparser.setPropertyBag( peerparser.peer()->provides()->properties() ); + //std::cerr << "ValueParser: seenpeer : "<< peerparser.taskObject()->getName() + // <<" has props :" << (peerparser.taskObject()->properties() != 0) << std::endl; + propparser.setPropertyBag( peerparser.taskObject()->properties() ); } void ValueParser::seenboolconstant( iter_t begin, iter_t end ) diff --git a/rtt/transports/corba/TaskContextFactory.hpp b/rtt/transports/corba/TaskContextFactory.hpp index 31afb0ee7..bc1869210 100644 --- a/rtt/transports/corba/TaskContextFactory.hpp +++ b/rtt/transports/corba/TaskContextFactory.hpp @@ -44,14 +44,20 @@ namespace RTT {namespace corba { + /** + * Use this class to create Corba TaskContext proxies, without including any + * CORBA header. This allows you to build applications that don't link with + * a CORBA library. + */ class TaskContextFactory { + public: /** * Invoke this method once to initialise the Orb which will * run the task servers. - * @param orb_timeout timeout value for each remote call, expressed in seconds. - * The resolution is up to 100 nano seconds. Anything smaller will be interpreted - * as a zero. + * @param orb_timeout timeout value for each remote call, expressed in seconds. + * The resolution is up to 100 nano seconds. Anything smaller will be interpreted + * as a zero. */ static bool InitOrb(int argc, char* argv[], Seconds orb_timeout=0 ); diff --git a/rtt/transports/mqueue/orocos-rtt-mqueue.pc.in b/rtt/transports/mqueue/orocos-rtt-mqueue.pc.in index f4e9a7811..61a6088ff 100644 --- a/rtt/transports/mqueue/orocos-rtt-mqueue.pc.in +++ b/rtt/transports/mqueue/orocos-rtt-mqueue.pc.in @@ -7,6 +7,6 @@ Name: Orocos-RTT-MQUEUE # human-readable nam Description: Open Robot Control Software: Real-Time Tookit # human-readable description Requires: orocos-rtt-@OROCOS_TARGET@ Version: @RTT_VERSION@ -Libs: -L${libdir} -lorocos-rtt-mqueue-@OROCOS_TARGET@ -Libs.private: @RTT_MQUEUE_LINKFLAGS@ -Cflags: -I${includedir}/rtt/mqueue @RTT_MQUEUE_DEFINES@ @RTT_MQUEUE_CFLAGS@ +Libs: -L${libdir} -lorocos-rtt-mqueue-@OROCOS_TARGET@ @MQ_LDFLAGS@ +Libs.private: +Cflags: -I${includedir}/rtt/mqueue @MQ_CFLAGS@ diff --git a/rtt/types/CompositionFactory.cpp b/rtt/types/CompositionFactory.cpp index 476c8e786..ef2bae109 100644 --- a/rtt/types/CompositionFactory.cpp +++ b/rtt/types/CompositionFactory.cpp @@ -1,7 +1,7 @@ #include "TemplateCompositionFactory.hpp" using namespace RTT; -using namespace detail; +using namespace RTT::types; base::DataSourceBase::shared_ptr CompositionFactory::convertType(base::DataSourceBase::shared_ptr source) const { diff --git a/rtt/types/CompositionFactory.hpp b/rtt/types/CompositionFactory.hpp index 1cf14ddd6..354807189 100644 --- a/rtt/types/CompositionFactory.hpp +++ b/rtt/types/CompositionFactory.hpp @@ -9,7 +9,7 @@ namespace RTT { /** * A factory for composing/decomposing and converting types to a form suitable for persistent storage, such as an XML file. */ - class CompositionFactory + class RTT_API CompositionFactory { public: diff --git a/rtt/types/TemplateConnFactory.hpp b/rtt/types/TemplateConnFactory.hpp index ba8455e22..fc2fb1811 100644 --- a/rtt/types/TemplateConnFactory.hpp +++ b/rtt/types/TemplateConnFactory.hpp @@ -13,7 +13,7 @@ namespace RTT using internal::ConnFactory; template - class RTT_API TemplateConnFactory : public ConnFactory + class TemplateConnFactory : public ConnFactory { public: base::InputPortInterface* inputPort(std::string const& name) const { return new InputPort(name); } diff --git a/rtt/types/TypeInfoGenerator.hpp b/rtt/types/TypeInfoGenerator.hpp index f7c1f4690..6bba7cc5d 100644 --- a/rtt/types/TypeInfoGenerator.hpp +++ b/rtt/types/TypeInfoGenerator.hpp @@ -2,6 +2,7 @@ #define RTT_TYPEINFO_GENERATOR_HPP #include +#include "../rtt-config.h" #include "rtt-types-fwd.hpp" namespace RTT @@ -16,7 +17,7 @@ namespace RTT * class to the type system which has no function * once the type registration is done. */ - class TypeInfoGenerator + class RTT_API TypeInfoGenerator { public: virtual ~TypeInfoGenerator() {} diff --git a/rtt/types/rtt-types-fwd.hpp b/rtt/types/rtt-types-fwd.hpp index f5832cb5a..bb07f3c30 100644 --- a/rtt/types/rtt-types-fwd.hpp +++ b/rtt/types/rtt-types-fwd.hpp @@ -9,6 +9,7 @@ namespace RTT { class OperatorRepository; class TransportPlugin; class TypeInfo; + class TypeInfoGenerator; class TypeInfoRepository; class TypeMarshaller; class TypeTransporter; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ffafd813e..dd63e8c34 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -46,6 +46,7 @@ IF (BUILD_TESTING) DEFINE_SYMBOL "RTT_UNIT_DLL_EXPORT" SOVERSION "${RTT_VERSION_MAJOR}.${RTT_VERSION_MINOR}" VERSION "${RTT_VERSION}" + LINK_FLAGS "${CMAKE_LD_FLAGS_ADD}" # Set accumulated compilation flags: (.so and .a) COMPILE_DEFINITIONS OROCOS_TARGET=${OROCOS_TARGET} ) @@ -128,7 +129,7 @@ IF (BUILD_TESTING) IF(UNIX AND NOT OROCOS_TARGET STREQUAL "xenomai" ) ADD_EXECUTABLE( specactivities-test test-runner.cpp specialized_activities.cpp) - TARGET_LINK_LIBRARIES( specactivities-test orocos-rtt-${OROCOS_TARGET}_dynamic ) + TARGET_LINK_LIBRARIES( specactivities-test orocos-rtt-${OROCOS_TARGET}_dynamic ${TEST_LIBRARIES}) SET_TARGET_PROPERTIES( specactivities-test PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS_ADD}" LINK_FLAGS "${CMAKE_LD_FLAGS_ADD}" diff --git a/tests/test-runner-corba.cpp b/tests/test-runner-corba.cpp index bdd06ef86..627f4e1cb 100644 --- a/tests/test-runner-corba.cpp +++ b/tests/test-runner-corba.cpp @@ -30,8 +30,9 @@ #include #include "test-runner.hpp" +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK #include -#include using boost::unit_test::test_suite; @@ -39,30 +40,6 @@ using namespace RTT; using namespace RTT::corba; using namespace std; -struct InitOrocos { -public: - InitOrocos(){ } - ~InitOrocos(){ - corba::CorbaDispatcher::ReleaseAll(); - corba::TaskContextServer::ShutdownOrb(true); - corba::TaskContextServer::DestroyOrb(); - - // If we call __os_exit() in Xenomai, we get an ABORT - // because the main task is cleaned up too early. - // The work around for now is to stop all threads but - // the main thread. To be fixed if boost::test allows it. -#ifndef OROCOS_TARGET_XENOMAI - __os_exit(); -#else - os::StartStopManager::Instance()->stop(); - os::StartStopManager::Release(); -#endif -} - -}; - -BOOST_GLOBAL_FIXTURE( InitOrocos ) - boost::unit_test::test_suite* init_unit_test_suite(int argc, char** const argv) { if ( argc > 1 && strncmp(argv[1],"--help",6) == 0 ) { @@ -117,3 +94,29 @@ boost::unit_test::test_suite* init_unit_test_suite(int argc, char** const argv) return 0; } +using namespace boost::unit_test; +struct InitOrocos { +public: + InitOrocos(){ + init_unit_test_suite(framework::master_test_suite().argc,framework::master_test_suite().argv); + } + ~InitOrocos(){ + corba::CorbaDispatcher::ReleaseAll(); + corba::TaskContextServer::ShutdownOrb(true); + corba::TaskContextServer::DestroyOrb(); + + // If we call __os_exit() in Xenomai, we get an ABORT + // because the main task is cleaned up too early. + // The work around for now is to stop all threads but + // the main thread. To be fixed if boost::test allows it. +#ifndef OROCOS_TARGET_XENOMAI + __os_exit(); +#else + os::StartStopManager::Instance()->stop(); + os::StartStopManager::Release(); +#endif +} + +}; + +BOOST_GLOBAL_FIXTURE( InitOrocos ) diff --git a/tests/test-runner.cpp b/tests/test-runner.cpp index 173e8e578..8c3a406bc 100644 --- a/tests/test-runner.cpp +++ b/tests/test-runner.cpp @@ -29,33 +29,17 @@ #include #include "test-runner.hpp" +#define BOOST_TEST_MAIN +#define BOOST_TEST_DYN_LINK #include -#include using boost::unit_test::test_suite; using namespace RTT; using namespace std; -struct InitOrocos { -public: - InitOrocos(){ } - ~InitOrocos(){ - // If we call __os_exit() in Xenomai, we get an ABORT - // because the main task is cleaned up too early. - // The work around for now is to stop all threads but - // the main thread. To be fixed if boost::test allows it. -#ifndef OROCOS_TARGET_XENOMAI - __os_exit(); -#else - os::StartStopManager::Instance()->stop(); - os::StartStopManager::Release(); -#endif -} -}; -BOOST_GLOBAL_FIXTURE( InitOrocos ) boost::unit_test::test_suite* init_unit_test_suite(int argc, char** const argv) { @@ -110,3 +94,25 @@ boost::unit_test::test_suite* init_unit_test_suite(int argc, char** const argv) return 0; } +using namespace boost::unit_test; +struct InitOrocos { +public: + InitOrocos(){ + init_unit_test_suite(framework::master_test_suite().argc,framework::master_test_suite().argv); + } + ~InitOrocos(){ + // If we call __os_exit() in Xenomai, we get an ABORT + // because the main task is cleaned up too early. + // The work around for now is to stop all threads but + // the main thread. To be fixed if boost::test allows it. +#ifndef OROCOS_TARGET_XENOMAI + __os_exit(); +#else + os::StartStopManager::Instance()->stop(); + os::StartStopManager::Release(); +#endif +} + +}; + +BOOST_GLOBAL_FIXTURE( InitOrocos ) diff --git a/tests/testtypes/types/CMakeLists.txt b/tests/testtypes/types/CMakeLists.txt index 3a9fc4ba0..4e1132516 100644 --- a/tests/testtypes/types/CMakeLists.txt +++ b/tests/testtypes/types/CMakeLists.txt @@ -9,7 +9,7 @@ SET_TARGET_PROPERTIES( testtypes_plugin PROPERTIES SOVERSION "${RTT_VERSION_MAJOR}.${RTT_VERSION_MINOR}" VERSION "${RTT_VERSION}" - OUTPUT_NAME typekit_plugin + OUTPUT_NAME typekit_plugin-${OROCOS_TARGET} COMPILE_FLAGS "${CMAKE_CXX_FLAGS_ADD}" LINK_FLAGS "${CMAKE_LD_FLAGS_ADD}" COMPILE_DEFINITIONS "${OROCOS-RTT_DEFINITIONS}" diff --git a/tests/unit.hpp b/tests/unit.hpp index f70d2332c..62c5ed39e 100644 --- a/tests/unit.hpp +++ b/tests/unit.hpp @@ -25,6 +25,7 @@ #include #include +#define BOOST_TEST_DYN_LINK #ifdef ORO_UNIT_TEST_SUITE_HACK // Modified version that contains checkpointing // We use this in the build farm to get more precise