diff options
-rw-r--r-- | CMakeLists.txt | 10 | ||||
-rw-r--r-- | cmake/Modules/CMakeLists.txt | 20 | ||||
-rw-r--r-- | cmake/Modules/GRASCommon.cmake | 64 | ||||
-rw-r--r-- | cmake/Modules/GRASTool.in.cmake | 262 | ||||
-rw-r--r-- | cmake/Modules/GrPython.cmake | 232 | ||||
-rw-r--r-- | cmake/Modules/GrTest.cmake | 139 | ||||
m--------- | grextras | 0 | ||||
-rw-r--r-- | include/gras/detail/factory.hpp | 88 | ||||
-rw-r--r-- | include/gras/factory.hpp | 260 | ||||
-rw-r--r-- | lib/callable.cpp | 2 | ||||
-rw-r--r-- | lib/factory.cpp | 18 | ||||
-rw-r--r-- | python/gras/CMakeLists.txt | 1 | ||||
-rw-r--r-- | python/gras/GRAS_Factory.i | 37 | ||||
-rw-r--r-- | python/gras/GRAS_Loader.py | 2 | ||||
-rw-r--r-- | python/gras/GRAS_TestUtils.py (renamed from tests/demo_blocks.py) | 18 | ||||
-rw-r--r-- | python/gras/__init__.py | 3 | ||||
-rw-r--r-- | tests/block_test.py | 42 | ||||
-rw-r--r-- | tests/example_module.cpp | 7 | ||||
-rw-r--r-- | tests/example_module.py | 2 | ||||
-rw-r--r-- | tests/factory_test.cpp | 8 | ||||
-rw-r--r-- | tests/module_loader_test.py | 4 | ||||
-rw-r--r-- | tests/query_test.py | 16 | ||||
-rw-r--r-- | tests/thread_pool_test.py | 9 | ||||
-rw-r--r-- | tmpl/factory.tmpl.hpp | 68 | ||||
-rw-r--r-- | tmpl/factory_detail.tmpl.hpp | 8 |
25 files changed, 1099 insertions, 221 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a65d3c3..d7f533c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,9 @@ GRAS_CHECK_SUBMODULE(gnuradio) GRAS_CHECK_SUBMODULE(grextras) list(APPEND CMAKE_MODULE_PATH ${GRAS_SOURCE_DIR}/PMC/cmake/Modules) -include(CMakeDefsHelper) +list(APPEND CMAKE_MODULE_PATH ${GRAS_SOURCE_DIR}/cmake/Modules) +list(APPEND CMAKE_MODULE_PATH ${GRAS_BINARY_DIR}/cmake/Modules) +include(GRASCommon) if(CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DGRAS_DEBUG) @@ -99,6 +101,7 @@ add_subdirectory(PMC) add_subdirectory(python/gras) add_subdirectory(tests) add_subdirectory(query) +add_subdirectory(cmake/Modules) ######################################################################## # add gnuradio as sub-project @@ -147,6 +150,10 @@ CPACK_COMPONENT("${GRAS_COMP_PYTHON}" ######################################################################## # GNU Radio Extras as sub-project ######################################################################## +list(APPEND CMAKE_MODULE_PATH ${GRAS_SOURCE_DIR}/cmake/Modules) +list(APPEND CMAKE_MODULE_PATH ${GRAS_BINARY_DIR}/cmake/Modules) +set(GRAS_ROOT ${GRAS_SOURCE_DIR}) +list(APPEND GR_TEST_ENVIRONS "GRAS_ROOT=${GRAS_SOURCE_DIR}") set(CMAKE_SOURCE_DIR ${GRAS_SOURCE_DIR}/grextras) set(CMAKE_BINARY_DIR ${GRAS_BINARY_DIR}/grextras) @@ -154,6 +161,7 @@ set(GRAS_FOUND TRUE) #GRAS_INCLUDE_DIRS, GRAS_LIBRARIES set above set(PMC_FOUND TRUE) +set(PMC_INCLUDE_DIRS ${GRAS_SOURCE_DIR}/PMC/include) set(PMC_LIBRARIES pmc) set(VOLK_FOUND ${ENABLE_VOLK}) diff --git a/cmake/Modules/CMakeLists.txt b/cmake/Modules/CMakeLists.txt new file mode 100644 index 0000000..d275f71 --- /dev/null +++ b/cmake/Modules/CMakeLists.txt @@ -0,0 +1,20 @@ +######################################################################## +# Install cmake modules to known location +######################################################################## +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/GRASTool.in.cmake + ${CMAKE_CURRENT_BINARY_DIR}/GRASTool.cmake +@ONLY) +list(APPEND GRAS_TOOL_SOURCES + ${CMAKE_CURRENT_BINARY_DIR}/GRASTool.cmake +) + +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/GRASTool.cmake + GRASCommon.cmake + GrTest.cmake + GrPython.cmake + DESTINATION share/gras/cmake/Modules + COMPONENT ${GRAS_COMP_DEVEL} +) diff --git a/cmake/Modules/GRASCommon.cmake b/cmake/Modules/GRASCommon.cmake new file mode 100644 index 0000000..6844dd4 --- /dev/null +++ b/cmake/Modules/GRASCommon.cmake @@ -0,0 +1,64 @@ +if(DEFINED __INCLUDED_GRAS_COMMON_CMAKE) + return() +endif() +set(__INCLUDED_GRAS_COMMON_CMAKE TRUE) + +######################################################################## +# select the release build type by default to get optimization flags +######################################################################## +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") + message(STATUS "Build type not specified: defaulting to release.") +endif(NOT CMAKE_BUILD_TYPE) +set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") + +######################################################################## +# Setup Boost defines that get used before find_package(Boost) +######################################################################## +if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64" AND NOT BOOST_LIBRARYDIR) + list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix +endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64" AND NOT BOOST_LIBRARYDIR) + +set(Boost_ADDITIONAL_VERSIONS + "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" + "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" + "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" + "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" + "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" + "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" + "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" +) + +if(NOT Boost_INCLUDE_DIRS) + find_package(Boost) + if(NOT Boost_FOUND) + message(FATAL_ERROR "Boost C++ headers not found - required for GRAS_TOOL") + endif() +endif() + +######################################################################## +# Linux detection stuff +######################################################################## +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(LINUX TRUE) +endif() + +if(LINUX AND EXISTS "/etc/debian_version") + set(DEBIAN TRUE) +endif() + +if(LINUX AND EXISTS "/etc/redhat-release") + set(REDHAT TRUE) +endif() + +if(LINUX AND EXISTS "/etc/slackware-version") + set(SLACKWARE TRUE) +endif() + +######################################################################## +# Automatic LIB_SUFFIX detection + configuration option +######################################################################## +IF(NOT DEFINED LIB_SUFFIX AND (REDHAT OR SLACKWARE) AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$") + SET(LIB_SUFFIX 64) +ENDIF() +SET(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix") diff --git a/cmake/Modules/GRASTool.in.cmake b/cmake/Modules/GRASTool.in.cmake new file mode 100644 index 0000000..502b271 --- /dev/null +++ b/cmake/Modules/GRASTool.in.cmake @@ -0,0 +1,262 @@ +if(DEFINED __INCLUDED_GRAS_TOOL_CMAKE) + return() +endif() +set(__INCLUDED_GRAS_TOOL_CMAKE TRUE) + +include(GRASCommon) + +######################################################################## +## Define GRAS_TOOL_PATH_SEP for utility purposes +######################################################################## +if(UNIX) + set(GRAS_TOOL_PATH_SEP ":") +elseif(WIN32) + set(GRAS_TOOL_PATH_SEP "\\;") +else() + set(GRAS_TOOL_PATH_SEP ":") +endif() + +######################################################################## +## Set installation constants +## The GRAS_ROOT can be set via arg or environment variable +######################################################################## +if(GRAS_ROOT) + #its already set +elseif($ENV{GRAS_ROOT}) + set(GRAS_ROOT $ENV{GRAS_ROOT}) +else() + set(GRAS_ROOT "@CMAKE_INSTALL_PREFIX@") +endif() + +######################################################################## +## where to look for development files +######################################################################## +set(GRAS_TOOL_INCLUDE_DIR ${GRAS_ROOT}/include) +set(GRAS_TOOL_LIBRARY_DIR ${GRAS_ROOT}/lib@LIBSUFFIX@) + +#locate PMC and GRAS includes +if (NOT PMC_INCLUDE_DIRS) + find_path( + PMC_INCLUDE_DIRS + NAMES PMC/PMC.hpp + PATHS ${GRAS_TOOL_INCLUDE_DIR} + ) +endif() +if (NOT GRAS_INCLUDE_DIRS) + find_path( + GRAS_INCLUDE_DIRS + NAMES gras/gras.hpp + PATHS ${GRAS_TOOL_INCLUDE_DIR} + ) +endif() + +#locate PMC and GRAS libraries +if (NOT PMC_LIBRARIES) + find_library( + PMC_LIBRARIES + NAMES pmc + PATHS ${GRAS_TOOL_LIBRARY_DIR} + ) +endif() +if (NOT GRAS_LIBRARIES) + find_library( + GRAS_LIBRARIES + NAMES gras + PATHS ${GRAS_TOOL_LIBRARY_DIR} + ) +endif() + +######################################################################## +## GRAS_TOOL cmake function - the swiss army knife for GRAS users +## +## Options: +## SOURCES - list of C++, Python, and GRC sources +## TARGET - project name, used for library, and install prefix +## DIRECTORY - name of installation directory or ${TARGET} +## COMPONENT - name of installation component or ${TARGET} +## +## External vars: +## GRAS_TOOL_LIBRARIES - list of additional libraries to link to +######################################################################## +function(GRAS_TOOL) + + include(CMakeParseArguments) + CMAKE_PARSE_ARGUMENTS(GRAS_TOOL "" "TARGET;DIRECTORY;COMPONENT" "SOURCES" ${ARGN}) + + #give an install directory if not specified + if(NOT GRAS_TOOL_DIRECTORY) + set(GRAS_TOOL_DIRECTORY ${GRAS_TOOL_TARGET}) + endif() + + #give the target a component name if not specified + if(NOT GRAS_TOOL_COMPONENT) + set(GRAS_TOOL_COMPONENT ${GRAS_TOOL_TARGET}) + endif() + + unset(GRAS_TOOL_CPP_SOURCES) + unset(GRAS_TOOL_PY_SOURCES) + unset(GRAS_TOOL_GRC_SOURCES) + foreach(source ${GRAS_TOOL_SOURCES}) + get_filename_component(source_ext ${source} EXT) + if ("${source_ext}" STREQUAL ".cpp") + list(APPEND GRAS_TOOL_CPP_SOURCES ${source}) + endif() + if ("${source_ext}" STREQUAL ".cxx") + list(APPEND GRAS_TOOL_CPP_SOURCES ${source}) + endif() + if ("${source_ext}" STREQUAL ".cc") + list(APPEND GRAS_TOOL_CPP_SOURCES ${source}) + endif() + if ("${source_ext}" STREQUAL ".c") + list(APPEND GRAS_TOOL_CPP_SOURCES ${source}) + endif() + if ("${source_ext}" STREQUAL ".py") + list(APPEND GRAS_TOOL_PY_SOURCES ${source}) + endif() + if ("${source_ext}" STREQUAL ".xml") + list(APPEND GRAS_TOOL_GRC_SOURCES ${source}) + endif() + if ("${source_ext}" STREQUAL ".yml") + list(APPEND GRAS_TOOL_GRC_SOURCES ${source}) + endif() + endforeach(source) + + #suffix install path for project name + set(GRAS_TOOL_MOD_DIR lib@LIBSUFFIX@/gras/modules/${GRAS_TOOL_DIRECTORY}) + set(GRAS_TOOL_PYTHON_DIR lib@LIBSUFFIX@/gras/python/${GRAS_TOOL_DIRECTORY}) + set(GRAS_TOOL_GRC_DIR share/gnuradio/grc/blocks/${GRAS_TOOL_DIRECTORY}) + + #development and framework directories + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + include_directories(${PMC_INCLUDE_DIRS}) + include_directories(${GRAS_INCLUDE_DIRS}) + list(APPEND GRAS_TOOL_LIBRARIES ${PMC_LIBRARIES}) + list(APPEND GRAS_TOOL_LIBRARIES ${GRAS_LIBRARIES}) + + #and boost includes as well + include_directories(${Boost_INCLUDE_DIRS}) + + #build and install module to path + if (GRAS_TOOL_CPP_SOURCES) + add_library(${GRAS_TOOL_TARGET} MODULE ${GRAS_TOOL_CPP_SOURCES}) + target_link_libraries(${GRAS_TOOL_TARGET} ${GRAS_TOOL_LIBRARIES}) + install(TARGETS ${GRAS_TOOL_TARGET} + LIBRARY DESTINATION ${GRAS_TOOL_MOD_DIR} COMPONENT ${GRAS_TOOL_COMPONENT} # .so file + ARCHIVE DESTINATION ${GRAS_TOOL_MOD_DIR} COMPONENT ${GRAS_TOOL_COMPONENT} # .lib file + RUNTIME DESTINATION ${GRAS_TOOL_MOD_DIR} COMPONENT ${GRAS_TOOL_COMPONENT} # .dll file + ) + + #export global variables for help locating build targets + get_target_property(module_location ${GRAS_TOOL_TARGET} LOCATION) + string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} module_location ${module_location}) + list(APPEND GRAS_TOOL_MODULE_LOCATIONS ${module_location}) + set(GRAS_TOOL_MODULE_LOCATIONS ${GRAS_TOOL_MODULE_LOCATIONS} CACHE INTERNAL "") + string(REPLACE ";" "${GRAS_TOOL_PATH_SEP}" GRAS_TOOL_MODULE_PATH "${GRAS_TOOL_MODULE_LOCATIONS}") + set(GRAS_TOOL_MODULE_PATH ${GRAS_TOOL_MODULE_PATH} CACHE INTERNAL "") + set(${GRAS_TOOL_TARGET}_LOCATION ${module_location} CACHE INTERNAL "") + endif() + + #python module install + if (GRAS_TOOL_PY_SOURCES) + install( + FILES ${GRAS_TOOL_PY_SOURCES} + DESTINATION ${GRAS_TOOL_PYTHON_DIR} + COMPONENT ${GRAS_TOOL_COMPONENT} + ) + endif() + + #install GRC files + if (GRAS_TOOL_GRC_SOURCES) + install( + FILES ${GRAS_TOOL_GRC_SOURCES} + DESTINATION ${GRAS_TOOL_GRC_DIR} + COMPONENT ${GRAS_TOOL_COMPONENT} + ) + endif() + +endfunction(GRAS_TOOL) + +######################################################################## +## GRAS_SWIG_TOOL cmake function - export new types for the loader +## +## Options: +## SOURCE - the swig .i file +## TARGET - target name for the build products +## DIRECTORY - name of installation directory or ${TARGET} +## COMPONENT - name of installation component or ${TARGET} +## +## External vars: +## GRAS_SWIG_TOOL_INCLUDES - list of additional include directories +## GRAS_SWIG_TOOL_LIBRARIES - list of additional libraries to link to +######################################################################## +function(GRAS_SWIG_TOOL) + + find_package(SWIG) + if(NOT SWIG_FOUND) + return() + endif() + + find_package(PythonLibs) + if(NOT PYTHONLIBS_FOUND) + return() + endif() + + include(CMakeParseArguments) + CMAKE_PARSE_ARGUMENTS(GRAS_SWIG_TOOL "" "SOURCE;TARGET;DIRECTORY;COMPONENT" "" ${ARGN}) + + #give an install directory if not specified + if(NOT GRAS_SWIG_TOOL_DIRECTORY) + set(GRAS_SWIG_TOOL_DIRECTORY ${GRAS_SWIG_TOOL_TARGET}) + endif() + + #give the target a component name if not specified + if(NOT GRAS_SWIG_TOOL_COMPONENT) + set(GRAS_SWIG_TOOL_COMPONENT ${GRAS_SWIG_TOOL_TARGET}) + endif() + + #development and framework directories + list(APPEND GRAS_SWIG_TOOL_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}) + list(APPEND GRAS_SWIG_TOOL_INCLUDES ${PMC_SWIG_INCLUDE_DIRS}) + list(APPEND GRAS_SWIG_TOOL_INCLUDES ${GRAS_SWIG_INCLUDE_DIRS}) + list(APPEND GRAS_SWIG_TOOL_LIBRARIES ${PMC_LIBRARIES}) + list(APPEND GRAS_SWIG_TOOL_LIBRARIES ${GRAS_LIBRARIES}) + + #and boost includes as well + include_directories(${Boost_INCLUDE_DIRS}) + + #setup python includes/libs + include_directories(${PYTHON_INCLUDE_PATH}) + include_directories(${PYTHON_INCLUDE_DIRS}) + list(APPEND GRAS_SWIG_TOOL_LIBRARIES ${PYTHON_LIBRARIES}) + + #include swig generation deps for compiling + include_directories(${GRAS_SWIG_TOOL_INCLUDES}) + + #set the C++ property on the swig .i file so it builds + set_source_files_properties(${GRAS_SWIG_TOOL_SOURCE} PROPERTIES CPLUSPLUS ON) + + #setup swig flags + foreach(inc ${GRAS_SWIG_TOOL_INCLUDES}) + list(APPEND CMAKE_SWIG_FLAGS "-I${inc}") + endforeach(inc) + set(CMAKE_SWIG_FLAGS -fvirtual -module ${GRAS_SWIG_TOOL_TARGET} ${CMAKE_SWIG_FLAGS}) + + #register swig build + include(UseSWIG) + SWIG_ADD_MODULE(${GRAS_SWIG_TOOL_TARGET} python ${GRAS_SWIG_TOOL_SOURCE}) + SWIG_LINK_LIBRARIES(${GRAS_SWIG_TOOL_TARGET} ${GRAS_SWIG_TOOL_LIBRARIES}) + + #install rules for generated module and py file + set(GRAS_TOOL_PYTHON_DIR lib@LIBSUFFIX@/gras/python/${GRAS_SWIG_TOOL_DIRECTORY}) + install( + TARGETS ${SWIG_MODULE_${GRAS_SWIG_TOOL_TARGET}_REAL_NAME} + DESTINATION ${GRAS_TOOL_PYTHON_DIR} + COMPONENT ${GRAS_SWIG_TOOL_COMPONENT} + ) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${GRAS_SWIG_TOOL_TARGET}.py + DESTINATION ${GRAS_TOOL_PYTHON_DIR} + COMPONENT ${GRAS_SWIG_TOOL_COMPONENT} + ) + +endfunction(GRAS_SWIG_TOOL) diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake new file mode 100644 index 0000000..e598df4 --- /dev/null +++ b/cmake/Modules/GrPython.cmake @@ -0,0 +1,232 @@ +# Copyright 2010-2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +if(DEFINED __INCLUDED_GR_PYTHON_CMAKE) + return() +endif() +set(__INCLUDED_GR_PYTHON_CMAKE TRUE) + +######################################################################## +# Setup the python interpreter: +# This allows the user to specify a specific interpreter, +# or finds the interpreter via the built-in cmake module. +######################################################################## +#this allows the user to override PYTHON_EXECUTABLE +if(PYTHON_EXECUTABLE) + + set(PYTHONINTERP_FOUND TRUE) + +#otherwise if not set, try to automatically find it +else(PYTHON_EXECUTABLE) + + #use the built-in find script + find_package(PythonInterp) + + #and if that fails use the find program routine + if(NOT PYTHONINTERP_FOUND) + find_program(PYTHON_EXECUTABLE NAMES python python2.7 python2.6 python2.5) + if(PYTHON_EXECUTABLE) + set(PYTHONINTERP_FOUND TRUE) + endif(PYTHON_EXECUTABLE) + endif(NOT PYTHONINTERP_FOUND) + +endif(PYTHON_EXECUTABLE) + +#make the path to the executable appear in the cmake gui +set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") + +#make sure we can use -B with python (introduced in 2.6) +if(PYTHON_EXECUTABLE) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -B -c "" + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT + ) + if(PYTHON_HAS_DASH_B_RESULT EQUAL 0) + set(PYTHON_DASH_B "-B") + endif() +endif(PYTHON_EXECUTABLE) + +######################################################################## +# Check for the existence of a python module: +# - desc a string description of the check +# - mod the name of the module to import +# - cmd an additional command to run +# - have the result variable to set +######################################################################## +macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) + message(STATUS "") + message(STATUS "Python checking for ${desc}") + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c " +######################################### +try: + import ${mod} + assert ${cmd} +except ImportError, AssertionError: exit(-1) +except: pass +#########################################" + RESULT_VARIABLE ${have} + ) + if(${have} EQUAL 0) + message(STATUS "Python checking for ${desc} - found") + set(${have} TRUE) + else(${have} EQUAL 0) + message(STATUS "Python checking for ${desc} - not found") + set(${have} FALSE) + endif(${have} EQUAL 0) +endmacro(GR_PYTHON_CHECK_MODULE) + +######################################################################## +# Sets the python installation directory GR_PYTHON_DIR +######################################################################## +execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " +from distutils import sysconfig +print sysconfig.get_python_lib(plat_specific=True, prefix='') +" OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE +) +file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) + +######################################################################## +# Create an always-built target with a unique name +# Usage: GR_UNIQUE_TARGET(<description> <dependencies list>) +######################################################################## +function(GR_UNIQUE_TARGET desc) + file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib +unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] +print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" + OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) + add_custom_target(${_target} ALL DEPENDS ${ARGN}) +endfunction(GR_UNIQUE_TARGET) + +######################################################################## +# Install python sources (also builds and installs byte-compiled python) +######################################################################## +function(GR_PYTHON_INSTALL) + include(CMakeParseArguments) + CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN}) + + #################################################################### + if(GR_PYTHON_INSTALL_FILES) + #################################################################### + install(${ARGN}) #installs regular python files + + #create a list of all generated files + unset(pysrcfiles) + unset(pycfiles) + unset(pyofiles) + foreach(pyfile ${GR_PYTHON_INSTALL_FILES}) + get_filename_component(pyfile ${pyfile} ABSOLUTE) + list(APPEND pysrcfiles ${pyfile}) + + #determine if this file is in the source or binary directory + file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile}) + string(LENGTH "${source_rel_path}" source_rel_path_len) + file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile}) + string(LENGTH "${binary_rel_path}" binary_rel_path_len) + + #and set the generated path appropriately + if(${source_rel_path_len} GREATER ${binary_rel_path_len}) + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path}) + else() + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path}) + endif() + list(APPEND pycfiles ${pygenfile}c) + list(APPEND pyofiles ${pygenfile}o) + + #ensure generation path exists + get_filename_component(pygen_path ${pygenfile} PATH) + file(MAKE_DIRECTORY ${pygen_path}) + + endforeach(pyfile) + + #the command to generate the pyc files + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pycfiles} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles} + ) + + #the command to generate the pyo files + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pyofiles} + COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles} + ) + + #create install rule and add generated files to target list + set(python_install_gen_targets ${pycfiles} ${pyofiles}) + install(FILES ${python_install_gen_targets} + DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} + COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} + ) + + + #################################################################### + elseif(GR_PYTHON_INSTALL_PROGRAMS) + #################################################################### + file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) + + if (CMAKE_CROSSCOMPILING) + set(pyexe_native /usr/bin/env python) + endif() + + foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS}) + get_filename_component(pyfile_name ${pyfile} NAME) + get_filename_component(pyfile ${pyfile} ABSOLUTE) + string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe") + list(APPEND python_install_gen_targets ${pyexefile}) + + get_filename_component(pyexefile_path ${pyexefile} PATH) + file(MAKE_DIRECTORY ${pyexefile_path}) + + add_custom_command( + OUTPUT ${pyexefile} DEPENDS ${pyfile} + COMMAND ${PYTHON_EXECUTABLE} -c + \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\" + COMMENT "Shebangin ${pyfile_name}" + ) + + #on windows, python files need an extension to execute + get_filename_component(pyfile_ext ${pyfile} EXT) + if(WIN32 AND NOT pyfile_ext) + set(pyfile_name "${pyfile_name}.py") + endif() + + install(PROGRAMS ${pyexefile} RENAME ${pyfile_name} + DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} + COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} + ) + endforeach(pyfile) + + endif() + + GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets}) + +endfunction(GR_PYTHON_INSTALL) + +######################################################################## +# Write the python helper script that generates byte code files +######################################################################## +file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " +import sys, py_compile +files = sys.argv[1:] +srcs, gens = files[:len(files)/2], files[len(files)/2:] +for src, gen in zip(srcs, gens): + py_compile.compile(file=src, cfile=gen, doraise=True) +") diff --git a/cmake/Modules/GrTest.cmake b/cmake/Modules/GrTest.cmake new file mode 100644 index 0000000..bb045dc --- /dev/null +++ b/cmake/Modules/GrTest.cmake @@ -0,0 +1,139 @@ +# Copyright 2010-2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +if(DEFINED __INCLUDED_GR_TEST_CMAKE) + return() +endif() +set(__INCLUDED_GR_TEST_CMAKE TRUE) + +######################################################################## +# Add a unit test and setup the environment for a unit test. +# Takes the same arguments as the ADD_TEST function. +# +# Before calling set the following variables: +# GR_TEST_TARGET_DEPS - built targets for the library path +# GR_TEST_LIBRARY_DIRS - directories for the library path +# GR_TEST_PYTHON_DIRS - directories for the python path +# GR_TEST_ENVIRONS - other environment key/value pairs +######################################################################## +function(GR_ADD_TEST test_name) + + #Ensure that the build exe also appears in the PATH. + list(APPEND GR_TEST_TARGET_DEPS ${ARGN}) + + #In the land of windows, all libraries must be in the PATH. + #Since the dependent libraries are not yet installed, + #we must manually set them in the PATH to run tests. + #The following appends the path of a target dependency. + foreach(target ${GR_TEST_TARGET_DEPS}) + get_target_property(location ${target} LOCATION) + if(location) + get_filename_component(path ${location} PATH) + string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path}) + list(APPEND GR_TEST_LIBRARY_DIRS ${path}) + endif(location) + endforeach(target) + + if(WIN32) + #SWIG generates the python library files into a subdirectory. + #Therefore, we must append this subdirectory into PYTHONPATH. + #Only do this for the python directories matching the following: + foreach(pydir ${GR_TEST_PYTHON_DIRS}) + get_filename_component(name ${pydir} NAME) + if(name MATCHES "^(swig|lib|src)$") + list(APPEND GR_TEST_PYTHON_DIRS ${pydir}/${CMAKE_BUILD_TYPE}) + endif() + endforeach(pydir) + endif(WIN32) + + file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} srcdir) + file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list? + file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list? + + set(environs "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}") + list(APPEND environs ${GR_TEST_ENVIRONS}) + + #http://www.cmake.org/pipermail/cmake/2009-May/029464.html + #Replaced this add test + set environs code with the shell script generation. + #Its nicer to be able to manually run the shell script to diagnose problems. + #ADD_TEST(${ARGV}) + #SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}") + + if(UNIX) + set(LD_PATH_VAR "LD_LIBRARY_PATH") + if(APPLE) + set(LD_PATH_VAR "DYLD_LIBRARY_PATH") + endif() + + set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH") + list(APPEND libpath "$${LD_PATH_VAR}") + list(APPEND pypath "$PYTHONPATH") + + #replace list separator with the path separator + string(REPLACE ";" ":" libpath "${libpath}") + string(REPLACE ";" ":" pypath "${pypath}") + list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}") + + #generate a bat file that sets the environment and runs the test + find_program(SHELL sh) + set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh) + file(WRITE ${sh_file} "#!${SHELL}\n") + #each line sets an environment variable + foreach(environ ${environs}) + file(APPEND ${sh_file} "export ${environ}\n") + endforeach(environ) + #load the command to run with its arguments + foreach(arg ${ARGN}) + file(APPEND ${sh_file} "${arg} ") + endforeach(arg) + file(APPEND ${sh_file} "\n") + + #make the shell file executable + execute_process(COMMAND chmod +x ${sh_file}) + + add_test(${test_name} ${SHELL} ${sh_file}) + + endif(UNIX) + + if(WIN32) + list(APPEND libpath ${DLL_PATHS} "%PATH%") + list(APPEND pypath "%PYTHONPATH%") + + #replace list separator with the path separator (escaped) + string(REPLACE ";" "\\;" libpath "${libpath}") + string(REPLACE ";" "\\;" pypath "${pypath}") + list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}") + + #generate a bat file that sets the environment and runs the test + set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat) + file(WRITE ${bat_file} "@echo off\n") + #each line sets an environment variable + foreach(environ ${environs}) + file(APPEND ${bat_file} "SET ${environ}\n") + endforeach(environ) + #load the command to run with its arguments + foreach(arg ${ARGN}) + file(APPEND ${bat_file} "${arg} ") + endforeach(arg) + file(APPEND ${bat_file} "\n") + + add_test(${test_name} ${bat_file}) + endif(WIN32) + +endfunction(GR_ADD_TEST) diff --git a/grextras b/grextras -Subproject 12cdd194513ec0fb05292950bfc133587b16685 +Subproject 274b6c3600faf12ef3ccbf9746c4457a465dcdb diff --git a/include/gras/detail/factory.hpp b/include/gras/detail/factory.hpp index ac4df6f..551ba9e 100644 --- a/include/gras/detail/factory.hpp +++ b/include/gras/detail/factory.hpp @@ -37,10 +37,10 @@ struct FactoryRegistryEntryImpl0 : FactoryRegistryEntry }; template <typename ReturnType> -void Factory::register_make(const std::string &name, ReturnType(*fcn)()) +void register_factory(const std::string &path, ReturnType(*fcn)()) { void *r = new FactoryRegistryEntryImpl0<ReturnType>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -61,10 +61,10 @@ struct FactoryRegistryEntryImpl1 : FactoryRegistryEntry }; template <typename ReturnType, typename A0> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &)) { void *r = new FactoryRegistryEntryImpl1<ReturnType, A0>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -85,10 +85,10 @@ struct FactoryRegistryEntryImpl2 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &)) { void *r = new FactoryRegistryEntryImpl2<ReturnType, A0, A1>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -109,10 +109,10 @@ struct FactoryRegistryEntryImpl3 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &)) { void *r = new FactoryRegistryEntryImpl3<ReturnType, A0, A1, A2>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -133,10 +133,10 @@ struct FactoryRegistryEntryImpl4 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &)) { void *r = new FactoryRegistryEntryImpl4<ReturnType, A0, A1, A2, A3>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -157,10 +157,10 @@ struct FactoryRegistryEntryImpl5 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &)) { void *r = new FactoryRegistryEntryImpl5<ReturnType, A0, A1, A2, A3, A4>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -181,10 +181,10 @@ struct FactoryRegistryEntryImpl6 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &)) { void *r = new FactoryRegistryEntryImpl6<ReturnType, A0, A1, A2, A3, A4, A5>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -205,10 +205,10 @@ struct FactoryRegistryEntryImpl7 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &)) { void *r = new FactoryRegistryEntryImpl7<ReturnType, A0, A1, A2, A3, A4, A5, A6>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -229,10 +229,10 @@ struct FactoryRegistryEntryImpl8 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)) { void *r = new FactoryRegistryEntryImpl8<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -253,10 +253,10 @@ struct FactoryRegistryEntryImpl9 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &)) { void *r = new FactoryRegistryEntryImpl9<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7, A8>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** @@ -277,62 +277,62 @@ struct FactoryRegistryEntryImpl10 : FactoryRegistryEntry }; template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> -void Factory::register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &)) +void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &)) { void *r = new FactoryRegistryEntryImpl10<ReturnType, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } /*********************************************************************** * Templated make implementations **********************************************************************/ inline -Element *Factory::make(const std::string &name) +Element *make(const std::string &path) { PMCList args(0); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0> -Element *Factory::make(const std::string &name, const A0 &a0) +Element *make(const std::string &path, const A0 &a0) { PMCList args(1); args[0] = PMC_M(a0); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1) +Element *make(const std::string &path, const A0 &a0, const A1 &a1) { PMCList args(2); args[0] = PMC_M(a0); args[1] = PMC_M(a1); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2) { PMCList args(3); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3) { PMCList args(4); args[0] = PMC_M(a0); args[1] = PMC_M(a1); args[2] = PMC_M(a2); args[3] = PMC_M(a3); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) { PMCList args(5); args[0] = PMC_M(a0); @@ -340,11 +340,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons args[2] = PMC_M(a2); args[3] = PMC_M(a3); args[4] = PMC_M(a4); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) { PMCList args(6); args[0] = PMC_M(a0); @@ -353,11 +353,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons args[3] = PMC_M(a3); args[4] = PMC_M(a4); args[5] = PMC_M(a5); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6) { PMCList args(7); args[0] = PMC_M(a0); @@ -367,11 +367,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons args[4] = PMC_M(a4); args[5] = PMC_M(a5); args[6] = PMC_M(a6); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7) { PMCList args(8); args[0] = PMC_M(a0); @@ -382,11 +382,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons args[5] = PMC_M(a5); args[6] = PMC_M(a6); args[7] = PMC_M(a7); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8) { PMCList args(9); args[0] = PMC_M(a0); @@ -398,11 +398,11 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons args[6] = PMC_M(a6); args[7] = PMC_M(a7); args[8] = PMC_M(a8); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> -Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) +Element *make(const std::string &path, const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) { PMCList args(10); args[0] = PMC_M(a0); @@ -415,7 +415,7 @@ Element *Factory::make(const std::string &name, const A0 &a0, const A1 &a1, cons args[7] = PMC_M(a7); args[8] = PMC_M(a8); args[9] = PMC_M(a9); - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } } diff --git a/include/gras/factory.hpp b/include/gras/factory.hpp index 13524a6..f9403fa 100644 --- a/include/gras/factory.hpp +++ b/include/gras/factory.hpp @@ -8,15 +8,6 @@ #include <PMC/PMC.hpp> #include <string> -/*! - * Register a block's factory function: - * Declare this macro at the global scope in a cpp file. - * The block will register at static initialization time. - */ -#define GRAS_REGISTER_FACTORY(name, fcn) \ - GRAS_STATIC_BLOCK(fcn) \ - {gras::Factory::register_make(name, &fcn);} - namespace gras { @@ -26,7 +17,7 @@ namespace gras * - Call make() to create element from global factory. * * Example register a factory function: - * gras::Factory::register_make("/proj/my_block", &make_my_block); + * gras::Factory::register_factory("/proj/my_block", &make_my_block); * * Example call into the factory: * gras::Element *my_block = gras::Factory::make("/proj/my_block", arg0, arg1); @@ -34,86 +25,227 @@ namespace gras struct GRAS_API Factory { /******************************************************************* - * Register API - don't look here, template magic, not helpful + * Private registration hooks ******************************************************************/ - template <typename ReturnType> - static void register_make(const std::string &name, ReturnType(*fcn)()); + static void _register_factory(const std::string &, void *); + static Element *_handle_make(const std::string &, const PMCC &); +}; - template <typename ReturnType, typename A0> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &)); +/*********************************************************************** + * Register API - don't look here, template magic, not helpful + **********************************************************************/ +template <typename ReturnType> +static void register_factory(const std::string &path, ReturnType(*fcn)()); - template <typename ReturnType, typename A0, typename A1> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &)); +template <typename ReturnType, typename A0> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &)); - template <typename ReturnType, typename A0, typename A1, typename A2> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &)); +template <typename ReturnType, typename A0, typename A1> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &)); - template <typename ReturnType, typename A0, typename A1, typename A2, typename A3> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &)); +template <typename ReturnType, typename A0, typename A1, typename A2> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &)); - template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &)); +template <typename ReturnType, typename A0, typename A1, typename A2, typename A3> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &)); - template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &)); +template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &)); - template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &)); +template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &)); - template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)); +template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &)); - template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &)); +template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &)); - template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> - static void register_make(const std::string &name, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &)); +template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &)); - /******************************************************************* - * Make API - don't look here, template magic, not helpful - ******************************************************************/; - inline - static Element *make(const std::string &name); +template <typename ReturnType, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> +static void register_factory(const std::string &path, ReturnType(*fcn)(const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &)); - template <typename A0> - static Element *make(const std::string &name, const A0 &); +/*********************************************************************** + * Make API - don't look here, template magic, not helpful + **********************************************************************/ +inline +static Element *make(const std::string &path); - template <typename A0, typename A1> - static Element *make(const std::string &name, const A0 &, const A1 &); +template <typename A0> +static Element *make(const std::string &path, const A0 &); - template <typename A0, typename A1, typename A2> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &); +template <typename A0, typename A1> +static Element *make(const std::string &path, const A0 &, const A1 &); - template <typename A0, typename A1, typename A2, typename A3> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &); +template <typename A0, typename A1, typename A2> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &); - template <typename A0, typename A1, typename A2, typename A3, typename A4> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &); +template <typename A0, typename A1, typename A2, typename A3> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &); - template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &); +template <typename A0, typename A1, typename A2, typename A3, typename A4> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &); - template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &); +template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &); - template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &); +template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &); - template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &); +template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &); - template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> - static Element *make(const std::string &name, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &); +template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &); - /******************************************************************* - * Private registration hooks - ******************************************************************/ - static void _register_make(const std::string &, void *); - static Element *_handle_make(const std::string &, const PMCC &); -}; +template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> +static Element *make(const std::string &path, const A0 &, const A1 &, const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 &); } +/*! + * Register a block's factory function: + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY(path, fcn) \ + GRAS_STATIC_BLOCK(fcn) \ + {gras::register_factory(path, &fcn);} + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY0(path, type) \ + static gras::Element *make_ ## type() \ + { return new type(); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY1(path, type, A0) \ + static gras::Element *make_ ## type(const A0 &a0) \ + { return new type(a0); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY2(path, type, A0, A1) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1) \ + { return new type(a0, a1); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY3(path, type, A0, A1, A2) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2) \ + { return new type(a0, a1, a2); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY4(path, type, A0, A1, A2, A3) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3) \ + { return new type(a0, a1, a2, a3); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY5(path, type, A0, A1, A2, A3, A4) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) \ + { return new type(a0, a1, a2, a3, a4); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY6(path, type, A0, A1, A2, A3, A4, A5) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) \ + { return new type(a0, a1, a2, a3, a4, a5); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY7(path, type, A0, A1, A2, A3, A4, A5, A6) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6) \ + { return new type(a0, a1, a2, a3, a4, a5, a6); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY8(path, type, A0, A1, A2, A3, A4, A5, A6, A7) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7) \ + { return new type(a0, a1, a2, a3, a4, a5, a6, a7); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY9(path, type, A0, A1, A2, A3, A4, A5, A6, A7, A8) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8) \ + { return new type(a0, a1, a2, a3, a4, a5, a6, a7, a8); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY10(path, type, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9) \ + static gras::Element *make_ ## type(const A0 &a0, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5, const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) \ + { return new type(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } \ + GRAS_REGISTER_FACTORY(path, make_##type) + #include <gras/detail/factory.hpp> #endif /*INCLUDED_GRAS_FACTORY_HPP*/ diff --git a/lib/callable.cpp b/lib/callable.cpp index 59ada7f..461eebd 100644 --- a/lib/callable.cpp +++ b/lib/callable.cpp @@ -67,5 +67,5 @@ CallableRegistryEntry::~CallableRegistryEntry(void) void CallableRegistryEntry::arg_check(const PMCList &args, const size_t nargs) { if (args.size() != nargs) throw std::runtime_error(str(boost::format( - "callable expected %u arguments but for %u") % nargs % args.size())); + "callable expected %u arguments but got %u") % nargs % args.size())); } diff --git a/lib/factory.cpp b/lib/factory.cpp index e07a2f2..7115197 100644 --- a/lib/factory.cpp +++ b/lib/factory.cpp @@ -23,7 +23,7 @@ FactoryRegistryEntry::~FactoryRegistryEntry(void) void FactoryRegistryEntry::arg_check(const PMCList &args, const size_t nargs) { if (args.size() != nargs) throw std::runtime_error(str(boost::format( - "factory expected %u arguments but for %u") % nargs % args.size())); + "factory expected %u arguments but got %u") % nargs % args.size())); } typedef std::map<std::string, boost::shared_ptr<FactoryRegistryEntry> > FactoryRegistryType; @@ -36,22 +36,22 @@ static FactoryRegistryType &get_factory_registry(void) static boost::mutex mutex; -void Factory::_register_make(const std::string &name, void *entry) +void Factory::_register_factory(const std::string &path, void *entry) { boost::mutex::scoped_lock l(mutex); - if (get_factory_registry().count(name) != 0) + if (get_factory_registry().count(path) != 0) { - std::cerr << "Warning: Factory - function already registered for name: " + name << std::endl; + std::cerr << "Warning: Factory - function already registered for path: " + path << std::endl; } - get_factory_registry()[name].reset(reinterpret_cast<FactoryRegistryEntry *>(entry)); + get_factory_registry()[path].reset(reinterpret_cast<FactoryRegistryEntry *>(entry)); } -Element *Factory::_handle_make(const std::string &name, const PMCC &args) +Element *Factory::_handle_make(const std::string &path, const PMCC &args) { boost::mutex::scoped_lock l(mutex); - if (get_factory_registry().count(name) == 0) + if (get_factory_registry().count(path) == 0) { - throw std::invalid_argument("Factory - no function registered for name: " + name); + throw std::invalid_argument("Factory - no function registered for path: " + path); } - return get_factory_registry()[name]->make(args); + return get_factory_registry()[path]->make(args); } diff --git a/python/gras/CMakeLists.txt b/python/gras/CMakeLists.txt index dda4934..766431d 100644 --- a/python/gras/CMakeLists.txt +++ b/python/gras/CMakeLists.txt @@ -88,6 +88,7 @@ GR_PYTHON_INSTALL( FILES __init__.py GRAS_Utils.py + GRAS_TestUtils.py ${CMAKE_CURRENT_BINARY_DIR}/GRAS_Loader.py DESTINATION ${GR_PYTHON_DIR}/gras COMPONENT ${GRAS_COMP_PYTHON} diff --git a/python/gras/GRAS_Factory.i b/python/gras/GRAS_Factory.i index 1124963..2740b39 100644 --- a/python/gras/GRAS_Factory.i +++ b/python/gras/GRAS_Factory.i @@ -9,7 +9,7 @@ namespace gras { - %ignore Factory::register_make; + %ignore Factory::register_factory; %ignore Factory::make; } @@ -30,25 +30,18 @@ namespace gras %pythoncode %{ #TODO we need to register this into the real factory _py_factory = dict() -%} -%extend gras::Factory -{ - %insert("python") - %{ - @staticmethod - def register_make(name, fcn): - #TODO we need to register this into the real factory - _py_factory[name] = fcn - - @staticmethod - def make(name, *args, **kwargs): - - #first try the local to python py factory #TODO real factory - if name in _py_factory: return _py_factory[name](*args, **kwargs) - - from PMC import PMC_M - pmcargs = PMC_M(list(args)) - return Factory._handle_make(name, pmcargs) - %} -} +def register_factory(path, fcn): + #TODO we need to register this into the real factory + _py_factory[path] = fcn + +def make(path, *args, **kwargs): + + #first try the local to python py factory #TODO real factory + if path in _py_factory: return _py_factory[path](*args, **kwargs) + + from PMC import PMC_M + pmcargs = PMC_M(list(args)) + return Factory._handle_make(path, pmcargs) + +%} diff --git a/python/gras/GRAS_Loader.py b/python/gras/GRAS_Loader.py index b70bc60..cc73d9b 100644 --- a/python/gras/GRAS_Loader.py +++ b/python/gras/GRAS_Loader.py @@ -2,6 +2,7 @@ import os import sys +import traceback #try to import module #http://effbot.org/zone/import-string.htm @@ -15,6 +16,7 @@ def __try_module_import(filename): module = __import__(module_name) except Exception as ex: print 'Could not import', filename, ex + print traceback.format_exc() finally: sys.path[:] = path # restore diff --git a/tests/demo_blocks.py b/python/gras/GRAS_TestUtils.py index 8550402..2960a2d 100644 --- a/tests/demo_blocks.py +++ b/python/gras/GRAS_TestUtils.py @@ -29,7 +29,7 @@ class VectorSource(gras.Block): outs[0][:num] = self._vec[:num] self.produce(0, num) self._vec = self._vec[num:] - if not self._vec: + if not len(self._vec): self.mark_done() class VectorSink(gras.Block): @@ -37,13 +37,27 @@ class VectorSink(gras.Block): gras.Block.__init__(self, name='VectorSink', in_sig=[in_sig]) self._vec = list() - def get_vector(self): + def data(self): return tuple(self._vec) def work(self, ins, outs): self._vec.extend(ins[0].copy()) self.consume(0, len(ins[0])) +class Head(gras.Block): + def __init__(self, sig, num_items): + gras.Block.__init__(self, name='Head', in_sig=[sig], out_sig=[sig]) + self._num_items = num_items + + def work(self, ins, outs): + n = min(len(ins[0]), len(outs[0]), self._num_items) + outs[0][:n] = ins[0][:n] + self.consume(0, n) + self.produce(0, n) + self._num_items -= n + if not self._num_items: + self.mark_done() + class Add2X(gras.Block): def __init__(self, sig): gras.Block.__init__(self, diff --git a/python/gras/__init__.py b/python/gras/__init__.py index 6dcd4cd..884182c 100644 --- a/python/gras/__init__.py +++ b/python/gras/__init__.py @@ -10,7 +10,7 @@ from GRAS_SBuffer import SBufferConfig, SBuffer from GRAS_Tags import Tag, StreamTag, PacketMsg from GRAS_TimeTag import TimeTag from GRAS_Element import Element -from GRAS_Factory import Factory +from GRAS_Factory import make, register_factory import GRAS_Block import GRAS_HierBlock import GRAS_TopBlock @@ -19,3 +19,4 @@ from GRAS_PyHierBlocks import PyHierBlock as HierBlock from GRAS_PyHierBlocks import PyTopBlock as TopBlock from GRAS_ThreadPool import ThreadPoolConfig, ThreadPool import GRAS_Loader +import GRAS_TestUtils as TestUtils diff --git a/tests/block_test.py b/tests/block_test.py index 2f8d91b..614e702 100644 --- a/tests/block_test.py +++ b/tests/block_test.py @@ -3,7 +3,7 @@ import unittest import gras import numpy -from demo_blocks import * +from gras import TestUtils class BlockTest(unittest.TestCase): @@ -14,55 +14,55 @@ class BlockTest(unittest.TestCase): self.tb = None def test_vector_blocks(self): - vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) - vec_sink = VectorSink(numpy.uint32) + vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) + vec_sink = TestUtils.VectorSink(numpy.uint32) self.tb.connect(vec_source, vec_sink) self.tb.run() - self.assertEqual(vec_sink.get_vector(), (0, 9, 8, 7, 6)) + self.assertEqual(vec_sink.data(), (0, 9, 8, 7, 6)) def test_add_f32(self): - src0 = VectorSource(numpy.float32, [1, 3, 5, 7, 9]) - src1 = VectorSource(numpy.float32, [0, 2, 4, 6, 8]) - adder = Add2X(numpy.float32) - sink = VectorSink(numpy.float32) + src0 = TestUtils.VectorSource(numpy.float32, [1, 3, 5, 7, 9]) + src1 = TestUtils.VectorSource(numpy.float32, [0, 2, 4, 6, 8]) + adder = TestUtils.Add2X(numpy.float32) + sink = TestUtils.VectorSink(numpy.float32) self.tb.connect((src0, 0), (adder, 0)) self.tb.connect((src1, 0), (adder, 1)) self.tb.connect(adder, sink) self.tb.run() - self.assertEqual(sink.get_vector(), (1, 5, 9, 13, 17)) + self.assertEqual(sink.data(), (1, 5, 9, 13, 17)) def test_add_fc32(self): - src0 = VectorSource(numpy.complex64, [1, 3j, 5, 7j, 9]) - src1 = VectorSource(numpy.complex64, [0, 2j, 4, 6j, 8]) - adder = Add2X(numpy.complex64) - sink = VectorSink(numpy.complex64) + src0 = TestUtils.VectorSource(numpy.complex64, [1, 3j, 5, 7j, 9]) + src1 = TestUtils.VectorSource(numpy.complex64, [0, 2j, 4, 6j, 8]) + adder = TestUtils.Add2X(numpy.complex64) + sink = TestUtils.VectorSink(numpy.complex64) self.tb.connect((src0, 0), (adder, 0)) self.tb.connect((src1, 0), (adder, 1)) self.tb.connect(adder, sink) self.tb.run() - self.assertEqual(sink.get_vector(), (1, 5j, 9, 13j, 17)) + self.assertEqual(sink.data(), (1, 5j, 9, 13j, 17)) def test_add_f32_feedback(self): """ Feedback adder output to input1 of the adder. Preload input1 of the adder to set the delay. """ - src0 = VectorSource(numpy.float32, [1, 3, 5, 7, 9]) - adder = Add2X(numpy.float32) + src0 = TestUtils.VectorSource(numpy.float32, [1, 3, 5, 7, 9]) + adder = TestUtils.Add2X(numpy.float32) adder.input_config(1).preload_items = 1 #make this a feedback delay of 1 - sink = VectorSink(numpy.float32) + sink = TestUtils.VectorSink(numpy.float32) self.tb.connect((src0, 0), (adder, 0)) self.tb.connect((adder, 0), (adder, 1)) self.tb.connect(adder, sink) self.tb.run() - self.assertEqual(sink.get_vector(), (1, 4, 9, 16, 25)) + self.assertEqual(sink.data(), (1, 4, 9, 16, 25)) def test_tag_source_sink(self): values = (0, 'hello', 4.2, True, None, [2, 3, 4], (9, 8, 7), 1j, {2:'d'}) - src = TagSource(values) - sink = TagSink() + src = TestUtils.TagSource(values) + sink = TestUtils.TagSink() self.tb.connect(src, sink) self.tb.run() self.assertEqual(sink.get_values(), values) @@ -79,7 +79,7 @@ class BlockTest(unittest.TestCase): except: pass self.consume(0, len(ins[0])) - source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) + source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) sink = BadTouch(numpy.uint32) self.tb.connect(source, sink) diff --git a/tests/example_module.cpp b/tests/example_module.cpp index d0316f8..389cf53 100644 --- a/tests/example_module.cpp +++ b/tests/example_module.cpp @@ -26,9 +26,4 @@ struct MyBlock : gras::Block void work(const InputItems &, const OutputItems &){} }; -gras::Block *make_my_block(void) -{ - return new MyBlock(); -} - -GRAS_REGISTER_FACTORY("/tests/my_block0", make_my_block) +GRAS_REGISTER_FACTORY0("/tests/my_block0", MyBlock) diff --git a/tests/example_module.py b/tests/example_module.py index 6c29435..3ef73dd 100644 --- a/tests/example_module.py +++ b/tests/example_module.py @@ -13,4 +13,4 @@ class MyBlock(gras.Block): def get_num(self): return 42 -gras.Factory.register_make("/tests/my_block1", MyBlock) +gras.register_factory("/tests/my_block1", MyBlock) diff --git a/tests/factory_test.cpp b/tests/factory_test.cpp index 999e86e..ca8b5ba 100644 --- a/tests/factory_test.cpp +++ b/tests/factory_test.cpp @@ -51,25 +51,25 @@ GRAS_REGISTER_FACTORY("/tests/my_block_args3", make_my_block_args3) BOOST_AUTO_TEST_CASE(test_register_and_make) { - gras::Element *my_block0 = gras::Factory::make("/tests/my_block_args0"); + gras::Element *my_block0 = gras::make("/tests/my_block_args0"); BOOST_CHECK(dynamic_cast<MyBlock *>(my_block0) != NULL); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block0)->a0, 0); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block0)->a1, ""); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block0)->a2, false); - gras::Element *my_block1 = gras::Factory::make("/tests/my_block_args1", 42); + gras::Element *my_block1 = gras::make("/tests/my_block_args1", 42); BOOST_CHECK(dynamic_cast<MyBlock *>(my_block1) != NULL); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block1)->a0, 42); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block1)->a1, ""); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block1)->a2, false); - gras::Element *my_block2 = gras::Factory::make("/tests/my_block_args2", 1, "foo"); + gras::Element *my_block2 = gras::make("/tests/my_block_args2", 1, "foo"); BOOST_CHECK(dynamic_cast<MyBlock *>(my_block2) != NULL); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block2)->a0, 1); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block2)->a1, "foo"); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block2)->a2, false); - gras::Element *my_block3 = gras::Factory::make("/tests/my_block_args3", -2, "bar", true); + gras::Element *my_block3 = gras::make("/tests/my_block_args3", -2, "bar", true); BOOST_CHECK(dynamic_cast<MyBlock *>(my_block3) != NULL); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block3)->a0, -2); BOOST_CHECK_EQUAL(dynamic_cast<MyBlock *>(my_block3)->a1, "bar"); diff --git a/tests/module_loader_test.py b/tests/module_loader_test.py index 4a8d64f..34423fd 100644 --- a/tests/module_loader_test.py +++ b/tests/module_loader_test.py @@ -6,11 +6,11 @@ import gras class ModuleLoaderTest(unittest.TestCase): def test_load_module_cpp(self): - my_block = gras.Factory.make("/tests/my_block0") + my_block = gras.make("/tests/my_block0") self.assertEqual(my_block.get_num(), 42) def test_load_module_py(self): - my_block = gras.Factory.make("/tests/my_block1") + my_block = gras.make("/tests/my_block1") self.assertEqual(my_block.get_num(), 42) if __name__ == '__main__': diff --git a/tests/query_test.py b/tests/query_test.py index 8e5bfaf..f4f45f9 100644 --- a/tests/query_test.py +++ b/tests/query_test.py @@ -3,7 +3,7 @@ import unittest import gras import numpy -from demo_blocks import * +from gras import TestUtils class MyBlock(gras.Block): def __init__(self): @@ -44,13 +44,13 @@ class QueryTest(unittest.TestCase): self.tb = None def test_simple(self): - vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) - vec_sink = VectorSink(numpy.uint32) + vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) + vec_sink = TestUtils.VectorSink(numpy.uint32) self.tb.connect(vec_source, vec_sink) self.tb.run() - self.assertEqual(vec_sink.get_vector(), (0, 9, 8, 7, 6)) + self.assertEqual(vec_sink.data(), (0, 9, 8, 7, 6)) #query the block list blocks_result = self.tb.query(dict(path="/blocks.json")) @@ -71,8 +71,8 @@ class QueryTest(unittest.TestCase): self.assertTrue(block_id in stats_result['blocks']) def test_numeric_query(self): - vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) - vec_sink = VectorSink(numpy.uint32) + vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) + vec_sink = TestUtils.VectorSink(numpy.uint32) block = MyBlock() block.set_uid("test_numeric_query") self.tb.connect(vec_source, block, vec_sink) @@ -120,8 +120,8 @@ class QueryTest(unittest.TestCase): self.assertEqual(result['value'], '(0,21)') def test_vector_query(self): - vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) - vec_sink = VectorSink(numpy.uint32) + vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) + vec_sink = TestUtils.VectorSink(numpy.uint32) block = MyBlock() block.set_uid("test_vector_query") self.tb.connect(vec_source, block, vec_sink) diff --git a/tests/thread_pool_test.py b/tests/thread_pool_test.py index 2765b07..58a00fe 100644 --- a/tests/thread_pool_test.py +++ b/tests/thread_pool_test.py @@ -2,7 +2,8 @@ import unittest import gras -from demo_blocks import * +from gras import TestUtils +import numpy class ThreadPoolTest(unittest.TestCase): @@ -26,8 +27,8 @@ class ThreadPoolTest(unittest.TestCase): def test_migrate_to_thread_pool(self): tb = gras.TopBlock() - vec_source = VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) - vec_sink = VectorSink(numpy.uint32) + vec_source = TestUtils.VectorSource(numpy.uint32, [0, 9, 8, 7, 6]) + vec_sink = TestUtils.VectorSink(numpy.uint32) c = gras.ThreadPoolConfig() tp = gras.ThreadPool(c) @@ -36,7 +37,7 @@ class ThreadPoolTest(unittest.TestCase): tb.connect(vec_source, vec_sink) tb.run() - self.assertEqual(vec_sink.get_vector(), (0, 9, 8, 7, 6)) + self.assertEqual(vec_sink.data(), (0, 9, 8, 7, 6)) if __name__ == '__main__': unittest.main() diff --git a/tmpl/factory.tmpl.hpp b/tmpl/factory.tmpl.hpp index 61a61ba..a8f0b5d 100644 --- a/tmpl/factory.tmpl.hpp +++ b/tmpl/factory.tmpl.hpp @@ -8,15 +8,6 @@ #include <PMC/PMC.hpp> #include <string> -/*! - * Register a block's factory function: - * Declare this macro at the global scope in a cpp file. - * The block will register at static initialization time. - */ -#define GRAS_REGISTER_FACTORY(name, fcn) \ - GRAS_STATIC_BLOCK(fcn) \ - {gras::Factory::register_make(name, &fcn);} - namespace gras { @@ -26,7 +17,7 @@ namespace gras * - Call make() to create element from global factory. * * Example register a factory function: - * gras::Factory::register_make("/proj/my_block", &make_my_block); + * gras::Factory::register_factory("/proj/my_block", &make_my_block); * * Example call into the factory: * gras::Element *my_block = gras::Factory::make("/proj/my_block", arg0, arg1); @@ -34,30 +25,53 @@ namespace gras struct GRAS_API Factory { /******************************************************************* - * Register API - don't look here, template magic, not helpful - ******************************************************************/ - #for $NARGS in range($MAX_ARGS) - template <typename ReturnType, $expand('typename A%d', $NARGS)> - static void register_make(const std::string &name, ReturnType(*fcn)($expand('const A%d &', $NARGS))); - - #end for - /******************************************************************* - * Make API - don't look here, template magic, not helpful - ******************************************************************/; - #for $NARGS in range($MAX_ARGS) - template <$expand('typename A%d', $NARGS)> - static Element *make(const std::string &name, $expand('const A%d &', $NARGS)); - - #end for - /******************************************************************* * Private registration hooks ******************************************************************/ - static void _register_make(const std::string &, void *); + static void _register_factory(const std::string &, void *); static Element *_handle_make(const std::string &, const PMCC &); }; +/*********************************************************************** + * Register API - don't look here, template magic, not helpful + **********************************************************************/ +#for $NARGS in range($MAX_ARGS) +template <typename ReturnType, $expand('typename A%d', $NARGS)> +static void register_factory(const std::string &path, ReturnType(*fcn)($expand('const A%d &', $NARGS))); + +#end for +/*********************************************************************** + * Make API - don't look here, template magic, not helpful + **********************************************************************/ +#for $NARGS in range($MAX_ARGS) +template <$expand('typename A%d', $NARGS)> +static Element *make(const std::string &path, $expand('const A%d &', $NARGS)); + +#end for } +/*! + * Register a block's factory function: + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY(path, fcn) \ + GRAS_STATIC_BLOCK(fcn) \ + {gras::register_factory(path, &fcn);} + +#for $NARGS in range($MAX_ARGS) +/*! + * Register a block's constructor into the factory: + * The arguments to this macro must be the types of each constructor argument. + * Example: GRAS_REGISTER_FACTORY2("/proj/my_block", MyBlock, std::string, size_t) + * Declare this macro at the global scope in a cpp file. + * The block will register at static initialization time. + */ +#define GRAS_REGISTER_FACTORY$(NARGS)(path, type, $expand('A%d', $NARGS)) \ + static gras::Element *make_ $('##') type($expand('const A%d &a%d', $NARGS)) \ + { return new type($expand('a%d', $NARGS)); } \ + GRAS_REGISTER_FACTORY(path, make_$('##')type) + +#end for #include <gras/detail/factory.hpp> #endif /*INCLUDED_GRAS_FACTORY_HPP*/ diff --git a/tmpl/factory_detail.tmpl.hpp b/tmpl/factory_detail.tmpl.hpp index ea30235..660a690 100644 --- a/tmpl/factory_detail.tmpl.hpp +++ b/tmpl/factory_detail.tmpl.hpp @@ -38,10 +38,10 @@ struct FactoryRegistryEntryImpl$(NARGS) : FactoryRegistryEntry }; template <typename ReturnType, $expand('typename A%d', $NARGS)> -void Factory::register_make(const std::string &name, ReturnType(*fcn)($expand('const A%d &', $NARGS))) +void register_factory(const std::string &path, ReturnType(*fcn)($expand('const A%d &', $NARGS))) { void *r = new FactoryRegistryEntryImpl$(NARGS)<ReturnType, $expand('A%d', $NARGS)>(fcn); - Factory::_register_make(name, r); + Factory::_register_factory(path, r); } #end for @@ -50,13 +50,13 @@ void Factory::register_make(const std::string &name, ReturnType(*fcn)($expand('c **********************************************************************/ #for $NARGS in range($MAX_ARGS) template <$expand('typename A%d', $NARGS)> -Element *Factory::make(const std::string &name, $expand('const A%d &a%d', $NARGS)) +Element *make(const std::string &path, $expand('const A%d &a%d', $NARGS)) { PMCList args($NARGS); #for $i in range($NARGS): args[$i] = PMC_M(a$i); #end for - return Factory::_handle_make(name, PMC_M(args)); + return Factory::_handle_make(path, PMC_M(args)); } #end for |