cmake_minimum_required(VERSION 3.0) project(cmetrics C) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # CMetrics Version set(CMT_VERSION_MAJOR 0) set(CMT_VERSION_MINOR 6) set(CMT_VERSION_PATCH 3) set(CMT_VERSION_STR "${CMT_VERSION_MAJOR}.${CMT_VERSION_MINOR}.${CMT_VERSION_PATCH}") # Include helpers include(cmake/macros.cmake) include(CheckCSourceCompiles) include(GNUInstallDirs) # On macOS, search Homebrew for keg-only versions of Bison and Flex. Xcode does # not provide new enough versions for us to use. if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin") execute_process( COMMAND brew --prefix bison RESULT_VARIABLE BREW_BISON OUTPUT_VARIABLE BREW_BISON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE ) if (BREW_BISON EQUAL 0 AND EXISTS "${BREW_BISON_PREFIX}") message(STATUS "Found Bison keg installed by Homebrew at ${BREW_BISON_PREFIX}") set(BISON_EXECUTABLE "${BREW_BISON_PREFIX}/bin/bison") endif() execute_process( COMMAND brew --prefix flex RESULT_VARIABLE BREW_FLEX OUTPUT_VARIABLE BREW_FLEX_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE ) if (BREW_FLEX EQUAL 0 AND EXISTS "${BREW_FLEX_PREFIX}") message(STATUS "Found Flex keg installed by Homebrew at ${BREW_FLEX_PREFIX}") set(FLEX_EXECUTABLE "${BREW_FLEX_PREFIX}/bin/flex") endif() endif() # Define macro to identify Windows system (without Cygwin) if(CMAKE_SYSTEM_NAME MATCHES "Windows") set(CMT_SYSTEM_WINDOWS On) add_definitions(-DCMT_SYSTEM_WINDOWS) # Disable unistd.h for flex/bison CMT_DEFINITION(YY_NO_UNISTD_H) message(STATUS "Specifying YY_NO_UNISTD_H") endif() # Define macro to identify macOS system if(CMAKE_SYSTEM_NAME MATCHES "Darwin") set(CMT_SYSTEM_MACOS On) add_definitions(-DCMT_SYSTEM_MACOS) endif() if(NOT MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") endif() # Define __CMT_FILENAME__ consistently across Operating Systems if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__CMT_FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__CMT_FILENAME__=__FILE__") endif() # Configuration options option(CMT_DEV "Enable development mode" No) option(CMT_TESTS "Enable unit testing" No) option(CMT_INSTALL_TARGETS "Enable subdirectory library installations" Yes) option(CMT_ENABLE_PROMETHEUS_DECODER "Enable prometheus decoder" Yes) if(CMT_DEV) set(CMT_TESTS Yes) endif() set(FLEX_BISON_GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}) # Bundled libraries include(cmake/libraries.cmake) include(cmake/headers.cmake) # Include headers and dependency headers include_directories( src include ${FLEX_BISON_GENERATED_DIR} ) # timespec_get() support check_c_source_compiles(" #include int main() { struct tm tm; return timespec_get(&tm, TIME_UTC); }" CMT_HAVE_TIMESPEC_GET) if(CMT_HAVE_TIMESPEC_GET) CMT_DEFINITION(CMT_HAVE_TIMESPEC_GET) endif() # gmtime_r() support check_c_source_compiles(" #include int main() { struct tm tm; struct timespec tms; return gmtime_r(&tms.tv_sec, &tm); }" CMT_HAVE_GMTIME_R) if(CMT_HAVE_GMTIME_R) CMT_DEFINITION(CMT_HAVE_GMTIME_R) endif() # gmtime_s() support check_c_source_compiles(" #include int main() { struct tm tm; struct timespec tms; return gmtime_s(&tm, &tms.tv_sec); }" CMT_HAVE_GMTIME_S) if(CMT_HAVE_GMTIME_S) CMT_DEFINITION(CMT_HAVE_GMTIME_S) endif() # clock_get_time() support for macOS. check_c_source_compiles(" #include #include int main() { clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); return mach_port_deallocate(mach_task_self(), cclock); }" CMT_HAVE_CLOCK_GET_TIME) if(CMT_HAVE_CLOCK_GET_TIME) CMT_DEFINITION(CMT_HAVE_CLOCK_GET_TIME) endif() # FIXME: MessagePack support check_c_source_compiles(" #include \"../../../lib/msgpack-c/include/msgpack.h\" int main() { msgpack_packer pck; msgpack_sbuffer sbuf; return 0; }" CMT_HAVE_MSGPACK) if(CMT_ENABLE_PROMETHEUS_DECODER) # Flex and Bison: check if the variables has not been defined before by # a parent project to avoid conflicts. if(NOT FLEX_FOUND) find_package(FLEX 2) endif() if(NOT BISON_FOUND) find_package(BISON 3) endif() if(FLEX_FOUND AND BISON_FOUND) set(CMT_BUILD_PROMETHEUS_DECODER 1) endif() endif() # Check if 'C Floppy' library is available in the environment, if not, # we will try to build a local copy at a later stage check_c_source_compiles(" #include int main() { return cfl_found(); }" CMT_HAVE_CFL) if(CMT_HAVE_CFL) CMT_DEFINITION(CMT_HAVE_CFL) message(STATUS "CFL found in the system. OK") endif() # Check if fluent-otel-proto library is available in the environment, if not, # we will try to build a local copy at a later stage check_c_source_compiles(" #include int main() { return fluent_otel_found(); }" CMT_HAVE_FLUENT_OTEL_PROTO) if(CMT_HAVE_FLUENT_OTEL_PROTO) CMT_DEFINITION(CMT_HAVE_FLUENT_OTEL_PROTO) endif() # Configure header files configure_file( "${PROJECT_SOURCE_DIR}/include/cmetrics/cmt_info.h.in" "${PROJECT_SOURCE_DIR}/include/cmetrics/cmt_info.h" ) configure_file( "${PROJECT_SOURCE_DIR}/include/cmetrics/cmt_version.h.in" "${PROJECT_SOURCE_DIR}/include/cmetrics/cmt_version.h" ) # Installation Directories # ======================== if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(CMT_INSTALL_LIBDIR "lib") set(CMT_INSTALL_INCLUDEDIR "include") else() set(CMT_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set(CMT_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include") endif() # mpack if(NOT TARGET mpack-static) include_directories(lib/mpack/src/) add_subdirectory(lib/mpack EXCLUDE_FROM_ALL) if (CMT_INSTALL_TARGETS) install(TARGETS mpack-static RUNTIME DESTINATION ${CMT_INSTALL_BINDIR} LIBRARY DESTINATION ${CMT_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMT_INSTALL_LIBDIR} COMPONENT library) install(FILES lib/mpack/src/mpack/mpack.h DESTINATION ${CMT_INSTALL_INCLUDEDIR}/mpack COMPONENT headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) endif() endif() # C Floppy if (NOT CMT_HAVE_CFL) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/${CMT_PATH_LIB_CFL}/include) add_subdirectory(lib/cfl) CMT_DEFINITION(CMT_HAVE_CFL) CMT_DEFINITION(CMT_HAVE_CFL_INTERNAL) if (CMT_INSTALL_TARGETS) file(GLOB bundledCFLHeaders "lib/cfl/include/cfl/*.h") install(FILES ${bundledCFLHeaders} DESTINATION ${CMT_INSTALL_INCLUDEDIR}/cfl COMPONENT headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) # xxHash install(FILES lib/cfl/lib/xxhash/xxh3.h DESTINATION ${CMT_INSTALL_INCLUDEDIR} COMPONENT headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) install(FILES lib/cfl/lib/xxhash/xxhash.h DESTINATION ${CMT_INSTALL_INCLUDEDIR} COMPONENT headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) install(TARGETS xxhash RUNTIME DESTINATION ${CMT_INSTALL_BINDIR} LIBRARY DESTINATION ${CMT_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMT_INSTALL_LIBDIR} COMPONENT library) endif() endif() # fluent-otel-proto if (NOT CMT_HAVE_FLUENT_OTEL_PROTO) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/${CMT_PATH_LIB_FLUENT_OTEL_PROTO}/include) CMT_OPTION(FLUENT_PROTO_METRICS "on") CMT_OPTION(FLUENT_PROTO_EXAMPLES "off") add_subdirectory(lib/fluent-otel-proto) CMT_DEFINITION(CMT_HAVE_FLUENT_OTEL_PROTO) CMT_DEFINITION(CMT_HAVE_FLUENT_OTEL_PROTO_INTERNAL) if (CMT_INSTALL_TARGETS) file(GLOB bundledOTELProtoHeaders "lib/fluent-otel-proto/include/fluent-otel-proto/*.h") install(FILES ${bundledOTELProtoHeaders} DESTINATION ${CMT_INSTALL_INCLUDEDIR}/fluent-otel-proto COMPONENT headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) install(TARGETS fluent-otel-proto RUNTIME DESTINATION ${CMT_INSTALL_BINDIR} LIBRARY DESTINATION ${CMT_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMT_INSTALL_LIBDIR} COMPONENT library) endif() endif() # Source code add_subdirectory(include) add_subdirectory(src) # Tests if(CMT_TESTS) enable_testing() add_subdirectory(tests) endif() # Installer Generation (Cpack) # ============================ set(CPACK_PACKAGE_VERSION ${CMT_VERSION_STR}) set(CPACK_PACKAGE_NAME "cmetrics") set(CPACK_PACKAGE_RELEASE 1) set(CPACK_PACKAGE_CONTACT "Eduardo Silva ") set(CPACK_PACKAGE_VENDOR "Calyptia") set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGING_INSTALL_PREFIX "/") set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}") if(CMT_SYSTEM_WINDOWS) set(CPACK_GENERATOR "ZIP") if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-win64") else() set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-win32") endif() endif() # Enable components set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_RPM_COMPONENT_INSTALL ON) set(CPACK_productbuild_COMPONENT_INSTALL ON) set(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} binary library headers) set(CPACK_COMPONENTS_GROUPING "ONE_PER_GROUP") set(CPACK_COMPONENT_BINARY_GROUP "RUNTIME") set(CPACK_COMPONENT_LIBRARY_GROUP "RUNTIME") # Debian package setup and name sanitizer set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems") if(DPKG_PROGRAM) execute_process( COMMAND ${DPKG_PROGRAM} --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE ) set(CPACK_DEBIAN_HEADERS_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}-headers.deb") set(CPACK_DEBIAN_RUNTIME_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") set(CPACK_DEBIAN_RUNTIME_FILE_NAME "${CPACK_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb") set(CPACK_DEBIAN_RUNTIME_PACKAGE_CONTROL_EXTRA ${CMAKE_CURRENT_SOURCE_DIR}/debian/conffiles ) endif() # RPM Generation information set(CPACK_RPM_PACKAGE_GROUP "System Environment/Daemons") set(CPACK_RPM_PACKAGE_LICENSE "Apache v2.0") set(CPACK_RPM_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE}) set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/cpack/description") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A standalone library to create and manipulate metrics in C") set(CPACK_RPM_SPEC_MORE_DEFINE "%define ignore \#") set(CPACK_RPM_USER_FILELIST "%ignore /lib" "%ignore /lib64" "%ignore /lib64/pkgconfig" "%ignore /usr/local" "%ignore /usr/local/bin") set(CPACK_RPM_PACKAGE_AUTOREQ ON) set(CPACK_RPM_RUNTIME_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") set(CPACK_RPM_HEADERS_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}-headers.rpm") set(CPACK_RPM_RUNTIME_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_RELEASE}.${CMAKE_SYSTEM_PROCESSOR}.rpm") # CPack: DEB set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) # CPack: Windows System if(CPACK_GENERATOR MATCHES "ZIP") set(CPACK_MONOLITHIC_INSTALL 1) set(CPACK_PACKAGE_INSTALL_DIRECTORY "cmetrics") endif() # CPack: macOS w/ productbuild if(CMT_SYSTEM_MACOS) # Determine the platform suffix execute_process( COMMAND uname -m RESULT_VARIABLE UNAME_M_RESULT OUTPUT_VARIABLE UNAME_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE ) if (UNAME_M_RESULT EQUAL 0 AND UNAME_ARCH STREQUAL "arm64") set(CMETRICS_PKG ${CMAKE_CURRENT_BINARY_DIR}/${CPACK_PACKAGE_NAME}-${CMT_VERSION_STR}-apple) elseif(UNAME_M_RESULT EQUAL 0 AND UNAME_ARCH STREQUAL "x86_64") set(CMETRICS_PKG ${CMAKE_CURRENT_BINARY_DIR}/${CPACK_PACKAGE_NAME}-${CMT_VERSION_STR}-intel) else() set(CMETRICS_PKG ${CMAKE_CURRENT_BINARY_DIR}/${CPACK_PACKAGE_NAME}-${CMT_VERSION_STR}-${UNAME_ARCH}) endif() if (CPACK_GENERATOR MATCHES "productbuild") set(CPACK_SET_DESTDIR "ON") configure_file(cpack/macos/welcome.txt.cmakein ${CMAKE_CURRENT_SOURCE_DIR}/welcome.txt) configure_file(LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt) find_program(CONVERTER textutil) if (NOT CONVERTER) message(FATAL_ERROR "textutil not found.") endif() if (CONVERTER) execute_process(COMMAND ${CONVERTER} -convert html "${CMAKE_CURRENT_SOURCE_DIR}/README.md" -output "${CMAKE_CURRENT_SOURCE_DIR}/README.html") endif() set(CPACK_PACKAGE_FILE_NAME "${CMETRICS_PKG}") set(CPACK_RESOURCE_FILE_WELCOME ${CMAKE_CURRENT_SOURCE_DIR}/welcome.txt) set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt) set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.html) set(CPACK_PRODUCTBUILD_IDENTIFIER "com.calyptia.${CPACK_PACKAGE_NAME}") endif() endif() # Create tarball add_custom_target(tarball COMMAND "bash" "${CMAKE_CURRENT_SOURCE_DIR}/create-submoduled-tarball.sh" "cmetrics-${CMT_VERSION_STR}") include(CPack)