Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for modern CMake #8

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# root key configurations (defaults).
dist: xenial

# operating systems configurations.
os:
- linux
- osx
- windows

# language configurations.
language: c

# env variable to toggle apps on and off.
env:
- CMAKE_OPTS=-DGKLIB_BUILD_APPS=ON
- CMAKE_OPTS=-DGKLIB_BUILD_APPS=OFF

# invalid configurations to be explicitly included.
jobs:
include:
- os: linux
compiler: clang
env: CMAKE_OPTS=-DGKLIB_BUILD_APPS=ON
- os: linux
compiler: clang
env: CMAKE_OPTS=-DGKLIB_BUILD_APPS=OFF

# Override default script.
script:
- cmake ${CMAKE_OPTS} . && cmake --build . && ctest --output-on-failure
224 changes: 200 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,31 +1,207 @@
cmake_minimum_required(VERSION 2.8)
project(GKlib C)
cmake_minimum_required(VERSION 3.1)

option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF)
# ...
project(GKlib
VERSION 0.0.1
LANGUAGES C)

get_filename_component(abs "." ABSOLUTE)
set(GKLIB_PATH ${abs})
unset(abs)
include(GKlibSystem.cmake)
# include required CMake modules
include(CheckCCompilerFlag)
include(CheckCSourceCompiles)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

include_directories(".")
if(MSVC)
include_directories("win32")
file(GLOB win32_sources RELATIVE "win32" "*.c")
else(MSVC)
set(win32_sources, "")
endif(MSVC)
#-------------------------------------------------------------------------------
# OPTIONS
#-------------------------------------------------------------------------------
option(ASSERT "turn asserts on" OFF)
option(ASSERT2 "additional assertions" OFF)
option(DEBUG "add debugging support" OFF)
option(GPROF "add gprof support" OFF)
option(GKRAND "enable GKRAND support" OFF)
option(GKREGEX "enable GKREGEX support" OFF)
option(OPENMP "enable OpenMP support" OFF)
option(PCRE "enable PCRE support" OFF)

add_library(GKlib ${GKlib_sources} ${win32_sources})
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
option(GKLIB_BUILD_APPS "build the GKlib applications" ON)
else()
option(GKLIB_BUILD_APPS "build the GKlib applications" OFF)
endif()

if(UNIX)
target_link_libraries(GKlib m)
endif(UNIX)
#-------------------------------------------------------------------------------
# LIBRARY configuration
#-------------------------------------------------------------------------------
add_library(${PROJECT_NAME})

include_directories("test")
add_subdirectory("test")
target_sources(${PROJECT_NAME}
PRIVATE src/b64.c src/blas.c src/cache.c src/csr.c src/error.c src/evaluate.c
src/fkvkselect.c src/fs.c src/getopt.c src/gk_util.c src/gkregex.c
src/graph.c src/htable.c src/io.c src/itemsets.c src/mcore.c
src/memory.c src/pqueue.c src/random.c src/rw.c src/seq.c src/sort.c
src/string.c src/timers.c src/tokenizer.c
# these are only included below so that they appear when using IDEs
include/GKlib/GKlib.h include/GKlib/gk_arch.h include/GKlib/gk_defs.h
include/GKlib/gk_externs.h include/GKlib/gk_getopt.h
include/GKlib/gk_macros.h include/GKlib/gk_mkblas.h
include/GKlib/gk_mkmemory.h include/GKlib/gk_mkpqueue.h
include/GKlib/gk_mkpqueue2.h include/GKlib/gk_mkrandom.h
include/GKlib/gk_mksort.h include/GKlib/gk_mkutils.h
include/GKlib/gk_proto.h include/GKlib/gk_struct.h
include/GKlib/gk_types.h include/GKlib/gkregex.h
include/GKlib/gk_ms_inttypes.h include/GKlib/gk_ms_stat.h
include/GKlib/gk_ms_stdint.h
# the following are shims for win32 systems
$<$<PLATFORM_ID:Windows>:src/win32/adapt.c
include/GKlib/win32/adapt.h>)

install(TARGETS GKlib
ARCHIVE DESTINATION lib/${LINSTALL_PATH}
LIBRARY DESTINATION lib/${LINSTALL_PATH})
install(FILES ${GKlib_includes} DESTINATION include/${HINSTALL_PATH})
target_compile_definitions(${PROJECT_NAME}
PUBLIC $<$<PLATFORM_ID:Linux>:LINUX>)

target_include_directories(${PROJECT_NAME}
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/GKlib>
$<INSTALL_INTERFACE:include/GKlib>)

target_link_libraries(${PROJECT_NAME}
PUBLIC $<$<NOT:$<C_COMPILER_ID:MSVC>>:m>)

set_target_properties(${PROJECT_NAME} PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}
VERSION ${PROJECT_VERSION})

add_library(GKlib::GKlib ALIAS ${PROJECT_NAME})

