project(libfort) # Required cmake version cmake_minimum_required(VERSION 2.8) include(${CMAKE_ROOT}/Modules/ExternalProject.cmake) # Built options option(FORT_CXX_BUILD "Compile with c++ compiler instead of c" OFF) option(FORT_ENABLE_ASTYLE "Enable astyle" OFF) option(FORT_ENABLE_WCHAR "Enable wchar support" ON) set(FORT_BUILD_TYPE "common" CACHE STRING "Build types(common, asan, ubsan, coveralls)") # Determine compiler (pos. values Clang, GNU, Intel, MSVC, AppleClang... # (https://cmake.org/cmake/help/v3.0/variable/CMAKE_LANG_COMPILER_ID.html) if(FORT_CXX_BUILD) set(FORT_COMPILER ${CMAKE_CXX_COMPILER_ID}) else() set(FORT_COMPILER ${CMAKE_C_COMPILER_ID}) endif() set(CMAKE_VERBOSE_MAKEFILE ON) # ------------------------------------------------------------------------------ # Add WChar support for the build # ------------------------------------------------------------------------------ if(FORT_ENABLE_WCHAR) add_definitions(-DFT_CONGIG_HAVE_WCHAR) endif() # ------------------------------------------------------------------------------ # Includes # ------------------------------------------------------------------------------ include_directories(lib) include_directories(src) include_directories(tests) # ------------------------------------------------------------------------------ # Warnings # ------------------------------------------------------------------------------ if("${FORT_COMPILER}" STREQUAL "MSVC") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W4") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W4") else() set(ADDITIONAL_WARNINGS "\ -Wall \ -Wextra \ -Werror \ -Wdouble-promotion \ -Wshadow \ -Wformat=2 \ -Wno-variadic-macros \ -Wcast-align \ -Wstrict-aliasing=2 \ -Wstrict-overflow=5 \ -Wfloat-equal \ -Wwrite-strings \ ") if("${FORT_COMPILER}" STREQUAL "GNU") set(ADDITIONAL_WARNINGS "${ADDITIONAL_WARNINGS} \ -Wtrampolines \ -Wlogical-op") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ADDITIONAL_WARNINGS} -Wpedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ADDITIONAL_WARNINGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -std=c99 ") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11") endif() # ------------------------------------------------------------------------------ # Sources and executables # ------------------------------------------------------------------------------ file(GLOB_RECURSE FortHeaders "lib/*.h" "lib/*.hpp" "tests/*.h" "tests/*.hpp" "src/*.h") add_custom_target(headers SOURCES ${FortHeaders}) set(FORT_DEV_SOURCES src/fort_impl.c src/vector.c src/string_buffer.c src/properties.c src/cell.c src/row.c src/table.c src/fort_utils.c src/wcwidth.c) set(EXAMPLE_SOURCES example/main.c) add_executable(${PROJECT_NAME}_example ${EXAMPLE_SOURCES} lib/fort.c) set(EXAMPLE_CPP_SOURCES example/main.cpp) add_executable(${PROJECT_NAME}_example_cpp ${EXAMPLE_CPP_SOURCES} lib/fort.c) set(TEST_SOURCES_DEV tests/main_test.c tests/wb_tests/test_vector.c tests/wb_tests/test_string_buffer.c tests/wb_tests/test_table_geometry.c tests/bb_tests/test_table_basic.c tests/bb_tests/test_table_border_style.c tests/bb_tests/test_table_properties.c tests/bb_tests/test_memory_errors.c tests/tests.c tests/test_utils.c) add_executable(${PROJECT_NAME}_test_dev ${FORT_DEV_SOURCES} ${TEST_SOURCES_DEV}) target_compile_definitions(${PROJECT_NAME}_test_dev PUBLIC FORT_WB_TESTING_ENABLED=1) set(TEST_SOURCES tests/main_test.c tests/bb_tests/test_table_basic.c tests/bb_tests/test_table_border_style.c tests/bb_tests/test_table_properties.c tests/bb_tests/test_memory_errors.c tests/tests.c tests/test_utils.c) add_executable(${PROJECT_NAME}_test lib/fort.c ${TEST_SOURCES}) set(TEST_SOURCES_CPP tests/main_test_cpp.cpp tests/bb_tests_cpp/test_table_basic.cpp tests/bb_tests_cpp/test_table_properties.cpp tests/tests.c tests/test_utils.cpp) add_executable(${PROJECT_NAME}_test_cpp lib/fort.c ${TEST_SOURCES_CPP}) if(FORT_CXX_BUILD) set_source_files_properties(${FORT_DEV_SOURCES} PROPERTIES LANGUAGE CXX) set_source_files_properties(${EXAMPLE_SOURCES} PROPERTIES LANGUAGE CXX) set_source_files_properties(${TEST_SOURCES} PROPERTIES LANGUAGE CXX) endif() # ------------------------------------------------------------------------------ # Set preprocessor macros for all test builds # ------------------------------------------------------------------------------ target_compile_definitions(${PROJECT_NAME}_test_dev PRIVATE FT_TEST_BUILD=1) target_compile_definitions(${PROJECT_NAME}_test_cpp PRIVATE FT_TEST_BUILD=1) target_compile_definitions(${PROJECT_NAME}_test PRIVATE FT_TEST_BUILD=1) # ------------------------------------------------------------------------------ # Sanitizers # ------------------------------------------------------------------------------ if("${FORT_COMPILER}" STREQUAL "GNU" OR "${FORT_COMPILER}" STREQUAL "Clang") # asan case if(FORT_BUILD_TYPE STREQUAL "asan") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") if("${FORT_COMPILER}" STREQUAL "GNU") target_link_libraries(${PROJECT_NAME}_example asan) target_link_libraries(${PROJECT_NAME}_test asan) target_link_libraries(${PROJECT_NAME}_example_cpp asan) endif() endif() #ubsan case if(FORT_BUILD_TYPE STREQUAL "ubsan") # -fno-sanitize-recover option is used to force faild set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") if("${FORT_COMPILER}" STREQUAL "GNU") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize-recover") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-sanitize-recover") target_link_libraries(${PROJECT_NAME}_example ubsan) target_link_libraries(${PROJECT_NAME}_example_cpp ubsan) target_link_libraries(${PROJECT_NAME}_test ubsan) elseif("${FORT_COMPILER}" STREQUAL "Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize-recover=all") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-sanitize-recover=all") endif() endif() #coveralls case if(FORT_BUILD_TYPE STREQUAL "coveralls") set(COVERAGE_FLAGS "-g -fprofile-arcs -ftest-coverage") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_FLAGS}") #target_link_libraries(${PROJECT_NAME}_example_cpp gcov) endif() endif() # Hack for some gcc versions if("${FORT_COMPILER}" STREQUAL "GNU") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") endif() # ------------------------------------------------------------------------------ # Astyle # ------------------------------------------------------------------------------ if(FORT_ENABLE_ASTYLE) list(APPEND ASTYLE_CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}" ) externalproject_add( astyle GIT_REPOSITORY https://github.com/Bareflank/astyle.git GIT_TAG v1.2 GIT_SHALLOW 1 CMAKE_ARGS ${ASTYLE_CMAKE_ARGS} PREFIX ${CMAKE_BINARY_DIR}/external/astyle/prefix TMP_DIR ${CMAKE_BINARY_DIR}/external/astyle/tmp STAMP_DIR ${CMAKE_BINARY_DIR}/external/astyle/stamp DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/astyle/download SOURCE_DIR ${CMAKE_BINARY_DIR}/external/astyle/src BINARY_DIR ${CMAKE_BINARY_DIR}/external/astyle/build ) list(APPEND ASTYLE_ARGS --style=kr --lineend=linux --suffix=none --pad-oper --unpad-paren --align-pointer=name --align-reference=name --indent-switches --keep-one-line-statements --keep-one-line-blocks --pad-header --convert-tabs --min-conditional-indent=0 --indent=spaces=4 ${CMAKE_SOURCE_DIR}/lib/*.h ${CMAKE_SOURCE_DIR}/lib/*.c ${CMAKE_SOURCE_DIR}/src/*.h ${CMAKE_SOURCE_DIR}/src/*.c ${CMAKE_SOURCE_DIR}/tests/*.c ${CMAKE_SOURCE_DIR}/tests/*.h ${CMAKE_SOURCE_DIR}/tests/*.hpp ${CMAKE_SOURCE_DIR}/tests/bb_tests/*.c ${CMAKE_SOURCE_DIR}/tests/wb_tests/*.c ${CMAKE_SOURCE_DIR}/tests/bb_tests_cpp/*.cpp ) if(NOT WIN32 STREQUAL "1") add_custom_target( format COMMAND ${CMAKE_BINARY_DIR}/bin/astyle ${ASTYLE_ARGS} COMMENT "running astyle" ) else() add_custom_target( format COMMAND ${CMAKE_BINARY_DIR}/bin/astyle.exe ${ASTYLE_ARGS} COMMENT "running astyle" ) endif() endif()