Skip to content

Commit

Permalink
use FetchContent to get libzmq
Browse files Browse the repository at this point in the history
build libsodium first, then import libzmq targets
  • Loading branch information
minrk committed Feb 15, 2024
1 parent 0bebce0 commit 48492a7
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 99 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ env
CMakeFiles
CMakeCache.txt
cmake_install.cmake
_deps
200 changes: 101 additions & 99 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.15...3.26)
project(${SKBUILD_PROJECT_NAME} LANGUAGES C)
# 3.28 needed for EXCLUDE_FROM_ALL
cmake_minimum_required(VERSION 3.28)
project(${SKBUILD_PROJECT_NAME} LANGUAGES C CXX)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)

list(PREPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(
Python
COMPONENTS Interpreter Development.Module
Expand All @@ -11,7 +14,7 @@ find_package(
# [x] find zmq pkg-config
# [x] find zmq prefix
# [x] bundle static libzmq posix
# [ ] bundle static libzmq windows
# [x] bundle static libzmq windows
# [ ] support draft API

set(ZMQ_PREFIX "auto" CACHE STRING "libzmq installation prefix or 'bundled'")
Expand All @@ -21,6 +24,8 @@ set(LIBSODIUM_BUNDLED_VERSION "1.0.19" CACHE STRING "libsodium version when bund
set(LIBZMQ_BUNDLED_URL "" CACHE STRING "full URL to download bundled libzmq")
set(LIBSODIUM_BUNDLED_URL "" CACHE STRING "full URL to download bundled libsodium")


#------- bundle libzmq ------
# get options from env
if (DEFINED ENV{ZMQ_PREFIX})
set(ZMQ_PREFIX "$ENV{ZMQ_PREFIX}")
Expand Down Expand Up @@ -68,9 +73,11 @@ if (DEFINED $ENV{PREFIX})
endif()
list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew" "/usr/local" "/usr")

set(libzmq_target "libzmq")

if (ZMQ_PREFIX STREQUAL "auto")
message(CHECK_START "Looking for libzmq")
find_package(ZeroMQx QUIET)
find_package(ZeroMQ QUIET)
if (ZeroMQ_FOUND AND TARGET libzmq)
get_target_property(_ZMQ_LOCATION libzmq IMPORTED_LOCATION)
message(CHECK_PASS "Found with cmake: ${_ZMQ_LOCATION}")
Expand All @@ -81,8 +88,9 @@ if (ZMQ_PREFIX STREQUAL "auto")
if (PkgConfig_FOUND)
message(CHECK_START "Looking for libzmq with pkg-config")
pkg_check_modules(libzmq libzmq IMPORTED_TARGET)
if (TARGET PkgConfig::libzmqx)
if (TARGET PkgConfig::libzmq)
set(ZeroMQ_FOUND TRUE)
set(libzmq_target "PkgConfig::libzmq")
message(CHECK_PASS "found: -l${libzmq_LIBRARIES}")
else()
message(CHECK_FAIL "no")
Expand Down Expand Up @@ -131,113 +139,102 @@ endif()

if (ZMQ_PREFIX STREQUAL "bundled")
message(STATUS "Bundling libzmq and libsodium")
include(ExternalProject)
include(FetchContent)
set(BUNDLE_DIR "${CMAKE_CURRENT_BINARY_DIR}/bundled")
make_directory("${BUNDLE_DIR}/lib")
include_directories(${BUNDLE_DIR}/include)
list(PREPEND CMAKE_PREFIX_PATH ${BUNDLE_DIR})

# libsodium
message(STATUS "Bundling libzmq and libsodium")
if (WIN32)
# build with msbuild
# msbuild /v:minimal /p:Configuration=%Configuration%DLL builds\msvc\%MSVCYEAR%\libsodium\libsodium.vcxproj
list(APPEND libsodium_configure "print")
list(APPEND libsodium_build
msbuild
"/m"
"/v:n"
"/p:Configuration=StaticRelease"
"/p:Platform=${CMAKE_GENERATOR_PLATFORM}"
"/p:OutputPath=${BUNDLE_DIR}/lib"
"builds/msvc/vs2022/libsodium.sln"
)
list(APPEND libsodium_install
"print"
"${BUNDLE_DIR}/bin/${CMAKE_GENERATOR_PLATFORM}/Release/v143/static/libsodium.lib"
"${BUNDLE_DIR}/bin/${CMAKE_GENERATOR_PLATFORM}/Release/v143/static/sodium.lib"
)
set(libsodium_lib "${BUNDLE_DIR}/bin/${CMAKE_GENERATOR_PLATFORM}/Release/v143/static/libsodium.lib")
# Copy-Item "bin\${env:Platform}\${env:Configuration}\${env:MSVCVERSION}\dynamic\libsodium.lib" -Destination "bin\${env:Platform}\${env:Configuration}\${env:MSVCVERSION}\dynamic\sodium.lib"

set(libsodium_lib "${BUNDLE_DIR}/lib/libsodium.lib")
else()
list(APPEND libsodium_configure
"./configure"
"--prefix=${BUNDLE_DIR}"
"--disable-shared"
"--enable-static"
)
list(APPEND libsodium_build "make")
list(APPEND libsodium_install "make" "install")
set(libsodium_lib "${BUNDLE_DIR}/lib/libsodium.a")
endif()

ExternalProject_Add(bundled_libsodium
FetchContent_Declare(bundled_libsodium
URL ${LIBSODIUM_BUNDLED_URL}
PREFIX ${BUNDLE_DIR}
BUILD_IN_SOURCE TRUE
CONFIGURE_COMMAND ${libsodium_configure}
BUILD_COMMAND ${libsodium_build}
INSTALL_COMMAND ${libsodium_install}
BUILD_BYPRODUCTS ${libsodium_lib}
)

# target for libsodium static
add_library(libsodium STATIC IMPORTED)
set_property(TARGET libsodium PROPERTY IMPORTED_LOCATION ${libsodium_lib})
add_dependencies(libsodium bundled_libsodium)

# libzmq
# TODO: passthrough current cmake args?
# which ones?
list(APPEND LIBZMQ_CMAKE_ARGS
-G ${CMAKE_GENERATOR}
-D CMAKE_INSTALL_PREFIX=${BUNDLE_DIR}
-D CMAKE_INCLUDE_DIRS=${BUNDLE_DIR}/include
-D SODIUM_INCLUDE_DIRS=${BUNDLE_DIR}/src/bundled_libsodium/src/libsodium/include
-D SODIUM_LIBRARIES=${libsodium_lib}
-D WITH_LIBSODIUM=ON
-D WITH_LIBSODIUM_STATIC=ON
-D ENABLE_CURVE=ON
-D ENABLE_DRAFTS=OFF
-D LIBZMQ_WERROR=OFF
-D WITH_DOC=OFF
-D WITH_DOCS=OFF
-D BUILD_TESTS=OFF
-D BUILD_SHARED=OFF
-D BUILD_STATIC=ON
)
if (WIN32)
set(libzmq_lib "${BUNDLE_DIR}/lib/libzmq-v143-mt-s-4_3_5.lib")
# cmake -D CMAKE_INCLUDE_PATH="%SODIUM_INCLUDE_DIR%" -D CMAKE_LIBRARY_PATH="%SODIUM_LIBRARY_DIR%" -D WITH_LIBSODIUM="%WITH_LIBSODIUM%" -D ENABLE_DRAFTS="%ENABLE_DRAFTS%" -D ENABLE_ANALYSIS="%ENABLE_ANALYSIS%" -D ENABLE_CURVE="%ENABLE_CURVE%" -D API_POLLER="%API_POLLER%" -D POLLER="%POLLER%" %EXTRA_FLAGS% -D WITH_LIBSODIUM="%WITH_LIBSODIUM%" -D LIBZMQ_WERROR="%LIBZMQ_WERROR%" -G "%CMAKE_GENERATOR%" "%LIBZMQ_SRCDIR%"
# cmake --build . --config %configuration% --target install -- -verbosity:Minimal -maxcpucount
else()
# list(APPEND libzmq_configure
# ./configure
# --prefix=${BUNDLE_DIR}
# --with-libsodium=${libsodium_lib}
# --without-docs
# --disable-libsodium_randombytes_close
# --disable-Werror
# --disable-shared
# --enable-static
# --disable-drafts
# )
# list(APPEND libzmq_build make)
# list(APPEND libzmq_install make install)
set(libzmq_lib "${BUNDLE_DIR}/lib/libzmq.a")
FetchContent_MakeAvailable(bundled_libsodium)
# run libsodium build explicitly here, so it's available to libzmq next
if(${bundled_libsodium_POPULATED} AND NOT EXISTS "${libsodium_lib}")
message(STATUS "building bundled libsodium")
if (WIN32)
# TODO: allow picking msvc build?
execute_process(
COMMAND msbuild
"/m"
"/v:n"
"/p:Configuration=Static${CMAKE_BUILD_TYPE}"
"/p:Platform=${CMAKE_GENERATOR_PLATFORM}"
"builds/msvc/vs2022/libsodium.sln"
WORKING_DIRECTORY ${bundled_libsodium_SOURCE_DIR}
COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
file(GLOB_RECURSE BUILT_LIBS "${bundled_libsodium_SOURCE_DIR}/**/libsodium.lib")
message(STATUS "built ${BUILT_LIBS}")
foreach(BUILT_LIB ${BUILT_LIBS})
file(COPY_FILE ${BUILT_LIB} ${libsodium_lib} ONLY_IF_DIFFERENT)
endforeach()

else()
list(APPEND libsodium_configure
./configure
--prefix=${BUNDLE_DIR}
--disable-shared
--enable-static
# TODO: enable extra arg passthrough
)
execute_process(
COMMAND ${libsodium_configure}
WORKING_DIRECTORY ${bundled_libsodium_SOURCE_DIR}
COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND make
WORKING_DIRECTORY ${bundled_libsodium_SOURCE_DIR}
COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND make install
WORKING_DIRECTORY ${bundled_libsodium_SOURCE_DIR}
COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY
)
endif()
endif()
ExternalProject_Add(bundled_libzmq

# use libzmq's own cmake, so we can import the libzmq-static target
set(ENABLE_CURVE ON)
set(ENABLE_DRAFTS ${ZMQ_DRAFT_API})
set(WITH_LIBSODIUM ON)
set(WITH_LIBSODIUM_STATIC ON)
set(LIBZMQ_PEDANTIC OFF)
set(LIBZMQ_WERROR OFF)
set(WITH_DOC OFF)
set(WITH_DOCS OFF)
set(BUILD_TESTS OFF)
set(BUILD_SHARED OFF)
set(BUILD_STATIC ON)

FetchContent_Declare(bundled_libzmq
URL ${LIBZMQ_BUNDLED_URL}
PREFIX ${BUNDLE_DIR}
CMAKE_ARGS ${LIBZMQ_CMAKE_ARGS}
BUILD_BYPRODUCTS ${libzmq_lib}
EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(bundled_libzmq)

# target for libzmq static
add_library(libzmq STATIC IMPORTED)
set_property(TARGET libzmq PROPERTY IMPORTED_LOCATION ${libzmq_lib})
# set_property(TARGET libzmq PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BUNDLE_DIR}/src/zeromq/include)
add_dependencies(bundled_libzmq libsodium)
add_dependencies(libzmq bundled_libzmq)
if (TARGET libzmq-static)
set(libzmq_target "libzmq-static")
else()
message(FATAL_ERROR "libzmq-static target not found in bundled libzmq")
endif()
endif()

if (NOT TARGET libzmq AND LIBZMQ_LIBRARY AND LIBZMQ_INCLUDE_DIR)
Expand All @@ -247,7 +244,11 @@ if (NOT TARGET libzmq AND LIBZMQ_LIBRARY AND LIBZMQ_INCLUDE_DIR)
set_property(TARGET libzmq PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${LIBZMQ_INCLUDE_DIR})
endif()

message(STATUS "Using Python ${Python_INTERPRETER_ID}")
#------- building pyzmq itself -------

message(STATUS "Using Python ${Python_INTERPRETER_ID} ${Python_EXECUTABLE}")


set(ZMQ_BACKEND "${CMAKE_CURRENT_BINARY_DIR}/zmq/backend")
set(ZMQ_BUILDUTILS "${CMAKE_CURRENT_SOURCE_DIR}/buildutils")

Expand Down Expand Up @@ -284,18 +285,19 @@ else()
endif()

make_directory(${ZMQ_BACKEND_DEST})

set(ext_name "_zmq")
python_add_library(
_zmq MODULE
WITH_SOABI
${ZMQ_C}
)

if (TARGET PkgConfig::libzmq)
target_link_libraries(_zmq PUBLIC PkgConfig::libzmq)
elseif (TARGET libzmq)
target_link_libraries(_zmq PUBLIC libzmq)
if (TARGET ${libzmq_target})
message(STATUS "Linking libzmq target ${libzmq_target}")
target_link_libraries(_zmq PUBLIC ${libzmq_target})
else()
message(FATAL_ERROR "should have a libzmq to link to...")
message(FATAL_ERROR "should have a libzmq target ${libzmq_target} to link to...")
endif()

target_include_directories(_zmq PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/zmq/utils")
Expand Down
42 changes: 42 additions & 0 deletions cmake/Findsodium.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# copy libzmq's findsodium, which can't be told where to look
# we want to get our local bundled static libsodium
# not any other
message(STATUS "in my findsodium")
set(SODIUM_FOUND FALSE)

set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON)
find_package(PkgConfig)
if (PkgConfig_FOUND)
pkg_check_modules(PC_SODIUM "libsodium")
if (PC_SODIUM_STATIC_FOUND)
set(pkg_config_names_private "${pkg_config_names_private} libsodium")
set(SODIUM_LIBRARIES ${PC_SODIUM_STATIC_LIBRARIES})
set(SODIUM_INCLUDE_DIRS ${PC_SODIUM_STATIC_INCLUDE_DIRS})
set(SODIUM_FOUND TRUE)
endif()
endif()

if (NOT SODIUM_FOUND)
find_path(
SODIUM_INCLUDE_DIRS
NAMES sodium.h
HINTS ${BUNDLE_DIR}/include
)
# TODO: find bundled sodium on msvc
find_library(
SODIUM_LIBRARIES
NAMES libsodium.a sodium.lib
HINTS ${BUNDLE_DIR}/lib
)
if (SODIUM_LIBRARIES)
# pkg-config didn't work, what do we need?
if (NOT MSVC)
list(APPEND SODIUM_LIBRARIES pthread)
endif()
set(SODIUM_FOUND TRUE)
endif()
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(sodium DEFAULT_MSG SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS)
mark_as_advanced(SODIUM_FOUND SODIUM_LIBRARIES SODIUM_INCLUDE_DIRS)

0 comments on commit 48492a7

Please sign in to comment.