# Copyright 2010-2011,2014 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}) if(${CMAKE_VERSION} VERSION_GREATER "2.8.4") string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_dup) if(${flag_dup} EQUAL -1) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}") endif(${flag_dup} EQUAL -1) endif(${CMAKE_VERSION} VERSION_GREATER "2.8.4") 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 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 ...) # add_custom_command( ${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) ######################################################################## # Control use of gr_logger # Usage: # GR_LOGGING() # # Will set ENABLE_GR_LOG to 1 by default. # Can manually set with -DENABLE_GR_LOG=0|1 ######################################################################## function(GR_LOGGING) find_package(Log4cpp) option(ENABLE_GR_LOG "Use gr_logger" ON) if(ENABLE_GR_LOG) # If gr_logger is enabled, make it usable add_definitions( -DENABLE_GR_LOG ) # also test LOG4CPP; if we have it, use this version of the logger # otherwise, default to the stdout/stderr model. if(LOG4CPP_FOUND) set(HAVE_LOG4CPP True CACHE INTERNAL "" FORCE) add_definitions( -DHAVE_LOG4CPP ) else(not LOG4CPP_FOUND) set(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE) set(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE) set(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE) set(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE) endif(LOG4CPP_FOUND) set(ENABLE_GR_LOG ${ENABLE_GR_LOG} CACHE INTERNAL "" FORCE) else(ENABLE_GR_LOG) set(HAVE_LOG4CPP False CACHE INTERNAL "" FORCE) set(LOG4CPP_INCLUDE_DIRS "" CACHE INTERNAL "" FORCE) set(LOG4CPP_LIBRARY_DIRS "" CACHE INTERNAL "" FORCE) set(LOG4CPP_LIBRARIES "" CACHE INTERNAL "" FORCE) endif(ENABLE_GR_LOG) message(STATUS "ENABLE_GR_LOG set to ${ENABLE_GR_LOG}.") message(STATUS "HAVE_LOG4CPP set to ${HAVE_LOG4CPP}.") message(STATUS "LOG4CPP_LIBRARIES set to ${LOG4CPP_LIBRARIES}.") endfunction(GR_LOGGING) ######################################################################## # Run GRCC to compile .grc files into .py files. # # Usage: GRCC(filename, directory) # - filenames: List of file name of .grc file # - directory: directory of built .py file - usually in # ${CMAKE_CURRENT_BINARY_DIR} # - Sets PYFILES: output converted GRC file names to Python files. ######################################################################## function(GRCC) # Extract directory from list of args, remove it for the list of filenames. list(GET ARGV -1 directory) list(REMOVE_AT ARGV -1) set(filenames ${ARGV}) file(MAKE_DIRECTORY ${directory}) set(GRCC_COMMAND ${CMAKE_SOURCE_DIR}/gr-utils/python/grcc) # GRCC uses some stuff in grc and gnuradio-runtime, so we force # the known paths here list(APPEND PYTHONPATHS ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/gnuradio-runtime/python ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/swig ${CMAKE_BINARY_DIR}/gnuradio-runtime/lib/swig ) 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 ${PYTHONPATHS}) get_filename_component(name ${pydir} NAME) if(name MATCHES "^(swig|lib|src)$") list(APPEND PYTHONPATHS ${pydir}/${CMAKE_BUILD_TYPE}) endif() endforeach(pydir) endif(WIN32) file(TO_NATIVE_PATH "${PYTHONPATHS}" pypath) if(UNIX) list(APPEND pypath "$PYTHONPATH") string(REPLACE ";" ":" pypath "${pypath}") set(ENV{PYTHONPATH} ${pypath}) endif(UNIX) if(WIN32) list(APPEND pypath "%PYTHONPATH%") string(REPLACE ";" "\\;" pypath "${pypath}") #list(APPEND environs "PYTHONPATH=${pypath}") set(ENV{PYTHONPATH} ${pypath}) endif(WIN32) foreach(f ${filenames}) execute_process( COMMAND ${GRCC_COMMAND} -d ${directory} ${f} ) string(REPLACE ".grc" ".py" pyfile "${f}") string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" pyfile "${pyfile}") list(APPEND pyfiles ${pyfile}) endforeach(f) set(PYFILES ${pyfiles} PARENT_SCOPE) endfunction(GRCC) ######################################################################## # Check if HAVE_PTHREAD_SETSCHEDPARAM and HAVE_SCHED_SETSCHEDULER # should be defined ######################################################################## macro(GR_CHECK_LINUX_SCHED_AVAIL) set(CMAKE_REQUIRED_LIBRARIES -lpthread) CHECK_CXX_SOURCE_COMPILES(" #include int main(){ pthread_t pthread; pthread_setschedparam(pthread, 0, 0); return 0; } " HAVE_PTHREAD_SETSCHEDPARAM ) GR_ADD_COND_DEF(HAVE_PTHREAD_SETSCHEDPARAM) CHECK_CXX_SOURCE_COMPILES(" #include int main(){ pid_t pid; sched_setscheduler(pid, 0, 0); return 0; } " HAVE_SCHED_SETSCHEDULER ) GR_ADD_COND_DEF(HAVE_SCHED_SETSCHEDULER) endmacro(GR_CHECK_LINUX_SCHED_AVAIL) ######################################################################## # Macros to generate source and header files from template ######################################################################## macro(GR_EXPAND_X_H component root) include(GrPython) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "#!${PYTHON_EXECUTABLE} import sys, os, re sys.path.append('${GR_RUNTIME_PYTHONPATH}') sys.path.append('${CMAKE_SOURCE_DIR}/python') os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' os.chdir('${CMAKE_CURRENT_BINARY_DIR}') if __name__ == '__main__': import build_utils root, inp = sys.argv[1:3] for sig in sys.argv[3:]: name = re.sub ('X+', sig, root) d = build_utils.standard_dict2(name, sig, '${component}') build_utils.expand_template(d, inp) ") #make a list of all the generated headers unset(expanded_files_h) foreach(sig ${ARGN}) string(REGEX REPLACE "X+" ${sig} name ${root}) list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h) endforeach(sig) unset(name) #create a command to generate the headers add_custom_command( OUTPUT ${expanded_files_h} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.h.t ${ARGN} ) #install rules for the generated headers list(APPEND generated_includes ${expanded_files_h}) endmacro(GR_EXPAND_X_H) macro(GR_EXPAND_X_CC_H component root) include(GrPython) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "#!${PYTHON_EXECUTABLE} import sys, os, re sys.path.append('${GR_RUNTIME_PYTHONPATH}') sys.path.append('${CMAKE_SOURCE_DIR}/python') os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' os.chdir('${CMAKE_CURRENT_BINARY_DIR}') if __name__ == '__main__': import build_utils root, inp = sys.argv[1:3] for sig in sys.argv[3:]: name = re.sub ('X+', sig, root) d = build_utils.standard_impl_dict2(name, sig, '${component}') build_utils.expand_template(d, inp) ") #make a list of all the generated files unset(expanded_files_cc) unset(expanded_files_h) foreach(sig ${ARGN}) string(REGEX REPLACE "X+" ${sig} name ${root}) list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc) list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h) endforeach(sig) unset(name) #create a command to generate the source files add_custom_command( OUTPUT ${expanded_files_cc} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.cc.t ${ARGN} ) #create a command to generate the header files add_custom_command( OUTPUT ${expanded_files_h} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.h.t ${ARGN} ) #make source files depends on headers to force generation set_source_files_properties(${expanded_files_cc} PROPERTIES OBJECT_DEPENDS "${expanded_files_h}" ) #install rules for the generated files list(APPEND generated_sources ${expanded_files_cc}) list(APPEND generated_headers ${expanded_files_h}) endmacro(GR_EXPAND_X_CC_H) macro(GR_EXPAND_X_CC_H_IMPL component root) include(GrPython) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "#!${PYTHON_EXECUTABLE} import sys, os, re sys.path.append('${GR_RUNTIME_PYTHONPATH}') sys.path.append('${CMAKE_SOURCE_DIR}/python') os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' os.chdir('${CMAKE_CURRENT_BINARY_DIR}') if __name__ == '__main__': import build_utils root, inp = sys.argv[1:3] for sig in sys.argv[3:]: name = re.sub ('X+', sig, root) d = build_utils.standard_dict(name, sig, '${component}') build_utils.expand_template(d, inp, '_impl') ") #make a list of all the generated files unset(expanded_files_cc_impl) unset(expanded_files_h_impl) unset(expanded_files_h) foreach(sig ${ARGN}) string(REGEX REPLACE "X+" ${sig} name ${root}) list(APPEND expanded_files_cc_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.cc) list(APPEND expanded_files_h_impl ${CMAKE_CURRENT_BINARY_DIR}/${name}_impl.h) list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/../include/gnuradio/${component}/${name}.h) endforeach(sig) unset(name) #create a command to generate the _impl.cc files add_custom_command( OUTPUT ${expanded_files_cc_impl} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.cc.t COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}_impl.cc.t ${ARGN} ) #create a command to generate the _impl.h files add_custom_command( OUTPUT ${expanded_files_h_impl} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.h.t COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}_impl.h.t ${ARGN} ) #make _impl.cc source files depend on _impl.h to force generation set_source_files_properties(${expanded_files_cc_impl} PROPERTIES OBJECT_DEPENDS "${expanded_files_h_impl}" ) #make _impl.h source files depend on headers to force generation set_source_files_properties(${expanded_files_h_impl} PROPERTIES OBJECT_DEPENDS "${expanded_files_h}" ) #install rules for the generated files list(APPEND generated_sources ${expanded_files_cc_impl}) list(APPEND generated_headers ${expanded_files_h_impl}) endmacro(GR_EXPAND_X_CC_H_IMPL)