1# Copyright 2010-2011,2019 Free Software Foundation, Inc.
2#
3# This file is part of GNU Radio
4#
5# GNU Radio is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3, or (at your option)
8# any later version.
9#
10# GNU Radio is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with GNU Radio; see the file COPYING.  If not, write to
17# the Free Software Foundation, Inc., 51 Franklin Street,
18# Boston, MA 02110-1301, USA.
19
20if(DEFINED __INCLUDED_GR_SWIG_CMAKE)
21    return()
22endif()
23set(__INCLUDED_GR_SWIG_CMAKE TRUE)
24
25include(GrPython)
26
27########################################################################
28# Builds a swig documentation file to be generated into python docstrings
29# Usage: GR_SWIG_MAKE_DOCS(output_file input_path input_path....)
30#
31# Set the following variable to specify extra dependent targets:
32#   - GR_SWIG_DOCS_SOURCE_DEPS
33#   - GR_SWIG_DOCS_TARGET_DEPS
34########################################################################
35function(GR_SWIG_MAKE_DOCS output_file)
36    if(ENABLE_DOXYGEN)
37
38        #setup the input files variable list, quote formatted
39        set(input_files)
40        unset(INPUT_PATHS)
41        foreach(input_path ${ARGN})
42            if(IS_DIRECTORY ${input_path}) #when input path is a directory
43                file(GLOB input_path_h_files ${input_path}/*.h)
44            else() #otherwise its just a file, no glob
45                set(input_path_h_files ${input_path})
46            endif()
47            list(APPEND input_files ${input_path_h_files})
48            set(INPUT_PATHS "${INPUT_PATHS} \"${input_path}\"")
49        endforeach(input_path)
50
51        #determine the output directory
52        get_filename_component(name ${output_file} NAME_WE)
53        get_filename_component(OUTPUT_DIRECTORY ${output_file} PATH)
54        set(OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}/${name}_swig_docs)
55        make_directory(${OUTPUT_DIRECTORY})
56
57        #generate the Doxyfile used by doxygen
58        configure_file(
59            ${CMAKE_SOURCE_DIR}/docs/doxygen/Doxyfile.swig_doc.in
60            ${OUTPUT_DIRECTORY}/Doxyfile
61        @ONLY)
62
63        #Create a dummy custom command that depends on other targets
64        include(GrMiscUtils)
65        GR_GEN_TARGET_DEPS(_${name}_tag tag_deps ${GR_SWIG_DOCS_TARGET_DEPS})
66
67        #call doxygen on the Doxyfile + input headers
68        add_custom_command(
69            OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml
70            DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps}
71            COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile
72            COMMENT "Generating doxygen xml for ${name} docs"
73        )
74
75        #call the swig_doc script on the xml files
76        add_custom_command(
77            OUTPUT ${output_file}
78            DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml
79            COMMAND ${PYTHON_EXECUTABLE} -B
80                ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py
81                ${OUTPUT_DIRECTORY}/xml
82                ${output_file}
83            COMMENT "Generating python docstrings for ${name}"
84            WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen
85        )
86
87    else(ENABLE_DOXYGEN)
88        file(WRITE ${output_file} "\n") #no doxygen -> empty file
89    endif(ENABLE_DOXYGEN)
90endfunction(GR_SWIG_MAKE_DOCS)
91
92########################################################################
93# Build a swig target for the common gnuradio use case. Usage:
94# GR_SWIG_MAKE(target ifile ifile ifile...)
95#
96# Set the following variables before calling:
97#   - GR_SWIG_FLAGS
98#   - GR_SWIG_INCLUDE_DIRS
99#   - GR_SWIG_LIBRARIES
100#   - GR_SWIG_SOURCE_DEPS
101#   - GR_SWIG_TARGET_DEPS
102#   - GR_SWIG_DOC_FILE
103#   - GR_SWIG_DOC_DIRS
104########################################################################
105macro(GR_SWIG_MAKE name)
106    set(ifiles ${ARGN})
107
108    #do swig doc generation if specified
109    if(GR_SWIG_DOC_FILE)
110        set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS})
111        list(APPEND GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS})
112        GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS})
113        add_custom_target(${name}_swig_doc DEPENDS ${GR_SWIG_DOC_FILE})
114        list(APPEND GR_SWIG_TARGET_DEPS ${name}_swig_doc)
115    endif()
116
117    #prepend local swig directories
118    list(INSERT GR_SWIG_INCLUDE_DIRS 0 "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
119    list(INSERT GR_SWIG_INCLUDE_DIRS 0 "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
120
121    if (PYTHON3)
122        set(py3 "-py3")
123    endif (PYTHON3)
124
125    #setup the swig flags with flags and include directories
126    set(modern_keyword "-modern")
127    if("${SWIG_VERSION}" VERSION_GREATER "3.0.12")
128      set(modern_keyword "")
129    endif()
130    set(CMAKE_SWIG_FLAGS -fvirtual ${modern_keyword} -keyword -w511 -w314 -relativeimport ${py3} -module ${name} ${GR_SWIG_FLAGS})
131
132    #set the C++ property on the swig .i file so it builds
133    set_source_files_properties(${ifiles} PROPERTIES CPLUSPLUS ON)
134
135    #setup the actual swig library target to be built
136    include(UseSWIG)
137    swig_add_library(${name} LANGUAGE python SOURCES ${ifiles})
138    if(${name} STREQUAL "runtime_swig")
139      set_target_properties(runtime_swig PROPERTIES DEFINE_SYMBOL "gnuradio_runtime_EXPORTS")
140    endif(${name} STREQUAL "runtime_swig")
141    set_target_properties(${name} PROPERTIES
142      SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE
143      )
144    target_include_directories(${name} PUBLIC ${GR_SWIG_INCLUDE_DIRS})
145    set_property(TARGET ${name} PROPERTY SWIG_DEPENDS ${GR_SWIG_TARGET_DEPS})
146    target_link_libraries(${name} Python::Python ${GR_SWIG_LIBRARIES})
147endmacro(GR_SWIG_MAKE)
148
149########################################################################
150# Install swig targets generated by GR_SWIG_MAKE. Usage:
151# GR_SWIG_INSTALL(
152#   TARGETS target target target...
153#   [DESTINATION destination]
154# )
155########################################################################
156macro(GR_SWIG_INSTALL)
157
158    include(CMakeParseArgumentsCopy)
159    CMAKE_PARSE_ARGUMENTS(GR_SWIG_INSTALL "" "DESTINATION" "TARGETS" ${ARGN})
160
161    foreach(name ${GR_SWIG_INSTALL_TARGETS})
162      install(TARGETS ${name}
163          DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
164        )
165
166        include(GrPython)
167        GR_PYTHON_INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.py
168          DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
169          DEPENDS ${name}
170        )
171
172    endforeach(name)
173
174endmacro(GR_SWIG_INSTALL)
175