1 cmake_minimum_required(VERSION 2.8.0) 2 project(harfbuzz) 3 4 enable_testing() 5 6 ## Limit framework build to Xcode generator 7 if (BUILD_FRAMEWORK) 8 # for a framework build on macOS, use: 9 # cmake -DBUILD_FRAMEWORK=ON -Bbuild -H. -GXcode && cmake --build build 10 if (NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode") 11 message(FATAL_ERROR 12 "You should use Xcode generator with BUILD_FRAMEWORK enabled") 13 endif () 14 set (CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)") 15 set (CMAKE_MACOSX_RPATH ON) 16 set (BUILD_SHARED_LIBS ON) 17 endif () 18 19 20 ## Disallow in-source builds, as CMake generated make files can collide with autotools ones 21 if (NOT MSVC AND "${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}") 22 message(FATAL_ERROR 23 " 24 In-source builds are not permitted! Make a separate folder for" 25 " building, e.g.," 26 " 27 mkdir build; cd build; cmake .." 28 " 29 Before that, remove the files created by this failed run with" 30 " 31 rm -rf CMakeCache.txt CMakeFiles") 32 endif () 33 34 35 ## HarfBuzz build configurations 36 option(HB_HAVE_FREETYPE "Enable freetype interop helpers" OFF) 37 option(HB_HAVE_GRAPHITE2 "Enable Graphite2 complementary shaper" OFF) 38 option(HB_BUILTIN_UCDN "Use HarfBuzz provided UCDN" ON) 39 option(HB_HAVE_GLIB "Enable glib unicode functions" OFF) 40 option(HB_HAVE_ICU "Enable icu unicode functions" OFF) 41 if (APPLE) 42 option(HB_HAVE_CORETEXT "Enable CoreText shaper backend on macOS" ON) 43 set (CMAKE_MACOSX_RPATH ON) 44 endif () 45 if (WIN32) 46 option(HB_HAVE_UNISCRIBE "Enable Uniscribe shaper backend on Windows" OFF) 47 option(HB_HAVE_DIRECTWRITE "Enable DirectWrite shaper backend on Windows" OFF) 48 endif () 49 option(HB_BUILD_UTILS "Build harfbuzz utils, needs cairo, freetype, and glib properly be installed" OFF) 50 if (HB_BUILD_UTILS) 51 set (HB_HAVE_GLIB ON) 52 set (HB_HAVE_FREETYPE ON) 53 endif () 54 55 option(HB_BUILD_SUBSET "Build harfbuzz-subset" ON) 56 option(HB_BUILD_TESTS "Build harfbuzz tests" ON) 57 58 option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF) 59 if (HB_HAVE_GOBJECT) 60 set (HB_HAVE_GLIB ON) 61 endif () 62 63 option(HB_HAVE_INTROSPECTION "Enable building introspection (.gir/.typelib) files" OFF) 64 if (HB_HAVE_INTROSPECTION) 65 set (HB_HAVE_GOBJECT ON) 66 set (HB_HAVE_GLIB ON) 67 endif () 68 69 option(HB_CHECK OFF "Do a configuration suitable for testing (shared library and enable all options)") 70 if (HB_CHECK) 71 set (BUILD_SHARED_LIBS ON) 72 set (HB_BUILD_UTILS ON) 73 set (HB_BUILTIN_UCDN ON) 74 set (HB_HAVE_ICU) 75 set (HB_HAVE_GLIB ON) 76 #set (HB_HAVE_GOBJECT ON) 77 #set (HB_HAVE_INTROSPECTION ON) 78 set (HB_HAVE_FREETYPE ON) 79 set (HB_HAVE_GRAPHITE2 ON) 80 if (WIN32) 81 set (HB_HAVE_UNISCRIBE ON) 82 set (HB_HAVE_DIRECTWRITE ON) 83 elseif (APPLE) 84 set (HB_HAVE_CORETEXT ON) 85 endif () 86 endif () 87 88 include_directories(AFTER 89 ${PROJECT_SOURCE_DIR}/src 90 ${PROJECT_BINARY_DIR}/src 91 ) 92 93 add_definitions(-DHAVE_FALLBACK) 94 95 # We need PYTHON_EXECUTABLE to be set for running the tests... 96 include (FindPythonInterp) 97 98 ## Functions and headers 99 include (CheckFunctionExists) 100 include (CheckIncludeFile) 101 macro (check_funcs) # Similar to AC_CHECK_FUNCS of autotools 102 foreach (func_name ${ARGN}) 103 string(TOUPPER ${func_name} definition_to_add) 104 check_function_exists(${func_name} HAVE_${definition_to_add}) 105 if (${HAVE_${definition_to_add}}) 106 add_definitions(-DHAVE_${definition_to_add}) 107 endif () 108 endforeach () 109 endmacro () 110 if (UNIX) 111 list(APPEND CMAKE_REQUIRED_LIBRARIES m) 112 endif () 113 check_funcs(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l round) 114 check_include_file(unistd.h HAVE_UNISTD_H) 115 if (${HAVE_UNISTD_H}) 116 add_definitions(-DHAVE_UNISTD_H) 117 endif () 118 check_include_file(sys/mman.h HAVE_SYS_MMAN_H) 119 if (${HAVE_SYS_MMAN_H}) 120 add_definitions(-DHAVE_SYS_MMAN_H) 121 endif () 122 check_include_file(xlocale.h HAVE_XLOCALE_H) 123 if (${HAVE_XLOCALE_H}) 124 add_definitions(-DHAVE_XLOCALE_H) 125 endif () 126 check_include_file(stdbool.h HAVE_STDBOOL_H) 127 if (${HAVE_STDBOOL_H}) 128 add_definitions(-DHAVE_STDBOOL_H) 129 endif () 130 131 132 if (MSVC) 133 add_definitions(-wd4244 -wd4267 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS) 134 endif () 135 136 137 ## Detect if we are running inside a distribution or regular repository folder 138 # if (EXISTS "${PROJECT_SOURCE_DIR}/ChangeLog") 139 # # perhaps we are on dist directory 140 # set (IN_HB_DIST TRUE) 141 # #set (HB_VERSION_H "${PROJECT_SOURCE_DIR}/src/hb-version.h") 142 # endif () 143 144 145 ## Extract variables from Makefile files 146 function (extract_make_variable variable makefile_source) 147 string(REGEX MATCH "${variable} = ([^$]+)\\$" temp ${makefile_source}) 148 string(REGEX MATCHALL "[^ \n\t\\]+" listVar ${CMAKE_MATCH_1}) 149 set (${variable} ${listVar} PARENT_SCOPE) 150 endfunction () 151 152 # http://stackoverflow.com/a/27630120 153 function (add_prefix_to_list var prefix) 154 set (listVar "") 155 foreach (f ${${var}}) 156 list(APPEND listVar "${prefix}${f}") 157 endforeach () 158 set (${var} "${listVar}" PARENT_SCOPE) 159 endfunction () 160 161 file(READ ${PROJECT_SOURCE_DIR}/src/Makefile.sources SRCSOURCES) 162 file(READ ${PROJECT_SOURCE_DIR}/util/Makefile.sources UTILSOURCES) 163 file(READ ${PROJECT_SOURCE_DIR}/src/hb-ucdn/Makefile.sources UCDNSOURCES) 164 165 extract_make_variable(HB_BASE_sources ${SRCSOURCES}) 166 add_prefix_to_list(HB_BASE_sources "${PROJECT_SOURCE_DIR}/src/") 167 extract_make_variable(HB_BASE_headers ${SRCSOURCES}) 168 add_prefix_to_list(HB_BASE_headers "${PROJECT_SOURCE_DIR}/src/") 169 extract_make_variable(HB_FALLBACK_sources ${SRCSOURCES}) 170 add_prefix_to_list(HB_FALLBACK_sources "${PROJECT_SOURCE_DIR}/src/") 171 172 extract_make_variable(HB_SUBSET_sources ${SRCSOURCES}) 173 add_prefix_to_list(HB_SUBSET_sources "${PROJECT_SOURCE_DIR}/src/") 174 175 extract_make_variable(HB_SUBSET_headers ${SRCSOURCES}) 176 add_prefix_to_list(HB_SUBSET_headers "${PROJECT_SOURCE_DIR}/src/") 177 178 extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES}) 179 #if (IN_HB_DIST) 180 add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/") 181 #else () 182 # add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/") 183 #endif () 184 185 extract_make_variable(HB_VIEW_sources ${UTILSOURCES}) 186 add_prefix_to_list(HB_VIEW_sources "${PROJECT_SOURCE_DIR}/util/") 187 extract_make_variable(HB_SHAPE_sources ${UTILSOURCES}) 188 add_prefix_to_list(HB_SHAPE_sources "${PROJECT_SOURCE_DIR}/util/") 189 extract_make_variable(HB_SUBSET_CLI_sources ${UTILSOURCES}) 190 add_prefix_to_list(HB_SUBSET_CLI_sources "${PROJECT_SOURCE_DIR}/util/") 191 extract_make_variable(HB_OT_SHAPE_CLOSURE_sources ${UTILSOURCES}) 192 add_prefix_to_list(HB_OT_SHAPE_CLOSURE_sources "${PROJECT_SOURCE_DIR}/util/") 193 194 extract_make_variable(LIBHB_UCDN_sources ${UCDNSOURCES}) 195 add_prefix_to_list(LIBHB_UCDN_sources "${PROJECT_SOURCE_DIR}/src/hb-ucdn/") 196 197 198 file(READ configure.ac CONFIGUREAC) 199 string(REGEX MATCH "\\[(([0-9]+)\\.([0-9]+)\\.([0-9]+))\\]" HB_VERSION_MATCH ${CONFIGUREAC}) 200 set (HB_VERSION ${CMAKE_MATCH_1}) 201 set (HB_VERSION_MAJOR ${CMAKE_MATCH_2}) 202 set (HB_VERSION_MINOR ${CMAKE_MATCH_3}) 203 set (HB_VERSION_MICRO ${CMAKE_MATCH_4}) 204 205 206 ## Define ragel tasks 207 # if (NOT IN_HB_DIST) 208 # foreach (ragel_output IN ITEMS ${HB_BASE_RAGEL_GENERATED_sources}) 209 # string(REGEX MATCH "([^/]+)\\.hh" temp ${ragel_output}) 210 # set (target_name ${CMAKE_MATCH_1}) 211 # add_custom_command(OUTPUT ${ragel_output} 212 # COMMAND ${RAGEL} -G2 -o ${ragel_output} ${PROJECT_SOURCE_DIR}/src/${target_name}.rl -I ${PROJECT_SOURCE_DIR} ${ARGN} 213 # DEPENDS ${PROJECT_SOURCE_DIR}/src/${target_name}.rl 214 # ) 215 # add_custom_target(harfbuzz_${target_name} DEPENDS ${PROJECT_BINARY_DIR}/src/${target_name}) 216 # endforeach () 217 218 # mark_as_advanced(RAGEL) 219 # endif () 220 221 222 ## Generate hb-version.h 223 # if (NOT IN_HB_DIST) 224 # set (HB_VERSION_H_IN "${PROJECT_SOURCE_DIR}/src/hb-version.h.in") 225 # set (HB_VERSION_H "${PROJECT_BINARY_DIR}/src/hb-version.h") 226 # set_source_files_properties("${HB_VERSION_H}" PROPERTIES GENERATED true) 227 # configure_file("${HB_VERSION_H_IN}" "${HB_VERSION_H}.tmp" @ONLY) 228 # execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different 229 # "${HB_VERSION_H}.tmp" 230 # "${HB_VERSION_H}" 231 # ) 232 # file(REMOVE "${HB_VERSION_H}.tmp") 233 # endif () 234 235 236 ## Define sources and headers of the project 237 set (project_sources 238 ${HB_BASE_sources} 239 ${HB_BASE_RAGEL_GENERATED_sources} 240 241 ${HB_FALLBACK_sources} 242 ) 243 244 set (subset_project_sources 245 ${HB_SUBSET_sources} 246 ) 247 248 set (project_extra_sources) 249 250 set (project_headers 251 #${HB_VERSION_H} 252 253 ${HB_BASE_headers} 254 ) 255 256 set (subset_project_headers 257 ${HB_SUBSET_headers} 258 ) 259 260 261 ## Find and include needed header folders and libraries 262 if (HB_HAVE_FREETYPE) 263 include (FindFreetype) 264 if (NOT FREETYPE_FOUND) 265 message(FATAL_ERROR "HB_HAVE_FREETYPE was set, but we failed to find it. Maybe add a CMAKE_PREFIX_PATH= to your Freetype2 install prefix") 266 endif () 267 268 list(APPEND THIRD_PARTY_LIBS ${FREETYPE_LIBRARIES}) 269 include_directories(AFTER ${FREETYPE_INCLUDE_DIRS}) 270 add_definitions(-DHAVE_FREETYPE=1) 271 272 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ft.cc) 273 list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-ft.h) 274 275 # So check_funcs can find its headers 276 set (CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${FREETYPE_INCLUDE_DIRS}) 277 set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${FREETYPE_LIBRARIES}) 278 279 check_funcs(FT_Get_Var_Blend_Coordinates FT_Set_Var_Blend_Coordinates FT_Done_MM_Var) 280 endif () 281 282 if (HB_HAVE_GRAPHITE2) 283 add_definitions(-DHAVE_GRAPHITE2) 284 285 find_path(GRAPHITE2_INCLUDE_DIR graphite2/Font.h) 286 find_library(GRAPHITE2_LIBRARY graphite2) 287 288 include_directories(${GRAPHITE2_INCLUDE_DIR}) 289 290 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-graphite2.cc) 291 list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-graphite2.h) 292 293 list(APPEND THIRD_PARTY_LIBS ${GRAPHITE2_LIBRARY}) 294 295 mark_as_advanced(GRAPHITE2_INCLUDE_DIR GRAPHITE2_LIBRARY) 296 endif () 297 298 if (HB_BUILTIN_UCDN) 299 include_directories(src/hb-ucdn) 300 add_definitions(-DHAVE_UCDN) 301 302 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-ucdn.cc) 303 list(APPEND project_extra_sources ${LIBHB_UCDN_sources}) 304 endif () 305 306 if (HB_HAVE_GLIB) 307 add_definitions(-DHAVE_GLIB) 308 309 # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindGLIB.cmake 310 find_package(PkgConfig) 311 pkg_check_modules(PC_GLIB QUIET glib-2.0) 312 313 find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS}) 314 find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/include) 315 find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0) 316 317 include_directories(${GLIBCONFIG_INCLUDE_DIR} ${GLIB_INCLUDE_DIR}) 318 319 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-glib.cc) 320 list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-glib.h) 321 322 list(APPEND THIRD_PARTY_LIBS ${GLIB_LIBRARIES}) 323 324 mark_as_advanced(GLIB_LIBRARIES GLIBCONFIG_INCLUDE_DIR GLIB_INCLUDE_DIR) 325 endif () 326 327 if (HB_HAVE_ICU) 328 add_definitions(-DHAVE_ICU) 329 330 # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindICU.cmake 331 find_package(PkgConfig) 332 pkg_check_modules(PC_ICU QUIET icu-uc) 333 334 find_path(ICU_INCLUDE_DIR NAMES unicode/utypes.h HINTS ${PC_ICU_INCLUDE_DIRS} ${PC_ICU_INCLUDEDIR}) 335 find_library(ICU_LIBRARY NAMES libicuuc cygicuuc cygicuuc32 icuuc HINTS ${PC_ICU_LIBRARY_DIRS} ${PC_ICU_LIBDIR}) 336 337 include_directories(${ICU_INCLUDE_DIR}) 338 339 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-icu.cc) 340 list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-icu.h) 341 342 list(APPEND THIRD_PARTY_LIBS ${ICU_LIBRARY}) 343 344 mark_as_advanced(ICU_INCLUDE_DIR ICU_LIBRARY) 345 endif () 346 347 if (APPLE AND HB_HAVE_CORETEXT) 348 # Apple Advanced Typography 349 add_definitions(-DHAVE_CORETEXT) 350 351 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-coretext.cc) 352 list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-coretext.h) 353 354 if (HB_IOS) 355 find_library(COREFOUNDATION CoreFoundation) 356 if (COREFOUNDATION) 357 list(APPEND THIRD_PARTY_LIBS ${COREFOUNDATION}) 358 endif () 359 mark_as_advanced(COREFOUNDATION) 360 361 find_library(CORETEXT CoreText) 362 if (CORETEXT) 363 list(APPEND THIRD_PARTY_LIBS ${CORETEXT}) 364 endif () 365 mark_as_advanced(CORETEXT) 366 367 find_library(COREGRAPHICS CoreGraphics) 368 if (COREGRAPHICS) 369 list(APPEND THIRD_PARTY_LIBS ${COREGRAPHICS}) 370 endif () 371 mark_as_advanced(COREGRAPHICS) 372 else () 373 find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices) 374 if (APPLICATION_SERVICES_FRAMEWORK) 375 list(APPEND THIRD_PARTY_LIBS ${APPLICATION_SERVICES_FRAMEWORK}) 376 endif () 377 378 mark_as_advanced(APPLICATION_SERVICES_FRAMEWORK) 379 endif () 380 endif () 381 382 if (WIN32 AND HB_HAVE_UNISCRIBE) 383 add_definitions(-DHAVE_UNISCRIBE) 384 385 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.cc) 386 list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-uniscribe.h) 387 388 list(APPEND THIRD_PARTY_LIBS usp10 gdi32 rpcrt4) 389 endif () 390 391 if (WIN32 AND HB_HAVE_DIRECTWRITE) 392 add_definitions(-DHAVE_DIRECTWRITE) 393 394 list(APPEND project_sources ${PROJECT_SOURCE_DIR}/src/hb-directwrite.cc) 395 list(APPEND project_headers ${PROJECT_SOURCE_DIR}/src/hb-directwrite.h) 396 397 list(APPEND THIRD_PARTY_LIBS dwrite rpcrt4) 398 endif () 399 400 if (HB_HAVE_GOBJECT) 401 include (FindPerl) 402 403 # Use the hints from glib-2.0.pc to find glib-mkenums 404 find_package(PkgConfig) 405 pkg_check_modules(PC_GLIB QUIET glib-2.0) 406 find_program(GLIB_MKENUMS glib-mkenums 407 HINTS ${PC_glib_mkenums} 408 ) 409 set (GLIB_MKENUMS_CMD) 410 411 if (WIN32 AND NOT MINGW) 412 # In Visual Studio builds, shebang lines are not supported 413 # in the standard cmd.exe shell that we use, so we need to 414 # first determine whether glib-mkenums is a Python or PERL 415 # script 416 execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}" --version 417 RESULT_VARIABLE GLIB_MKENUMS_PYTHON 418 OUTPUT_QUIET ERROR_QUIET 419 ) 420 if (GLIB_MKENUMS_PYTHON EQUAL 0) 421 message("${GLIB_MKENUMS} is a Python script.") 422 set (GLIB_MKENUMS_CMD "${PYTHON_EXECUTABLE}" "${GLIB_MKENUMS}") 423 else () 424 execute_process(COMMAND "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}" --version 425 RESULT_VARIABLE GLIB_MKENUMS_PERL 426 OUTPUT_QUIET ERROR_QUIET 427 ) 428 if (GLIB_MKENUMS_PERL EQUAL 0) 429 message("${GLIB_MKENUMS} is a PERL script.") 430 set (GLIB_MKENUMS_CMD "${PERL_EXECUTABLE}" "${GLIB_MKENUMS}") 431 endif () 432 if (NOT GLIB_MKENUMS_PERL EQUAL 0 AND NOT GLIB_MKENUMS_PYTHON EQUAL 0) 433 message(FATAL_ERROR "Unable to determine type of glib-mkenums script") 434 endif () 435 endif () 436 else () 437 set (GLIB_MKENUMS_CMD "${GLIB_MKENUMS}") 438 endif () 439 if (NOT GLIB_MKENUMS_CMD) 440 message(FATAL_ERROR "HB_HAVE_GOBJECT was set, but we failed to find glib-mkenums, which is required") 441 endif () 442 443 pkg_check_modules(PC_GOBJECT QUIET gobject-2.0) 444 445 find_library(GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS}) 446 find_path(GOBJECT_INCLUDE_DIR NAMES glib-object.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0) 447 448 include_directories(${GOBJECTCONFIG_INCLUDE_DIR} ${GOBJECT_INCLUDE_DIR}) 449 mark_as_advanced(GOBJECT_LIBRARIES GOBJECT_INCLUDE_DIR) 450 451 list(APPEND hb_gobject_sources ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.cc) 452 list(APPEND hb_gobject_gen_sources 453 ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc 454 ) 455 list(APPEND hb_gobject_structs_headers 456 ${PROJECT_SOURCE_DIR}/src/hb-gobject-structs.h 457 ) 458 list(APPEND hb_gobject_headers 459 ${PROJECT_SOURCE_DIR}/src/hb-gobject.h 460 ${hb_gobject_structs_headers} 461 ) 462 list(APPEND hb_gobject_gen_headers 463 ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h 464 ) 465 466 add_custom_command( 467 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h 468 COMMAND ${GLIB_MKENUMS_CMD} 469 --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl 470 --identifier-prefix hb_ 471 --symbol-prefix hb_gobject 472 ${hb_gobject_structs_headers} 473 ${project_headers} 474 > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp 475 COMMAND "${CMAKE_COMMAND}" 476 "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h.tmp" 477 "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h" 478 -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake 479 DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.h.tmpl 480 ${hb_gobject_header} 481 ${project_headers} 482 ) 483 484 add_custom_command( 485 OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc 486 COMMAND ${GLIB_MKENUMS_CMD} 487 --template=${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl 488 --identifier-prefix hb_ 489 --symbol-prefix hb_gobject 490 ${hb_gobject_header} 491 ${project_headers} 492 > ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp 493 COMMAND "${CMAKE_COMMAND}" 494 "-DENUM_INPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc.tmp" 495 "-DENUM_OUTPUT_SRC=${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.cc" 496 -P ${PROJECT_SOURCE_DIR}/replace-enum-strings.cmake 497 DEPENDS ${PROJECT_SOURCE_DIR}/src/hb-gobject-enums.cc.tmpl 498 ${CMAKE_CURRENT_BINARY_DIR}/src/hb-gobject-enums.h 499 ${hb_gobject_header} 500 ${project_headers} 501 ) 502 endif () 503 504 505 ## Atomic ops availability detection 506 file(WRITE "${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c" 507 " void memory_barrier (void) { __sync_synchronize (); } 508 int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); } 509 int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); } 510 void mutex_unlock (int *m) { __sync_lock_release (m); } 511 int main () { return 0; } 512 ") 513 try_compile(HB_HAVE_INTEL_ATOMIC_PRIMITIVES 514 ${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives 515 ${PROJECT_BINARY_DIR}/try_compile_intel_atomic_primitives.c) 516 if (HB_HAVE_INTEL_ATOMIC_PRIMITIVES) 517 add_definitions(-DHAVE_INTEL_ATOMIC_PRIMITIVES) 518 endif () 519 520 file(WRITE "${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c" 521 " #include <atomic.h> 522 /* This requires Solaris Studio 12.2 or newer: */ 523 #include <mbarrier.h> 524 void memory_barrier (void) { __machine_rw_barrier (); } 525 int atomic_add (volatile unsigned *i) { return atomic_add_int_nv (i, 1); } 526 void *atomic_ptr_cmpxchg (volatile void **target, void *cmp, void *newval) { return atomic_cas_ptr (target, cmp, newval); } 527 int main () { return 0; } 528 ") 529 try_compile(HB_HAVE_SOLARIS_ATOMIC_OPS 530 ${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops 531 ${PROJECT_BINARY_DIR}/try_compile_solaris_atomic_ops.c) 532 if (HB_HAVE_SOLARIS_ATOMIC_OPS) 533 add_definitions(-DHAVE_SOLARIS_ATOMIC_OPS) 534 endif () 535 536 537 ## Define harfbuzz library 538 add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_headers}) 539 target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS}) 540 541 ## Define harfbuzz-subset library 542 if (HB_BUILD_SUBSET) 543 add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers}) 544 add_dependencies(harfbuzz-subset harfbuzz) 545 target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS}) 546 547 if (BUILD_SHARED_LIBS) 548 set_target_properties(harfbuzz harfbuzz-subset PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE) 549 endif () 550 endif () 551 552 if (UNIX OR MINGW) 553 # Make symbols link locally 554 include (CheckCXXCompilerFlag) 555 check_cxx_compiler_flag(-Bsymbolic-functions CXX_SUPPORTS_FLAG_BSYMB_FUNCS) 556 if (CXX_SUPPORTS_FLAG_BSYMB_FUNCS) 557 link_libraries(-Bsymbolic-functions) 558 endif () 559 560 if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 561 # Make sure we don't link to libstdc++ 562 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions") 563 set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm 564 set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") 565 set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C) 566 if (HB_BUILD_SUBSET) 567 set_target_properties(harfbuzz-subset PROPERTIES LINKER_LANGUAGE C) 568 endif () 569 570 # No threadsafe statics as we do it ourselves 571 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics") 572 endif () 573 endif () 574 575 ## Define harfbuzz-gobject library 576 if (HB_HAVE_GOBJECT) 577 add_library(harfbuzz-gobject 578 ${hb_gobject_sources} 579 ${hb_gobject_gen_sources} 580 ${hb_gobject_headers} 581 ${hb_gobject_gen_headers} 582 ) 583 include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/src) 584 add_dependencies(harfbuzz-gobject harfbuzz) 585 target_link_libraries(harfbuzz-gobject harfbuzz ${GOBJECT_LIBRARIES} ${THIRD_PARTY_LIBS}) 586 587 if (BUILD_SHARED_LIBS) 588 set_target_properties(harfbuzz-gobject PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE) 589 endif () 590 endif () 591 592 if (BUILD_SHARED_LIBS AND WIN32 AND NOT MINGW) 593 add_definitions("-DHB_DLL_EXPORT") 594 endif () 595 596 # On Windows, g-ir-scanner requires a DLL build in order for it to work 597 if (WIN32) 598 if (NOT BUILD_SHARED_LIBS) 599 message("Building introspection files on Windows requires BUILD_SHARED_LIBS to be enabled.") 600 set (HB_HAVE_INTROSPECTION OFF) 601 endif () 602 endif () 603 604 if (HB_HAVE_INTROSPECTION) 605 606 find_package(PkgConfig) 607 pkg_check_modules(PC_GI QUIET gobject-introspection-1.0) 608 609 find_program(G_IR_SCANNER g-ir-scanner 610 HINTS ${PC_g_ir_scanner} 611 ) 612 613 find_program(G_IR_COMPILER g-ir-compiler 614 HINTS ${PC_g_ir_compiler} 615 ) 616 617 if (WIN32 AND NOT MINGW) 618 # Note that since we already enable HB_HAVE_GOBJECT 619 # we would already have PYTHON_EXECUTABLE handy 620 set (G_IR_SCANNER_CMD "${PYTHON_EXECUTABLE}" "${G_IR_SCANNER}") 621 else () 622 set (G_IR_SCANNER_CMD "${G_IR_SCANNER}") 623 endif () 624 625 # We need to account for the varying output directories 626 # when we build using Visual Studio projects 627 if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*") 628 set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>") 629 else () 630 set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>") 631 endif () 632 633 # Get the CFlags that we used to build HarfBuzz/HarfBuzz-GObject 634 set (hb_defines_cflags "") 635 foreach (hb_cflag ${hb_cflags}) 636 list(APPEND hb_defines_cflags "-D${hb_cflag}") 637 endforeach (hb_cflag) 638 639 # Get the other dependent libraries we used to build HarfBuzz/HarfBuzz-GObject 640 set (extra_libs "") 641 foreach (extra_lib ${THIRD_PARTY_LIBS}) 642 # We don't want the .lib extension here... 643 string(REPLACE ".lib" "" extra_lib_stripped "${extra_lib}") 644 list(APPEND extra_libs "--extra-library=${extra_lib_stripped}") 645 endforeach () 646 647 set (introspected_sources) 648 foreach (f 649 ${project_headers} 650 ${project_sources} 651 ${hb_gobject_gen_sources} 652 ${hb_gobject_gen_headers} 653 ${hb_gobject_sources} 654 ${hb_gobject_headers} 655 ) 656 if (WIN32) 657 # Nasty issue: We need to make drive letters lower case, 658 # otherwise g-ir-scanner won't like it and give us a bunch 659 # of invalid items and unresolved types... 660 STRING(SUBSTRING "${f}" 0 1 drive) 661 STRING(SUBSTRING "${f}" 1 -1 path) 662 if (drive MATCHES "[A-Z]") 663 STRING(TOLOWER ${drive} drive_lower) 664 list(APPEND introspected_sources "${drive_lower}${path}") 665 else () 666 list(APPEND introspected_sources "${f}") 667 endif () 668 else () 669 list(APPEND introspected_sources "${f}") 670 endif () 671 endforeach () 672 673 file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list) 674 foreach (s ${introspected_sources}) 675 file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list "${s}\n") 676 endforeach () 677 678 # Finally, build the introspection files... 679 add_custom_command( 680 TARGET harfbuzz-gobject 681 POST_BUILD 682 COMMAND ${G_IR_SCANNER_CMD} 683 --warn-all --no-libtool --verbose 684 -n hb 685 --namespace=HarfBuzz 686 --nsversion=0.0 687 --identifier-prefix=hb_ 688 --include GObject-2.0 689 --pkg-export=harfbuzz 690 --cflags-begin 691 -I${PROJECT_SOURCE_DIR}/src 692 -I${PROJECT_BINARY_DIR}/src 693 ${hb_includedir_cflags} 694 ${hb_defines_cflags} 695 -DHB_H 696 -DHB_H_IN 697 -DHB_OT_H 698 -DHB_OT_H_IN 699 -DHB_AAT_H 700 -DHB_AAT_H_IN 701 -DHB_GOBJECT_H 702 -DHB_GOBJECT_H_IN 703 -DHB_EXTERN= 704 --cflags-end 705 --library=harfbuzz-gobject 706 --library=harfbuzz 707 -L${hb_libpath} 708 ${extra_libs} 709 --filelist ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list 710 -o ${hb_libpath}/HarfBuzz-0.0.gir 711 DEPENDS harfbuzz-gobject harfbuzz ${CMAKE_CURRENT_BINARY_DIR}/src/hb_gir_list 712 ) 713 714 add_custom_command( 715 TARGET harfbuzz-gobject 716 POST_BUILD 717 COMMAND "${G_IR_COMPILER}" 718 --verbose --debug 719 --includedir ${CMAKE_CURRENT_BINARY_DIR} 720 ${hb_libpath}/HarfBuzz-0.0.gir 721 -o ${hb_libpath}/HarfBuzz-0.0.typelib 722 DEPENDS ${hb_libpath}/HarfBuzz-0.0.gir harfbuzz-gobject 723 ) 724 endif () 725 726 727 ## Additional framework build configs 728 if (BUILD_FRAMEWORK) 729 set (CMAKE_MACOSX_RPATH ON) 730 set_target_properties(harfbuzz PROPERTIES 731 FRAMEWORK TRUE 732 PUBLIC_HEADER "${project_headers}" 733 XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" 734 ) 735 set (MACOSX_FRAMEWORK_IDENTIFIER "harfbuzz") 736 set (MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${HB_VERSION}") 737 set (MACOSX_FRAMEWORK_BUNDLE_VERSION "${HB_VERSION}") 738 endif () 739 740 741 ## Additional harfbuzz build artifacts 742 if (HB_BUILD_UTILS) 743 # https://github.com/WebKit/webkit/blob/master/Source/cmake/FindCairo.cmake 744 find_package(PkgConfig) 745 pkg_check_modules(PC_CAIRO QUIET cairo) 746 747 find_path(CAIRO_INCLUDE_DIRS NAMES cairo.h HINTS ${PC_CAIRO_INCLUDEDIR} ${PC_CAIRO_INCLUDE_DIRS} PATH_SUFFIXES cairo) 748 find_library(CAIRO_LIBRARIESNAMES cairo HINTS ${PC_CAIRO_LIBDIR} ${PC_CAIRO_LIBRARY_DIRS}) 749 750 add_definitions("-DPACKAGE_NAME=\"HarfBuzz\"") 751 add_definitions("-DPACKAGE_VERSION=\"${HB_VERSION}\"") 752 include_directories(${CAIRO_INCLUDE_DIRS}) 753 754 add_executable(hb-view ${HB_VIEW_sources}) 755 target_link_libraries(hb-view harfbuzz ${CAIRO_LIBRARIESNAMES}) 756 757 add_executable(hb-shape ${HB_SHAPE_sources}) 758 target_link_libraries(hb-shape harfbuzz) 759 760 add_executable(hb-subset ${HB_SUBSET_CLI_sources}) 761 target_link_libraries(hb-subset harfbuzz harfbuzz-subset) 762 763 add_executable(hb-ot-shape-closure ${HB_OT_SHAPE_CLOSURE_sources}) 764 target_link_libraries(hb-ot-shape-closure harfbuzz) 765 766 mark_as_advanced(CAIRO_INCLUDE_DIRS CAIRO_LIBRARIESNAMES) 767 endif () 768 769 770 ## Install 771 include (GNUInstallDirs) 772 773 if (NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) 774 install(FILES ${project_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz) 775 if (HB_HAVE_GOBJECT) 776 install(FILES ${hb_gobject_headers} ${hb_gobject_gen_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/harfbuzz) 777 endif () 778 endif () 779 780 if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) 781 install(TARGETS harfbuzz 782 EXPORT harfbuzzConfig 783 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 784 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 785 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 786 FRAMEWORK DESTINATION Library/Frameworks 787 ) 788 install(EXPORT harfbuzzConfig 789 NAMESPACE harfbuzz:: 790 DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/harfbuzz 791 ) 792 if (HB_BUILD_UTILS) 793 if (WIN32 AND BUILD_SHARED_LIBS) 794 install(TARGETS harfbuzz-subset 795 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 796 ) 797 endif () 798 install(TARGETS hb-view 799 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 800 ) 801 install(TARGETS hb-subset 802 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 803 ) 804 805 install(TARGETS hb-shape 806 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 807 ) 808 809 install(TARGETS hb-ot-shape-closure 810 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 811 ) 812 endif () 813 if (HB_HAVE_GOBJECT) 814 install(TARGETS harfbuzz-gobject 815 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 816 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 817 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 818 ) 819 if (HB_HAVE_INTROSPECTION) 820 if ("${CMAKE_GENERATOR}" MATCHES "Visual Studio*") 821 set (hb_libpath "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>") 822 else () 823 set (hb_libpath "$<TARGET_FILE_DIR:harfbuzz-gobject>") 824 endif () 825 826 install(FILES "${hb_libpath}/HarfBuzz-0.0.gir" 827 DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gir-1.0 828 ) 829 830 install(FILES "${hb_libpath}/HarfBuzz-0.0.typelib" 831 DESTINATION ${CMAKE_INSTALL_LIBDIR}/girepository-1.0 832 ) 833 endif () 834 endif () 835 endif () 836 837 if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja") 838 if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 839 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics") 840 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcolor-diagnostics") 841 endif () 842 if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 843 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color") 844 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color") 845 endif () 846 endif () 847 848 849 if (HB_BUILD_TESTS) 850 ## src/ executables 851 foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges) 852 set (prog_name ${prog}) 853 if (${prog_name} STREQUAL "test") 854 # test can not be used as a valid executable name on cmake, lets special case it 855 set (prog_name test-test) 856 endif () 857 add_executable(${prog_name} ${PROJECT_SOURCE_DIR}/src/${prog}.cc) 858 target_link_libraries(${prog_name} harfbuzz ${THIRD_PARTY_LIBS}) 859 endforeach () 860 set_target_properties(hb-ot-tag PROPERTIES COMPILE_FLAGS "-DMAIN") 861 862 ## Tests 863 if (UNIX OR MINGW) 864 if (BUILD_SHARED_LIBS) 865 # generate harfbuzz.def after build completion 866 add_custom_command(TARGET harfbuzz POST_BUILD 867 COMMAND "${PYTHON_EXECUTABLE}" ${PROJECT_SOURCE_DIR}/src/gen-def.py ${PROJECT_BINARY_DIR}/harfbuzz.def ${project_headers} 868 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src) 869 870 add_test(NAME check-static-inits.sh 871 COMMAND ${PROJECT_SOURCE_DIR}/src/check-static-inits.sh 872 WORKING_DIRECTORY ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/harfbuzz.dir/src # ugly hack 873 ) 874 add_test(NAME check-libstdc++.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-libstdc++.sh) 875 add_test(NAME check-symbols.sh COMMAND ${PROJECT_SOURCE_DIR}/src/check-symbols.sh) 876 877 set_tests_properties( 878 check-static-inits.sh check-libstdc++.sh check-symbols.sh 879 PROPERTIES 880 ENVIRONMENT "libs=.;srcdir=${PROJECT_SOURCE_DIR}/src" 881 SKIP_RETURN_CODE 77) 882 endif () 883 884 add_test(NAME check-c-linkage-decls.sh COMMAND ./check-c-linkage-decls.sh) 885 add_test(NAME check-header-guards.sh COMMAND ./check-header-guards.sh) 886 add_test(NAME check-externs.sh COMMAND ./check-externs.sh) 887 add_test(NAME check-includes.sh COMMAND ./check-includes.sh) 888 set_tests_properties( 889 check-c-linkage-decls.sh check-header-guards.sh check-externs.sh check-includes.sh 890 PROPERTIES 891 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src 892 SKIP_RETURN_CODE 77) 893 endif () 894 895 # Needs to come last so that variables defined above are passed to 896 # subdirectories. 897 add_subdirectory(test) 898 endif () 899