Skip to content
CMakeLists.txt 12.5 KiB
Newer Older
Luker's avatar
Luker committed
#
Luker's avatar
Luker committed
# Copyright (c) 2015-2016, Luca Fulchir<luca@fulchir.it>, All rights reserved.
Luker's avatar
Luker committed
#
# This file is part of "libRaptorQ".
#
# libRaptorQ 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 3
# of the License, or (at your option) any later version.
#
# libRaptorQ 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# and a copy of the GNU Lesser General Public License
# along with libRaptorQ.  If not, see <http://www.gnu.org/licenses/>.

Luker's avatar
Luker committed
cmake_minimum_required (VERSION 2.8.12)
Luker's avatar
Luker committed
project (libRaptorQ)
enable_language(CXX)
enable_language(C)

Luker's avatar
Luker committed
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake; ${CMAKE_MODULE_PATH})
set(RQ_VERSION 0.2-prealpha)
message(STATUS "libRaptorQ version ${RQ_VERSION}")
Luker's avatar
Luker committed

# default values
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release")
endif()


include(GNUInstallDirs)

option(DYNAMIC_LIB "Build dynamic library" ON)
option(STATIC_LIB "Build static library" ON)
option(CLANG_STDLIB "Use clang's libc++" OFF)

Luker's avatar
Luker committed
# defaults: only enable LTO/PROFILING with known compielrs
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
   option(LTO "Link Time Optimization" ON)
   option(PROFILING "Profiling: speedup library" ON)
else()
   option(LTO "Link Time Optimization" OFF)
   option(PROFILING "Profiling: speedup library" OFF)
endif()
Luker's avatar
Luker committed

message(STATUS "Build selected: ${CMAKE_BUILD_TYPE}")

if(NOT (STATIC_LIB MATCHES "ON"))
    if (NOT (DYNAMIC_LIB MATCHES "ON"))
        message(FATAL_ERROR "Do you want to actually build the library?")
    endif()
endif()

Luker's avatar
Luker committed

Luker's avatar
Luker committed
# with LTO each compiler needs its own AR/NM/RANLIB?
if(LTO MATCHES "ON")
    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
        if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
            find_program(RQ_AR "llvm-ar")
            find_program(RQ_NM "llvm-nm")
            find_program(RQ_RANLIB "llvm-ranlib")
        elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
            find_program(RQ_AR "gcc-ar")
            find_program(RQ_NM "gcc-nm")
            find_program(RQ_RANLIB "gcc-ranlib")
        endif()
        set(CMAKE_AR ${RQ_AR})
        set(CMAKE_NM ${RQ_NM})
        set(CMAKE_RANLIB ${RQ_RANLIB})
        mark_as_advanced(FORCE RQ_AR RQ_NM RQ_RANLIB)
	    message(STATUS "Link Time Optimization activated")
    else()
        message(FATAL_ERROR "Sorry, don't know how to do LTO with your compiler")
    endif()
else()
	message(STATUS "Link Time Optimization deactivated")
endif()

# Profiling is pretty compiler-specific....
if(PROFILING MATCHES "ON")
    if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
        message(STATUS "Profiling activated")
        if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
            message(WARNING "Clang's profile support breaks deterministic builds!")
        endif()
    else()
        message(FATAL_ERROR "Sorry, don't know how to profile with your compiler")
    endif()
else()
    message(STATUS "Profiling deactivated")
endif()

if(CLANG_STDLIB MATCHES "ON")
Luker's avatar
Luker committed
	if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
Luker's avatar
Luker committed
		message(FATAL_ERROR "libc++ is only supported by clang")
Luker's avatar
Luker committed
	endif()
endif()
Luker's avatar
Luker committed
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
	set(STDLIB stdc++)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
	if(CLANG_STDLIB MATCHES "ON")
		set(RQ_STDLIB_FLAG -stdlib=libc++)
		set(STDLIB c++)
	else()
		set(STDLIB stdc++)
	endif()
Luker's avatar
Luker committed
endif()

find_package(Threads REQUIRED)
find_package(git)
find_package(eigen REQUIRED)
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
Luker's avatar
Luker committed
find_package(RQ_LZ4 REQUIRED)
include_directories(SYSTEM ${RQ_LZ4_INCLUDE_DIR})
#lz4 build if necessary
Luker's avatar
Luker committed
include(${CMAKE_CURRENT_SOURCE_DIR}/external/build_deps.cmake)
Luker's avatar
Luker committed

Luker's avatar
Luker committed
# LATEX documentation
Luker's avatar
Luker committed
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/doc)
Luker's avatar
Luker committed


if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.git/ AND GIT_FOUND)
    execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --sq HEAD OUTPUT_VARIABLE RQ_SEED)
Luker's avatar
Luker committed
else()
    set(RQ_SEED RaptorQ_nongit_v${RQ_VERSION})
Luker's avatar
Luker committed
    message(WARNING "Not inside a git repository. Compiler seed is now constant.")
endif()
set(DETERMINISTIC -frandom-seed=${RQ_SEED})

if(CMAKE_SYSTEM_NAME MATCHES "Windows")
    add_definitions(-DRQ_WINDOWS)
else()
    add_definitions(-DRQ_UNIX)
    # used by ftok to get a key. Track both the file and the version
    add_definitions(-DRQ_SHMPATH="${CMAKE_INSTALL_PREFIX}/lib/libRaptorQ.so-${RQ_VERSION}")
endif()
Luker's avatar
Luker committed


Luker's avatar
Luker committed
SET(SOURCES src/Operation.cpp
		src/Thread_Pool.cpp
Luker's avatar
Luker committed
		src/Bitmask.cpp
Luker's avatar
Luker committed
		src/Rand.cpp
		src/Parameters.cpp
		src/Graph.cpp
		src/Shared_Computation/Decaying_LF.cpp
Luker's avatar
Luker committed
		src/Precode_Matrix_Instantiation.cpp
Luker's avatar
Luker committed
		src/RaptorQ.cpp
Luker's avatar
Luker committed
		src/cRaptorQ.cpp)
Luker's avatar
Luker committed

SET(HEADERS	src/Interleaver.hpp
		src/Thread_Pool.hpp
Luker's avatar
Luker committed
		src/multiplication.hpp
		src/table2.hpp
		src/degree.hpp
		src/common.hpp
		src/Encoder.hpp
		src/Decoder.hpp
		src/Rand.hpp
Luker's avatar
Luker committed
		src/Operation.hpp
Luker's avatar
Luker committed
		src/Precode_Matrix.hpp
Luker's avatar
Luker committed
		src/Precode_Matrix_Init.hpp
		src/Precode_Matrix_Solver.hpp
Luker's avatar
Luker committed
		src/Parameters.hpp
		src/Graph.hpp
		src/De_Interleaver.hpp
		src/RaptorQ.hpp
		src/Shared_Computation/Decaying_LF.hpp
Luker's avatar
Luker committed
		src/Shared_Computation/LZ4_Wrapper.hpp
Luker's avatar
Luker committed
		src/cRaptorQ.h)
Luker's avatar
Luker committed


Luker's avatar
Luker committed
include(cmake/compiler_flags.cmake)
Luker's avatar
Luker committed

Luker's avatar
Luker committed
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_definitions(-DUSING_CLANG)
    set(LD_OPT "-flto -fuse-ld=gold")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
    set(LD_OPT "")
endif()


########################################
## TODO: if windows, add notelemetry.obj
########################################
Luker's avatar
Luker committed


if(PROFILING MATCHES "ON")
    if (CMAKE_C_COMPILER_ID MATCHES "Clang")
        set(PROFILE_GET           "-fprofile-instr-generate -g")
        set(PROFILE_GET_FILE      RaptorQ.profraw)
        set(PROFILE_SET_FILE      RaptorQ.profdata)
        set(PROFILE_SET           "-fprofile-instr-use=${PROFILE_SET_FILE}")
    elseif(CMAKE_C_COMPILER_ID MATCHES "GNU")
        set(PROFILE_GET           -fprofile-generate)
        # gcc creates a couple more files than clang for prifiling. Track them.
        set(PROFILE_GET_FILE
CMakeFiles/RaptorQ_Static_Profiling.dir/src/Graph.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/Parameters.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/Rand.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/Precode_Matrix.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/Precode_Matrix_solver.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/cRaptorQ.cpp.gcda
CMakeFiles/test_c_profiled.dir/test/test_c.c.gcda)
        set(PROFILE_SET_FILE      ${PROFILE_GET_FILE})
        set(PROFILE_SET           -fprofile-use)
    endif()

    # PRE-run: build a library, generate the profile.
    add_library(RaptorQ_Static_Profiling STATIC ${SOURCES} ${HEADERS})
