Commit 772cc086 authored by Michka Popoff's avatar Michka Popoff

ENH: Do not link against libpython when possible

This is similar to what is already done in ITK and SimpleITK.

The new vtkTargetLinkLibrariesWithDynamicLookup.cmake file is slightly modified copy from ITK (things have been renamed from ITK to VTK). The explanation of what this patch tries to achieve is documented in this file.

A new argument is introduced, called OPTIONAL_PYTHON_LINK. When used, the module will be optionally be linked against libpython. In the module.cmake files, most vtkPython dependencies were moved to COMPILE_DEPENDS, so that libpython is not added to the target_link_libraries() call.

The vtkPython is explicitely linked against the python libraries, as this is a python executable.

Also, the find_package calls for the PythonLibs were made optional when possible.

This fixes the following bug: http://www.vtk.org/Bug/view.php?id=16068
parent d92cebe1
......@@ -5,6 +5,7 @@ set(_VTKModuleMacros_DEFAULT_LABEL "VTKModular")
include(${_VTKModuleMacros_DIR}/vtkModuleAPI.cmake)
include(GenerateExportHeader)
include(vtkWrapping)
include(vtkTargetLinkLibrariesWithDynamicLookup)
if(VTK_MAKE_INSTANTIATORS)
include(vtkMakeInstantiator)
endif()
......@@ -22,6 +23,7 @@ endif()
# DEPENDS = Modules that will be publicly linked to this module
# PRIVATE_DEPENDS = Modules that will be privately linked to this module
# COMPILE_DEPENDS = Modules that are needed at compile time by this module
# OPTIONAL_PYTHON_LINK = Optionally link the python library to this module
# TEST_DEPENDS = Modules that are needed by this modules testing executables
# DESCRIPTION = Free text description of the module
# TCL_NAME = Alternative name for the TCL wrapping (cannot contain numbers)
......@@ -47,6 +49,7 @@ macro(vtk_module _name)
set(${vtk-module-test}_DECLARED 1)
set(${vtk-module}_DEPENDS "")
set(${vtk-module}_COMPILE_DEPENDS "")
set(${vtk-module}_OPTIONAL_PYTHON_LINK 0)
set(${vtk-module}_PRIVATE_DEPENDS "")
set(${vtk-module-test}_DEPENDS "${vtk-module}")
set(${vtk-module}_IMPLEMENTS "")
......@@ -79,6 +82,9 @@ macro(vtk_module _name)
elseif("${arg}" STREQUAL "IMPLEMENTATION_REQUIRED_BY_BACKEND")
set(_doing "")
set(${vtk-module}_IMPLEMENTATION_REQUIRED_BY_BACKEND 1)
elseif("${arg}" STREQUAL "OPTIONAL_PYTHON_LINK")
set(_doing "")
set(${vtk-module}_OPTIONAL_PYTHON_LINK 1)
elseif("${arg}" MATCHES "^[A-Z][A-Z][A-Z]$" AND
NOT "${arg}" MATCHES "^(ON|OFF|MPI)$")
set(_doing "")
......@@ -650,6 +656,11 @@ function(vtk_module_library name)
endif()
endforeach()
# Optionally link the module to the python library
if(${${vtk-module}_OPTIONAL_PYTHON_LINK})
vtk_target_link_libraries_with_dynamic_lookup(${vtk-module} LINK_PUBLIC ${vtkPython_LIBRARIES})
endif()
# Handle the private dependencies, setting up link/include directories.
foreach(dep IN LISTS ${vtk-module}_PRIVATE_DEPENDS)
if(${dep}_INCLUDE_DIRS)
......
......@@ -503,6 +503,7 @@ if (NOT VTK_INSTALL_NO_DEVELOPMENT)
CMake/vtkObjectFactory.h.in
CMake/vtkPythonPackages.cmake
CMake/vtkPythonWrapping.cmake
CMake/vtkTargetLinkLibrariesWithDynamicLookup.cmake
CMake/vtkTclWrapping.cmake
CMake/vtkThirdParty.cmake
CMake/vtkWrapHierarchy.cmake
......
find_package(PythonLibs REQUIRED)
if (VTK_UNDEFINED_SYMBOLS_ALLOWED)
set(_QUIET_LIBRARY "QUIET")
else()
set(_QUIET_LIBRARY "REQUIRED")
endif()
find_package(PythonLibs ${_QUIET_LIBRARY})
include(vtkWrapPython)
include(vtkTargetLinkLibrariesWithDynamicLookup)
if(PYTHONINTERP_FOUND AND PYTHONLIBS_FOUND)
set(_interp_version "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")
set(_libs_version "${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}")
......@@ -104,7 +111,9 @@ function(vtk_add_python_wrapping_library module srcs)
PROPERTY INCLUDE_DIRECTORIES ${_python_include_dirs})
endif()
target_link_libraries(${module}PythonD LINK_PUBLIC
vtkWrappingPythonCore ${extra_links} ${VTK_PYTHON_LIBRARIES})
vtkWrappingPythonCore ${extra_links})
vtk_target_link_libraries_with_dynamic_lookup(
${module}PythonD LINK_PUBLIC ${VTK_PYTHON_LIBRARIES})
if (MSVC)
set_target_properties(${module}PythonD
......
#
# - This module provides the function
# vtk_target_link_libraries_with_dynamic_lookup which can be used to
# "weakly" link loadable module.
#
# Link a library to a target such that the symbols are resolved at
# run-time not link-time. This should be used when compiling a
# loadable module when the symbols should be resolve from the run-time
# environment where the module is loaded, and not a specific system
# library.
#
# Specifically, for OSX it uses undefined dynamic_lookup. This is
# simular to using "-shared" on Linux where undefined symbols are
# ignored.
#
# Additionally, the linker is checked to see if it supports undefined
# symbols when linking a shared library. If it does then the library
# is not linked when specified with this function.
#
# http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/
#
# Function: _vtkCheckUndefinedSymbolsAllowed
#
# Check if the linker allows undefined symbols for shared libraries.
#
# VTK_UNDEFINED_SYMBOLS_ALLOWED - true if the linker will allow
# undefined symbols for shared libraries
#
function(_vtkCheckUndefinedSymbolsAllowed)
set(VARIABLE "VTK_UNDEFINED_SYMBOLS_ALLOWED")
set(cache_var "${VARIABLE}_hash")
# hash the CMAKE_FLAGS passed and check cache to know if we need to rerun
string(MD5 cmake_flags_hash "${CMAKE_SHARED_LINKER_FLAGS}")
if(NOT DEFINED "${cache_var}" )
unset("${VARIABLE}" CACHE)
elseif(NOT "${${cache_var}}" STREQUAL "${cmake_flags_hash}" )
unset("${VARIABLE}" CACHE)
endif()
if(NOT DEFINED "${VARIABLE}")
set(test_project_dir "${PROJECT_BINARY_DIR}/CMakeTmp/${VARIABLE}")
file(WRITE "${test_project_dir}/CMakeLists.txt"
"
project(undefined C)
add_library(foo SHARED \"foo.c\")
")
file(WRITE "${test_project_dir}/foo.c"
"
extern int bar(void);
int foo(void) {return bar()+1;}
")
if(APPLE AND ${CMAKE_VERSION} VERSION_GREATER 2.8.11)
set( _rpath_arg "-DCMAKE_MACOSX_RPATH='${CMAKE_MACOSX_RPATH}'" )
else()
set( _rpath_arg )
endif()
try_compile(${VARIABLE}
"${test_project_dir}"
"${test_project_dir}"
undefined
CMAKE_FLAGS
"-DCMAKE_SHARED_LINKER_FLAGS='${CMAKE_SHARED_LINKER_FLAGS}'"
${_rpath_arg}
OUTPUT_VARIABLE output)
set(${cache_var} "${cmake_flags_hash}" CACHE INTERNAL "hashed try_compile flags")
if(${VARIABLE})
message(STATUS "Performing Test ${VARIABLE} - Success")
else()
message(STATUS "Performing Test ${VARIABLE} - Failed")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing Test ${VARIABLE} failed with the following output:\n"
"${OUTPUT}\n")
endif()
endif()
endfunction()
_vtkCheckUndefinedSymbolsAllowed()
macro( vtk_target_link_libraries_with_dynamic_lookup target )
if ( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" )
set_target_properties( ${target} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" )
elseif(VTK_UNDEFINED_SYMBOLS_ALLOWED)
# linker allows undefined symbols, let's just not link
else()
target_link_libraries ( ${target} ${ARGN} )
endif()
endmacro()
\ No newline at end of file
......@@ -179,7 +179,12 @@ endmacro()
if(VTK_WRAP_PYTHON_FIND_LIBS)
get_filename_component(_CURRENT_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
find_package(PythonLibs)
if (VTK_UNDEFINED_SYMBOLS_ALLOWED)
set(_QUIET_LIBRARY "QUIET")
else()
set(_QUIET_LIBRARY "REQUIRED")
endif()
find_package(PythonLibs ${_QUIET_LIBRARY})
# Use separate debug/optimized libraries if they are different.
if(PYTHON_DEBUG_LIBRARY)
......
......@@ -4,9 +4,11 @@ if (VTK_WRAP_PYTHON)
StandAlone
DEPENDS
vtkCommonExecutionModel
vtkPython
PRIVATE_DEPENDS
vtkWrappingPythonCore
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_TCL_WRAPPING
EXCLUDE_FROM_JAVA_WRAPPING
TEST_DEPENDS
......
......@@ -4,9 +4,10 @@ if (VTK_WRAP_PYTHON)
MPI
DEPENDS
vtkParallelMPI
vtkPython
COMPILE_DEPENDS
vtkmpi4py
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_TCL_WRAPPING
EXCLUDE_FROM_JAVA_WRAPPING
KIT
......
......@@ -3,4 +3,5 @@ vtk_module(AutobahnPython
SixPython
Twisted
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_WRAPPING)
vtk_module(SixPython
DEPENDS
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_WRAPPING)
vtk_module(Twisted
DEPENDS
ZopeInterface
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_WRAPPING)
vtk_module(ZopeInterface
DEPENDS
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_WRAPPING)
......@@ -24,7 +24,12 @@ if (NOT MPI4PY_PACKAGE_BINARY_DIR)
endif()
FIND_PACKAGE(PythonInterp ${VTK_PYTHON_VERSION})
FIND_PACKAGE(PythonLibs ${VTK_PYTHON_VERSION})
if (VTK_UNDEFINED_SYMBOLS_ALLOWED)
set(_QUIET_LIBRARY "QUIET")
else()
set(_QUIET_LIBRARY "${VTK_PYTHON_VERSION}" "REQUIRED")
endif()
FIND_PACKAGE(PythonLibs ${_QUIET_LIBRARY})
FIND_PACKAGE(MPI)
# -------------------------------------------------------------------------
......
......@@ -99,7 +99,14 @@ endif()
# If we are wrapping python, let's include it in the top level
if(XDMF_WRAP_PYTHON)
find_package(PythonInterp ${REQUESTED_PYTHON_VERSION} REQUIRED)
find_package(PythonLibs ${REQUESTED_PYTHON_VERSION} REQUIRED)
if (VTK_UNDEFINED_SYMBOLS_ALLOWED)
set(_QUIET_LIBRARY "QUIET")
else()
set(_QUIET_LIBRARY "${REQUESTED_PYTHON_VERSION}" "REQUIRED")
endif()
find_package(PythonLibs ${_QUIET_LIBRARY})
if (XDMF_BUILD_DSM)
find_package (MPI4PY REQUIRED)
if (MPI4PY_FOUND)
......
......@@ -93,7 +93,8 @@ def ParseModuleFile(fileName):
languages = ['PYTHON', 'TCL', 'JAVA']
keywords = ['BACKEND', 'COMPILE_DEPENDS', 'DEPENDS', 'EXCLUDE_FROM_ALL',
'EXCLUDE_FROM_WRAPPING', 'GROUPS', 'IMPLEMENTS', 'KIT',
'PRIVATE_DEPENDS', 'TEST_DEPENDS', 'IMPLEMENTATION_REQUIRED_BY_BACKEND'] + \
'PRIVATE_DEPENDS', 'TEST_DEPENDS', 'OPTIONAL_PYTHON_LINK'
'IMPLEMENTATION_REQUIRED_BY_BACKEND'] + \
map(lambda l: 'EXCLUDE_FROM_%s_WRAPPING' % l, languages)
moduleName = ""
depends = []
......
......@@ -168,7 +168,8 @@ def ParseModuleFile(fileName, renderingBackend='OpenGL'):
languages = ['PYTHON', 'TCL', 'JAVA']
keywords = ['BACKEND', 'COMPILE_DEPENDS', 'DEPENDS', 'EXCLUDE_FROM_ALL',
'EXCLUDE_FROM_WRAPPING', 'GROUPS', 'IMPLEMENTS', 'KIT',
'PRIVATE_DEPENDS', 'TEST_DEPENDS', 'IMPLEMENTATION_REQUIRED_BY_BACKEND'] + \
'PRIVATE_DEPENDS', 'TEST_DEPENDS',
'IMPLEMENTATION_REQUIRED_BY_BACKEND', 'OPTIONAL_PYTHON_LINK'] + \
map(lambda l: 'EXCLUDE_FROM_%s_WRAPPING' % l, languages)
moduleName = ""
depends = []
......
vtk_module(vtkPythonInterpreter
DEPENDS
vtkCommonCore
vtkPython
vtksys
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
KIT
vtkWrapping
)
......@@ -6,12 +6,14 @@ vtk_module(vtkWebCore
PRIVATE_DEPENDS
vtksys
vtkFiltersGeneral
vtkPython
vtkIOCore
vtkIOImage
vtkRenderingCore
vtkParallelCore
vtkWebGLExporter
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
TEST_DEPENDS
vtkImagingSources
vtkTestingCore
......
......@@ -3,6 +3,8 @@ vtk_module(vtkWebPython
Web
DEPENDS
AutobahnPython
COMPILE_DEPENDS
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_WRAPPING
EXCLUDE_FROM_ALL)
......@@ -240,6 +240,11 @@ if(VTK_USE_FFMPEG_ENCODER)
list(APPEND VTKPYTHON_LINK_LIBS ${FFMPEG_BASIC_LIBRARIES})
endif()
# Add the libPython.dylib file and link explicitly against it.
# This is needed because this is a new python executable, which needs it's libraries.
find_package(PythonLibs REQUIRED)
list(APPEND VTKPYTHON_LINK_LIBS ${vtkPython_LIBRARIES})
target_link_libraries(vtkpython ${VTKPYTHON_LINK_LIBS})
unset(PVTKPYTHON_EXECUTABLE)
......
vtk_module(vtkWrappingPythonCore
DEPENDS
vtkPython
vtkCommonCore
vtksys
COMPILE_DEPENDS
vtkWrappingTools
vtkPython
OPTIONAL_PYTHON_LINK
EXCLUDE_FROM_ALL
EXCLUDE_FROM_WRAPPING
)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment