File: PythonBindingsUtils.cmake

package info (click to toggle)
ompl 1.1.0%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 37,164 kB
  • ctags: 8,045
  • sloc: cpp: 55,692; python: 3,843; sh: 147; makefile: 60
file content (160 lines) | stat: -rw-r--r-- 7,405 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
find_package(Boost COMPONENTS python)
# The python version needs to match the one used to build Boost.Python.
# You can optionally specify the desired version like so:
#   find_package(Python 2.6)
find_package(Python QUIET)
set(ENV{PYTHONPATH} "${PROJECT_BINARY_DIR}/pyplusplus/lib/python${PYTHON_VERSION}/site-packages:$ENV{PYTHONPATH}")
find_python_module(pyplusplus QUIET)
find_python_module(pygccxml QUIET)
find_package(GCCXML QUIET)

if(APPLE)
    # The latest gccxml can be *compiled* with clang, but cannot *simulate*
    # clang. If you compiled gccxml with clang, then you have to specify a
    # g++ compiler by adding the following to PYOMPL_EXTRA_CFLAGS:
    #   --gccxml-compiler /opt/local/bin/g++-mp-4.8
    # (You can use other versions of g++ as well.) Note that /usr/bin/g++
    # is actually clang++ in Xcode 5.0, so that won't work.
    #
    # Gccxml mistakenly thinks that OS X is a 32-bit architecture.
    set(PYOMPL_EXTRA_CFLAGS "-m64")
endif(APPLE)

# Trick gccxml to ignore some compiler intrinsics that are used in Boost.Atomic
# in Boost 1.55.
if(CMAKE_COMPILER_IS_GNUCXX AND Boost_VERSION VERSION_GREATER "105400")
    set(PYOMPL_EXTRA_CFLAGS "${PYOMPL_EXTRA_CFLAGS} -DBOOST_INTEL_CXX_VERSION")
endif()

if(PYTHON_FOUND AND Boost_PYTHON_LIBRARY)
    include_directories(${PYTHON_INCLUDE_DIRS})
    # make sure target is defined only once
    if(NOT TARGET py_ompl)
        # top-level target for compiling python modules
        add_custom_target(py_ompl)
    endif()
    set(PY_OMPL_COMPILE ON CACHE BOOL
        "Whether the OMPL Python modules can be built")
    mark_as_advanced(PY_OMPL_COMPILE)
    set(OMPL_PYTHON_INSTALL_DIR "${PYTHON_SITE_MODULES}" CACHE STRING
        "Path to directory where OMPL python modules will be installed")
endif()

if(PYTHON_FOUND AND Boost_PYTHON_LIBRARY AND PY_PYPLUSPLUS
    AND PY_PYGCCXML AND GCCXML)
    # make sure targets are defined only once
    if(NOT TARGET generate_headers)
        # top-level target for updating all-in-one header file for each module
        add_custom_target(generate_headers)
        # top-level target for regenerating code for all python modules
        add_custom_target(update_bindings)
    endif()
    set(PY_OMPL_GENERATE ON CACHE BOOL
        "Whether the C++ code for the OMPL Python module can be generated")
    mark_as_advanced(PY_OMPL_GENERATE)
endif()

function(create_module_header_file_target module dir)
    # create list of absolute paths to header files, which we
    # will add as a list of dependencies for the target
    file(READ "headers_${module}.txt" headers_string)
    separate_arguments(rel_headers UNIX_COMMAND "${headers_string}")
    set(headers "")
    foreach(header ${rel_headers})
        list(APPEND headers "${header}")
    endforeach(header)
    # target for all-in-one header for module
    add_custom_target(${module}.h
        COMMAND ${CMAKE_COMMAND} -D module=${module} -D exclude=${ARGV2}
        -P "${OMPL_CMAKE_UTIL_DIR}/generate_header.cmake"
        DEPENDS ${headers} WORKING_DIRECTORY "${dir}"
        COMMENT "Preparing C++ header file for Python binding generation for module ${module}")
    add_dependencies(generate_headers ${module}.h)
endfunction(create_module_header_file_target)

