aboutsummaryrefslogtreecommitdiff
path: root/CMakeLists.txt
blob: 0db32647b723dbb49161b7774f34c3088eee3c4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
CMAKE_MINIMUM_REQUIRED(VERSION 3.5 FATAL_ERROR)

# ---[ Project
PROJECT(pthreadpool C CXX)

# ---[ Options.
SET(PTHREADPOOL_LIBRARY_TYPE "default" CACHE STRING "Type of library (shared, static, or default) to build")
SET_PROPERTY(CACHE PTHREADPOOL_LIBRARY_TYPE PROPERTY STRINGS default static shared)
OPTION(PTHREADPOOL_ALLOW_DEPRECATED_API "Enable deprecated API functions" ON)
SET(PTHREADPOOL_SYNC_PRIMITIVE "default" CACHE STRING "Synchronization primitive (condvar, futex, gcd, event, or default) for worker threads")
SET_PROPERTY(CACHE PTHREADPOOL_SYNC_PRIMITIVE PROPERTY STRINGS default condvar futex gcd event)
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?)$")
  OPTION(PTHREADPOOL_ENABLE_FASTPATH "Enable fast path using atomic decrement instead of atomic compare-and-swap" ON)
ELSE()
  OPTION(PTHREADPOOL_ENABLE_FASTPATH "Enable fast path using atomic decrement instead of atomic compare-and-swap" OFF)
ENDIF()
IF("${CMAKE_SOURCE_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}")
  OPTION(PTHREADPOOL_BUILD_TESTS "Build pthreadpool unit tests" ON)
  OPTION(PTHREADPOOL_BUILD_BENCHMARKS "Build pthreadpool micro-benchmarks" ON)
ELSE()
  SET(PTHREADPOOL_BUILD_TESTS OFF CACHE BOOL "Build pthreadpool unit tests")
  SET(PTHREADPOOL_BUILD_BENCHMARKS OFF CACHE BOOL "Build pthreadpool micro-benchmarks")
ENDIF()

# ---[ CMake options
INCLUDE(GNUInstallDirs)

IF(PTHREADPOOL_BUILD_TESTS)
  ENABLE_TESTING()
ENDIF()

MACRO(PTHREADPOOL_TARGET_ENABLE_CXX11 target)
  SET_TARGET_PROPERTIES(${target} PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS NO)
ENDMACRO()

# ---[ Download deps
IF(NOT DEFINED FXDIV_SOURCE_DIR)
  MESSAGE(STATUS "Downloading FXdiv to ${CMAKE_BINARY_DIR}/FXdiv-source (define FXDIV_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadFXdiv.cmake "${CMAKE_BINARY_DIR}/FXdiv-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/FXdiv-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/FXdiv-download")
  SET(FXDIV_SOURCE_DIR "${CMAKE_BINARY_DIR}/FXdiv-source" CACHE STRING "FXdiv source directory")
ENDIF()

IF(PTHREADPOOL_BUILD_TESTS AND NOT DEFINED GOOGLETEST_SOURCE_DIR)
  MESSAGE(STATUS "Downloading Google Test to ${CMAKE_BINARY_DIR}/googletest-source (define GOOGLETEST_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadGoogleTest.cmake "${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googletest-download")
  SET(GOOGLETEST_SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-source" CACHE STRING "Google Test source directory")
ENDIF()

IF(PTHREADPOOL_BUILD_BENCHMARKS AND NOT DEFINED GOOGLEBENCHMARK_SOURCE_DIR)
  MESSAGE(STATUS "Downloading Google Benchmark to ${CMAKE_BINARY_DIR}/googlebenchmark-source (define GOOGLEBENCHMARK_SOURCE_DIR to avoid it)")
  CONFIGURE_FILE(cmake/DownloadGoogleBenchmark.cmake "${CMAKE_BINARY_DIR}/googlebenchmark-download/CMakeLists.txt")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googlebenchmark-download")
  EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/googlebenchmark-download")
  SET(GOOGLEBENCHMARK_SOURCE_DIR "${CMAKE_BINARY_DIR}/googlebenchmark-source" CACHE STRING "Google Benchmark source directory")
ENDIF()

# ---[ pthreadpool library
IF(PTHREADPOOL_ALLOW_DEPRECATED_API)
  SET(PTHREADPOOL_SRCS src/legacy-api.c)
ENDIF()
IF(EMSCRIPTEN)
  LIST(APPEND PTHREADPOOL_SRCS src/shim.c)
ELSE()
  LIST(APPEND PTHREADPOOL_SRCS src/portable-api.c src/memory.c)
  IF(APPLE AND (PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "default" OR PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "gcd"))
    LIST(APPEND PTHREADPOOL_SRCS src/gcd.c)
  ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$" AND (PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "default" OR PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "event"))
    LIST(APPEND PTHREADPOOL_SRCS src/windows.c)
  ELSE()
    LIST(APPEND PTHREADPOOL_SRCS src/pthreads.c)
  ENDIF()
  IF(PTHREADPOOL_ENABLE_FASTPATH)
    LIST(APPEND PTHREADPOOL_SRCS src/fastpath.c)
  ENDIF()
ENDIF()

ADD_LIBRARY(pthreadpool_interface INTERFACE)
TARGET_INCLUDE_DIRECTORIES(pthreadpool_interface INTERFACE include)
IF(NOT PTHREADPOOL_ALLOW_DEPRECATED_API)
  TARGET_COMPILE_DEFINITIONS(pthreadpool_interface INTERFACE PTHREADPOOL_NO_DEPRECATED_API=1)
ENDIF()
INSTALL(FILES include/pthreadpool.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

IF(PTHREADPOOL_LIBRARY_TYPE STREQUAL "default")
  ADD_LIBRARY(pthreadpool ${PTHREADPOOL_SRCS})
ELSEIF(PTHREADPOOL_LIBRARY_TYPE STREQUAL "shared")
  ADD_LIBRARY(pthreadpool SHARED ${PTHREADPOOL_SRCS})
ELSEIF(PTHREADPOOL_LIBRARY_TYPE STREQUAL "static")
  ADD_LIBRARY(pthreadpool STATIC ${PTHREADPOOL_SRCS})
ELSE()
  MESSAGE(FATAL_ERROR "Unsupported library type ${PTHREADPOOL_LIBRARY_TYPE}")
ENDIF()

IF(PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "condvar")
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_FUTEX=0)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_GCD=0)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_EVENT=0)
ELSEIF(PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "futex")
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_FUTEX=1)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_GCD=0)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_EVENT=0)
ELSEIF(PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "gcd")
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_FUTEX=0)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_GCD=1)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_EVENT=0)
ELSEIF(PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "event")
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_FUTEX=0)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_GCD=0)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_EVENT=1)
ELSEIF(NOT PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "default")
  MESSAGE(FATAL_ERROR "Unsupported synchronization primitive ${PTHREADPOOL_SYNC_PRIMITIVE}")
