Files
rdkit/Code/cmake/Modules/RDKitUtils.cmake
Riccardo Vianello 560d5ad604 export the targets with a python dependency to a different config file (#7914)
* export the targets with a python dependency to a different config file

* add the forgotten file

* improve the dependency from boost components

* fix management of dependencies for RDKitPython

* fix install location for RdkitPython cmake config file

* fix finding boost components

* put libraries that depend on rdkit_py_base in the python component
2025-02-19 05:53:30 +01:00

362 lines
14 KiB
CMake

include(BoostUtils)
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# Mac OS X specific code
set(RDKit_VERSION "${RDKit_Year}.${RDKit_Month}")
ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(RDKit_VERSION "${RDKit_ABI}.${RDKit_Year}.${RDKit_Month}")
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(RDKit_VERSION "${RDKit_VERSION}.${RDKit_Revision}${RDKit_RevisionModifier}")
set(RDKit_RELEASENAME "${RDKit_Year}.${RDKit_Month}.${RDKit_Revision}${RDKit_RevisionModifier}")
set(compilerID "${CMAKE_CXX_COMPILER_ID}")
set(systemAttribute "")
if(MINGW)
set(systemAttribute "MINGW")
endif(MINGW)
if(UNIX)
set(systemAttribute "UNIX")
endif(UNIX)
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(bit3264 "32-bit")
else()
set(bit3264 "64-bit")
endif()
set(RDKit_BUILDNAME "${CMAKE_SYSTEM_NAME}|${CMAKE_SYSTEM_VERSION}|${systemAttribute}|${compilerID}|${bit3264}")
set(RDKit_EXPORTED_TARGETS rdkit-targets)
set(RDKitPython_EXPORTED_TARGETS rdkitpython-targets)
macro(rdkit_library)
PARSE_ARGUMENTS(RDKLIB
"LINK_LIBRARIES;DEST"
"SHARED"
${ARGN})
CAR(RDKLIB_NAME ${RDKLIB_DEFAULT_ARGS})
CDR(RDKLIB_SOURCES ${RDKLIB_DEFAULT_ARGS})
# select the export and component name for the installed library
set(exportName ${RDKit_EXPORTED_TARGETS})
set(sharedLibComponent runtime)
set(staticLibComponent dev)
foreach(linkLib ${RDKLIB_LINK_LIBRARIES})
if("${linkLib}" STREQUAL "rdkit_py_base")
set(exportName ${RDKitPython_EXPORTED_TARGETS})
set(sharedLibComponent python)
set(staticLibComponent python)
break()
endif()
endforeach()
if((MSVC AND (NOT RDK_INSTALL_DLLS_MSVC)) OR (WIN32 AND RDK_INSTALL_STATIC_LIBS))
add_library(${RDKLIB_NAME} ${RDKLIB_SOURCES})
target_link_libraries(${RDKLIB_NAME} PUBLIC rdkit_base)
if(RDK_INSTALL_DEV_COMPONENT)
INSTALL(TARGETS ${RDKLIB_NAME} EXPORT ${exportName}
DESTINATION ${RDKit_LibDir}/${RDKLIB_DEST}
COMPONENT ${staticLibComponent})
endif(RDK_INSTALL_DEV_COMPONENT)
else()
# we're going to always build in shared mode since we
# need exceptions to be (correctly) catchable across
# boundaries. As of now (June 2010), this doesn't work
# with g++ unless libraries are shared.
add_library(${RDKLIB_NAME} SHARED ${RDKLIB_SOURCES})
target_link_libraries(${RDKLIB_NAME} PUBLIC rdkit_base)
INSTALL(TARGETS ${RDKLIB_NAME} EXPORT ${exportName}
DESTINATION ${RDKit_LibDir}/${RDKLIB_DEST}
COMPONENT ${sharedLibComponent})
if(RDK_INSTALL_STATIC_LIBS)
add_library(${RDKLIB_NAME}_static ${RDKLIB_SOURCES})
set(skipNext FALSE)
foreach(linkLib ${RDKLIB_LINK_LIBRARIES})
if(skipNext)
set(skipNext FALSE)
continue()
endif()
if("${linkLib}" STREQUAL "rdkit_py_base")
# rdkit_py_base is an interface target, keep it as-is
target_link_libraries(${RDKLIB_NAME}_static PUBLIC "${linkLib}")
continue()
elseif(TARGET "${linkLib}")
get_target_property(linkLib_IMPORTED "${linkLib}" IMPORTED)
if (linkLib_IMPORTED)
# linkLib is an imported target: use it as-is
target_link_libraries(${RDKLIB_NAME}_static PUBLIC "${linkLib}")
continue()
endif()
elseif(EXISTS "${linkLib}")
# linkLib is a file, so keep it as-is
target_link_libraries(${RDKLIB_NAME}_static PUBLIC "${linkLib}")
continue()
# cmake prepends the special keywords debug, optimized, general
# before the library name depending on whether they should be
# linked in Debug, Release or generic builds. Therefore we need
# to skip those, and also skip the library that follows if it
# is not relevant for the current build type
elseif ("${linkLib}" STREQUAL "debug")
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
set(skipNext TRUE)
endif()
continue()
elseif ("${linkLib}" STREQUAL "optimized")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(skipNext TRUE)
endif()
continue()
elseif ("${linkLib}" STREQUAL "general")
continue()
endif()
# We haven't seen linkLib yet. This probably means it is a target
# we will be creating at some point (if not, then we are missing a find_package).
# Add the "_static" suffix to link against its static variant
target_link_libraries(${RDKLIB_NAME}_static PUBLIC "${linkLib}_static")
endforeach()
target_link_libraries(${RDKLIB_NAME}_static PUBLIC rdkit_base)
if(RDK_INSTALL_DEV_COMPONENT)
INSTALL(TARGETS ${RDKLIB_NAME}_static EXPORT ${exportName}
DESTINATION ${RDKit_LibDir}/${RDKLIB_DEST}
COMPONENT ${staticLibComponent})
endif(RDK_INSTALL_DEV_COMPONENT)
set_target_properties(${RDKLIB_NAME}_static PROPERTIES
OUTPUT_NAME "RDKit${RDKLIB_NAME}_static")
endif(RDK_INSTALL_STATIC_LIBS)
endif()
IF(RDKLIB_LINK_LIBRARIES)
target_link_libraries(${RDKLIB_NAME} PUBLIC ${RDKLIB_LINK_LIBRARIES})
ENDIF(RDKLIB_LINK_LIBRARIES)
if((NOT MSVC) OR RDK_INSTALL_DLLS_MSVC)
set_target_properties(${RDKLIB_NAME} PROPERTIES
OUTPUT_NAME "RDKit${RDKLIB_NAME}"
VERSION "${RDKit_ABI}.${RDKit_Year}.${RDKit_Month}.${RDKit_Revision}"
VERSION ${RDKit_VERSION}
SOVERSION ${RDKit_ABI} )
endif()
set_target_properties(${RDKLIB_NAME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${RDK_ARCHIVE_OUTPUT_DIRECTORY}
RUNTIME_OUTPUT_DIRECTORY ${RDK_RUNTIME_OUTPUT_DIRECTORY}
LIBRARY_OUTPUT_DIRECTORY ${RDK_LIBRARY_OUTPUT_DIRECTORY})
endmacro(rdkit_library)
macro(rdkit_headers)
if (NOT RDK_INSTALL_INTREE)
PARSE_ARGUMENTS(RDKHDR
"DEST"
""
${ARGN})
# RDKHDR_DEFAULT_ARGS -> RDKHDR_DEST
if(RDK_INSTALL_DEV_COMPONENT)
install(FILES ${RDKHDR_DEFAULT_ARGS}
DESTINATION ${RDKit_HdrDir}/${RDKHDR_DEST}
COMPONENT dev )
endif(RDK_INSTALL_DEV_COMPONENT)
endif(NOT RDK_INSTALL_INTREE)
endmacro(rdkit_headers)
macro(rdkit_python_extension)
PARSE_ARGUMENTS(RDKPY
"LINK_LIBRARIES;DEPENDS;DEST"
""
${ARGN})
CAR(RDKPY_NAME ${RDKPY_DEFAULT_ARGS})
CDR(RDKPY_SOURCES ${RDKPY_DEFAULT_ARGS})
if(RDK_BUILD_PYTHON_WRAPPERS)
Python3_add_library(${RDKPY_NAME} MODULE ${RDKPY_SOURCES})
set_target_properties(${RDKPY_NAME} PROPERTIES PREFIX "")
if(WIN32)
set_target_properties(${RDKPY_NAME} PROPERTIES SUFFIX ".pyd"
LIBRARY_OUTPUT_DIRECTORY
${RDK_PYTHON_OUTPUT_DIRECTORY}/${RDKPY_DEST})
else(WIN32)
set_target_properties(${RDKPY_NAME} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY
${RDK_PYTHON_OUTPUT_DIRECTORY}/${RDKPY_DEST})
endif(WIN32)
target_link_libraries(${RDKPY_NAME} PUBLIC ${RDKPY_LINK_LIBRARIES}
RDBoost rdkit_py_base rdkit_base )
if("${PYTHON_LDSHARED}" STREQUAL "")
else()
set_target_properties(${RDKPY_NAME} PROPERTIES LINK_FLAGS ${PYTHON_LDSHARED})
endif()
INSTALL(TARGETS ${RDKPY_NAME}
LIBRARY DESTINATION ${RDKit_PythonDir}/${RDKPY_DEST} COMPONENT python)
endif(RDK_BUILD_PYTHON_WRAPPERS)
endmacro(rdkit_python_extension)
macro(rdkit_test)
PARSE_ARGUMENTS(RDKTEST
"LINK_LIBRARIES;DEPENDS;DEST"
""
${ARGN})
CAR(RDKTEST_NAME ${RDKTEST_DEFAULT_ARGS})
CDR(RDKTEST_SOURCES ${RDKTEST_DEFAULT_ARGS})
if(RDK_BUILD_CPP_TESTS)
add_executable(${RDKTEST_NAME} ${RDKTEST_SOURCES})
target_link_libraries(${RDKTEST_NAME} ${RDKTEST_LINK_LIBRARIES})
add_test(${RDKTEST_NAME} ${EXECUTABLE_OUTPUT_PATH}/${RDKTEST_NAME})
endif(RDK_BUILD_CPP_TESTS)
endmacro(rdkit_test)
macro(rdkit_catch_test)
PARSE_ARGUMENTS(RDKTEST
"LINK_LIBRARIES;DEPENDS;DEST"
""
${ARGN})
CAR(RDKTEST_NAME ${RDKTEST_DEFAULT_ARGS})
CDR(RDKTEST_SOURCES ${RDKTEST_DEFAULT_ARGS})
if(RDK_BUILD_CPP_TESTS)
add_executable(${RDKTEST_NAME} ${RDKTEST_SOURCES})
target_link_libraries(${RDKTEST_NAME} PRIVATE rdkitCatch ${RDKTEST_LINK_LIBRARIES} Catch2::Catch2)
add_test(${RDKTEST_NAME} ${EXECUTABLE_OUTPUT_PATH}/${RDKTEST_NAME})
endif(RDK_BUILD_CPP_TESTS)
endmacro(rdkit_catch_test)
macro(add_pytest)
PARSE_ARGUMENTS(PYTEST
"LINK_LIBRARIES;DEPENDS;DEST"
""
${ARGN})
CAR(PYTEST_NAME ${PYTEST_DEFAULT_ARGS})
CDR(PYTEST_SOURCES ${PYTEST_DEFAULT_ARGS})
if(RDK_BUILD_PYTHON_WRAPPERS)
add_test(${PYTEST_NAME} ${Python3_EXECUTABLE}
${PYTEST_SOURCES})
SET(RDKIT_PYTEST_CACHE "${PYTEST_NAME};${RDKIT_PYTEST_CACHE}" CACHE INTERNAL "Global list of python tests")
endif(RDK_BUILD_PYTHON_WRAPPERS)
endmacro(add_pytest)
function(add_jupytertest testname workingdir notebook)
if(RDK_BUILD_PYTHON_WRAPPERS AND RDK_NBVAL_AVAILABLE)
add_test(NAME ${testname} COMMAND ${Python3_EXECUTABLE} -m pytest --nbval ${notebook}
WORKING_DIRECTORY ${workingdir} )
SET(RDKIT_JUPYTERTEST_CACHE "${testname};${RDKIT_JUPYTERTEST_CACHE}" CACHE INTERNAL "Global list of jupyter tests")
endif()
endfunction(add_jupytertest)
function(add_pythonpytest testname workingdir)
if(RDK_BUILD_PYTHON_WRAPPERS)
add_test(NAME ${testname} COMMAND ${Python3_EXECUTABLE} -m pytest
WORKING_DIRECTORY ${workingdir} )
SET(RDKIT_PYTHONTEST_CACHE "${testname};${RDKIT_PYTHONTEST_CACHE}" CACHE INTERNAL "Global list of pytest tests")
endif()
endfunction(add_pythonpytest)
function(computeMD5 target md5chksum)
execute_process(COMMAND ${CMAKE_COMMAND} -E md5sum ${target} OUTPUT_VARIABLE md5list)
string(REGEX REPLACE "([a-z0-9]+)" "\\1;" md5list "${md5list}")
list(GET md5list 0 md5)
set(${md5chksum} ${md5} PARENT_SCOPE)
endfunction(computeMD5)
function(downloadAndCheckMD5 url target md5chksum)
if ("${url}" STREQUAL "")
return()
endif()
get_filename_component(targetDir ${target} PATH)
message("Downloading ${url}...")
file(DOWNLOAD "${url}" "${target}"
STATUS status)
# CMake < 2.8.10 does not seem to support HTTPS out of the box
# and since SourceForge redirects to HTTPS, the CMake download fails
# so we try to use Powershell (Windows) or system curl (Unix, OS X) if available
if (NOT status EQUAL 0)
if(WIN32)
execute_process(COMMAND powershell -Command "(New-Object Net.WebClient).DownloadFile('${url}', '${target}')")
else(WIN32)
execute_process(COMMAND curl -L "${url}" -o ${target} WORKING_DIRECTORY ${targetDir})
endif(WIN32)
endif()
if (NOT EXISTS ${target})
MESSAGE(FATAL_ERROR "The download of ${url} failed.")
endif()
if (NOT "${md5chksum}" STREQUAL "")
computeMD5(${target} md5)
if (NOT md5 STREQUAL ${md5chksum})
MESSAGE(FATAL_ERROR "The md5 checksum for ${target} is incorrect; expected: ${md5chksum}, found: ${md5}")
endif()
endif()
endfunction(downloadAndCheckMD5)
function(createExportTestHeaders)
file(GLOB_RECURSE cmakeLists LIST_DIRECTORIES false
${CMAKE_SOURCE_DIR}/CMakeLists.txt)
set(exportLibs "")
foreach(cmakeList ${cmakeLists})
file(STRINGS ${cmakeList} rdkitLibraryItems REGEX "rdkit_library[ ]*\\([ ]*[^ ]+.*$")
if (NOT "${rdkitLibraryItems}" STREQUAL "")
foreach (rdkitLibrary ${rdkitLibraryItems})
string(REGEX REPLACE "^[ ]*rdkit_library[ ]*\\([ ]*([^ ]+).*$" "\\1" libName "${rdkitLibrary}")
list(APPEND exportLibs "${libName}")
endforeach()
endif()
endforeach()
list(REMOVE_DUPLICATES exportLibs)
list(SORT exportLibs)
set(exportPath "Code/RDGeneral/export.h")
file(WRITE "${CMAKE_BINARY_DIR}/${exportPath}.tmp"
"// auto-generated export definition header\n"
"#pragma once\n"
"#include <RDGeneral/RDExportMacros.h>\n")
set(testPath "Code/RDGeneral/test.h")
file(WRITE "${CMAKE_BINARY_DIR}/${testPath}.tmp"
"// auto-generated header to be imported in all cpp tests\n"
"#pragma once\n")
foreach(exportLib ${exportLibs})
string(TOUPPER "${exportLib}" exportLib)
file(APPEND "${CMAKE_BINARY_DIR}/${exportPath}.tmp"
"\n"
"// RDKIT_${exportLib}_EXPORT definitions\n"
"#ifdef RDKIT_${exportLib}_BUILD\n"
"#define RDKIT_${exportLib}_EXPORT RDKIT_EXPORT_API\n"
"#else\n"
"#define RDKIT_${exportLib}_EXPORT RDKIT_IMPORT_API\n"
"#endif\n"
"// RDKIT_${exportLib}_EXPORT end definitions\n")
file(APPEND "${CMAKE_BINARY_DIR}/${testPath}.tmp"
"\n"
"#ifdef RDKIT_${exportLib}_BUILD\n"
"#undef RDKIT_${exportLib}_BUILD\n"
"#endif\n")
endforeach()
file(APPEND "${CMAKE_BINARY_DIR}/${exportPath}.tmp"
"\n"
"/*\n"
" * Do not dll export/import to export queries (it will mess up with the\n"
" * templates), but make sure it is visible for *nix\n"
" */\n"
"// RDKIT_QUERY_EXPORT definitions\n"
"#if defined(RDKIT_DYN_LINK) && defined(WIN32) && defined(BOOST_HAS_DECLSPEC)\n"
"#define RDKIT_QUERY_EXPORT\n"
"#else\n"
"#define RDKIT_QUERY_EXPORT RDKIT_GRAPHMOL_EXPORT\n"
"#endif\n"
"// RDKIT_QUERY_EXPORT end definitions\n")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_BINARY_DIR}/${exportPath}.tmp" "${CMAKE_SOURCE_DIR}/${exportPath}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_BINARY_DIR}/${testPath}.tmp" "${CMAKE_SOURCE_DIR}/${testPath}")
endfunction(createExportTestHeaders)
function(patchCoordGenMaeExportHeaders keyword path)
file(APPEND "${path}"
"// appended by CMake patchCoordGenMaeExportHeaders\n"
"#if !defined(RDKIT_DYN_LINK) || defined(SWIG)\n"
"#ifdef EXPORT_${keyword}\n"
"#undef EXPORT_${keyword}\n"
"#endif\n"
"#define EXPORT_${keyword}\n"
"#endif\n"
"#ifndef SWIG\n"
"#ifdef _MSC_VER\n"
"#pragma warning(disable:4251)\n"
"#pragma warning(disable:4275)\n"
"#endif\n"
"#endif\n")
endfunction(patchCoordGenMaeExportHeaders)