function(create_module_code_generation_target module dir)
    # target for regenerating code. Cmake is run so that the list of
    # sources for the py_ompl_${module} target (see below) is updated.
    add_custom_target(update_${module}_bindings
        COMMAND env
        PYTHONPATH="${PROJECT_BINARY_DIR}/pyplusplus/lib/python${PYTHON_VERSION}/site-packages:$ENV{PYTHONPATH}"
        ${PYTHON_EXEC}
        "${CMAKE_CURRENT_SOURCE_DIR}/generate_bindings.py" "${module}"
        "1>${CMAKE_BINARY_DIR}/pyplusplus_${module}.log" "2>&1"
        COMMAND ${CMAKE_COMMAND} -D "PATH=${dir}/bindings/${module}"
        -P "${OMPL_CMAKE_UTIL_DIR}/workaround_for_gccxml_bug.cmake"
        COMMAND ${CMAKE_COMMAND} ${CMAKE_BINARY_DIR}
        WORKING_DIRECTORY ${dir}
        COMMENT "Creating C++ code for Python module ${module} (see pyplusplus_${module}.log)")
    add_dependencies(update_${module}_bindings ${module}.h)
    add_dependencies(update_bindings update_${module}_bindings)
endfunction(create_module_code_generation_target)

function(create_module_generation_targets module dir)
    create_module_header_file_target("${module}" "${dir}" "${ARGV2}")
    create_module_code_generation_target("${module}" "${dir}")
endfunction(create_module_generation_targets)

function(create_module_target module dir)
    # target for each python module
    aux_source_directory("${dir}/bindings/${module}" PY${module}BINDINGS)
    list(LENGTH PY${module}BINDINGS NUM_SOURCE_FILES)
    if(NUM_SOURCE_FILES GREATER 0)
        if(ARGC GREATER 2)
            set(_dest_dir "${ARGV2}")
            if(ARGC GREATER 3)
                set(_extra_libs "${ARGV3}")
            endif()
        else()
            set(_dest_dir "${dir}/ompl")
        endif()
        if(WIN32)
            # If this is built as a 'module', the compiler complains upon link,
            # complaining that the symbol WinMain is undefined.
            # Python on windows will NOT read this file unless the extension is .pyd
            add_library(py_ompl_${module} SHARED ${PY${module}BINDINGS})
            set_target_properties(py_ompl_${module} PROPERTIES OUTPUT_NAME ${module} PREFIX _ SUFFIX .pyd)
        else(WIN32)
            add_library(py_ompl_${module} MODULE ${PY${module}BINDINGS})
            set_target_properties(py_ompl_${module} PROPERTIES OUTPUT_NAME _${module})
        endif(WIN32)

        target_link_libraries(py_ompl_${module}
            ompl
            ${_extra_libs}
            ${Boost_PYTHON_LIBRARY}
            ${PYTHON_LIBRARIES})
        add_dependencies(py_ompl py_ompl_${module})
        if(WIN32)
            add_custom_command(TARGET py_ompl_${module} POST_BUILD
                COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:py_ompl_${module}>"
                "${_dest_dir}/${module}/_${module}.pyd"
                WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
                COMMENT "Copying python module ${module} into place")
        else(WIN32)
            add_custom_command(TARGET py_ompl_${module} POST_BUILD
                COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:py_ompl_${module}>"
                "${_dest_dir}/${module}/_${module}${CMAKE_SHARED_MODULE_SUFFIX}"
                WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
                COMMENT "Copying python module ${module} into place")
        endif(WIN32)
        # put omplapp and MORSE bindings in separate components
        if(${module} STREQUAL "app")
            set(_component "omplapp")
        elseif(${module} STREQUAL "morse")
            set(_component "morse")
        else()
            set(_component "python")
        endif()
        install(TARGETS py_ompl_${module}
            DESTINATION "${OMPL_PYTHON_INSTALL_DIR}/ompl/${module}/"
            COMPONENT ${_component})
        include_directories("${dir}/bindings/${module}" "${dir}")
    else(NUM_SOURCE_FILES GREATER 0)
        if(PY_OMPL_GENERATE)
            message(STATUS "Code for module ${module} not found; type \"make update_bindings\"")
        else()
            message(STATUS "Code for module ${module} not found")
        endif()
    endif(NUM_SOURCE_FILES GREATER 0)
endfunction(create_module_target)