Skip to content

Commit

Permalink
Adds support for modern CMake
Browse files Browse the repository at this point in the history
The primary purpose of this commit is to incorporate modern CMake
(>=3.1) best practices. As a result, a reorganization of the directory
structure as well as a few minor code cleanups was required. A summary
of those changes follows:
* Moves all header files into a separate include directory.
* The test directory was renamed to apps, to allow for future unit tests
  to be written and included in a directory named test.
* The win32 shims should only be included when compiling in a Windows
  environment. Upstream checks this by testing the CMake variable
  `MSVC`. However, this commit uses generator expressions and the more
  general test of the CMake Platform ID being equal to `Windows`.
* All options and other configurable behavior of the CMakeLists file is
  implemented using generator-expressions.
* Makes the GKlib apps disabled by default if the GKlib library is not
  the top CMake project and enabled if it is. This way, when GKlib is a
  dependency of another project, the apps are not build by default. An
  option, GKLIB_BUILD_APPS, was added to allow projects depending on
  GKlib to also build the apps.
* Moves feature availability checks from `GKlibSystem.cmake` to the main
  `CMakeLists.txt`. This is to separate concerns, `CMakeLists.txt`
  contains core CMake logic, while `GKlibSystem.cmake` contains common
  compiler options and the like, which are convenient defaults, but may
  not be appropriate for all user of the build system.
* Adds the CMake variable GKLIB_SYSTEM which, when defined, will point
  to a CMake script, like `GKlibSystem.cmake`, where compiler options
  and the like can be specified. This allows the user of the build
  system to have a file where they manage common CMake settings without
  affecting the core CMake logic and thus imposing those settings on
  other users of this build.
  • Loading branch information
jiverson002 committed Dec 1, 2020
1 parent 426ece3 commit da0f037
Show file tree
Hide file tree
Showing 67 changed files with 320 additions and 230 deletions.
229 changes: 205 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,31 +1,212 @@
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)
#-------------------------------------------------------------------------------
# DEFAULT CONFIGURATIONS
#-------------------------------------------------------------------------------
if (DEFINED GKLIB_SYSTEM)
include(${GKLIB_SYSTEM})
endif()

add_library(GKlib ${GKlib_sources} ${win32_sources})
#-------------------------------------------------------------------------------
# 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)

if(UNIX)
target_link_libraries(GKlib m)
endif(UNIX)
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()

include_directories("test")
add_subdirectory("test")
#-------------------------------------------------------------------------------
# LIBRARY configuration
#-------------------------------------------------------------------------------
add_library(${PROJECT_NAME})

install(TARGETS GKlib
ARCHIVE DESTINATION lib/${LINSTALL_PATH}
LIBRARY DESTINATION lib/${LINSTALL_PATH})
install(FILES ${GKlib_includes} DESTINATION include/${HINSTALL_PATH})
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>)

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
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)
137 changes: 0 additions & 137 deletions GKlibSystem.cmake

This file was deleted.

Loading

0 comments on commit da0f037

Please sign in to comment.