summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt74
-rw-r--r--README40
-rw-r--r--README.windows5
-rw-r--r--TestCInline.cmake28
-rw-r--r--cmake/FindPOPT.cmake18
-rw-r--r--cmake/LibFindMacros.cmake99
-rw-r--r--examples/CMakeLists.txt37
-rw-r--r--librabbitmq/CMakeLists.txt82
-rw-r--r--tools/CMakeLists.txt34
9 files changed, 415 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..7601431
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,74 @@
+cmake_minimum_required(VERSION 2.8)
+project(rabbitmq-c "C")
+
+#find python
+find_package(PythonInterp REQUIRED)
+
+#check for json or simplejson
+execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import json"
+ RESULT_VARIABLE CHECK_PYTHON_JSON_FAILED
+)
+
+if (CHECK_PYTHON_JSON_FAILED)
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import simplejson"
+ RESULT_VARIABLE CHECK_PYTHON_SIMPLEJSON_FAILED
+ )
+
+ if (CHECK_PYTHON_SIMPLEJSON_FAILED)
+ message(FATAL_ERROR "could not find a python that can 'import simplejson")
+ endif (CHECK_PYTHON_SIMPLEJSON_FAILED)
+endif (CHECK_PYTHON_JSON_FAILED)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR})
+include(TestCInline)
+
+option(FETCH_CODEGEN_FROM_GIT "Fetch codegen directly from the git repository" OFF)
+
+set(CODEGEN_GIT_TAG rabbitmq_v2_5_1 CACHE STRING "Git tag in rabbitmq-codegen to fetch with FETCH_CODEGEN_FROM_GIT")
+if (FETCH_CODEGEN_FROM_GIT)
+ include(ExternalProject)
+ ExternalProject_Add(
+ amqp_codegen
+ GIT_REPOSITORY https://github.com/rabbitmq/rabbitmq-codegen.git
+ GIT_TAG ${CODEGEN_GIT_TAG}
+ CONFIGURE_COMMAND ""
+ UPDATE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND "")
+
+ ExternalProject_Get_Property(amqp_codegen SOURCE_DIR)
+ set(AMQP_CODEGEN_DIR ${SOURCE_DIR} CACHE PATH "Path to rabbitmq-codegen" FORCE)
+ SET(AMQP_CODEGEN_TARGET amqp_codegen)
+ message(STATUS "Using amqp_codegen.py in ${AMQP_CODEGEN_DIR}")
+else (FETCH_CODEGEN_FROM_GIT)
+ find_path(RABBITMQ_CODEGEN_DIR
+ amqp_codegen.py
+ PATHS ${CMAKE_SOURCE_DIR}/rabbitmq-codegen
+ ${CMAKE_SOURCE_DIR}/../rabbitmq-codegen
+ DOC "Path to directory containing amqp_codegen.py (rabbitmq-codegen)"
+ NO_DEFAULT_PATH
+ )
+
+ if (RABBITMQ_CODEGEN_DIR STREQUAL "RABBITMQ_CODEGEN_DIR-NOTFOUND")
+ message(SEND_ERROR "Cannot find rabbitmq-codegen, set RABBITMQ_CODEGEN_DIR to a rabbitmq-codegen checkout, or set FETCH_CODEGEN_FROM_GIT to download it from git automatically")
+ else ()
+ message(STATUS "Using amqp_codegen.py in ${RABBITMQ_CODEGEN_DIR}")
+ endif()
+
+ set(AMQP_CODEGEN_DIR ${RABBITMQ_CODEGEN_DIR} CACHE PATH "Path to rabbitmq-codegen" FORCE)
+endif (FETCH_CODEGEN_FROM_GIT)
+
+mark_as_advanced(AMQP_CODEGEN_DIR)
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
+
+find_package(POPT)
+
+add_subdirectory(librabbitmq)
+add_subdirectory(examples)
+
+if (POPT_FOUND)
+ add_subdirectory(tools)
+endif (POPT_FOUND)
+
diff --git a/README b/README
index 6ae88dc..e27656f 100644
--- a/README
+++ b/README
@@ -25,10 +25,13 @@ the necessary pieces:
hg clone http://hg.rabbitmq.com/rabbitmq-c/
You will also need a recent python with the simplejson module
-installed, and the GNU autotools (autoconf, automake, libtool etc).
+installed, and the GNU autotools (autoconf, automake, libtool etc)
+or as an alternative CMake
## Building the code
+# Using autoconf
+
Once you have all the prerequisites, change to the `rabbitmq-c`
directory and run
@@ -42,6 +45,41 @@ by
to build the `librabbitmq` library and the example programs.
+# Using cmake
+
+You will need CMake http://cmake.org/
+You will need a working python install in your path.
+If you would like the build system to fetch the rabbitmq-codegen automatically
+you will need to have a working git install in your path. Otherwise you will
+need to checkout the rabbitmq-codegen as stated above.
+
+Create a binary directory in a sibling directory from the directory
+you cloned the rabbitmq-c repository
+ mkdir bin-rabbitmq-c
+
+Run CMake in the binary directory
+ cmake /path/to/source/directory
+
+Build it
+ On linux: make
+ On win32: nmake or msbuild, or open it in visual studio and build from there
+
+Things you can pass to cmake to change the build:
+
+ -DRABBITMQ_CODEGEN_DIR=/path/to/rabbitmq-codegen/checkout - if you have your codegen
+ directory in a different place [Default is sibiling directory to source]
+ -DFETCH_CODEGEN_FROM_GIT=ON - if you want cmake to fetch the rabbitmq-codegen from
+ https://github.com/rabbitmq/rabbitmq-c at build time. If this option is selected
+ -DRABBITMQ_CODEGEN_DIR will be ignored [Default is off]
+ -DCODEGEN_GIT_TAG=rabbitmq_v2_5_1 - specifies the tag to check out if using the
+ -DFETCH_CODEGEN_FROM_GIT option above. [Default is rabbitmq_v2_5_1]
+ -DBUILD_TOOLS=OFF build the programs in the tools directory
+ [Default is ON if the POPT library can be found]
+
+Other interesting flags to pass to CMake (see cmake docs for more info)
+ -DCMAKE_BUILD_TYPE - specify the type of build (Debug or Release)
+ -DCMAKE_INSTALL_PREFIX - specify where the install target puts files
+
## Running the examples
Arrange for a RabbitMQ or other AMQP server to be running on
diff --git a/README.windows b/README.windows
index cfff065..2774f19 100644
--- a/README.windows
+++ b/README.windows
@@ -1,6 +1,6 @@
# Using rabbitmq-c on Windows
-There are two approaches to building rabbitmq-c under Windows:
+There are three approaches to building rabbitmq-c under Windows:
- Build using the MinGW/MSYS (MinGW/MSYS is a port of the GNU
toolchain and utilities to Windows, including the gcc compiler).
@@ -19,6 +19,9 @@ There are two approaches to building rabbitmq-c under Windows:
this approach is that the rabbitmq-c tools cannot be built, due to
dependencies on other libraries.
+- Build using CMake, which will cover building with MSVC or MinGW
+ See the README file for details on how to build with cmake.
+
## Common steps
diff --git a/TestCInline.cmake b/TestCInline.cmake
new file mode 100644
index 0000000..4fdd4c5
--- /dev/null
+++ b/TestCInline.cmake
@@ -0,0 +1,28 @@
+#Inspired from http://www.cmake.org/Wiki/CMakeTestInline
+
+IF(NOT DEFINED C_INLINE_DETECTED)
+
+ SET(INLINE_TEST_SRC "/* Inspired by autoconf's c.m4 */
+static inline int static_foo() {return 0\;}
+int main(int argc, char *argv[]){return 0\;}
+")
+
+ FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/CMakeTestCInline.c ${INLINE_TEST_SRC})
+
+ FOREACH(KEYWORD "inline" "__inline__" "__inline")
+ IF(NOT DEFINED C_INLINE)
+ TRY_COMPILE(C_HAS_${KEYWORD}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/CMakeTestCInline.c
+ COMPILE_DEFINITIONS "-Dinline=${KEYWORD}"
+ )
+ IF(C_HAS_${KEYWORD})
+ SET(C_INLINE ${KEYWORD})
+ ENDIF(C_HAS_${KEYWORD})
+ ENDIF(NOT DEFINED C_INLINE)
+ ENDFOREACH(KEYWORD)
+
+ SET(C_INLINE_DETECTED True CACHE BOOL INTERNAL)
+
+ENDIF(NOT DEFINED C_INLINE_DETECTED)
+
diff --git a/cmake/FindPOPT.cmake b/cmake/FindPOPT.cmake
new file mode 100644
index 0000000..e0af678
--- /dev/null
+++ b/cmake/FindPOPT.cmake
@@ -0,0 +1,18 @@
+INCLUDE(LibFindMacros)
+
+# Find the include directories
+FIND_PATH(POPT_INCLUDE_DIR
+ NAMES popt.h
+ HINTS ${POPT_PREFIX}/include
+ )
+
+FIND_LIBRARY(POPT_LIBRARY
+ NAMES popt
+ HINTS ${POPT_PREFIX}/lib
+ )
+
+SET(POPT_PROCESS_INCLUDES POPT_INCLUDE_DIR)
+SET(POPT_PROCESS_LIBS POPT_LIBRARY)
+
+LIBFIND_PROCESS(POPT)
+
diff --git a/cmake/LibFindMacros.cmake b/cmake/LibFindMacros.cmake
new file mode 100644
index 0000000..69975c5
--- /dev/null
+++ b/cmake/LibFindMacros.cmake
@@ -0,0 +1,99 @@
+# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments
+# used for the current package. For this to work, the first parameter must be the
+# prefix of the current package, then the prefix of the new package etc, which are
+# passed to find_package.
+macro (libfind_package PREFIX)
+ set (LIBFIND_PACKAGE_ARGS ${ARGN})
+ if (${PREFIX}_FIND_QUIETLY)
+ set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET)
+ endif (${PREFIX}_FIND_QUIETLY)
+ if (${PREFIX}_FIND_REQUIRED)
+ set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED)
+ endif (${PREFIX}_FIND_REQUIRED)
+ find_package(${LIBFIND_PACKAGE_ARGS})
+endmacro (libfind_package)
+
+# CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
+# where they added pkg_check_modules. Consequently I need to support both in my scripts
+# to avoid those deprecated warnings. Here's a helper that does just that.
+# Works identically to pkg_check_modules, except that no checks are needed prior to use.
+macro (libfind_pkg_check_modules PREFIX PKGNAME)
+ if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ include(UsePkgConfig)
+ pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
+ else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(${PREFIX} ${PKGNAME})
+ endif (PKG_CONFIG_FOUND)
+ endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
+endmacro (libfind_pkg_check_modules)
+
+# Do the final processing once the paths have been detected.
+# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
+# all the variables, each of which contain one include directory.
+# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
+# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
+# Also handles errors in case library detection was required, etc.
+macro (libfind_process PREFIX)
+ # Skip processing if already processed during this run
+ if (NOT ${PREFIX}_FOUND)
+ # Start with the assumption that the library was found
+ set (${PREFIX}_FOUND TRUE)
+
+ # Process all includes and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES})
+ if (${i})
+ set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+ # Process all libraries and set _FOUND to false if any are missing
+ foreach (i ${${PREFIX}_PROCESS_LIBS})
+ if (${i})
+ set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
+ mark_as_advanced(${i})
+ else (${i})
+ set (${PREFIX}_FOUND FALSE)
+ endif (${i})
+ endforeach (i)
+
+ # Print message and/or exit on fatal error
+ if (${PREFIX}_FOUND)
+ if (NOT ${PREFIX}_FIND_QUIETLY)
+ message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
+ endif (NOT ${PREFIX}_FIND_QUIETLY)
+ else (${PREFIX}_FOUND)
+ if (${PREFIX}_FIND_REQUIRED)
+ foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
+ message("${i}=${${i}}")
+ endforeach (i)
+ message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
+ endif (${PREFIX}_FIND_REQUIRED)
+ endif (${PREFIX}_FOUND)
+ endif (NOT ${PREFIX}_FOUND)
+endmacro (libfind_process)
+
+macro(libfind_library PREFIX basename)
+ set(TMP "")
+ if(MSVC80)
+ set(TMP -vc80)
+ endif(MSVC80)
+ if(MSVC90)
+ set(TMP -vc90)
+ endif(MSVC90)
+ set(${PREFIX}_LIBNAMES ${basename}${TMP})
+ if(${ARGC} GREATER 2)
+ set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2})
+ string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES})
+ set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP})
+ endif(${ARGC} GREATER 2)
+ find_library(${PREFIX}_LIBRARY
+ NAMES ${${PREFIX}_LIBNAMES}
+ PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}
+ )
+endmacro(libfind_library)
+
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 0000000..8b58e8b
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,37 @@
+include_directories(${librabbitmq_SOURCE_DIR} ${librabbitmq_BINARY_DIR})
+
+if (WIN32)
+ set(PLATFORM_DIR windows)
+else (WIN32)
+ set(PLATFORM_DIR unix)
+endif (WIN32)
+
+set(COMMON_SRCS
+ utils.h
+ utils.c
+ ${PLATFORM_DIR}/platform_utils.c
+ )
+
+add_executable(amqp_sendstring amqp_sendstring.c ${COMMON_SRCS})
+target_link_libraries(amqp_sendstring rabbitmq)
+
+add_executable(amqp_exchange_declare amqp_exchange_declare.c ${COMMON_SRCS})
+target_link_libraries(amqp_exchange_declare rabbitmq)
+
+add_executable(amqp_listen amqp_listen.c ${COMMON_SRCS})
+target_link_libraries(amqp_listen rabbitmq)
+
+add_executable(amqp_producer amqp_producer.c ${COMMON_SRCS})
+target_link_libraries(amqp_producer rabbitmq)
+
+add_executable(amqp_consumer amqp_consumer.c ${COMMON_SRCS})
+target_link_libraries(amqp_consumer rabbitmq)
+
+add_executable(amqp_unbind amqp_unbind.c ${COMMON_SRCS})
+target_link_libraries(amqp_unbind rabbitmq)
+
+add_executable(amqp_bind amqp_bind.c ${COMMON_SRCS})
+target_link_libraries(amqp_bind rabbitmq)
+
+add_executable(amqp_listenq amqp_listenq.c ${COMMON_SRCS})
+target_link_libraries(amqp_listenq rabbitmq)
diff --git a/librabbitmq/CMakeLists.txt b/librabbitmq/CMakeLists.txt
new file mode 100644
index 0000000..80632ed
--- /dev/null
+++ b/librabbitmq/CMakeLists.txt
@@ -0,0 +1,82 @@
+project(librabbitmq "C")
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+# Stuff dealing with code generation
+set(AMQP_CODEGEN_PY "${CMAKE_CURRENT_BINARY_DIR}/amqp_codegen.py")
+set(CODEGEN_PY "${CMAKE_CURRENT_BINARY_DIR}/codegen.py")
+set(AMQP_SPEC_JSON_PATH "${AMQP_CODEGEN_DIR}/amqp-rabbitmq-0.9.1.json")
+
+#generate amqp_framing.h/amqp_framing.c
+add_custom_command(
+ OUTPUT ${CODEGEN_PY}
+ COMMAND ${CMAKE_COMMAND} ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/codegen.py ${CODEGEN_PY}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/codegen.py
+ VERBATIM)
+
+add_custom_command(
+ OUTPUT ${AMQP_CODEGEN_PY}
+ COMMAND ${CMAKE_COMMAND} ARGS -E copy ${AMQP_CODEGEN_DIR}/amqp_codegen.py ${AMQP_CODEGEN_PY}
+ DEPENDS ${AMQP_CODEGEN_DIR}/amqp_codegen.py ${AMQP_CODEGEN_TARGET}
+ VERBATIM)
+
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/amqp_framing.h
+ COMMAND ${PYTHON_EXECUTABLE} ARGS ${CODEGEN_PY} header ${AMQP_SPEC_JSON_PATH} ${CMAKE_CURRENT_BINARY_DIR}/amqp_framing.h
+ DEPENDS ${AMQP_SPEC_JSON_PATH} ${CODEGEN_PY} ${AMQP_CODEGEN_PY}
+ VERBATIM)
+
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/amqp_framing.c
+ COMMAND ${PYTHON_EXECUTABLE} ARGS ${CODEGEN_PY} body ${AMQP_SPEC_JSON_PATH} ${CMAKE_CURRENT_BINARY_DIR}/amqp_framing.c
+ DEPENDS ${AMQP_SPEC_JSON_PATH} ${CODEGEN_PY} ${AMQP_CODEGEN_PY}
+ VERBATIM)
+
+
+SET(CONFIG_CONTENTS "#define VERSION \"0.0.1\"
+#ifndef __cplusplus
+# define inline ${C_INLINE}
+#endif // __cplusplus
+")
+
+#prepare config.h
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/config.h" ${CONFIG_CONTENTS})
+
+if(WIN32)
+ set(SOCKET_IMPL "windows")
+else(WIN32)
+ set(SOCKET_IMPL "unix")
+endif(WIN32)
+
+if(MSVC)
+ set(MSINTTYPES_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/../msinttypes")
+endif(MSVC)
+
+include_directories(${SOCKET_IMPL} ${MSINTTYPES_INCLUDE})
+add_definitions(-DBUILDING_LIBRABBITMQ)
+
+set(RABBITMQ_SOURCES
+ ${CMAKE_CURRENT_BINARY_DIR}/amqp_framing.h
+ ${CMAKE_CURRENT_BINARY_DIR}/amqp_framing.c
+ amqp_api.c amqp.h
+ amqp_connection.c amqp_mem.c amqp_private.h amqp_socket.c amqp_table.c
+ amqp_url.c
+ ${SOCKET_IMPL}/socket.h ${SOCKET_IMPL}/socket.c
+)
+
+add_library(rabbitmq SHARED ${RABBITMQ_SOURCES})
+
+if(WIN32)
+ target_link_libraries(rabbitmq ws2_32)
+endif(WIN32)
+
+install(TARGETS rabbitmq
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+ PUBLIC_HEADER DESTINATION include)
+
+install(FILES amqp.h ${CMAKE_CURRENT_BINARY_DIR}/amqp_framing.h
+ DESTINATION include)
+
+
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644
index 0000000..579a3b9
--- /dev/null
+++ b/tools/CMakeLists.txt
@@ -0,0 +1,34 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${librabbitmq_SOURCE_DIR} ${librabbitmq_BINARY_DIR} ${POPT_INCLUDE_DIRS})
+
+if (WIN32)
+ set(PLATFORM_DIR win32)
+ set(PLATFORM_SRCS
+ windows/compat.c
+ )
+else (WIN32)
+ set(PLATFORM_DIR unix)
+endif (WIN32)
+
+include_directories(${PLATFORM_DIR})
+
+set(COMMON_SRCS
+ common.h
+ common.c
+ ${PLATFORM_SRCS}
+ )
+
+add_executable(amqp-publish publish.c ${COMMON_SRCS})
+target_link_libraries(amqp-publish rabbitmq ${POPT_LIBRARY})
+
+add_executable(amqp-get get.c ${COMMON_SRCS})
+target_link_libraries(amqp-get rabbitmq ${POPT_LIBRARY})
+
+add_executable(amqp-consume consume.c ${PLATFORM_DIR}/process.c ${COMMON_SRCS})
+target_link_libraries(amqp-consume rabbitmq ${POPT_LIBRARY})
+
+add_executable(amqp-declare-queue declare_queue.c ${COMMON_SRCS})
+target_link_libraries(amqp-declare-queue rabbitmq ${POPT_LIBRARY})
+
+add_executable(amqp-delete-queue delete_queue.c ${COMMON_SRCS})
+target_link_libraries(amqp-delete-queue rabbitmq ${POPT_LIBRARY})
+