Newer
Older
# Copyright (c) 2015-2016, Luca Fulchir<luca@fulchir.it>, All rights reserved.
#
# 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/>.
project (libRaptorQ)
enable_language(CXX)
enable_language(C)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake; ${CMAKE_MODULE_PATH})
message(STATUS "libRaptorQ version ${RQ_VERSION}")
# 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)
# 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()
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()
# 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()
# check if we found the linker
if (RQ_AR STREQUAL "RQ_AR-NOTFOUND" OR RQ_NM STREQUAL "RQ_NM-NOTFOUND" OR RQ_RANLIB STREQUAL "RQ_RANLIB-NOTFOUND")
message(FATAL_ERROR "${RQ_AR} ${RQ_NM} ${RQ_RANLIB} Can't find the linker programs. Please disable LTO")
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")
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()
endif()
find_package(Threads REQUIRED)
find_package(git)
find_package(eigen REQUIRED)
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
if (USE_LZ4 MATCHES "ON")
find_package(RQ_LZ4 REQUIRED)
include_directories(SYSTEM ${RQ_LZ4_INCLUDE_DIR})
add_definitions(-DRQ_USE_LZ4)
endif()
include(${CMAKE_CURRENT_SOURCE_DIR}/external/build_deps.cmake)
if (CLI MATCHES "ON")
message(STATUS "Building CLI tools")
else()
message(STATUS "NOT Building CLI tools")
endif()
# our include tree
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.git/ AND GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --sq HEAD OUTPUT_VARIABLE RQ_SEED)
set(RQ_SEED RaptorQ_nongit_v${RQ_VERSION})
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_LIBDIR}/libRaptorQ.so-${RQ_VERSION}")
SET(SOURCES src/RaptorQ/v1/API_Wrapper_C.cpp
src/RaptorQ/v1/Bitmask.cpp
src/RaptorQ/v1/Graph.cpp
src/RaptorQ/v1/Operation.cpp
src/RaptorQ/v1/Parameters.cpp
src/RaptorQ/v1/Precode_Matrix_Instantiation.cpp
src/RaptorQ/v1/Rand.cpp
src/RaptorQ/v1/RFC.cpp
src/RaptorQ/v1/Shared_Computation/Decaying_LF.cpp
src/RaptorQ/v1/Thread_Pool.cpp)
SET(HEADERS
src/RaptorQ/v1/API_Iterators.hpp
src/RaptorQ/v1/API_Wrapper.h
src/RaptorQ/v1/API_Wrapper.hpp
src/RaptorQ/v1/API_Wrapper_Raw.hpp
src/RaptorQ/v1/common.hpp
src/RaptorQ/v1/De_Interleaver.hpp
src/RaptorQ/v1/Decoder.hpp
src/RaptorQ/v1/degree.hpp
src/RaptorQ/v1/Graph.hpp
src/RaptorQ/v1/Interleaver.hpp
src/RaptorQ/v1/multiplication.hpp
src/RaptorQ/v1/Operation.hpp
src/RaptorQ/v1/Parameters.hpp
src/RaptorQ/v1/Precode_Matrix.hpp
src/RaptorQ/v1/Precode_Matrix_Init.hpp
src/RaptorQ/v1/Precode_Matrix_Solver.hpp
src/RaptorQ/v1/Rand.hpp
src/RaptorQ/v1/RaptorQ.hpp
src/RaptorQ/v1/RaptorQ_Iterators.hpp
src/RaptorQ/v1/RFC.hpp
src/RaptorQ/v1/Shared_Computation/Decaying_LF.hpp
src/RaptorQ/v1/table2.hpp
src/RaptorQ/v1/Thread_Pool.hpp
src/RaptorQ/RFC6330_v1.hpp
src/RaptorQ/RFC6330_v1.h
src/RaptorQ/RaptorQ_v1.hpp)
if (USE_LZ4 MATCHES "ON")
SET (HEADERS ${HEADERS}
src/RaptorQ/v1/Shared_Computation/LZ4_Wrapper.hpp)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_definitions(-DUSING_CLANG)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(LD_OPT "")
endif()
########################################
## TODO: if windows, add notelemetry.obj
########################################
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(PROFILE_GET -fprofile-instr-generate)
set(PROFILE_GET_FILE RaptorQ.profraw)
set(PROFILE_SET_FILE RaptorQ.profdata)
set(PROFILE_SET "-fprofile-instr-use=${PROFILE_SET_FILE}")
set(PROFILE_GET -fprofile-generate)
# gcc creates a couple more files than clang for prifiling. Track them.
set(PROFILE_GET_FILE
CMakeFiles/test_c_profiled.dir/test/test_c.c.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Shared_Computation/Decaying_LF.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Graph.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Rand.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Operation.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/RFC.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Precode_Matrix_Instantiation.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Parameters.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Bitmask.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/Thread_Pool.cpp.gcda
CMakeFiles/RaptorQ_Static_Profiling.dir/src/RaptorQ/v1/API_Wrapper_C.cpp.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})
target_link_libraries(RaptorQ_Static_Profiling ${STDLIB} ${RQ_LZ4_DEP} ${RQ_UBSAN})
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)
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})
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
)
add_custom_command(
OUTPUT ${PROFILE_GET_FILE}
COMMAND ./test_c_profiled
DEPENDS test_c_profiled
COMMENT "Running profiling test..."
VERBATIM
)
endif()
# 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})
set_target_properties(RaptorQ_Static PROPERTIES OUTPUT_NAME RaptorQ.${RQ_ABI})
endif()
target_compile_options(
RaptorQ_Static PRIVATE
${CXX_COMPILER_FLAGS}
)
if(LTO MATCHES "ON")
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}"
)
set_property(TARGET RaptorQ_Static PROPERTY ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
# make the library deterministic (only on *nix)
add_executable(make_deterministic src/deterministic.cpp)
target_compile_options(
make_deterministic PRIVATE
${CXX_COMPILER_FLAGS}
)
COMMAND make_deterministic ${CMAKE_CURRENT_BINARY_DIR}/lib/libRaptorQ.${RQ_ABI}.a
DEPENDS RaptorQ_Static
COMMENT "Removing creation date from library..."
VERBATIM
)
endif()
#build dynamic library
if(DYNAMIC_LIB MATCHES "ON")
add_definitions(-DRAPTORQ_DLL)
add_definitions(-DRAPTORQ_DLL_EXPORTS)
add_library(RaptorQ SHARED ${SOURCES} ${HEADERS})
target_compile_options(
RaptorQ PRIVATE
${CXX_COMPILER_FLAGS}
)
if(LTO MATCHES "ON")
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_property(TARGET RaptorQ PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
add_executable(libRaptorQ-test EXCLUDE_FROM_ALL test/rfc_test.cpp)
target_compile_options(
libRaptorQ-test PRIVATE
${CXX_COMPILER_FLAGS}
)
target_link_libraries(libRaptorQ-test ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
target_compile_options(
test_c PRIVATE
${C_COMPILER_FLAGS}
-Wno-disabled-macro-expansion
)
target_link_libraries(test_c RaptorQ m ${RQ_UBSAN} ${STDLIB} ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
# CPP interface - RFC interface
add_executable(test_cpp_rfc EXCLUDE_FROM_ALL test/test_cpp_rfc.cpp)
target_compile_options(
test_cpp_rfc PRIVATE
${CXX_COMPILER_FLAGS}
)
add_dependencies(test_cpp_rfc RaptorQ)
target_link_libraries(test_cpp_rfc ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
# CPP interface - RAW interface
add_executable(test_cpp_raw EXCLUDE_FROM_ALL test/test_cpp_raw.cpp)
target_compile_options(
test_cpp_raw PRIVATE
${CXX_COMPILER_FLAGS}
)
add_dependencies(test_cpp_raw RaptorQ)
target_link_libraries(test_cpp_raw ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
add_custom_target(examples DEPENDS test_c test_cpp_rfc test_cpp_raw)
# CPP interface - RAW interface
add_executable(CLI src/cli/RaptorQ.cpp external/optionparser-1.4/optionparser.h)
target_compile_options(
CLI PRIVATE
${CXX_COMPILER_FLAGS}
)
add_dependencies(CLI RaptorQ)
set_target_properties(CLI PROPERTIES OUTPUT_NAME RaptorQ
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
target_link_libraries(CLI ${RQ_UBSAN} ${STDLIB} RaptorQ ${CMAKE_THREAD_LIBS_INIT} ${RQ_LZ4_DEP})
add_custom_target(everything DEPENDS make_static_deterministic tests examples docs CLI)
install(FILES ${HEADERS} DESTINATION include/RaptorQ/)
install(TARGETS RaptorQ RaptorQ_Static