summaryrefslogtreecommitdiff
path: root/gr-howto-write-a-block-cmake/cmake
diff options
context:
space:
mode:
Diffstat (limited to 'gr-howto-write-a-block-cmake/cmake')
-rw-r--r--gr-howto-write-a-block-cmake/cmake/Modules/CMakeParseArgumentsCopy.cmake138
-rw-r--r--gr-howto-write-a-block-cmake/cmake/Modules/FindGnuradioCore.cmake26
-rw-r--r--gr-howto-write-a-block-cmake/cmake/Modules/FindGruel.cmake26
-rw-r--r--gr-howto-write-a-block-cmake/cmake/Modules/GrPlatform.cmake46
-rw-r--r--gr-howto-write-a-block-cmake/cmake/Modules/GrPython.cmake177
-rw-r--r--gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake136
-rw-r--r--gr-howto-write-a-block-cmake/cmake/Modules/GrTest.cmake133
7 files changed, 682 insertions, 0 deletions
diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/CMakeParseArgumentsCopy.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/CMakeParseArgumentsCopy.cmake
new file mode 100644
index 000000000..7ce4c49ae
--- /dev/null
+++ b/gr-howto-write-a-block-cmake/cmake/Modules/CMakeParseArgumentsCopy.cmake
@@ -0,0 +1,138 @@
+# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)
+#
+# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for
+# parsing the arguments given to that macro or function.
+# It processes the arguments and defines a set of variables which hold the
+# values of the respective options.
+#
+# The <options> argument contains all options for the respective macro,
+# i.e. keywords which can be used when calling the macro without any value
+# following, like e.g. the OPTIONAL keyword of the install() command.
+#
+# The <one_value_keywords> argument contains all keywords for this macro
+# which are followed by one value, like e.g. DESTINATION keyword of the
+# install() command.
+#
+# The <multi_value_keywords> argument contains all keywords for this macro
+# which can be followed by more than one value, like e.g. the TARGETS or
+# FILES keywords of the install() command.
+#
+# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
+# keywords listed in <options>, <one_value_keywords> and
+# <multi_value_keywords> a variable composed of the given <prefix>
+# followed by "_" and the name of the respective keyword.
+# These variables will then hold the respective value from the argument list.
+# For the <options> keywords this will be TRUE or FALSE.
+#
+# All remaining arguments are collected in a variable
+# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see whether
+# your macro was called with unrecognized parameters.
+#
+# As an example here a my_install() macro, which takes similar arguments as the
+# real install() command:
+#
+# function(MY_INSTALL)
+# set(options OPTIONAL FAST)
+# set(oneValueArgs DESTINATION RENAME)
+# set(multiValueArgs TARGETS CONFIGURATIONS)
+# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+# ...
+#
+# Assume my_install() has been called like this:
+# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
+#
+# After the cmake_parse_arguments() call the macro will have set the following
+# variables:
+# MY_INSTALL_OPTIONAL = TRUE
+# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
+# MY_INSTALL_DESTINATION = "bin"
+# MY_INSTALL_RENAME = "" (was not used)
+# MY_INSTALL_TARGETS = "foo;bar"
+# MY_INSTALL_CONFIGURATIONS = "" (was not used)
+# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
+#
+# You can the continue and process these variables.
+#
+# Keywords terminate lists of values, e.g. if directly after a one_value_keyword
+# another recognized keyword follows, this is interpreted as the beginning of
+# the new option.
+# E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in
+# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would
+# be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
+
+#=============================================================================
+# Copyright 2010 Alexander Neundorf <neundorf@kde.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+
+if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
+ return()
+endif()
+set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
+
+
+function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
+ # first set all result variables to empty/FALSE
+ foreach(arg_name ${_singleArgNames} ${_multiArgNames})
+ set(${prefix}_${arg_name})
+ endforeach(arg_name)
+
+ foreach(option ${_optionNames})
+ set(${prefix}_${option} FALSE)
+ endforeach(option)
+
+ set(${prefix}_UNPARSED_ARGUMENTS)
+
+ set(insideValues FALSE)
+ set(currentArgName)
+
+ # now iterate over all arguments and fill the result variables
+ foreach(currentArg ${ARGN})
+ list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
+ list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
+ list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
+
+ if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
+ if(insideValues)
+ if("${insideValues}" STREQUAL "SINGLE")
+ set(${prefix}_${currentArgName} ${currentArg})
+ set(insideValues FALSE)
+ elseif("${insideValues}" STREQUAL "MULTI")
+ list(APPEND ${prefix}_${currentArgName} ${currentArg})
+ endif()
+ else(insideValues)
+ list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
+ endif(insideValues)
+ else()
+ if(NOT ${optionIndex} EQUAL -1)
+ set(${prefix}_${currentArg} TRUE)
+ set(insideValues FALSE)
+ elseif(NOT ${singleArgIndex} EQUAL -1)
+ set(currentArgName ${currentArg})
+ set(${prefix}_${currentArgName})
+ set(insideValues "SINGLE")
+ elseif(NOT ${multiArgIndex} EQUAL -1)
+ set(currentArgName ${currentArg})
+ set(${prefix}_${currentArgName})
+ set(insideValues "MULTI")
+ endif()
+ endif()
+
+ endforeach(currentArg)
+
+ # propagate the result variables to the caller:
+ foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
+ set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
+ endforeach(arg_name)
+ set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
+
+endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs)
diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/FindGnuradioCore.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/FindGnuradioCore.cmake
new file mode 100644
index 000000000..ffa6582a2
--- /dev/null
+++ b/gr-howto-write-a-block-cmake/cmake/Modules/FindGnuradioCore.cmake
@@ -0,0 +1,26 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_GNURADIO_CORE gnuradio-core QUIET)
+
+FIND_PATH(
+ GNURADIO_CORE_INCLUDE_DIRS
+ NAMES gr_random.h
+ HINTS $ENV{GNURADIO_CORE_DIR}/include/gnuradio
+ ${PC_GNURADIO_CORE_INCLUDE_DIRS}
+ PATHS /usr/local/include/gnuradio
+ /usr/include/gnuradio
+)
+
+FIND_LIBRARY(
+ GNURADIO_CORE_LIBRARIES
+ NAMES gnuradio-core
+ HINTS $ENV{GNURADIO_CORE_DIR}/lib
+ ${PC_GNURADIO_CORE_LIBRARIES}
+ PATHS /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_CORE DEFAULT_MSG GNURADIO_CORE_LIBRARIES GNURADIO_CORE_INCLUDE_DIRS)
+MARK_AS_ADVANCED(GNURADIO_CORE_LIBRARIES GNURADIO_CORE_INCLUDE_DIRS)
diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/FindGruel.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/FindGruel.cmake
new file mode 100644
index 000000000..3c21af91d
--- /dev/null
+++ b/gr-howto-write-a-block-cmake/cmake/Modules/FindGruel.cmake
@@ -0,0 +1,26 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_GRUEL gnuradio-core QUIET)
+
+FIND_PATH(
+ GRUEL_INCLUDE_DIRS
+ NAMES gruel/attributes.h
+ HINTS $ENV{GRUEL_DIR}/include
+ ${PC_GRUEL_INCLUDE_DIRS}
+ PATHS /usr/local/include
+ /usr/include
+)
+
+FIND_LIBRARY(
+ GRUEL_LIBRARIES
+ NAMES gruel
+ HINTS $ENV{GRUEL_DIR}/lib
+ ${PC_GRUEL_LIBRARIES}
+ PATHS /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(GRUEL DEFAULT_MSG GRUEL_LIBRARIES GRUEL_INCLUDE_DIRS)
+MARK_AS_ADVANCED(GRUEL_LIBRARIES GRUEL_INCLUDE_DIRS)
diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/GrPlatform.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/GrPlatform.cmake
new file mode 100644
index 000000000..85f318618
--- /dev/null
+++ b/gr-howto-write-a-block-cmake/cmake/Modules/GrPlatform.cmake
@@ -0,0 +1,46 @@
+# Copyright 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_PLATFORM_CMAKE)
+ RETURN()
+ENDIF()
+SET(__INCLUDED_GR_PLATFORM_CMAKE TRUE)
+
+########################################################################
+# Setup additional defines for OS types
+########################################################################
+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()
+
+########################################################################
+# when the library suffix should be 64 (applies to redhat linux family)
+########################################################################
+IF(NOT DEFINED LIB_SUFFIX AND REDHAT AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$")
+ SET(LIB_SUFFIX 64)
+ENDIF()
+SET(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix")
diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/GrPython.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/GrPython.cmake
new file mode 100644
index 000000000..f54dbc9ba
--- /dev/null
+++ b/gr-howto-write-a-block-cmake/cmake/Modules/GrPython.cmake
@@ -0,0 +1,177 @@
+# 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")
+
+########################################################################
+# 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}
+except: exit(-1)
+try: assert ${cmd}
+except: exit(-1)
+#########################################"
+ 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(CMakeParseArgumentsCopy)
+ CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN})
+
+ ####################################################################
+ IF(GR_PYTHON_INSTALL_FILES)
+ ####################################################################
+ INSTALL(${ARGN}) #installs regular python files
+
+ FOREACH(pyfile ${GR_PYTHON_INSTALL_FILES})
+ GET_FILENAME_COMPONENT(pyfile_name ${pyfile} NAME)
+ GET_FILENAME_COMPONENT(pyfile ${pyfile} ABSOLUTE)
+ STRING(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pycfile "${pyfile}c")
+ LIST(APPEND python_install_gen_targets ${pycfile})
+
+ GET_FILENAME_COMPONENT(pycfile_path ${pycfile} PATH)
+ FILE(MAKE_DIRECTORY ${pycfile_path})
+
+ #create a command to generate the byte-compiled pyc file
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${pycfile} DEPENDS ${pyfile}
+ COMMAND ${PYTHON_EXECUTABLE} -c
+ \"import py_compile\; py_compile.compile(file='${pyfile}', cfile='${pycfile}', doraise=True)\"
+ COMMENT "Byte-compiling ${pyfile_name}"
+ )
+ INSTALL(FILES ${pycfile}
+ DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
+ COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
+ )
+ ENDFOREACH(pyfile)
+
+ ####################################################################
+ ELSEIF(GR_PYTHON_INSTALL_PROGRAMS)
+ ####################################################################
+ FILE(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native)
+
+ 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)
diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake
new file mode 100644
index 000000000..0d4cce2b3
--- /dev/null
+++ b/gr-howto-write-a-block-cmake/cmake/Modules/GrSwig.cmake
@@ -0,0 +1,136 @@
+# 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_SWIG_CMAKE)
+ RETURN()
+ENDIF()
+SET(__INCLUDED_GR_SWIG_CMAKE TRUE)
+
+INCLUDE(GrPython)
+
+########################################################################
+# Build a swig target for the common gnuradio use case. Usage:
+# GR_SWIG_MAKE(target ifile ifile ifile...)
+#
+# Set the following variables before calling:
+# - GR_SWIG_FLAGS
+# - GR_SWIG_INCLUDE_DIRS
+# - GR_SWIG_LIBRARIES
+# - GR_SWIG_SOURCE_DEPS
+# - GR_SWIG_TARGET_DEPS
+########################################################################
+MACRO(GR_SWIG_MAKE name)
+ SET(ifiles ${ARGN})
+
+ #determine include dependencies for swig file
+ EXECUTE_PROCESS(
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/get_swig_deps.py
+ "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}"
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+
+ #append the specified include directories
+ INCLUDE_DIRECTORIES(${GR_SWIG_INCLUDE_DIRS})
+ LIST(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${GR_SWIG_SOURCE_DEPS})
+
+ FIND_PACKAGE(PythonLibs)
+ INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
+
+ #setup the swig flags with flags and include directories
+ SET(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS})
+ FOREACH(dir ${GR_SWIG_INCLUDE_DIRS})
+ LIST(APPEND CMAKE_SWIG_FLAGS "-I${dir}")
+ ENDFOREACH(dir)
+
+ #set the C++ property on the swig .i file so it builds
+ SET_SOURCE_FILES_PROPERTIES(${ifiles} PROPERTIES CPLUSPLUS ON)
+
+ #setup the actual swig library target to be built
+ INCLUDE(UseSWIG)
+ SWIG_ADD_MODULE(${name} python ${ifiles})
+ SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES})
+ IF(GR_SWIG_TARGET_DEPS)
+ ADD_DEPENDENCIES(${SWIG_MODULE_${name}_REAL_NAME} ${GR_SWIG_TARGET_DEPS})
+ ENDIF(GR_SWIG_TARGET_DEPS)
+
+ENDMACRO(GR_SWIG_MAKE)
+
+########################################################################
+# Install swig targets generated by GR_SWIG_MAKE. Usage:
+# GR_SWIG_INSTALL(
+# TARGETS target target target...
+# [DESTINATION destination]
+# [COMPONENT component]
+# )
+########################################################################
+MACRO(GR_SWIG_INSTALL)
+
+ INCLUDE(CMakeParseArgumentsCopy)
+ CMAKE_PARSE_ARGUMENTS(GR_SWIG_INSTALL "" "DESTINATION;COMPONENT" "TARGETS" ${ARGN})
+
+ FOREACH(name ${GR_SWIG_INSTALL_TARGETS})
+ INSTALL(TARGETS ${SWIG_MODULE_${name}_REAL_NAME}
+ DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
+ COMPONENT ${GR_SWIG_INSTALL_COMPONENT}
+ )
+
+ INCLUDE(GrPython)
+ GR_PYTHON_INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.py
+ DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
+ COMPONENT ${GR_SWIG_INSTALL_COMPONENT}
+ )
+ ENDFOREACH(name)
+
+ENDMACRO(GR_SWIG_INSTALL)
+
+########################################################################
+# Generate a python file that can determine swig dependencies.
+# Used by the make macro above to determine extra dependencies.
+# When you build C++, CMake figures out the header dependencies.
+# This code essentially performs that logic for swig includes.
+########################################################################
+FILE(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py "
+
+import os, sys, re
+
+include_matcher = re.compile('[#|%]include\\s*[<|\"](.*)[>|\"]')
+include_dirs = sys.argv[2].split(';')
+
+def get_swig_incs(file_path):
+ file_contents = open(file_path, 'r').read()
+ return include_matcher.findall(file_contents, re.MULTILINE)
+
+def get_swig_deps(file_path, level):
+ deps = [file_path]
+ if level == 0: return deps
+ for inc_file in get_swig_incs(file_path):
+ for inc_dir in include_dirs:
+ inc_path = os.path.join(inc_dir, inc_file)
+ if not os.path.exists(inc_path): continue
+ deps.extend(get_swig_deps(inc_path, level-1))
+ return deps
+
+if __name__ == '__main__':
+ ifiles = sys.argv[1].split(';')
+ deps = sum([get_swig_deps(ifile, 3) for ifile in ifiles], [])
+ #sys.stderr.write(';'.join(set(deps)) + '\\n\\n')
+ print(';'.join(set(deps)))
+")
diff --git a/gr-howto-write-a-block-cmake/cmake/Modules/GrTest.cmake b/gr-howto-write-a-block-cmake/cmake/Modules/GrTest.cmake
new file mode 100644
index 000000000..e9e2a0c2e
--- /dev/null
+++ b/gr-howto-write-a-block-cmake/cmake/Modules/GrTest.cmake
@@ -0,0 +1,133 @@
+# 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
+########################################################################
+FUNCTION(GR_ADD_TEST test_name)
+
+ IF(WIN32)
+ #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)
+
+ #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}")
+
+ #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(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH")
+ #set both LD and DYLD paths to cover multiple UNIX OS library paths
+ LIST(APPEND libpath "$LD_LIBRARY_PATH" "$DYLD_LIBRARY_PATH")
+ 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_LIBRARY_PATH=${libpath}" "DYLD_LIBRARY_PATH=${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)