summaryrefslogtreecommitdiff
path: root/CMakeLists.txt
blob: 758c95afa51ce193bf6892ffc7eeb4a53285a1b1 (plain)
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
# SPDX-License-Identifier: mit

cmake_minimum_required(VERSION 3.22...3.26)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

# Follow all steps below in order to calculate new ABI version when updating the library
# NOTE: THIS IS UNRELATED to the actual project version
#
# 1. If the library source code has changed at all since the last update, then increment revision
# 2. If any interfaces have been added, removed, or changed since the last update, increment current and set revision to 0.
# 3. If any interfaces have been added since the last public release, then increment age.
# 4. If any interfaces have been removed since the last public release, then set age to 0.

set(RMQ_SOVERSION_CURRENT   9)
set(RMQ_SOVERSION_REVISION  4)
set(RMQ_SOVERSION_AGE       5)

include(VersionFunctions)
get_library_version(RMQ_VERSION)
compute_soversion(${RMQ_SOVERSION_CURRENT} ${RMQ_SOVERSION_REVISION} ${RMQ_SOVERSION_AGE} RMQ_SOVERSION)

project(rabbitmq-c 
  VERSION ${RMQ_VERSION}
  DESCRIPTION "C RabbitMQ AMQP client library"
  LANGUAGES C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)

set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)

set(default_build_type "Release")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
  set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

include(CheckSymbolExists)
include(CheckLibraryExists)
include(CMakePushCheckState)
include(GNUInstallDirs)

# Detect if we need to link against a socket library:
cmake_push_check_state()
if (WIN32)
  # Always use WinSock2 on Windows
  set(SOCKET_LIBRARIES ws2_32)
else ()
  # Is it in the default link?
  check_symbol_exists(getaddrinfo "sys/types.h;sys/socket.h;netdb.h" HAVE_GETADDRINFO)
  if (NOT (HAVE_GETADDRINFO EQUAL 1))
    SET(CMAKE_REQUIRED_LIBRARIES "socket")
    check_symbol_exists(getaddrinfo "sys/types.h;sys/socket.h;netdb.h" HAVE_GETADDRINFO2)
    if (HAVE_GETADDRINFO2 EQUAL 1)
      set(SOCKET_LIBRARIES socket)
    else ()
      SET(CMAKE_REQUIRED_LIBRARIES "socket;nsl")
      check_symbol_exists(getaddrinfo "sys/types.h;sys/socket.h;netdb.h" HAVE_GETADDRINFO3)
      if (HAVE_GETADDRINFO3 EQUAL 1)
        set(SOCKET_LIBRARIES socket nsl)
      else ()
        message(FATAL_ERROR "Cannot find name resolution library (containing symbol getaddrinfo)")
      endif ()
    endif ()
  endif ()

  set(CMAKE_REQUIRED_LIBRARIES ${SOCKET_LIBRARIES})
  check_symbol_exists(socket "sys/types.h;sys/socket.h" HAVE_SOCKET)
  if (NOT HAVE_SOCKET EQUAL 1)
    set(CMAKE_REQUIRED_LIBRARIES socket ${SOCKET_LIBRARIES})
    check_symbol_exists(socket "sys/types.h;sys/socket.h" HAVE_SOCKET2)
    if (HAVE_SOCKET2 EQUAL 1)
      set(SOCKET_LIBRARIES socket ${SOCKET_LIBRARIES})
    else ()
      set(CMAKE_REQUIRED_LIBRARIES socket nsl ${SOCKET_LIBRARIES})
      check_symbol_exists(socket "sys/types.h;sys/socket.h" HAVE_SOCKET3)
      if (HAVE_SOCKET3 EQUAL 1)
        set(SOCKET_LIBRARIES socket nsl ${SOCKET_LIBRARIES})
      else ()
        message(FATAL_ERROR "Cannot find socket library (containing symbol socket)")
      endif ()
    endif ()
  endif ()
endif ()
cmake_pop_check_state()

cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${SOCKET_LIBRARIES})
check_symbol_exists(poll poll.h HAVE_POLL)
if (NOT HAVE_POLL)
  if (WIN32)
    set(HAVE_SELECT 1)
  else()
    check_symbol_exists(select sys/select.h HAVE_SELECT)
  endif()
  if (NOT HAVE_SELECT)
    message(FATAL_ERROR "rabbitmq-c requires poll() or select() to be available")
  endif()
endif()
cmake_pop_check_state()

check_library_exists(rt clock_gettime "time.h" CLOCK_GETTIME_NEEDS_LIBRT)
check_library_exists(rt posix_spawnp "spawn.h" POSIX_SPAWNP_NEEDS_LIBRT)
if (CLOCK_GETTIME_NEEDS_LIBRT OR POSIX_SPAWNP_NEEDS_LIBRT)
  set(LIBRT rt)
endif()

option(ENABLE_SSL_SUPPORT "Enable SSL support" ON)

if (ENABLE_SSL_SUPPORT)
  set(RMQ_OPENSSL_MIN_VERSION 1.1.1)
  find_package(OpenSSL "${RMQ_OPENSSL_MIN_VERSION}" REQUIRED)

  cmake_push_check_state()
  set(THREADS_PREFER_PTHREAD_FLAG ON)
  find_package(Threads REQUIRED)
  cmake_pop_check_state()