Luker's avatar
Luker committed
    target_link_libraries(RaptorQ_Static_Profiling ${STDLIB} ${RQ_LZ4_DEP} ${RQ_UBSAN})
Luker's avatar
Luker committed
	add_dependencies(RaptorQ_Static_Profiling LZ4)
Luker's avatar
Luker committed
    set(CMAKE_CXX_FLAGS )
    target_compile_options(
        RaptorQ_Static_Profiling PRIVATE
        ${CXX_COMPILER_FLAGS}
    )
    set_target_properties(RaptorQ_Static_Profiling PROPERTIES COMPILER_FLAGS ${PROFILE_GET})

    # build the C example test for profiling
    add_executable(test_c_profiled test/test_c.c)
    add_dependencies(test_c_profiled RaptorQ_Static_Profiling)
    set(CMAKE_C_FLAGS )
    set(CMAKE_CXX_FLAGS )
    target_compile_options(
        test_c_profiled PRIVATE
        ${C_COMPILER_FLAGS}
    )
    target_link_libraries(test_c_profiled RaptorQ_Static_Profiling ${STDLIB} m ${CMAKE_THREAD_LIBS_INIT})
    set_target_properties(test_c_profiled PROPERTIES LINK_FLAGS ${PROFILE_GET})

    if(CMAKE_C_COMPILER_ID MATCHES "Clang")
        add_custom_command(
            OUTPUT ${PROFILE_GET_FILE}
            COMMAND LLVM_PROFILE_FILE=${PROFILE_GET_FILE} ./test_c_profiled
            DEPENDS test_c_profiled
            COMMENT "Running profiling test..."
            VERBATIM
        )
    elseif(CMAKE_C_COMPILER_ID MATCHES "GNU")
        add_custom_command(
            OUTPUT ${PROFILE_GET_FILE}
            COMMAND ./test_c_profiled
            DEPENDS test_c_profiled
            COMMENT "Running profiling test..."
            VERBATIM
        )
    endif()
    if(CMAKE_C_COMPILER_ID MATCHES "Clang")
        # the profile must be translated into readable form
        add_custom_command(
            OUTPUT ${PROFILE_SET_FILE}
            COMMAND llvm-profdata merge -output=${PROFILE_SET_FILE} ${PROFILE_GET_FILE}
            DEPENDS ${PROFILE_GET_FILE}
            COMMENT "Creating profile data..."
            VERBATIM
        )
    endif()
    add_custom_target(
        profile ALL
        DEPENDS ${PROFILE_SET_FILE}
    )
endif()



# build the static library
if(STATIC_LIB MATCHES "ON")
    add_library(RaptorQ_Static STATIC ${SOURCES} ${HEADERS})
Luker's avatar
Luker committed
	add_dependencies(RaptorQ_Static LZ4)
Luker's avatar
Luker committed
    if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
        set_target_properties(RaptorQ_Static PROPERTIES OUTPUT_NAME RaptorQ-${RQ_VERSION})
Luker's avatar
Luker committed
    endif()
    target_compile_options(
        RaptorQ_Static PRIVATE
        ${CXX_COMPILER_FLAGS}
    )
    if(LTO MATCHES "ON")
        target_compile_options(RaptorQ_Static PRIVATE -flto -fuse-ld=gold)
    endif()
    if(PROFILING MATCHES "ON")
        add_dependencies(RaptorQ_Static profile)
        target_compile_options(RaptorQ_Static PRIVATE ${PROFILE_SET})
    endif()
    set_target_properties (
        RaptorQ_Static
        PROPERTIES
        LINK_FLAGS "-Wl,-z,now,-z,relro -pie ${LD_OPT}"
    )
