-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCMakeLists.txt
232 lines (182 loc) · 10.5 KB
/
CMakeLists.txt
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
cmake_minimum_required(VERSION 3.28)
project(Textract)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(INPUT_OPEN_TEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/images/screenshot.png")
set(IMAGE_FOLDER_PATH "${CMAKE_CURRENT_SOURCE_DIR}/images")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
# ─────────────────────────────────────────────────────────────────
# Macros and Optional Flags
# ─────────────────────────────────────────────────────────────────
option(DEBUG "Enable debug logging" ON)
option(DEBUG_THREADLOCAL "Enable thread-local debug logging" ON)
option(DEBUG_CACHE "Enable cache debug logging" ON)
option(DEBUG_MUTEX "Enable mutex debug logging" OFF)
option(ENABLE_TIMING "Enable timing functionality" OFF)
option(BENCHMARK "Build the benchmark tests" OFF)
# Static Linking - enforces Static Linking for all Targets
# set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
# set(BUILD_SHARED_LIBS OFF)
macro(enable_options target options)
foreach(option IN LISTS ${options})
if(${option})
target_compile_definitions(${target} PUBLIC ${option})
endif()
endforeach()
endmacro()
macro(link_llvm) # ensure LLVM_DIR is set
add_compile_options(-Wno-deprecated-declarations)
set(llvm_components core support irreader)
llvm_map_components_to_libnames(llvm_libs ${llvm_components})
foreach(target ${ARGN})
target_link_libraries(${target} PUBLIC ${llvm_libs})
endforeach()
endmacro()
macro(find_pkg PKG_NAME PKG_CONFIG_NAME)
find_package(PkgConfig REQUIRED)
set(PKG_VERSION_OPTIONAL ${ARGN})
list(LENGTH PKG_VERSION_OPTIONAL PKG_VERSION_ARG_COUNT)
if(PKG_VERSION_ARG_COUNT EQUAL 1)
set(REQUIRED_VERSION ${PKG_VERSION_OPTIONAL})
pkg_check_modules(${PKG_NAME} IMPORTED_TARGET ${PKG_CONFIG_NAME}>=${REQUIRED_VERSION})
if(NOT ${PKG_NAME}_FOUND)
message(WARNING "${PKG_NAME} version ${REQUIRED_VERSION} not found. Trying any available version.")
pkg_check_modules(${PKG_NAME} REQUIRED IMPORTED_TARGET ${PKG_CONFIG_NAME})
endif()
else()
pkg_check_modules(${PKG_NAME} REQUIRED IMPORTED_TARGET ${PKG_CONFIG_NAME})
endif()
endmacro()
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT APPLE)
add_compile_definitions(_DEBUGAPP)
add_compile_definitions("ASAN_OPTIONS=detect_leaks=1,detect_stack_use_after_return=1")
# Enable LLVM ASan (Address Sanitizer, Mem Leaks Detection)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fsanitize=address")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address")
endif()
if(ENABLE_TIMING)
add_compile_definitions(ENABLE_TIMING)
endif()
# ─────────────────────────────────────────────────────────────────
# PGO Instrumentation Builds
# ─────────────────────────────────────────────────────────────────
if(PROFILE_GENERATE) # PGO instrumentation build | cmbc -DCMAKE_BUILD_TYPE=All -DPROFILE_GENERATE=ON
set(PGO_GENERATE_FLAGS "-fprofile-instr-generate -fcoverage-mapping")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PGO_GENERATE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PGO_GENERATE_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PGO_GENERATE_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${PGO_GENERATE_FLAGS}")
endif()
if(PROFILE_USE) # PGO optimized build cmbc -DCMAKE_BUILD_TYPE=All -DPROFILE_USE=ON
message(STATUS "PROFILE_USE is enabled")
set(MERGED_PROFDATA "${CMAKE_BINARY_DIR}/merged.profdata")
if(EXISTS "${MERGED_PROFDATA}")
message(STATUS "Found merged.profdata in build directory")
set(PGO_USE_FLAGS "-fprofile-instr-use=${MERGED_PROFDATA}")
elseif(DEFINED PROF_DATA_PATH AND EXISTS "${PROF_DATA_PATH}")
message(STATUS "Found merged.profdata in PROF_DATA_PATH: ${PROF_DATA_PATH}")
set(PGO_USE_FLAGS "-fprofile-instr-use=${PROF_DATA_PATH}")
else()
message(FATAL_ERROR "merged.profdata not found in build directory or PROF_DATA_PATH. Please provide a valid profile data file.")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PGO_USE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PGO_USE_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PGO_USE_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${PGO_USE_FLAGS}")
endif()
# ─────────────────────────────────────────────────────────────────
# Dependencies
# ─────────────────────────────────────────────────────────────────
find_pkg(Tesseract tesseract "5.0.0")
find_pkg(Leptonica lept)
find_package(LLVM REQUIRED CONFIG)
find_package(OpenSSL REQUIRED)
find_package(Folly CONFIG REQUIRED)
find_package(gflags CONFIG REQUIRED)
find_package(OpenMP)
find_package(GTest REQUIRED)
find_package(CURL REQUIRED)
if(APPLE)
set(TESSDATA_PREFIX "/opt/homebrew/opt/tesseract/share/tessdata" CACHE PATH "Path to Tesseract trained data")
elseif(UNIX AND NOT APPLE)
set(TESSDATA_PREFIX "/usr/local/share/tessdata" CACHE PATH "Path to Tesseract trained data")
endif()
add_definitions(-DTESSDATA_PREFIX="${TESSDATA_PREFIX}")
# ─────────────────────────────────────────────────────────────────
# Static Library - Linking all Libraries with common_lib
# ─────────────────────────────────────────────────────────────────
file(GLOB_RECURSE SRC_FILES "${CMAKE_SOURCE_DIR}/src/*.cc")
add_library(common_lib ${SRC_FILES})
set(DEBUG_OPTIONS DEBUG DEBUG_THREADLOCAL DEBUG_CACHE DEBUG_MUTEX)
enable_options(common_lib DEBUG_OPTIONS)
target_include_directories(common_lib PUBLIC "${CMAKE_SOURCE_DIR}/include" PUBLIC ${OPENSSL_INCLUDE_DIR})
link_llvm(common_lib)
message(STATUS "OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}")
message(STATUS "OpenSSL libraries: ${OPENSSL_LIBRARIES}")
target_link_libraries(common_lib
PUBLIC GTest::gtest_main
PUBLIC OpenSSL::Crypto
PUBLIC OpenSSL::SSL
PUBLIC Folly::folly
PUBLIC PkgConfig::Tesseract
PUBLIC PkgConfig::Leptonica
PUBLIC CURL::libcurl) # Add this line
if(OpenMP_CXX_FOUND)
message(STATUS "Linking OpenMP with Lib")
target_link_libraries(common_lib PUBLIC OpenMP::OpenMP_CXX)
else()
message(STATUS "OpenMP not found")
endif()
# ─────────────────────────────────────────────────────────────────
# Executables, Tests , and Benchmarks
# ─────────────────────────────────────────────────────────────────
add_executable(main main.cc)
target_link_libraries(main PUBLIC common_lib)
# Add Static Binary for main.cc as well in /static
add_executable(textract_static main.cc)
target_link_libraries(textract_static PUBLIC common_lib)
set_target_properties(textract_static PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/static")
# Ensure static linking for textract_static
set_target_properties(textract_static PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(textract_static PROPERTIES LINK_SEARCH_END_STATIC 1)
if (BENCHMARK)
add_executable(cache_benchmark benchmarks/cache_benchmark.cc)
target_link_libraries(cache_benchmark PUBLIC Folly::folly PUBLIC Folly::follybenchmark)
endif()
enable_testing()
set(TEST_EXECUTABLES)
file(GLOB TEST_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/tests" "tests/*.cc")
foreach(TEST_SOURCE IN LISTS TEST_SOURCES)
get_filename_component(TEST_EXECUTABLE ${TEST_SOURCE} NAME_WE)
add_executable(${TEST_EXECUTABLE} tests/${TEST_SOURCE})
target_link_libraries(${TEST_EXECUTABLE} PUBLIC common_lib) # link static library with methods
list(APPEND TEST_EXECUTABLES ${TEST_EXECUTABLE})
target_compile_definitions(${TEST_EXECUTABLE}
PRIVATE IMAGE_FOLDER_PATH="${IMAGE_FOLDER_PATH}"
PRIVATE INPUT_OPEN_TEST_PATH="${INPUT_OPEN_TEST_PATH}")
set_target_properties(${TEST_EXECUTABLE} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
include(GoogleTest)
gtest_discover_tests(${TEST_EXECUTABLE})
endforeach()
# ──────────────────────────────────────────────────────────────────────
# CodeGen -> Dynamically setting Constexprs based on Build Time Files
# ──────────────────────────────────────────────────────────────────────
set(IMAGE_DIR "${IMAGE_FOLDER_PATH}")
file(GLOB files "${IMAGE_DIR}/*")
list(LENGTH files files_SIZE)
set(header_content "#pragma once\n#include <array>\nconstexpr std::array<const char*, ${files_SIZE}> fileNames = {\n")
foreach(file IN LISTS files)
get_filename_component(fname "${file}" NAME)
set(header_content "${header_content} \"${IMAGE_DIR}/${fname}\",\n")
endforeach()
set(header_content "${header_content}};\n")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
file(WRITE "${CMAKE_BINARY_DIR}/include/generated_files.h" "${header_content}")
include_directories(${CMAKE_BINARY_DIR}/include)
message(STATUS "Codegen Generated fileNames array<const char*> : #include <generated_files.h>")
message(STATUS "Build Successful.\nInvoke all tests:\n ctest")