diff options
-rw-r--r-- | CMakeLists.txt | 74 | ||||
-rw-r--r-- | README | 40 | ||||
-rw-r--r-- | README.windows | 5 | ||||
-rw-r--r-- | TestCInline.cmake | 28 | ||||
-rw-r--r-- | cmake/FindPOPT.cmake | 18 | ||||
-rw-r--r-- | cmake/LibFindMacros.cmake | 99 | ||||
-rw-r--r-- | examples/CMakeLists.txt | 37 | ||||
-rw-r--r-- | librabbitmq/CMakeLists.txt | 82 | ||||
-rw-r--r-- | tools/CMakeLists.txt | 34 |
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) + @@ -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}) + |