#-------------------------------------------------------------------------------
# OPTIONS configuration
#-------------------------------------------------------------------------------
target_compile_definitions(${PROJECT_NAME}
PUBLIC $<$<NOT:$<BOOL:${ASSERT}>>:NDEBUG>
$<$<NOT:$<BOOL:${ASSERT2}>>:NDEBUG2>
$<$<BOOL:${DEBUG}>:DEBUG>
$<$<BOOL:${GKRAND}>:GKRAND>)

#-------------------------------------------------------------------------------
# FEATURE AVAILABILITY checks
#-------------------------------------------------------------------------------
check_include_file(execinfo.h HAVE_EXECINFO_H)
check_function_exists(getline HAVE_GETLINE)

# regular expressions
if(PCRE)
check_include_file(pcreposix.h HAVE_PCREPOSIX_H)
if(NOT HAVE_PCREPOSIX_H)
message(WARNING "PCRE was requested, but is not available")
endif()
endif()
if(NOT HAVE_PCREPOSIX_H)
check_include_file(regex.h HAVE_REGEX_H)
if(NOT HAVE_REGEX_H)
set(USE_GKREGEX ON)
endif()
endif()

# profiling support
if(GPROF)
check_c_compiler_flag("-pg" HAVE_GPROF_SUPPORT)
if(NOT HAVE_GPROF_SUPPORT)
message(WARNING "GPROF support was requested, but is not available")
endif()
endif()

# openmp support
if(OPENMP)
find_package(OpenMP)
if(NOT OpenMP_C_FOUND)
message(WARNING "OpenMP was requested, but is not available")
endif()
endif()

# thread local storage
if(NOT DEFINED HAVE_TLS)
set(TLS_NAME "" CACHE INTERNAL "Thread local keyword")
foreach(tls_name "__thread" "__declspec(thread)")
unset(HAVE_TLS CACHE)
check_c_source_compiles("${tls_name} int x; int main(void) { return 0; }"
HAVE_TLS)
if (HAVE_TLS)
set(TLS_NAME ${tls_name} CACHE INTERNAL "Thread local keyword")
break()
else()
endif()
endforeach()
endif()

target_compile_definitions(${PROJECT_NAME}
PUBLIC $<$<BOOL:${HAVE_EXECINFO_H}>:HAVE_EXEC_INFO_H>
$<$<BOOL:${PCRE}>:USE_PCRE>
$<$<AND:$<BOOL:${PCRE}>,$<BOOL:${HAVE_PCREPOSIX_H}>>:HAVE_PCREPOSIX_H>
$<$<BOOL:${HAVE_REGEX_H}>:HAVE_REGEX_H>
$<$<BOOL:${USE_GKREGEX}>:USE_GKREGEX>
$<$<BOOL:${HAVE_GETLINE}>:HAVE_GETLINE>
__thread=${TLS_NAME})

target_compile_options(${PROJECT_NAME}
PUBLIC $<$<AND:$<BOOL:${GPROF}>,$<BOOL:${HAVE_GPROF_SUPPORT}>>:-pg>)

target_link_libraries(${PROJECT_NAME}
PUBLIC $<$<BOOL:${OpenMP_C_FOUND}>:OpenMP::OpenMP_C>)

#-------------------------------------------------------------------------------
# APPS configuration
#-------------------------------------------------------------------------------
if(GKLIB_BUILD_APPS)
add_subdirectory("apps")
endif()

#-------------------------------------------------------------------------------
# PACKAGE configuration
#-------------------------------------------------------------------------------
# generate files
configure_package_config_file(GKlibConfig.cmake.in cmake/GKlibConfig.cmake
INSTALL_DESTINATION lib/cmake/GKlib)

write_basic_package_version_file(cmake/GKlibConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)

# install library
install(TARGETS ${PROJECT_NAME} EXPORT GKlibTargets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT GKlib_Runtime
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT GKlib_Runtime
NAMELINK_SKIP
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT GKlib_Development
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# The previous install() command is repeated here to distinguish installations
# that include a namelink versus those that do not. Unfortunately, prior to
# CMake 3.12, when the NAMELINK_COMPONENT property was introduced, this was
# necessary to get the desired behavior.
if(BUILD_SHARED_LIBS)
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT GKlib_Development
NAMELINK_ONLY)
endif()

# install header files
install(DIRECTORY "${CMAKE_SOURCE_DIR}/include/"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT GKlib_Development)

# install files necessary to use find_package() with GKlib
install(EXPORT GKlibTargets
FILE GKlibTargets.cmake
NAMESPACE GKlib::
DESTINATION lib/cmake/GKlib
COMPONENT GKlib_Development)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/GKlibConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/cmake/GKlibConfigVersion.cmake
DESTINATION lib/cmake/GKlib
COMPONENT GKlib_Development)
1 change: 1 addition & 0 deletions GKlibConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include(${CMAKE_CURRENT_LIST_DIR}/GKlibTargets.cmake)
Loading