diff options
Diffstat (limited to 'gr-howto-write-a-block/cmake/Modules')
8 files changed, 1035 insertions, 0 deletions
diff --git a/gr-howto-write-a-block/cmake/Modules/CMakeParseArgumentsCopy.cmake b/gr-howto-write-a-block/cmake/Modules/CMakeParseArgumentsCopy.cmake new file mode 100644 index 000000000..7ce4c49ae --- /dev/null +++ b/gr-howto-write-a-block/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/Modules/FindGnuradioCore.cmake b/gr-howto-write-a-block/cmake/Modules/FindGnuradioCore.cmake new file mode 100644 index 000000000..b45cf95e6 --- /dev/null +++ b/gr-howto-write-a-block/cmake/Modules/FindGnuradioCore.cmake @@ -0,0 +1,26 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_GNURADIO_CORE QUIET gnuradio-core) + +FIND_PATH( + GNURADIO_CORE_INCLUDE_DIRS + NAMES gr_random.h + HINTS $ENV{GNURADIO_CORE_DIR}/include/gnuradio + ${PC_GNURADIO_CORE_INCLUDE_DIR} + 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_LIBDIR} + 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/Modules/FindGruel.cmake b/gr-howto-write-a-block/cmake/Modules/FindGruel.cmake new file mode 100644 index 000000000..56b8b1773 --- /dev/null +++ b/gr-howto-write-a-block/cmake/Modules/FindGruel.cmake @@ -0,0 +1,26 @@ +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PC_GRUEL QUIET gnuradio-core) + +FIND_PATH( + GRUEL_INCLUDE_DIRS + NAMES gruel/attributes.h + HINTS $ENV{GRUEL_DIR}/include + ${PC_GRUEL_INCLUDE_DIR} + PATHS /usr/local/include + /usr/include +) + +FIND_LIBRARY( + GRUEL_LIBRARIES + NAMES gruel + HINTS $ENV{GRUEL_DIR}/lib + ${PC_GRUEL_LIBDIR} + 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/Modules/GrMiscUtils.cmake b/gr-howto-write-a-block/cmake/Modules/GrMiscUtils.cmake new file mode 100644 index 000000000..0e1f40027 --- /dev/null +++ b/gr-howto-write-a-block/cmake/Modules/GrMiscUtils.cmake @@ -0,0 +1,210 @@ +# 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_MISC_UTILS_CMAKE) + return() +endif() +set(__INCLUDED_GR_MISC_UTILS_CMAKE TRUE) + +######################################################################## +# Set global variable macro. +# Used for subdirectories to export settings. +# Example: include and library paths. +######################################################################## +function(GR_SET_GLOBAL var) + set(${var} ${ARGN} CACHE INTERNAL "" FORCE) +endfunction(GR_SET_GLOBAL) + +######################################################################## +# Set the pre-processor definition if the condition is true. +# - def the pre-processor definition to set and condition name +######################################################################## +function(GR_ADD_COND_DEF def) + if(${def}) + add_definitions(-D${def}) + endif(${def}) +endfunction(GR_ADD_COND_DEF) + +######################################################################## +# Check for a header and conditionally set a compile define. +# - hdr the relative path to the header file +# - def the pre-processor definition to set +######################################################################## +function(GR_CHECK_HDR_N_DEF hdr def) + include(CheckIncludeFileCXX) + CHECK_INCLUDE_FILE_CXX(${hdr} ${def}) + GR_ADD_COND_DEF(${def}) +endfunction(GR_CHECK_HDR_N_DEF) + +######################################################################## +# Include subdirectory macro. +# Sets the CMake directory variables, +# includes the subdirectory CMakeLists.txt, +# resets the CMake directory variables. +# +# This macro includes subdirectories rather than adding them +# so that the subdirectory can affect variables in the level above. +# This provides a work-around for the lack of convenience libraries. +# This way a subdirectory can append to the list of library sources. +######################################################################## +macro(GR_INCLUDE_SUBDIRECTORY subdir) + #insert the current directories on the front of the list + list(INSERT _cmake_source_dirs 0 ${CMAKE_CURRENT_SOURCE_DIR}) + list(INSERT _cmake_binary_dirs 0 ${CMAKE_CURRENT_BINARY_DIR}) + + #set the current directories to the names of the subdirs + set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${subdir}) + set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${subdir}) + + #include the subdirectory CMakeLists to run it + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + include(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt) + + #reset the value of the current directories + list(GET _cmake_source_dirs 0 CMAKE_CURRENT_SOURCE_DIR) + list(GET _cmake_binary_dirs 0 CMAKE_CURRENT_BINARY_DIR) + + #pop the subdir names of the front of the list + list(REMOVE_AT _cmake_source_dirs 0) + list(REMOVE_AT _cmake_binary_dirs 0) +endmacro(GR_INCLUDE_SUBDIRECTORY) + +######################################################################## +# Check if a compiler flag works and conditionally set a compile define. +# - flag the compiler flag to check for +# - have the variable to set with result +######################################################################## +macro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(${flag} ${have}) + if(${have}) + add_definitions(${flag}) + endif(${have}) +endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE) + +######################################################################## +# Generates the .la libtool file +# This appears to generate libtool files that cannot be used by auto*. +# Usage GR_LIBTOOL(TARGET [target] DESTINATION [dest]) +# Notice: there is not COMPONENT option, these will not get distributed. +######################################################################## +function(GR_LIBTOOL) + if(NOT DEFINED GENERATE_LIBTOOL) + set(GENERATE_LIBTOOL OFF) #disabled by default + endif() + + if(GENERATE_LIBTOOL) + include(CMakeParseArgumentsCopy) + CMAKE_PARSE_ARGUMENTS(GR_LIBTOOL "" "TARGET;DESTINATION" "" ${ARGN}) + + find_program(LIBTOOL libtool) + if(LIBTOOL) + include(CMakeMacroLibtoolFile) + CREATE_LIBTOOL_FILE(${GR_LIBTOOL_TARGET} /${GR_LIBTOOL_DESTINATION}) + endif(LIBTOOL) + endif(GENERATE_LIBTOOL) + +endfunction(GR_LIBTOOL) + +######################################################################## +# Do standard things to the library target +# - set target properties +# - make install rules +# Also handle gnuradio custom naming conventions w/ extras mode. +######################################################################## +function(GR_LIBRARY_FOO target) + #parse the arguments for component names + include(CMakeParseArgumentsCopy) + CMAKE_PARSE_ARGUMENTS(GR_LIBRARY "" "RUNTIME_COMPONENT;DEVEL_COMPONENT" "" ${ARGN}) + + #set additional target properties + set_target_properties(${target} PROPERTIES SOVERSION ${LIBVER}) + + #install the generated files like so... + install(TARGETS ${target} + LIBRARY DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .so/.dylib file + ARCHIVE DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_DEVEL_COMPONENT} # .lib file + RUNTIME DESTINATION ${GR_RUNTIME_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} # .dll file + ) + + #extras mode enabled automatically on linux + if(NOT DEFINED LIBRARY_EXTRAS) + set(LIBRARY_EXTRAS ${LINUX}) + endif() + + #special extras mode to enable alternative naming conventions + if(LIBRARY_EXTRAS) + + #create .la file before changing props + GR_LIBTOOL(TARGET ${target} DESTINATION ${GR_LIBRARY_DIR}) + + #give the library a special name with ultra-zero soversion + set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_NAME ${target}-${LIBVER} SOVERSION "0.0.0") + set(target_name lib${target}-${LIBVER}.so.0.0.0) + + #custom command to generate symlinks + add_custom_command( + TARGET ${target} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so + COMMAND ${CMAKE_COMMAND} -E create_symlink ${target_name} ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 + COMMAND ${CMAKE_COMMAND} -E touch ${target_name} #so the symlinks point to something valid so cmake 2.6 will install + ) + + #and install the extra symlinks + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/lib${target}.so + ${CMAKE_CURRENT_BINARY_DIR}/lib${target}-${LIBVER}.so.0 + DESTINATION ${GR_LIBRARY_DIR} COMPONENT ${GR_LIBRARY_RUNTIME_COMPONENT} + ) + + endif(LIBRARY_EXTRAS) +endfunction(GR_LIBRARY_FOO) + +######################################################################## +# Create a dummy custom command that depends on other targets. +# Usage: +# GR_GEN_TARGET_DEPS(unique_name target_deps <target1> <target2> ...) +# ADD_CUSTOM_COMMAND(<the usual args> ${target_deps}) +# +# Custom command cant depend on targets, but can depend on executables, +# and executables can depend on targets. So this is the process: +######################################################################## +function(GR_GEN_TARGET_DEPS name var) + file( + WRITE ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in + "int main(void){return 0;}\n" + ) + execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp.in + ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp + ) + add_executable(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp) + if(ARGN) + add_dependencies(${name} ${ARGN}) + endif(ARGN) + + if(CMAKE_CROSSCOMPILING) + set(${var} "DEPENDS;${name}" PARENT_SCOPE) #cant call command when cross + else() + set(${var} "DEPENDS;${name};COMMAND;${name}" PARENT_SCOPE) + endif() +endfunction(GR_GEN_TARGET_DEPS) diff --git a/gr-howto-write-a-block/cmake/Modules/GrPlatform.cmake b/gr-howto-write-a-block/cmake/Modules/GrPlatform.cmake new file mode 100644 index 000000000..ce2e15fef --- /dev/null +++ b/gr-howto-write-a-block/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/Modules/GrPython.cmake b/gr-howto-write-a-block/cmake/Modules/GrPython.cmake new file mode 100644 index 000000000..efdddf371 --- /dev/null +++ b/gr-howto-write-a-block/cmake/Modules/GrPython.cmake @@ -0,0 +1,227 @@ +# 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} +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 + + #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) + + 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/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake b/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake new file mode 100644 index 000000000..47e18085b --- /dev/null +++ b/gr-howto-write-a-block/cmake/Modules/GrSwig.cmake @@ -0,0 +1,229 @@ +# 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) + +######################################################################## +# Builds a swig documentation file to be generated into python docstrings +# Usage: GR_SWIG_MAKE_DOCS(output_file input_path input_path....) +# +# Set the following variable to specify extra dependent targets: +# - GR_SWIG_DOCS_SOURCE_DEPS +# - GR_SWIG_DOCS_TARGET_DEPS +######################################################################## +function(GR_SWIG_MAKE_DOCS output_file) + find_package(Doxygen) + if(DOXYGEN_FOUND) + + #setup the input files variable list, quote formated + set(input_files) + unset(INPUT_PATHS) + foreach(input_path ${ARGN}) + if (IS_DIRECTORY ${input_path}) #when input path is a directory + file(GLOB input_path_h_files ${input_path}/*.h) + else() #otherwise its just a file, no glob + set(input_path_h_files ${input_path}) + endif() + list(APPEND input_files ${input_path_h_files}) + set(INPUT_PATHS "${INPUT_PATHS} \"${input_path}\"") + endforeach(input_path) + + #determine the output directory + get_filename_component(name ${output_file} NAME_WE) + get_filename_component(OUTPUT_DIRECTORY ${output_file} PATH) + set(OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}/${name}_swig_docs) + make_directory(${OUTPUT_DIRECTORY}) + + #generate the Doxyfile used by doxygen + configure_file( + ${CMAKE_SOURCE_DIR}/docs/doxygen/Doxyfile.swig_doc.in + ${OUTPUT_DIRECTORY}/Doxyfile + @ONLY) + + #Create a dummy custom command that depends on other targets + include(GrMiscUtils) + GR_GEN_TARGET_DEPS(_${name}_tag tag_deps ${GR_SWIG_DOCS_TARGET_DEPS}) + + #call doxygen on the Doxyfile + input headers + add_custom_command( + OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml + DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps} + COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile + COMMENT "Generating doxygen xml for ${name} docs" + ) + + #call the swig_doc script on the xml files + add_custom_command( + OUTPUT ${output_file} + DEPENDS ${input_files} ${OUTPUT_DIRECTORY}/xml/index.xml + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py + ${OUTPUT_DIRECTORY}/xml + ${output_file} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen + ) + + else(DOXYGEN_FOUND) + file(WRITE ${output_file} "\n") #no doxygen -> empty file + endif(DOXYGEN_FOUND) +endfunction(GR_SWIG_MAKE_DOCS) + +######################################################################## +# 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 +# - GR_SWIG_DOC_FILE +# - GR_SWIG_DOC_DIRS +######################################################################## +macro(GR_SWIG_MAKE name) + set(ifiles ${ARGN}) + + #do swig doc generation if specified + if (GR_SWIG_DOC_FILE) + set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS}) + set(GR_SWIG_DOCS_TAREGT_DEPS ${GR_SWIG_TARGET_DEPS}) + GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS}) + list(APPEND GR_SWIG_SOURCE_DEPS ${GR_SWIG_DOC_FILE}) + endif() + + #append additional include directories + find_package(PythonLibs) + list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) + list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) + list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) + list(APPEND GR_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) + + #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} + ) + + #Create a dummy custom command that depends on other targets + include(GrMiscUtils) + GR_GEN_TARGET_DEPS(_${name}_swig_tag tag_deps ${GR_SWIG_TARGET_DEPS}) + set(tag_file ${CMAKE_CURRENT_BINARY_DIR}/${name}.tag) + add_custom_command( + OUTPUT ${tag_file} + DEPENDS ${GR_SWIG_SOURCE_DEPS} ${tag_deps} + COMMAND ${CMAKE_COMMAND} -E touch ${tag_file} + ) + + #append the specified include directories + include_directories(${GR_SWIG_INCLUDE_DIRS}) + list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file}) + + #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}) + +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} + ) + + GR_LIBTOOL( + TARGET ${SWIG_MODULE_${name}_REAL_NAME} + DESTINATION ${GR_SWIG_INSTALL_DESTINATION} + ) + + 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/Modules/GrTest.cmake b/gr-howto-write-a-block/cmake/Modules/GrTest.cmake new file mode 100644 index 000000000..9ec3141f9 --- /dev/null +++ b/gr-howto-write-a-block/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) |