diff --git a/CMakeLists.txt b/CMakeLists.txt index cb73c91b..64ccb39b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,10 +24,16 @@ cmake_minimum_required(VERSION 3.16) project(wolfMQTT VERSION 1.17.1 LANGUAGES C) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/functions.cmake) + +find_package(Threads) + set(MQTT_SOURCES src/mqtt_client.c src/mqtt_packet.c src/mqtt_socket.c + src/mqtt_sn_client.c + src/mqtt_sn_packet.c ) # default to build shared library @@ -39,57 +45,35 @@ if (WITH_WOLFSSL) target_link_libraries(wolfmqtt PUBLIC wolfssl) target_include_directories(wolfmqtt PUBLIC ${WITH_WOLFSSL}/include) target_link_directories(wolfmqtt PUBLIC ${WITH_WOLFSSL}/lib) - target_compile_definitions(wolfmqtt PUBLIC - "ENABLE_MQTT_TLS" - ) + list(APPEND WOLFMQTT_DEFINITIONS "-DENABLE_MQTT_TLS") elseif (WITH_WOLFSSL_TREE) set(WOLFSSL_EXAMPLES "no" CACHE STRING "") set(WOLFSSL_CRYPT_TESTS "no" CACHE STRING "") add_subdirectory(${WITH_WOLFSSL_TREE} wolfssl) target_link_libraries(wolfmqtt PUBLIC wolfssl) - target_compile_definitions(wolfmqtt PUBLIC - "ENABLE_MQTT_TLS" - ) + list(APPEND WOLFMQTT_DEFINITIONS "-DENABLE_MQTT_TLS") else() find_package(PkgConfig) pkg_check_modules(WOLFSSL wolfssl) if (WOLFSSL_FOUND) - target_compile_definitions(wolfmqtt PUBLIC - "ENABLE_MQTT_TLS" - ) + list(APPEND WOLFMQTT_DEFINITIONS "-DENABLE_MQTT_TLS") target_link_libraries(wolfmqtt PUBLIC ${WOLFSSL_LIBRARIES}) target_include_directories(wolfmqtt PUBLIC ${WOLFSSL_INCLUDE_DIRS}) target_link_directories(wolfmqtt PUBLIC ${WOLFSSL_LIBRARY_DIRS}) target_compile_options(wolfmqtt PUBLIC ${WOLFSSL_CFLAGS_OTHER}) else() # For support with vcpkg - find_package(wolfssl CONFIG) + find_package(wolfssl CONFIG REQUIRED) if (wolfssl_FOUND) - find_path(WOLFSSL_INCLUDE_DIR NAMES wolfssl/ssl.h) - find_library(WOLFSSL_LIBRARY_PATH NAMES wolfssl) - target_compile_definitions(wolfmqtt PUBLIC - "ENABLE_MQTT_TLS" - ) - include_directories(${WOLFSSL_INCLUDE_DIR}) - target_link_libraries(wolfmqtt PUBLIC ${WOLFSSL_LIBRARY_PATH}) + list(APPEND WOLFMQTT_DEFINITIONS "-DENABLE_MQTT_TLS") + target_link_libraries(wolfmqtt PUBLIC wolfssl::wolfssl) endif() endif() endif() -# TODO: add options -# * tls -# * sn -# * nonblock -# * timeout -# * errorstrings -# * stdincap -# * v5 -# * discb -# * mt - set(WOLFMQTT_EXAMPLES "yes" CACHE BOOL "Build examples") @@ -102,8 +86,124 @@ target_compile_definitions(wolfmqtt PRIVATE "BUILDING_CMAKE" ) -#TODO generate options file -configure_file(wolfmqtt/options.h.in wolfmqtt/options.h) +add_option(WOLFMQTT_TLS + "Enable TLS support with wolfSSL" + "yes" "yes;no") +if (WOLFMQTT_TLS) + list(APPEND WOLFMQTT_DEFINITIONS "-DENABLE_MQTT_TLS") +endif() + +add_option("WOLFMQTT_SN" + "Enable MQTT-SN support" + "no" "yes;no") +if (WOLFMQTT_SN) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_SN") +endif() + +add_option("WOLFMQTT_NONBLOCK" + "Enable non-blocking support" + "no" "yes;no") +if (WOLFMQTT_NONBLOCK) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_NONBLOCK") +endif() + +add_option(WOLFMQTT_TIMEOUT + "Enable timeout support" + "yes" "yes;no") +if (NOT WOLFMQTT_TIMEOUT) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_NO_TIMEOUT") +endif() + +add_option(WOLFMQTT_ERRORSTRINGS + "Enable error strings" + "yes" "yes;no") +if (NOT WOLFMQTT_ERRORSTRINGS) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_NO_ERROR_STRINGS") +endif() + +add_option(WOLFMQTT_STDINCAP + "Enable examples STDIN capture" + "yes" "yes;no") +if (NOT WOLFMQTT_STDINCAP) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_NO_STDIN_CAP") +endif() + +add_option("WOLFMQTT_V5" + "Enable MQTT v5.0 support" + "no" "yes;no") +if (WOLFMQTT_V5) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_V5") +endif() + +add_option(WOLFMQTT_DISCB + "Enable disconnect callback" + "yes" "yes;no") +if (WOLFMQTT_DISCB) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_DISCONNECT_CB") +endif() + +add_option(WOLFMQTT_MT + "Enable multiple thread support" + "no" "yes;no") +if (WOLFMQTT_MT) + list(APPEND WOLFMQTT_DEFINITIONS "-DWOLFMQTT_MULTITHREAD") +endif() + +add_option(WOLFMQTT_CURL + "Enable curl easy socket backend" + "no" "yes;no") +if (WOLFMQTT_CURL) + list(APPEND WOLFMQTT_DEFINITIONS "-DENABLE_MQTT_CURL") +endif() + + +# generate options file +message("Generating user options header...") +if (${CMAKE_DISABLE_SOURCE_CHANGES}) + set(WOLFMQTT_BUILD_OUT_OF_TREE_DEFAULT "${CMAKE_DISABLE_SOURCE_CHANGES}") +else() + set(WOLFMQTT_BUILD_OUT_OF_TREE_DEFAULT "no") +endif() + +set(WOLFMQTT_BUILD_OUT_OF_TREE "${WOLFMQTT_BUILD_OUT_OF_TREE_DEFAULT}" CACHE STRING + "Don't generate files in the source tree (default: ${WOLFMQTT_BUILD_OUT_OF_TREE_DEFAULT})") +set_property(CACHE WOLFMQTT_BUILD_OUT_OF_TREE + PROPERTY STRINGS "yes;no") + +if (${WOLFMQTT_BUILD_OUT_OF_TREE}) + set(WOLFMQTT_OUTPUT_BASE ${CMAKE_CURRENT_BINARY_DIR}) +else() + set(WOLFMQTT_OUTPUT_BASE ${CMAKE_CURRENT_SOURCE_DIR}) +endif() +set(OPTION_FILE "${WOLFMQTT_OUTPUT_BASE}/wolfmqtt/options.h") + +file(REMOVE ${OPTION_FILE}) + +file(APPEND ${OPTION_FILE} "/* wolfmqtt options.h\n") +file(APPEND ${OPTION_FILE} " * generated from cmake configure options\n") +file(APPEND ${OPTION_FILE} " *\n") +file(APPEND ${OPTION_FILE} " * Copyright (C) 2006-2024 wolfSSL Inc.\n") +file(APPEND ${OPTION_FILE} " *\n") +file(APPEND ${OPTION_FILE} " * This file is part of wolfSSL.\n") +file(APPEND ${OPTION_FILE} " *\n") +file(APPEND ${OPTION_FILE} " */\n\n") +file(APPEND ${OPTION_FILE} "#ifndef WOLFMQTT_OPTIONS_H\n") +file(APPEND ${OPTION_FILE} "#define WOLFMQTT_OPTIONS_H\n\n\n") +file(APPEND ${OPTION_FILE} "#ifdef __cplusplus\n") +file(APPEND ${OPTION_FILE} "extern \"C\" {\n") +file(APPEND ${OPTION_FILE} "#endif\n\n") + +add_to_options_file("${WOLFMQTT_DEFINITIONS}" "${OPTION_FILE}") +# CMAKE_C_FLAGS is just a string of space-separated flags to pass to the C +# compiler. We need to replace those spaces with semicolons in order to treat it +# as a CMake list. +string(REPLACE " " ";" CMAKE_C_FLAGS_LIST "${CMAKE_C_FLAGS}") +add_to_options_file("${CMAKE_C_FLAGS_LIST}" "${OPTION_FILE}") + +file(APPEND ${OPTION_FILE} "\n#ifdef __cplusplus\n") +file(APPEND ${OPTION_FILE} "}\n") +file(APPEND ${OPTION_FILE} "#endif\n\n\n") +file(APPEND ${OPTION_FILE} "#endif /* WOLFMQTT_OPTIONS_H */\n\n") if(WIN32) target_compile_definitions(wolfmqtt PRIVATE diff --git a/Makefile.am b/Makefile.am index 3cc35a43..98762876 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,6 +36,7 @@ include wolfmqtt/include.am include examples/include.am include scripts/include.am include IDE/include.am +include cmake/include.am EXTRA_DIST+= README.md EXTRA_DIST+= ChangeLog.md diff --git a/cmake/README.md b/cmake/README.md new file mode 100644 index 00000000..f3d9a526 --- /dev/null +++ b/cmake/README.md @@ -0,0 +1,7 @@ +# wolfSSL CMake + +This directory contains some supplementary functions for the [CMakeLists.txt](../CMakeLists.txt) in the root. + +See also cmake notes in the [INSTALL](../INSTALL) documentation file. + + diff --git a/cmake/functions.cmake b/cmake/functions.cmake new file mode 100644 index 00000000..ba3bf6d6 --- /dev/null +++ b/cmake/functions.cmake @@ -0,0 +1,65 @@ +function(override_cache VAR VAL) + get_property(VAR_STRINGS CACHE ${VAR} PROPERTY STRINGS) + LIST(FIND VAR_STRINGS ${VAL} CK) + if(-1 EQUAL ${CK}) + message(SEND_ERROR + "\"${VAL}\" is not valid override value for \"${VAR}\"." + " Please select value from \"${VAR_STRINGS}\"\n") + endif() + set_property(CACHE ${VAR} PROPERTY VALUE ${VAL}) +endfunction() + +function(add_option NAME HELP_STRING DEFAULT VALUES) + # Set the default value for the option. + set(${NAME} ${DEFAULT} CACHE STRING ${HELP_STRING}) + # Set the list of allowed values for the option. + set_property(CACHE ${NAME} PROPERTY STRINGS ${VALUES}) + + if(DEFINED ${NAME}) + list(FIND VALUES ${${NAME}} IDX) + # + # If the given value isn't in the list of allowed values for the option, + # reduce it to yes/no according to CMake's "if" logic: + # https://cmake.org/cmake/help/latest/command/if.html#basic-expressions + # + # This has no functional impact; it just makes the settings in + # CMakeCache.txt and cmake-gui easier to read. + # + if (${IDX} EQUAL -1) + if(${${NAME}}) + override_cache(${NAME} "yes") + else() + override_cache(${NAME} "no") + endif() + endif() + endif() +endfunction() + +function(add_to_options_file DEFINITIONS OPTION_FILE) + list(REMOVE_DUPLICATES DEFINITIONS) + foreach(DEF IN LISTS DEFINITIONS) + if(DEF MATCHES "^-D") + if(DEF MATCHES "^-D(N)?DEBUG(=.+)?") + message("not outputting (N)DEBUG to ${OPTION_FILE}") + endif() + + # allow user to ignore system options + if(DEF MATCHES "^-D_.*") + file(APPEND ${OPTION_FILE} "#ifndef WOLFSSL_OPTIONS_IGNORE_SYS\n") + endif() + + string(REGEX REPLACE "^-D" "" DEF_NO_PREFIX ${DEF}) + string(REGEX REPLACE "=.*$" "" DEF_NO_EQUAL_NO_VAL ${DEF_NO_PREFIX}) + string(REPLACE "=" " " DEF_NO_EQUAL ${DEF_NO_PREFIX}) + + file(APPEND ${OPTION_FILE} "#undef ${DEF_NO_EQUAL_NO_VAL}\n") + file(APPEND ${OPTION_FILE} "#define ${DEF_NO_EQUAL}\n") + + if(DEF MATCHES "^-D_.*") + file(APPEND ${OPTION_FILE} "#endif\n") + endif() + + file(APPEND ${OPTION_FILE} "\n") + endif() + endforeach() +endfunction() diff --git a/cmake/include.am b/cmake/include.am new file mode 100644 index 00000000..04e169fb --- /dev/null +++ b/cmake/include.am @@ -0,0 +1,2 @@ +EXTRA_DIST += cmake/README.md +EXTRA_DIST += cmake/functions.cmake