cmake_minimum_required(VERSION 3.7.0) project(util-cruft LANGUAGES CXX C) include (nc) include(CheckFunctionExists) include(CheckCXXCompilerFlag) include (search_libs) find_package (Python3 REQUIRED COMPONENTS Interpreter) find_package (RAGEL 6.9 REQUIRED) find_package (fmt REQUIRED) if (WIN32) # Enable features for Windows Vista and higher add_definitions("-D_WIN32_WINNT=0x0600") endif () ############################################################################### include (TestBigEndian) TEST_BIG_ENDIAN(ENDIANNESS) if (ENDIANNESS) add_definitions(-DWORDS_BIGENDIAN) endif() ############################################################################### RAGEL_TARGET(uri uri.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/uri.rl.cpp COMPILE_FLAGS -G2) RAGEL_TARGET(version version.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/version.cpp) RAGEL_TARGET(parse8601 time/parse8601.cpp.rl ${CMAKE_CURRENT_BINARY_DIR}/time/parse8601.cpp) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) ############################################################################### add_library(cruft) target_link_libraries(cruft ${NC_CXX_STDCXXFS} fmt::fmt) # Setup a directory to hold built sources we may need to export to clients. set (PREFIX "cruft/util") file (MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/prefix/${PREFIX}") target_include_directories(cruft PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix/${PREFIX}") target_include_directories(cruft PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/prefix/") target_include_directories(cruft INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/prefix/") # Preemptively define an identity panic macro so that TCL doens't fuck us over # by renaming a commonly used symbol. target_compile_definitions(cruft PUBLIC "-Dpanic=panic") ############################################################################### search_libs (BACKTRACE_LIB backtrace execinfo) search_libs (DBGHELP_LIB SymFromAddr dbghelp) check_function_exists (RtlCaptureStackBackTrace HAVE_CAPTURESTACKBACKTRACE) ##----------------------------------------------------------------------------- if (BACKTRACE_LIB_FOUND) list (APPEND UTIL_FILES backtrace_execinfo.cpp) elseif (HAVE_CAPTURESTACKBACKTRACE) list (APPEND UTIL_FILES backtrace_stackwalk.cpp) target_link_libraries(cruft dbghelp) else () list (APPEND UTIL_FILES backtrace_null.cpp) endif () ############################################################################### # Platform wrappers if (LINUX) list (APPEND UTIL_FILES exe_linux.cpp) elseif (FREEBSD) list (APPEND UTIL_FILES exe_freebsd.cpp) elseif (WIN32) list (APPEND UTIL_FILES exe_win32.cpp) else () message (FATAL_ERROR "unhandled platform") endif () ############################################################################### # platform wrappers list ( APPEND UTIL_FILES posix/dir.cpp posix/dir.hpp posix/except.cpp posix/except.hpp posix/fd.cpp posix/fd.hpp posix/flock.cpp posix/flock.hpp posix/ostream.cpp posix/ostream.hpp posix/util.cpp posix/util.hpp ) ##----------------------------------------------------------------------------- if (LINUX) list (APPEND UTIL_FILES thread/event_futex.cpp thread/flag_futex.cpp rand/system_linux.cpp rand/system_linux.hpp ) endif () ##----------------------------------------------------------------------------- if (NOT WIN32) list ( APPEND UTIL_FILES buffer/circular.cpp buffer/circular.hpp buffer/paged.cpp buffer/paged.hpp memory/system.cpp memory/system.hpp debug_posix.cpp debug/crash_posix.cpp debug/fpe_posix.cpp debug/system_posix.cpp io_posix.cpp io_posix.hpp library_posix.hpp library_posix.cpp paths_posix.cpp posix/fwd.hpp posix/interface.hpp posix/interface.cpp posix/map.cpp posix/map.hpp posix/socket.cpp posix/socket.hpp time_posix.cpp ) endif () ##----------------------------------------------------------------------------- if (WIN32) list ( APPEND UTIL_FILES debug_win32.cpp debug/crash_win32.cpp debug/fpe_win32.cpp debug/system_win32.cpp exe_win32.cpp io_win32.cpp io_win32.hpp library_win32.cpp library_win32.hpp paths_win32.cpp rand/system_win32.cpp rand/system_win32.hpp time_win32.cpp win32/windows.hpp win32/except.cpp win32/except.hpp win32/file.cpp win32/file.hpp win32/handle.cpp win32/handle.hpp win32/registry.cpp win32/registry.hpp ) target_link_libraries (cruft ws2_32) endif () ############################################################################### list (APPEND UTIL_FILES thread/event.hpp thread/flag.hpp thread/primitive.hpp thread/semaphore.hpp ) if (LINUX) list (APPEND UTIL_FILES thread/event_futex.cpp thread/event_futex.hpp thread/semaphore_linux.hpp thread/semaphore_linux.cpp thread/flag_futex.cpp thread/flag_futex.hpp ) elseif (WIN32) list (APPEND UTIL_FILES thread/event_std.cpp thread/event_std.hpp thread/event_win32.cpp thread/semaphore_win32.hpp thread/semaphore_win32.cpp thread/flag_std.cpp thread/flag_std.hpp ) else () message (FATAL_ERROR "Unsupported thread platform") endif () if (host_cpu STREQUAL "x86_64") list (APPEND UTIL_FILES cpuid/x86.cpp cpuid/x86.hpp ) else () message (WARNING "Unknown architecture ${host_cpu}. Defaulting to null implementation") list (APPEND UTIL_FILES cpuid/none.cpp cpuid/none.hpp ) endif () if (WIN32) list (APPEND UTIL_FILES sysinfo_win32.cpp) else () list (APPEND UTIL_FILES sysinfo_posix.cpp) endif () ############################################################################### # Common files list ( APPEND UTIL_FILES fwd.hpp adapter.hpp adapter.cpp algo/search.hpp algo/sort.cpp algo/sort.hpp alloc/fwd.hpp alloc/affix.cpp alloc/affix.hpp alloc/aligned/direct.hpp alloc/aligned/foreign.hpp alloc/allocator.cpp alloc/allocator.hpp alloc/chunked.cpp alloc/chunked.hpp alloc/easy.hpp alloc/fallback.cpp alloc/fallback.hpp alloc/linear.cpp alloc/linear.hpp alloc/malloc.cpp alloc/malloc.hpp alloc/null.cpp alloc/null.hpp alloc/stack.cpp alloc/stack.hpp alloc/std.hpp alloc/traits.hpp alloc/traits.hpp annotation.hpp array/darray.hpp array/md.cpp array/md.hpp array/parray.cpp array/parray.hpp array/sarray.cpp array/sarray.hpp array/varray.hpp ascii.hpp backtrace.hpp bezier.cpp bezier1.cpp bezier2.cpp bezier3.cpp bezier.hpp bitwise.cpp bitwise.hpp bool.cpp bool.hpp buffer/simple.cpp buffer/simple.hpp buffer/traits.hpp cast.hpp cmdopt.cpp cmdopt.hpp cmdopt2/fwd.hpp cmdopt2/args.cpp cmdopt2/args.hpp cmdopt2/parser.cpp cmdopt2/parser.hpp colour.cpp colour.hpp concepts.hpp concepts/clock.hpp concepts/string.hpp container.hpp coord.hpp coord/fwd.hpp coord/base.hpp coord/comparator.hpp coord/init.hpp coord/iostream.hpp coord/ops.hpp coord/store.hpp coord/traits.hpp cpp.cpp cpp.hpp cpuid.cpp cpuid.hpp debug/assert.cpp debug/assert.hpp debug/common.cpp debug/common.hpp debug/compiler.cpp debug/compiler.hpp debug/crash.hpp debug/debugger.cpp debug/debugger.hpp debug/fpe.hpp debug/fpe.cpp debug/memory.cpp debug/memory.hpp debug/panic.cpp debug/panic.hpp debug/system.cpp debug/system.hpp debug/trace.cpp debug/trace.hpp debug/validate.cpp debug/validate.hpp debug/warn.cpp debug/warn.hpp encode/number.hpp encode/base.cpp encode/base.hpp endian.cpp endian.hpp except.cpp except.hpp exe.hpp expected.hpp extent.cpp extent.hpp fixed.cpp fixed.hpp fixed_string.hpp float.cpp float.hpp format/quoted.hpp fourcc.cpp fourcc.hpp fs/scoped.cpp fs/scoped.hpp fs/tmp_posix.cpp fs/tmp.hpp functor.hpp geom/fwd.hpp geom/aabb.cpp geom/aabb.hpp geom/cylinder.cpp geom/cylinder.hpp geom/ellipse.cpp geom/ellipse.hpp geom/frustum.cpp geom/frustum.hpp geom/iostream.cpp geom/iostream.hpp geom/line.hpp geom/line.cpp geom/ops.cpp geom/ops.hpp geom/plane.cpp geom/plane.hpp geom/ray.cpp geom/ray.hpp geom/rect.cpp geom/rect.hpp geom/region.cpp geom/sample/fwd.hpp geom/sample/edge.hpp geom/sample/surface.hpp geom/sample/volume.hpp geom/sample/subregion.hpp geom/segment.cpp geom/segment.hpp geom/sphere.cpp geom/sphere.hpp geom/traits.hpp geom/tri.cpp geom/tri.hpp hash.hpp hash/fwd.hpp hash/adapter.hpp hash/adler.cpp hash/adler.hpp hash/buzhash.hpp hash/bsdsum.cpp hash/bsdsum.hpp hash/crc.cpp hash/crc.hpp hash/fasthash.cpp hash/fasthash.hpp hash/fletcher.cpp hash/fletcher.hpp hash/fnv1a.cpp hash/fnv1a.hpp hash/halfsipmix.cpp hash/halfsipmix.hpp hash/mix.cpp hash/mix.hpp hash/murmur/common.cpp hash/murmur/common.hpp hash/murmur.hpp hash/murmur/murmur1.cpp hash/murmur/murmur1.hpp hash/murmur/murmur2.cpp hash/murmur/murmur2.hpp hash/murmur/murmur3.cpp hash/murmur/murmur3.hpp hash/siphash.cpp hash/siphash.hpp hash/std.cpp hash/std.hpp hash/table.cpp hash/table.hpp hash/tuple.cpp hash/tuple.hpp hash/wang.hpp hash/xxhash.cpp hash/xxhash.hpp init.cpp init.hpp introspection/enum_manual.cpp introspection/enum_manual.hpp introspection/enum_simple.cpp introspection/enum_simple.hpp introspection/name.cpp introspection/name.hpp introspection/type.cpp introspection/type.hpp io.cpp io.hpp iterator/cast.hpp iterator/constant.hpp iterator/counting.hpp iterator/dereference.hpp iterator/discard.hpp iterator/indices.hpp iterator/infix.hpp iterator/iota.hpp iterator/numeric.hpp iterator/placement_output.hpp iterator/referencing.hpp iterator/transform.hpp iterator/tuple_picker.hpp iterator/unequal.hpp iterator/unordered_insert.hpp iterator/zip.hpp job/fwd.hpp job/dispatch.hpp job/queue.cpp job/queue.hpp kmeans.hpp library.hpp list/node.hpp list/sort.hpp log.hpp log/fwd.hpp log/level.cpp log/level.hpp log/log.cpp log/log.hpp log/packet.cpp log/packet.hpp log/scoped.cpp log/scoped.hpp log/sink/base.cpp log/sink/base.hpp log/sink/console.cpp log/sink/console.hpp log/sink/null.cpp log/sink/null.hpp log/sink/path.cpp log/sink/path.hpp map/multi_fixed.cpp map/multi_fixed.hpp map/fixed.cpp map/fixed.hpp maths.cpp maths.hpp maths/fast.hpp matrix.cpp matrix2.cpp matrix3.cpp matrix4.cpp matrix.hpp memory/deleter.cpp memory/deleter.hpp parallel/queue.cpp parallel/queue.hpp parallel/stack.cpp parallel/stack.hpp parse/fwd.hpp parse/enum.cpp parse/enum.hpp parse/time.cpp parse/time.hpp parse/value.cpp parse/value.hpp parse/si.cpp parse/si.hpp paths.cpp paths.hpp platform.hpp point.cpp point.hpp pointer.hpp polynomial.cpp polynomial.hpp pool.cpp pool.hpp "${CMAKE_CURRENT_BINARY_DIR}/prefix/${PREFIX}/preprocessor.hpp" quaternion.cpp quaternion.hpp rand/distribution/normal.cpp rand/distribution/normal.hpp rand/distribution/uniform.cpp rand/distribution/uniform.hpp rand/generic.hpp rand/lcg.cpp rand/lcg.hpp rand/mwc64x.cpp rand/mwc64x.hpp rand/pcg.cpp rand/pcg.hpp rand/rdrand.cpp rand/rdrand.hpp rand/splitmix64.hpp rand/system.hpp rand/xoshiro.cpp rand/xoshiro.hpp rand/xorshift.cpp rand/xorshift.hpp random.cpp random.hpp range.cpp range.hpp rational.cpp rational.hpp region.cpp region.hpp registrar.cpp registrar.hpp roots/bisection.hpp scoped.hpp serialise/converter.hpp serialise/ops.hpp serialise/std.hpp set/dset.cpp set/dset.hpp signal.cpp signal.hpp singleton.hpp stats.cpp stats.hpp std.hpp stream.cpp stream.hpp string.cpp string.hpp stringcache.cpp stringcache.hpp stringid.cpp stringid.hpp strongdef.cpp strongdef.hpp sysinfo.hpp tap.cpp tap.hpp term.cpp term.hpp thread/event.hpp thread/flag.hpp thread/monitor.cpp thread/monitor.hpp thread/ticketlock.cpp thread/ticketlock.hpp thread/spinlock.cpp thread/spinlock.hpp time.cpp time.hpp time/parse.hpp time/parse8601.cpp tuple/index.hpp tuple/type.hpp tuple/value.hpp typeidx.cpp typeidx.hpp types.hpp types/sized.hpp types/comparator.hpp types/description.cpp types/description.hpp types/dispatch.hpp types/string.cpp types/string.hpp types/tagged.hpp types/traits.hpp uri.cpp uri.rl.cpp uri.hpp utf8.cpp utf8.hpp variadic.cpp variadic.hpp vector.cpp vector.hpp version.cpp version.hpp view.cpp view.hpp ) option (SIMD "enable simd support" OFF) if (SIMD) list (APPEND UTIL_FILES "coord/simd.cpp" "coord/simd.hpp" "coord/simd_sse.hpp" "coord/simd_neon.hpp" ) endif () ##----------------------------------------------------------------------------- ## We shouldn't be building into the source directory, but I can't stand trying ## to coax CMake into behaving here any longer. Feel free to fix it. add_custom_command ( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/prefix/${PREFIX}/preprocessor.hpp" COMMENT "[preprocessor.py] preprocessor.hpp" COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/preprocessor.py" "${CMAKE_CURRENT_BINARY_DIR}/prefix/${PREFIX}/preprocessor.hpp" 480 DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/preprocessor.py" ) ############################################################################### target_sources(cruft PRIVATE ${UTIL_FILES}) add_library(cruft-util ALIAS cruft) target_include_directories(cruft PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") install (TARGETS cruft LIBRARY COMPONENT development) set (headers ${UTIL_FILES}) list (FILTER headers INCLUDE REGEX "\\.hpp$") install (FILES ${headers} DESTINATION "include/cruft/util" COMPONENT development) search_libs (SHM_LIBS shm_open rt) search_libs (DL_LIBS dlopen dl) search_libs (CLOCK_LIBS clock_gettime rt c) search_libs (MATH_LIBS cos m) target_link_libraries(cruft ${SHM_LIBS}) target_link_libraries(cruft ${DL_LIBS}) target_link_libraries(cruft ${CLOCK_LIBS}) target_link_libraries(cruft ${MATH_LIBS}) # HACK: -ldl isn't getting discovered correctly so we add it unconditionally # for the time being. if (NOT WIN32) target_link_libraries(cruft dl) endif () ############################################################################### foreach (tool backtrace cpuid crash log poisson macro scratch) add_executable (util_${tool} tools/${tool}.cpp) set_target_properties (util_${tool} PROPERTIES OUTPUT_NAME ${tool}) target_link_libraries (util_${tool} cruft) target_include_directories(util_${tool} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(util_${tool} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix/${PREFIX}") endforeach () ############################################################################### option (TESTS "enable unit testing" ON) if (TESTS) include(CTest) enable_testing() list ( APPEND TEST_BIN ascii algo/search algo/sort alloc/aligned/foreign alloc/aligned/direct alloc/easy alloc/linear alloc/stack affine array/darray array/sarray array/parray backtrace bezier bitwise bool buffer/simple cmdopt cmdopt2 colour concepts comparator coord debug/fpe encode/number encode/base endian exe expected extent fixed float format/quoted fs/scoped fs/tmp geom/aabb geom/ellipse geom/frustum geom/line geom/plane geom/ray geom/sample/edge geom/sample/subregion geom/segment geom/sphere hash/buzhash hash/checksum hash/crc hash/fasthash hash/fnv1a hash/halfsipmix hash/murmur hash/siphash hash/table hash/tuple hash/xxhash hton io introspection introspection/enum_simple iterator job/dispatch job/queue kmeans list/sort map/fixed map/multi_fixed maths maths/fast matrix memory/deleter parallel/queue parallel/stack parse/enum parse/value parse/time parse/si paths point polynomial pool preprocessor quaternion rand/buckets rand/generator/normal random range rational region registrar roots/bisection scoped serialise set/dset signal singleton stream string stringid stringcache strongdef thread/event thread/flag thread/monitor thread/semaphore thread/spinlock thread/ticketlock time/8601 traits tuple/index tuple/value tuple/type typeidx types/description types/tagged uri utf8 vector version view ) if (NOT WIN32) list (APPEND TEST_BIN buffer/circular buffer/paged ) endif () if (SIMD) list (APPEND TEST_BIN coord/simd ) endif() add_custom_target(util_test) foreach(t ${TEST_BIN}) string(REPLACE "/" "_" name "test/${t}") add_executable(util_${name} test/${t}.cpp) target_link_libraries(util_${name} PRIVATE cruft) target_include_directories(util_${name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(util_${name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix/${PREFIX}") add_test(NAME util_${name} COMMAND util_${name}) set_tests_properties(util_${name} PROPERTIES FAIL_REGULAR_EXPRESSION "not ok -") add_dependencies(util_test util_${name}) endforeach(t) configure_file (test/cpp.py.in util_test_cpp.py @ONLY) add_test (NAME util_test_cpp COMMAND ${Python3_EXECUTABLE} util_test_cpp.py) set_property (TEST util_test_cpp APPEND PROPERTY DEPENDS util_macro) set_tests_properties(util_test_cpp PROPERTIES FAIL_REGULAR_EXPRESSION "not ok -") endif () ############################################################################### configure_file(libcruft.pc.in libcruft.pc @ONLY) install ( FILES "${CMAKE_CURRENT_BINARY_DIR}/libcruft.pc" DESTINATION "share/pkgconfig" COMPONENT development ) configure_file(Doxyfile.in Doxyfile)