Luker's avatar
Luker committed
    set_property(TARGET RaptorQ_Static PROPERTY ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
Luker's avatar
Luker committed

	# make the library deterministic (only on *nix)
    add_executable(make_deterministic src/deterministic.cpp)
    target_compile_options(
        make_deterministic PRIVATE
        ${CXX_COMPILER_FLAGS}
    )
Luker's avatar
Luker committed
	target_link_libraries(make_deterministic ${STDLIB} ${RQ_UBSAN})
Luker's avatar
Luker committed
    add_custom_command(
        OUTPUT deterministic.run
Luker's avatar
Luker committed
        COMMAND make_deterministic ${CMAKE_CURRENT_BINARY_DIR}/lib/libRaptorQ-${RQ_VERSION}.a
Luker's avatar
Luker committed
        DEPENDS RaptorQ_Static
        COMMENT "Removing creation date from library..."
        VERBATIM
    )

Luker's avatar
Luker committed
	add_custom_target(
	    Make_static_deterministic ALL
	    DEPENDS deterministic.run
	)
Luker's avatar
Luker committed
endif()

#build dynamic library
if(DYNAMIC_LIB MATCHES "ON")
    add_definitions(-DRAPTORQ_DLL)
    add_definitions(-DRAPTORQ_DLL_EXPORTS)

    add_library(RaptorQ SHARED ${SOURCES} ${HEADERS})
Luker's avatar
Luker committed
	add_dependencies(RaptorQ LZ4)
Luker's avatar
Luker committed
    target_compile_options(
        RaptorQ PRIVATE
        ${CXX_COMPILER_FLAGS}
    )
    if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
        set_target_properties(RaptorQ PROPERTIES OUTPUT_NAME RaptorQ-${RQ_VERSION})
    endif()
Luker's avatar
Luker committed
    if(LTO MATCHES "ON")
        target_compile_options(RaptorQ PRIVATE -flto -fuse-ld=gold)
    endif()
    if(PROFILING MATCHES "ON")
        add_dependencies(RaptorQ profile)
        target_compile_options(RaptorQ PRIVATE ${PROFILE_SET})
    endif()
    set_target_properties (
        RaptorQ
        PROPERTIES
        LINK_FLAGS "-Wl,-z,now,-z,relro ${LD_OPT}"
    )
set_target_properties (
	RaptorQ
	PROPERTIES
		SO_VERSION libRaptorQ.1
		VERSION ${RQ_VERSION}
	)
Luker's avatar
Luker committed
    set_property(TARGET RaptorQ PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
Luker's avatar
Luker committed
endif()
Luker's avatar
Luker committed

# add main tests
Luker's avatar
Luker committed
add_executable(libRaptorQ-test EXCLUDE_FROM_ALL test/rfc_test.cpp)
    target_compile_options(
        libRaptorQ-test PRIVATE
        ${CXX_COMPILER_FLAGS}
    )
add_dependencies(libRaptorQ-test RaptorQ)
Luker's avatar
Luker committed
target_link_libraries(libRaptorQ-test ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
Luker's avatar
Luker committed
add_custom_target(tests DEPENDS libRaptorQ-test)

# build examples
# C interface
Luker's avatar
Luker committed
add_executable(test_c EXCLUDE_FROM_ALL test/test_c.c)
    target_compile_options(
        test_c PRIVATE
        ${C_COMPILER_FLAGS}
Luker's avatar
Luker committed
		-Wno-disabled-macro-expansion
Luker's avatar
Luker committed
    )
add_dependencies(test_c RaptorQ)
Luker's avatar
Luker committed
target_link_libraries(test_c RaptorQ m ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
Luker's avatar
Luker committed

# CPP interface
Luker's avatar
Luker committed
add_executable(test_cpp EXCLUDE_FROM_ALL test/test_cpp.cpp)
    target_compile_options(
        test_cpp PRIVATE
Luker's avatar
Luker committed
		${CXX_COMPILER_FLAGS}
Luker's avatar
Luker committed
    )
add_dependencies(test_cpp RaptorQ)
Luker's avatar
Luker committed
target_link_libraries(test_cpp ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
Luker's avatar
Luker committed
add_custom_target(examples DEPENDS test_c test_cpp)

add_custom_target(everything DEPENDS Make_static_deterministic tests examples docs)
Luker's avatar
Luker committed
install(FILES ${HEADERS} DESTINATION include/RaptorQ/)
install(TARGETS RaptorQ RaptorQ_Static
     LIBRARY DESTINATION lib COMPONENT libraries
     ARCHIVE DESTINATION lib COMPONENT libraries)
Luker's avatar
Luker committed