ENDIF()
IF(PTHREADPOOL_ENABLE_FASTPATH)
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_ENABLE_FASTPATH=1)
ELSE()
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_ENABLE_FASTPATH=0)
ENDIF()

SET_TARGET_PROPERTIES(pthreadpool PROPERTIES
  C_STANDARD 11
  C_EXTENSIONS NO)
TARGET_LINK_LIBRARIES(pthreadpool PUBLIC pthreadpool_interface)
TARGET_INCLUDE_DIRECTORIES(pthreadpool PRIVATE src)
IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
  SET(CMAKE_THREAD_PREFER_PTHREAD TRUE)
  IF(NOT CMAKE_GENERATOR STREQUAL "Xcode")
    FIND_PACKAGE(Threads REQUIRED)
  ENDIF()
  IF(CMAKE_USE_PTHREADS_INIT)
    IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
      TARGET_COMPILE_OPTIONS(pthreadpool PUBLIC -pthread)
    ENDIF()
  ENDIF()
  TARGET_LINK_LIBRARIES(pthreadpool PUBLIC ${CMAKE_THREAD_LIBS_INIT})
ENDIF()
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE _GNU_SOURCE=1)
ENDIF()

# ---[ Configure FXdiv
IF(NOT TARGET fxdiv)
  SET(FXDIV_BUILD_TESTS OFF CACHE BOOL "")
  SET(FXDIV_BUILD_BENCHMARKS OFF CACHE BOOL "")
  ADD_SUBDIRECTORY(
    "${FXDIV_SOURCE_DIR}"
    "${CMAKE_BINARY_DIR}/FXdiv")
ENDIF()
TARGET_LINK_LIBRARIES(pthreadpool PRIVATE fxdiv)

INSTALL(TARGETS pthreadpool
  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

IF(PTHREADPOOL_BUILD_TESTS)
  # ---[ Build google test
  IF(NOT TARGET gtest)
    SET(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
    ADD_SUBDIRECTORY(
      "${GOOGLETEST_SOURCE_DIR}"
      "${CMAKE_BINARY_DIR}/googletest")
  ENDIF()

  ADD_EXECUTABLE(pthreadpool-test test/pthreadpool.cc)
  SET_TARGET_PROPERTIES(pthreadpool-test PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS NO)
  TARGET_LINK_LIBRARIES(pthreadpool-test pthreadpool gtest gtest_main)
  ADD_TEST(pthreadpool pthreadpool-test)
ENDIF()

IF(PTHREADPOOL_BUILD_BENCHMARKS)
  # ---[ Build google benchmark
  IF(NOT TARGET benchmark)
    SET(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "")
    ADD_SUBDIRECTORY(
      "${GOOGLEBENCHMARK_SOURCE_DIR}"
      "${CMAKE_BINARY_DIR}/googlebenchmark")
  ENDIF()

  ADD_EXECUTABLE(latency-bench bench/latency.cc)
  SET_TARGET_PROPERTIES(latency-bench PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS NO)
  TARGET_LINK_LIBRARIES(latency-bench pthreadpool benchmark)

  ADD_EXECUTABLE(throughput-bench bench/throughput.cc)
  SET_TARGET_PROPERTIES(throughput-bench PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS NO)
  TARGET_LINK_LIBRARIES(throughput-bench pthreadpool benchmark)
ENDIF()