endif()

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
  include(CTest)
endif()

include(CMakeDependentOption)

option(BUILD_SHARED_LIBS "Build rabbitmq-c as a shared library" ON)
option(BUILD_STATIC_LIBS "Build rabbitmq-c as a static library" ON)
option(INSTALL_STATIC_LIBS "Install rabbitmq-c static library" ON)

option(BUILD_EXAMPLES "Build Examples" OFF)
option(BUILD_TOOLS "Build Tools (requires POPT Library)" OFF)
cmake_dependent_option(BUILD_TOOLS_DOCS "Build man pages for tools (requires xmlto)" OFF "BUILD_TOOLS" OFF)
option(BUILD_API_DOCS "Build Doxygen API docs" OFF)
option(RUN_SYSTEM_TESTS "Run system tests (i.e. tests requiring an accessible RabbitMQ server instance on localhost)" OFF)
option(BUILD_OSSFUZZ "Build OSSFUZZ" OFF)

if (NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
    message(FATAL_ERROR "One or both of BUILD_SHARED_LIBS or BUILD_STATIC_LIBS must be set to ON to build")
endif()

set(targets_export_name rabbitmq-targets)

if(BUILD_OSSFUZZ)
  if (NOT BUILD_STATIC_LIBS)
    message(FATAL_ERROR "OSS-FUZZ can only be built against static libraries " "(set BUILD_STATIC_LIBS=ON)")
  endif ()
  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
endif ()

add_subdirectory(librabbitmq)

if(BUILD_EXAMPLES)
  if(NOT BUILD_SHARED_LIBS)
    message(FATAL_ERROR "Examples require -DBUILD_SHARED_LIBS=ON")
  endif()
  add_subdirectory(examples)
endif()

if(BUILD_TOOLS)
  find_package(POPT REQUIRED)
  if(BUILD_TOOLS_DOCS)
    find_package(XMLTO REQUIRED)
  endif()
  add_subdirectory(tools)
endif()

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
  if (NOT BUILD_STATIC_LIBS)
    message(FATAL_ERROR
      "Tests can only be built against static libraries "
      "(set BUILD_STATIC_LIBS=ON)")
  endif ()
  add_subdirectory(tests)
endif ()

if(BUILD_OSSFUZZ)
  add_subdirectory(fuzz)
endif ()

if (BUILD_API_DOCS)
  find_package(Doxygen REQUIRED)
  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/docs/Doxyfile @ONLY)

  add_custom_target(docs
    COMMAND ${DOXYGEN_EXECUTABLE}
    VERBATIM
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/docs
    DEPENDS rabbitmq
    COMMENT "Generating API documentation"
    SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
    )
endif ()

foreach (lib ${SOCKET_LIBRARIES})
    set(libs_private "${libs_private} -l${lib}")
endforeach(lib)
set(libs_private "${libs_private} -l${LIBRT}")
if (ENABLE_SSL_SUPPORT)
  set(libs_private "${libs_private} -lssl -lcrypto ${CMAKE_THREAD_LIBS_INIT}")
endif()

set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "\${prefix}")
cmake_path(APPEND libdir "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
cmake_path(APPEND includedir "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")

configure_file(cmake/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/librabbitmq/config.h)
configure_file(librabbitmq.pc.in ${CMAKE_CURRENT_BINARY_DIR}/librabbitmq.pc @ONLY)

include(CMakePackageConfigHelpers)
set(RMQ_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/rabbitmq-c)
set(project_config "${CMAKE_CURRENT_BINARY_DIR}/rabbitmq-c-config.cmake")
set(version_config "${CMAKE_CURRENT_BINARY_DIR}/rabbitmq-c-config-version.cmake")

write_basic_package_version_file(
    "${version_config}"
    VERSION ${RMQ_VERSION}
    COMPATIBILITY SameMajorVersion)

configure_package_config_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake/rabbitmq-c-config.cmake.in"
    "${project_config}"
    INSTALL_DESTINATION "${RMQ_CMAKE_DIR}")


if(BUILD_SHARED_LIBS)
    list(APPEND INSTALL_TARGETS rabbitmq)
endif()
if(BUILD_STATIC_LIBS AND INSTALL_STATIC_LIBS)
    list(APPEND INSTALL_TARGETS rabbitmq-static)
endif()

export(TARGETS ${INSTALL_TARGETS} 
    NAMESPACE rabbitmq:: 
    FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)

install(FILES ${project_config} ${version_config}
    DESTINATION ${RMQ_CMAKE_DIR}
    COMPONENT rabbitmq-c-development
    )

install(EXPORT ${targets_export_name} 
    DESTINATION ${RMQ_CMAKE_DIR}
    NAMESPACE rabbitmq::
    COMPONENT rabbitmq-c-development
    )

install(FILES
  ${CMAKE_CURRENT_BINARY_DIR}/librabbitmq.pc
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
  )

if (BUILD_SHARED_LIBS)
  message(STATUS "Building rabbitmq as a shared library - yes")
else ()
  message(STATUS "Building rabbitmq as a shared library - no")
endif ()

if (BUILD_STATIC_LIBS)
  message(STATUS "Building rabbitmq as a static library - yes")
else ()
  message(STATUS "Building rabbitmq as a static library - no")
endif ()