CMake Header-Only Target (#46)

Make header only library target. 

Use the CMake INTERFACE target type to include the build settings for
snmalloc in other projects using headers only.

Made warnings setting a macro for reuse.
This commit is contained in:
Matthew Parkinson
2019-05-09 12:32:32 +01:00
committed by GitHub
parent b38c36b40f
commit 1e4eb3dea3
2 changed files with 150 additions and 127 deletions

View File

@@ -3,164 +3,177 @@ project(snmalloc C CXX)
option(USE_SNMALLOC_STATS "Track allocation stats" OFF)
option(USE_MEASURE "Measure performance with histograms" OFF)
option(USE_SBRK "Use sbrk instead of mmap" OFF)
option(EXPOSE_EXTERNAL_PAGEMAP "Expose the global pagemap" OFF)
option(EXPOSE_EXTERNAL_RESERVE "Expose an interface to reserve memory using the default memory provider" OFF)
set(CACHE_FRIENDLY_OFFSET OFF CACHE STRING "Base offset to place linked-list nodes.")
macro(subdirlist result curdir)
file(GLOB children LIST_DIRECTORIES true RELATIVE ${curdir} ${curdir}/*)
set(dirlist "")
foreach(child ${children})
if(IS_DIRECTORY ${curdir}/${child})
list(APPEND dirlist ${child})
endif()
endforeach()
set(${result} ${dirlist})
endmacro()
macro(linklibs project)
if(NOT MSVC)
target_link_libraries(${project} ${CMAKE_THREAD_LIBS_INIT})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_link_libraries(${project} atomic)
# Provide as macro so other projects can reuse
macro(warnings_high)
if(MSVC)
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
add_compile_options(/WX /wd4127 /wd4324 /wd4201)
else()
# VirtualAlloc2 is exposed by mincore.lib, not Kernel32.lib (as the
# documentation says)
target_link_libraries(${project} mincore)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wsign-conversion)
endif ()
add_compile_options(-Wall -Wextra -Werror)
endif()
endmacro()
if(MSVC)
# The main target for snmalloc
add_library(snmalloc_lib INTERFACE)
target_include_directories(snmalloc_lib INTERFACE src/)
if(NOT MSVC)
find_package(Threads REQUIRED COMPONENTS snmalloc_lib)
target_link_libraries(snmalloc_lib INTERFACE ${CMAKE_THREAD_LIBS_INIT})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_link_libraries(snmalloc_lib INTERFACE atomic)
endif()
target_compile_options(snmalloc_lib INTERFACE -mcx16)
else()
set(WIN8COMPAT FALSE CACHE BOOL "Avoid Windows 10 APIs")
if (WIN8COMPAT)
add_definitions(-DWINVER=0x0603)
message(STATUS "Avoiding Windows 10 APIs")
target_compile_definitions(snmalloc_lib INTERFACE -DWINVER=0x0603)
message(STATUS "snmalloc: Avoiding Windows 10 APIs")
else()
message(STATUS "Using Windows 10 APIs")
message(STATUS "snmalloc: Using Windows 10 APIs")
# VirtualAlloc2 is exposed by mincore.lib, not Kernel32.lib (as the
# documentation says)
target_link_libraries(snmalloc_lib INTERFACE mincore)
endif()
# Force to always compile with W4
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
add_compile_options(/WX /wd4127 /wd4324 /wd4201)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
else()
find_package(Threads REQUIRED)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wsign-conversion)
endif ()
add_compile_options(-mcx16 -march=native -Wall -Wextra -Werror -g -fno-exceptions -fno-rtti)
endif()
# Have to set this globally, as can't be set on an interface target.
set(CMAKE_CXX_STANDARD 17)
if(USE_SNMALLOC_STATS)
add_definitions(-DUSE_SNMALLOC_STATS)
target_compile_definitions(snmalloc_lib INTERFACE -DUSE_SNMALLOC_STATS)
endif()
if(USE_MEASURE)
add_definitions(-DUSE_MEASURE)
target_compile_definitions(snmalloc_lib INTERFACE -DUSE_MEASURE)
endif()
if(USE_SBRK)
add_definitions(-DUSE_SBRK)
endif()
# To build with just the header library target define SNMALLOC_ONLY_HEADER_LIBRARY
# in containing Cmake file.
if(NOT DEFINED SNMALLOC_ONLY_HEADER_LIBRARY)
macro(add_shim name)
add_library(${name} SHARED src/override/malloc.cc)
target_link_libraries(${name} -pthread)
target_include_directories(${name} PRIVATE src)
target_compile_definitions(${name} PRIVATE "SNMALLOC_EXPORT=__attribute__((visibility(\"default\")))")
set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET hidden)
warnings_high()
if(CACHE_FRIENDLY_OFFSET)
target_compile_definitions(${name} PRIVATE -DCACHE_FRIENDLY_OFFSET=${CACHE_FRIENDLY_OFFSET})
if(MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
else()
add_compile_options(-march=native -fno-exceptions -fno-rtti -g)
endif()
if(EXPOSE_EXTERNAL_PAGEMAP)
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_PAGEMAP)
endif()
if(EXPOSE_EXTERNAL_RESERVE)
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_RESERVE)
endif()
endmacro()
if(NOT MSVC)
add_shim(snmallocshim)
add_shim(snmallocshim-1mib)
target_compile_definitions(snmallocshim-1mib PRIVATE IS_ADDRESS_SPACE_CONSTRAINED)
endif()
enable_testing()
set(TESTDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/test)
subdirlist(TEST_CATEGORIES ${TESTDIR})
list(REVERSE TEST_CATEGORIES)
foreach(TEST_CATEGORY ${TEST_CATEGORIES})
subdirlist(TESTS ${TESTDIR}/${TEST_CATEGORY})
foreach(TEST ${TESTS})
foreach(SUPER_SLAB_SIZE 1;16)
unset(SRC)
aux_source_directory(${TESTDIR}/${TEST_CATEGORY}/${TEST} SRC)
set(TESTNAME "${TEST_CATEGORY}-${TEST}-${SUPER_SLAB_SIZE}")
add_executable(${TESTNAME} ${SRC} src/override/new.cc)
if (${SUPER_SLAB_SIZE} EQUAL 1)
target_compile_definitions(${TESTNAME} PRIVATE IS_ADDRESS_SPACE_CONSTRAINED)
endif()
target_include_directories(${TESTNAME} PRIVATE src)
linklibs(${TESTNAME})
if (${TEST} MATCHES "release-.*")
message(STATUS "Adding test: ${TESTNAME} only for release configs")
add_test(NAME ${TESTNAME} COMMAND ${TESTNAME} CONFIGURATIONS "Release")
else()
message(STATUS "Adding test: ${TESTNAME}")
add_test(${TESTNAME} ${TESTNAME})
endif()
if (${TEST_CATEGORY} MATCHES "perf")
set_tests_properties(${TESTNAME} PROPERTIES PROCESSORS 3)
macro(subdirlist result curdir)
file(GLOB children LIST_DIRECTORIES true RELATIVE ${curdir} ${curdir}/*)
set(dirlist "")
foreach(child ${children})
if(IS_DIRECTORY ${curdir}/${child})
list(APPEND dirlist ${child})
endif()
endforeach()
set(${result} ${dirlist})
endmacro()
macro(add_shim name)
add_library(${name} SHARED src/override/malloc.cc)
target_link_libraries(${name} snmalloc_lib)
target_compile_definitions(${name} PRIVATE "SNMALLOC_EXPORT=__attribute__((visibility(\"default\")))")
set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET hidden)
if(CACHE_FRIENDLY_OFFSET)
target_compile_definitions(${name} PRIVATE -DCACHE_FRIENDLY_OFFSET=${CACHE_FRIENDLY_OFFSET})
endif()
if(EXPOSE_EXTERNAL_PAGEMAP)
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_PAGEMAP)
endif()
if(EXPOSE_EXTERNAL_RESERVE)
target_compile_definitions(${name} PRIVATE -DSNMALLOC_EXPOSE_RESERVE)
endif()
endmacro()
if(NOT MSVC)
add_shim(snmallocshim)
add_shim(snmallocshim-1mib)
target_compile_definitions(snmallocshim-1mib PRIVATE IS_ADDRESS_SPACE_CONSTRAINED)
endif()
enable_testing()
set(TESTDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/test)
subdirlist(TEST_CATEGORIES ${TESTDIR})
list(REVERSE TEST_CATEGORIES)
foreach(TEST_CATEGORY ${TEST_CATEGORIES})
subdirlist(TESTS ${TESTDIR}/${TEST_CATEGORY})
foreach(TEST ${TESTS})
foreach(SUPER_SLAB_SIZE 1;16)
unset(SRC)
aux_source_directory(${TESTDIR}/${TEST_CATEGORY}/${TEST} SRC)
set(TESTNAME "${TEST_CATEGORY}-${TEST}-${SUPER_SLAB_SIZE}")
add_executable(${TESTNAME} ${SRC} src/override/new.cc)
if (${SUPER_SLAB_SIZE} EQUAL 1)
target_compile_definitions(${TESTNAME} PRIVATE IS_ADDRESS_SPACE_CONSTRAINED)
endif()
target_include_directories(${TESTNAME} PRIVATE src)
target_link_libraries(${TESTNAME} snmalloc_lib)
if (${TEST} MATCHES "release-.*")
message(STATUS "Adding test: ${TESTNAME} only for release configs")
add_test(NAME ${TESTNAME} COMMAND ${TESTNAME} CONFIGURATIONS "Release")
else()
message(STATUS "Adding test: ${TESTNAME}")
add_test(${TESTNAME} ${TESTNAME})
endif()
if (${TEST_CATEGORY} MATCHES "perf")
set_tests_properties(${TESTNAME} PROPERTIES PROCESSORS 3)
endif()
endforeach()
endforeach()
endforeach()
endforeach()
# The clang-format tool is installed under a variety of different names. Try
# to find a sensible one. Only look for 6.0 and 7.0 versions explicitly - we
# don't know whether our clang-format file will work with newer versions of the
# tool
set(CLANG_FORMAT_NAMES
clang-format-7.0
clang-format-6.0
clang-format70
clang-format60
clang-format)
# The clang-format tool is installed under a variety of different names. Try
# to find a sensible one. Only look for 6.0 and 7.0 versions explicitly - we
# don't know whether our clang-format file will work with newer versions of the
# tool
set(CLANG_FORMAT_NAMES
clang-format-7.0
clang-format-6.0
clang-format70
clang-format60
clang-format)
# Loop over each of the possible names of clang-format and try to find one.
set(CLANG_FORMAT CLANG_FORMAT-NOTFOUND)
foreach (NAME IN ITEMS ${CLANG_FORMAT_NAMES})
# Loop over each of the possible names of clang-format and try to find one.
set(CLANG_FORMAT CLANG_FORMAT-NOTFOUND)
foreach (NAME IN ITEMS ${CLANG_FORMAT_NAMES})
if (${CLANG_FORMAT} STREQUAL "CLANG_FORMAT-NOTFOUND")
find_program(CLANG_FORMAT ${NAME})
endif ()
endforeach()
# If we've found a clang-format tool, generate a target for it, otherwise emit
# a warning.
if (${CLANG_FORMAT} STREQUAL "CLANG_FORMAT-NOTFOUND")
find_program(CLANG_FORMAT ${NAME})
endif ()
endforeach()
# If we've found a clang-format tool, generate a target for it, otherwise emit
# a warning.
if (${CLANG_FORMAT} STREQUAL "CLANG_FORMAT-NOTFOUND")
message(WARNING "Not generating clangformat target, no clang-format tool found")
else ()
message(STATUS "Generating clangformat target using ${CLANG_FORMAT}")
file(GLOB_RECURSE ALL_SOURCE_FILES *.cc *.h *.hh)
add_custom_target(
clangformat
COMMAND ${CLANG_FORMAT}
-i
${ALL_SOURCE_FILES}
)
endif()
message(WARNING "Not generating clangformat target, no clang-format tool found")
else ()
message(STATUS "Generating clangformat target using ${CLANG_FORMAT}")
file(GLOB_RECURSE ALL_SOURCE_FILES *.cc *.h *.hh)
add_custom_target(
clangformat
COMMAND ${CLANG_FORMAT}
-i
${ALL_SOURCE_FILES}
)
endif()
endif()

View File

@@ -82,6 +82,16 @@ These can be added to your cmake command line.
-DUSE_MEASURE=ON // Measure performance with histograms
```
The project can be included in other CMake projects as a header
only library:
```
set(SNMALLOC_ONLY_HEADER_LIBRARY ON)
add_subdirectory([...]/snmalloc EXCLUDE_FROM_ALL)
```
This has a single build target `snmalloc_lib`, which includes
the necessary compiler and linker flags, to use snmalloc as a header-only
library.
# Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a