blob: eef942b589e950456a9e486adc6df79e21d5700e [file] [log] [blame]
# Copyright (C) 2015 Adam Schubert <adam.schubert@sg1-game.net>
# Copyright 2016 Martin Pool
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
project(librsync C)
cmake_minimum_required(VERSION 3.6)
INCLUDE(CMakeDependentOption)
include(GNUInstallDirs)
set(LIBRSYNC_MAJOR_VERSION 2)
set(LIBRSYNC_MINOR_VERSION 3)
set(LIBRSYNC_PATCH_VERSION 2)
set(LIBRSYNC_VERSION
${LIBRSYNC_MAJOR_VERSION}.${LIBRSYNC_MINOR_VERSION}.${LIBRSYNC_PATCH_VERSION})
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
if (NOT CMAKE_SYSTEM_PROCESSOR)
message(FATAL_ERROR "No target CPU architecture set")
endif()
if (NOT CMAKE_SYSTEM_NAME)
message(FATAL_ERROR "No target OS set")
endif()
option(BUILD_SHARED_LIBS "Build librsync as a shared library." ON)
set(DO_RS_TRACE 0)
option(ENABLE_TRACE "Compile in detailed trace messages" OFF)
if (ENABLE_TRACE)
set(DO_RS_TRACE 1)
endif (ENABLE_TRACE)
message(STATUS "DO_RS_TRACE=${DO_RS_TRACE}")
# Add an option to include compression support
option(ENABLE_COMPRESSION "Whether or not to build with compression support" OFF)
# TODO: Remove this warning when compression is implemented.
# Consider turning compression ON by default.
if (ENABLE_COMPRESSION)
message(WARNING "Compression support is not functional. See issue #8.")
endif (ENABLE_COMPRESSION)
include ( CheckIncludeFiles )
check_include_files ( sys/file.h HAVE_SYS_FILE_H )
check_include_files ( sys/stat.h HAVE_SYS_STAT_H )
check_include_files ( sys/types.h HAVE_SYS_TYPES_H )
check_include_files ( unistd.h HAVE_UNISTD_H )
check_include_files ( io.h HAVE_IO_H )
check_include_files ( fcntl.h HAVE_FCNTL_H )
check_include_files ( mcheck.h HAVE_MCHECK_H )
check_include_files ( zlib.h HAVE_ZLIB_H )
check_include_files ( bzlib.h HAVE_BZLIB_H )
# Remove compression support if not needed
if (NOT ENABLE_COMPRESSION)
SET(HAVE_BZLIB_H 0)
SET(HAVE_ZLIB_H 0)
endif (NOT ENABLE_COMPRESSION)
include ( CheckSymbolExists )
check_symbol_exists ( __func__ "" HAVE___FUNC__ )
check_symbol_exists ( __FUNCTION__ "" HAVE___FUNCTION__ )
include ( CheckFunctionExists )
check_function_exists ( fseeko HAVE_FSEEKO )
check_function_exists ( fseeko64 HAVE_FSEEKO64 )
check_function_exists ( _fseeki64 HAVE__FSEEKI64 )
check_function_exists ( fstat64 HAVE_FSTAT64 )
check_function_exists ( _fstati64 HAVE__FSTATI64 )
check_function_exists ( fileno HAVE_FILENO )
check_function_exists ( _fileno HAVE__FILENO )
include(CheckTypeSize)
check_type_size ( "long" SIZEOF_LONG )
check_type_size ( "long long" SIZEOF_LONG_LONG )
check_type_size ( "off_t" SIZEOF_OFF_T )
check_type_size ( "off64_t" SIZEOF_OFF64_T )
check_type_size ( "size_t" SIZEOF_SIZE_T )
check_type_size ( "unsigned int" SIZEOF_UNSIGNED_INT )
check_type_size ( "unsigned long" SIZEOF_UNSIGNED_LONG )
check_type_size ( "unsigned short" SIZEOF_UNSIGNED_SHORT )
# Check for printf "%zu" size_t formatting support.
if(WIN32)
# CheckCSourceRuns checking for "%zu" succeeds but still gives warnings on win32.
set(HAVE_PRINTF_Z OFF)
# Not using unsupported %zu generates warnings about using %I64 with MinGW.
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format")
message (STATUS "Compiling to Win32 - printf \"%zu\" size_t formatting support disabled")
elseif(CMAKE_CROSSCOMPILING)
# CheckCSourceRuns doesn't work when cross-compiling; assume C99 compliant support.
set(HAVE_PRINTF_Z ON)
message (STATUS "Cross compiling - assuming printf \"%zu\" size_t formatting support")
else()
include(CheckCSourceRuns)
check_c_source_runs("#include <stdio.h>\nint main(){char o[8];sprintf(o, \"%zu\", (size_t)7);return o[0] != '7';}" HAVE_PRINTF_Z)
endif()
include (TestBigEndian)
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
if (WORDS_BIGENDIAN)
message(STATUS "System is big-endian.")
else (WORDS_BIGENDIAN)
message(STATUS "System is little-endian.")
endif (WORDS_BIGENDIAN)
# OS X
if(APPLE)
set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
endif()
endif()
if (CMAKE_C_COMPILER_ID MATCHES "(Clang|Gnu|GNU)")
# TODO: Set -Werror when the build is clean.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -std=c99 -pedantic")
if (CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-sign-conversion")
endif()
elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D_CRT_SECURE_NO_WARNINGS")
endif()
site_name(BUILD_HOSTNAME)
message (STATUS "PROJECT_NAME = ${PROJECT_NAME}")
message (STATUS "BUILD_HOSTNAME = ${BUILD_HOSTNAME}")
message (STATUS "CMAKE_SYSTEM = ${CMAKE_SYSTEM}")
# Find POPT
find_package(POPT)
if (POPT_FOUND)
message (STATUS "POPT_INCLUDE_DIRS = ${POPT_INCLUDE_DIRS}")
message (STATUS "POPT_LIBRARIES = ${POPT_LIBRARIES}")
include_directories(${POPT_INCLUDE_DIRS})
endif (POPT_FOUND)
# Add an option to exclude rdiff executable from build
# This is useful, because it allows to remove POPT dependency if a user is interested only in the
# rsync library itself and not in the rdiff executable
cmake_dependent_option(BUILD_RDIFF "Whether or not to build rdiff executable" ON "POPT_FOUND" OFF)
# Find BZIP
find_package (BZip2)
if (BZIP2_FOUND)
message (STATUS "BZIP2_INCLUDE_DIRS = ${BZIP2_INCLUDE_DIRS}")
message (STATUS "BZIP2_LIBRARIES = ${BZIP2_LIBRARIES}")
include_directories(${BZIP2_INCLUDE_DIRS})
endif (BZIP2_FOUND)
# Find ZLIB
find_package (ZLIB)
if (ZLIB_FOUND)
message (STATUS "ZLIB_INCLUDE_DIRS = ${ZLIB_INCLUDE_DIRS}")
message (STATUS "ZLIB_LIBRARIES = ${ZLIB_LIBRARIES}")
include_directories(${ZLIB_INCLUDE_DIRS})
endif (ZLIB_FOUND)
# Find libb2
find_package(libb2)
if (LIBB2_FOUND)
message (STATUS "LIBB2_INCLUDE_DIRS = ${LIBB2_INCLUDE_DIRS}")
message (STATUS "LIBB2_LIBRARIES = ${LIBB2_LIBRARIES}")
endif (LIBB2_FOUND)
# Add an option to use LIBB2 if found. It defaults to off because the
# reference implementation is currently faster.
cmake_dependent_option(USE_LIBB2 "Use the libb2 blake2 implementation." OFF "LIBB2_FOUND" OFF)
if (USE_LIBB2)
message (STATUS "Using libb2 blake2 implementation.")
include_directories(${LIBB2_INCLUDE_DIRS})
set(blake2_LIBS ${LIBB2_LIBRARIES})
else (USE_LIBB2)
message (STATUS "Using included blake2 implementation.")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/blake2)
set(blake2_SRCS src/blake2/blake2b-ref.c)
endif (USE_LIBB2)
# Doxygen doc generator.
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/doc/Doxyfile @ONLY)
add_custom_target(doc
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doc/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
endif(DOXYGEN_FOUND)
# Code tidy target to reformat code with indent.
file(GLOB tidy_SRCS src/*.[ch] tests/*.[ch])
set(TYPE_RE "(\\w+_t)")
set(CAST_RE "(\\(${TYPE_RE}( \\*+)?\\))")
add_custom_target(tidy
COMMENT "Reformatting all code to preferred coding style."
# Note indent requires all userdefined types to be specified with '-T <type>' args to
# format them correctly. Rather than do that, we just postprocess with sed.
#
# Hide the enclosing 'extern "C" {...}' block for indenting in librsync.h
COMMAND sed -r -i "s:^(extern \"C\") \\{:\\1;:; s:^\\}(\\s+/\\* extern \"C\" \\*/):;\\1:" src/librsync.h
# Linux format with no tabs, indent 4, preproc indent 2, 80 columns, swallow blank lines.
COMMAND indent -linux -nut -i4 -ppi2 -l80 -lc80 -fc1 -sob -T FILE -T Rollsum -T rs_result ${tidy_SRCS}
# Remove space between * or & and identifier after userdefined types,
# remove space after type cast for userdefined types like indent -ncs,
# and remove trailing whitespace.
COMMAND sed -r -i "s:((${TYPE_RE}|${CAST_RE}) (&|\\*+)) :\\1:g; s:(${CAST_RE}) :\\1:g; s:\\s+$::" ${tidy_SRCS}
# Restore the enclosing 'extern "C" {...}' block in librsync.h
COMMAND sed -r -i "s:^(extern \"C\");:\\1 {:; s:^;(\\s+/\\* extern \"C\" \\*/):}\\1:" src/librsync.h
VERBATIM
)
# Code tidyc target to reformat all code and comments with https://github.com/dbaarda/tidyc.
add_custom_target(tidyc
COMMENT "Reformatting all code and comments to preferred coding style."
# Recomended format, reformat linebreaks, reformat comments, 80 columns.
COMMAND tidyc -R -C -l80 -T FILE -T Rollsum -T rs_result ${tidy_SRCS}
VERBATIM
)
# Testing
add_executable(isprefix_test
tests/isprefix_test.c src/isprefix.c)
add_test(NAME isprefix_test COMMAND isprefix_test)
add_executable(netint_test
tests/netint_test.c src/netint.c src/util.c src/trace.c src/tube.c
src/scoop.c)
target_compile_options(netint_test PRIVATE -DLIBRSYNC_STATIC_DEFINE)
add_test(NAME netint_test COMMAND netint_test)
add_executable(rollsum_test
tests/rollsum_test.c src/rollsum.c)
add_test(NAME rollsum_test COMMAND rollsum_test)
add_executable(rabinkarp_test
tests/rabinkarp_test.c src/rabinkarp.c)
add_test(NAME rabinkarp_test COMMAND rabinkarp_test)
add_executable(rabinkarp_perf
tests/rabinkarp_perf.c src/rabinkarp.c)
add_executable(hashtable_test
tests/hashtable_test.c src/hashtable.c)
add_test(NAME hashtable_test COMMAND hashtable_test)
add_executable(checksum_test
tests/checksum_test.c src/checksum.c src/rollsum.c src/rabinkarp.c src/mdfour.c ${blake2_SRCS})
target_compile_options(checksum_test PRIVATE -DLIBRSYNC_STATIC_DEFINE)
target_link_libraries(checksum_test ${blake2_LIBS})
add_test(NAME checksum_test COMMAND checksum_test)
add_executable(sumset_test
tests/sumset_test.c src/sumset.c src/util.c src/trace.c src/hex.c
src/checksum.c src/rollsum.c src/rabinkarp.c src/mdfour.c src/hashtable.c ${blake2_SRCS})
target_compile_options(sumset_test PRIVATE -DLIBRSYNC_STATIC_DEFINE)
target_link_libraries(sumset_test ${blake2_LIBS})
add_test(NAME sumset_test COMMAND sumset_test)
# Disable rdiff specific tests
if (BUILD_RDIFF)
add_test(NAME rdiff_bad_option
COMMAND rdiff_bad_option.sh ${CMAKE_CURRENT_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(NAME Help COMMAND help.test ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(NAME Mutate COMMAND mutate.test ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(NAME Signature COMMAND signature.test ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(NAME Sources COMMAND sources.test ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(NAME Triple COMMAND triple.test ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(NAME Delta COMMAND delta.test ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(NAME Changes COMMAND changes.test ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)
endif (BUILD_RDIFF)
# `make check` that will build everything and then run the tests.
# See https://cmake.org/Wiki/CMakeEmulateMakeCheck and
# https://github.com/librsync/librsync/issues/49
if (BUILD_RDIFF)
set(LAST_TARGET rdiff)
else (BUILD_RDIFF)
set(LAST_TARGET rsync)
endif (BUILD_RDIFF)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C Debug)
add_dependencies(check ${LAST_TARGET}
isprefix_test
netint_test
rollsum_test
rabinkarp_test
hashtable_test
checksum_test
sumset_test)
enable_testing()
# Create conf files
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/src/config.h)
# We need to be able to #include "file" from a few places,
# * The original source dir
# * The generated source dir
include_directories(${CMAKE_CURRENT_BINARY_DIR}/src)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
########### next target ###############
# Only list the .c files that need to be compiled
# (Don't list .h files)
set(rsync_LIB_SRCS
src/prototab.c
src/base64.c
src/buf.c
src/checksum.c
src/command.c
src/delta.c
src/emit.c
src/fileutil.c
src/hashtable.c
src/hex.c
src/job.c
src/mdfour.c
src/mksum.c
src/msg.c
src/netint.c
src/patch.c
src/readsums.c
src/rollsum.c
src/rabinkarp.c
src/scoop.c
src/stats.c
src/sumset.c
src/trace.c
src/tube.c
src/util.c
src/version.c
src/whole.c
${blake2_SRCS})
add_library(rsync ${rsync_LIB_SRCS})
# TODO: Enable this when GenerateExportHeader works more widely.
# include(GenerateExportHeader)
# generate_export_header(rsync BASE_NAME librsync
# EXPORT_FILE_NAME ${CMAKE_SOURCE_DIR}/src/librsync_export.h)
target_link_libraries(rsync ${blake2_LIBS})
# Optionally link zlib and bzip2 if
# - compression is enabled
# - and libraries are found
if (ENABLE_COMPRESSION)
if (ZLIB_FOUND AND BZIP2_FOUND)
target_link_libraries(rsync ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES})
else (ZLIB_FOUND AND BZIP2_FOUND)
message (WARNING "zlib and bzip2 librares are required to enable compression")
endif (ZLIB_FOUND AND BZIP2_FOUND)
endif (ENABLE_COMPRESSION)
# Set properties/options for shared vs static library.
if (BUILD_SHARED_LIBS)
set_target_properties(rsync PROPERTIES C_VISIBILITY_PRESET hidden)
else (BUILD_SHARED_LIBS)
target_compile_options(rsync PUBLIC -DLIBRSYNC_STATIC_DEFINE)
endif (BUILD_SHARED_LIBS)
set_target_properties(rsync PROPERTIES
VERSION ${LIBRSYNC_VERSION}
SOVERSION ${LIBRSYNC_MAJOR_VERSION})
install(TARGETS rsync ${INSTALL_TARGETS_DEFAULT_ARGS}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
########### next target ###############
if (BUILD_RDIFF)
set(rdiff_SRCS
src/rdiff.c
src/isprefix.c)
add_executable(rdiff ${rdiff_SRCS})
if (POPT_FOUND)
target_link_libraries(rdiff rsync ${POPT_LIBRARIES})
else (POPT_FOUND)
message (WARNING "Popt library is required for rdiff target")
endif (POPT_FOUND)
install(TARGETS rdiff ${INSTALL_TARGETS_DEFAULT_ARGS}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
endif (BUILD_RDIFF)
########### install files ###############
install(FILES
src/librsync.h
src/librsync_export.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
message (STATUS "CMAKE_C_FLAGS = ${CMAKE_C_FLAGS}")
install(FILES
doc/librsync.3
DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
install(FILES
doc/rdiff.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
# vim: shiftwidth=4 expandtab