cmake_minimum_required(VERSION 3.16)
project(nwflaim VERSION 1.0 LANGUAGES CXX)

include(GNUInstallDirs)
include(CTest)

option(NWFLAIM_BUILD_SHARED "Build shared nwflaim libraries" ON)
option(NWFLAIM_BUILD_STATIC "Build static nwflaim libraries" OFF)
option(NWFLAIM_BUILD_SQL "Build SQL FLAIM library" ON)
option(NWFLAIM_BUILD_XFLAIM "Build XML FLAIM library" ON)
option(NWFLAIM_BUILD_TOOLS "Build installable FLAIM command line tools with nw-prefixed names" ON)
option(NWFLAIM_WITH_OPENSSL "Build FTK legacy OpenSSL/TLS helpers" ON)
option(NWFLAIM_USE_NICI "Build FLAIM NICI/CCS encrypted-storage path" OFF)
set(NWFLAIM_SSL_TARGET "" CACHE STRING "Optional SSL/Crypto target, for example mars_nwe::ssl")
set(NWFLAIM_NICI_INCLUDE_DIR "" CACHE PATH "Optional private NICI/CCS compatibility include directory")
set(NWFLAIM_LIBRARY_PREFIX nw CACHE STRING "Library output prefix used to avoid system FLAIM collisions")
# Hard-coded from the individual upstream configure.ac files.  FLAIM is
# effectively frozen, so keep this simple and explicit instead of parsing
# autotools metadata during the CMake configure step.
set(NWFLAIM_FTK_LIBRARY_VERSION 1.2 CACHE STRING "FTK library version from ftk/configure.ac")
set(NWFLAIM_FTK_LIBRARY_SOVERSION 1 CACHE STRING "FTK ABI version")
set(NWFLAIM_FLAIM_LIBRARY_VERSION 4.62 CACHE STRING "FLAIM library version from flaim/src/flaim.h")
set(NWFLAIM_FLAIM_LIBRARY_SOVERSION 4 CACHE STRING "FLAIM ABI version")
set(NWFLAIM_SQL_LIBRARY_VERSION 6.00 CACHE STRING "SQL FLAIM library version from sql/src/flaimsql.h")
set(NWFLAIM_SQL_LIBRARY_SOVERSION 6 CACHE STRING "SQL FLAIM ABI version")
set(NWFLAIM_XFLAIM_LIBRARY_VERSION 5.12 CACHE STRING "XFLAIM library version from xflaim/src/xflaim.h")
set(NWFLAIM_XFLAIM_LIBRARY_SOVERSION 5 CACHE STRING "XFLAIM ABI version")

if(NOT NWFLAIM_BUILD_SHARED AND NOT NWFLAIM_BUILD_STATIC)
    message(FATAL_ERROR "Enable at least one of NWFLAIM_BUILD_SHARED or NWFLAIM_BUILD_STATIC")
endif()

set(_nwflaim_common_defs
    N_PLAT_UNIX
    _LARGEFILE64_SOURCE
    _FILE_OFFSET_BITS=64
    _REENTRANT)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    list(APPEND _nwflaim_common_defs FLM_64BIT)
endif()
if(NWFLAIM_USE_NICI)
    list(APPEND _nwflaim_common_defs FLM_USE_NICI)
endif()

find_package(Threads REQUIRED)
find_library(NWFLAIM_RT_LIBRARY rt)
find_library(NWFLAIM_DL_LIBRARY dl)
find_package(Curses QUIET)
if(CURSES_FOUND)
    set(_nwflaim_curses_include_dirs "")
    if(CURSES_INCLUDE_DIRS)
        set(_nwflaim_curses_include_dirs "${CURSES_INCLUDE_DIRS}")
    elseif(CURSES_INCLUDE_DIR)
        set(_nwflaim_curses_include_dirs "${CURSES_INCLUDE_DIR}")
    endif()

    message(STATUS "NWFLAIM: curses/ncurses found")
    if(_nwflaim_curses_include_dirs)
        message(STATUS "NWFLAIM: curses include dirs: ${_nwflaim_curses_include_dirs}")
    else()
        message(STATUS "NWFLAIM: curses include dirs: <none reported>")
    endif()
    if(CURSES_LIBRARIES)
        message(STATUS "NWFLAIM: curses libraries: ${CURSES_LIBRARIES}")
    else()
        message(STATUS "NWFLAIM: curses libraries: <none reported>")
    endif()
    if(NWFLAIM_BUILD_TOOLS)
        message(STATUS "NWFLAIM: tools enabled; curses-backed tools will be built")
    endif()
else()
    message(STATUS "NWFLAIM: curses/ncurses not found")
endif()
if(NWFLAIM_BUILD_TOOLS AND NOT CURSES_FOUND)
    message(FATAL_ERROR "NWFLAIM_BUILD_TOOLS requires curses/ncurses")
endif()

set(_nwflaim_ssl_target "")
if(NWFLAIM_WITH_OPENSSL)
    if(NOT NWFLAIM_SSL_TARGET STREQUAL "")
        if(NOT TARGET ${NWFLAIM_SSL_TARGET})
            message(FATAL_ERROR "NWFLAIM_SSL_TARGET=${NWFLAIM_SSL_TARGET} is not a CMake target")
        endif()
        set(_nwflaim_ssl_target ${NWFLAIM_SSL_TARGET})
    elseif(TARGET mars_nwe::ssl)
        set(_nwflaim_ssl_target mars_nwe::ssl)
    else()
        find_package(OpenSSL REQUIRED COMPONENTS SSL Crypto)
        set(_nwflaim_ssl_target OpenSSL::SSL OpenSSL::Crypto)
    endif()
    list(APPEND _nwflaim_common_defs FLM_OPENSSL)
endif()

set(NWFLAIM_FTK_SOURCES
    ftk/src/ftkarg.cpp
    ftk/src/ftkbtree.cpp
    ftk/src/ftkcmem.cpp
    ftk/src/ftkcoll.cpp
    ftk/src/ftkcsum.cpp
    ftk/src/ftkdir.cpp
    ftk/src/ftkdynbtree.cpp
    ftk/src/ftkdynrset.cpp
    ftk/src/ftkerror.cpp
    ftk/src/ftkfsys.cpp
    ftk/src/ftkhttp.cpp
    ftk/src/ftkini.cpp
    ftk/src/ftkiobuf.cpp
    ftk/src/ftklock.cpp
    ftk/src/ftklog.cpp
    ftk/src/ftkmem.cpp
    ftk/src/ftkmfh.cpp
    ftk/src/ftkmisc.cpp
    ftk/src/ftknet.cpp
    ftk/src/ftknlm.cpp
    ftk/src/ftkntab.cpp
    ftk/src/ftkprntf.cpp
    ftk/src/ftkrand.cpp
    ftk/src/ftkrset.cpp
    ftk/src/ftksem.cpp
    ftk/src/ftkstrm.cpp
    ftk/src/ftksupr.cpp
    ftk/src/ftktext.cpp
    ftk/src/ftkthrd.cpp
    ftk/src/ftktime.cpp
    ftk/src/ftkunix.cpp
    ftk/src/ftkwin.cpp
    ftk/src/ftkxml.cpp)

if(CURSES_FOUND)
    list(APPEND NWFLAIM_FTK_SOURCES ftk/src/ftkftx.cpp)
else()
    message(STATUS "Curses not found; building libnwflaimtk without console FTX helpers")
endif()

set(NWFLAIM_FLAIM_SOURCES
    flaim/src/checksum.cpp
    flaim/src/fblob.cpp
    flaim/src/fcs.cpp
    flaim/src/fdbcnfig.cpp
    flaim/src/fdbcopy.cpp
    flaim/src/fdb.cpp
    flaim/src/fdbremov.cpp
    flaim/src/fdbrenam.cpp
    flaim/src/fdict.cpp
    flaim/src/ffilehdr.cpp
    flaim/src/fgedcom.cpp
    flaim/src/flbackup.cpp
    flaim/src/flchkdb.cpp
    flaim/src/flclose.cpp
    flaim/src/flconvrt.cpp
    flaim/src/flcreate.cpp
    flaim/src/fldbglog.cpp
    flaim/src/flerror.cpp
    flaim/src/flindex.cpp
    flaim/src/flkeyret.cpp
    flaim/src/flmimon.cpp
    flaim/src/flmstat.cpp
    flaim/src/flopen.cpp
    flaim/src/flrddrct.cpp
    flaim/src/flreduce.cpp
    flaim/src/flsweep.cpp
    flaim/src/flupdate.cpp
    flaim/src/flverify.cpp
    flaim/src/fmisc.cpp
    flaim/src/f_nici.cpp
    flaim/src/fntable.cpp
    flaim/src/fnumber.cpp
    flaim/src/fqcur.cpp
    flaim/src/fqdecl.cpp
    flaim/src/fqeval.cpp
    flaim/src/fqget.cpp
    flaim/src/fqkeys.cpp
    flaim/src/fqlog.cpp
    flaim/src/fqopt.cpp
    flaim/src/fqparse.cpp
    flaim/src/fqprep.cpp
    flaim/src/fqread.cpp
    flaim/src/fqsrch.cpp
    flaim/src/fqstack.cpp
    flaim/src/frebuild.cpp
    flaim/src/frec.cpp
    flaim/src/frecset.cpp
    flaim/src/fsblk_u.cpp
    flaim/src/fscomblk.cpp
    flaim/src/fsconvrt.cpp
    flaim/src/fscounts.cpp
    flaim/src/fscursor.cpp
    flaim/src/fsdatacu.cpp
    flaim/src/fsdelelm.cpp
    flaim/src/fsinselm.cpp
    flaim/src/fslfile.cpp
    flaim/src/fslfileu.cpp
    flaim/src/fsnext.cpp
    flaim/src/fsprev.cpp
    flaim/src/fsrecget.cpp
    flaim/src/fsrecupd.cpp
    flaim/src/fsrefspl.cpp
    flaim/src/fsrefupd.cpp
    flaim/src/fssearch.cpp
    flaim/src/fssplblk.cpp
    flaim/src/fsv.cpp
    flaim/src/fsysdata.cpp
    flaim/src/ftext.cpp
    flaim/src/ftrans.cpp
    flaim/src/furl.cpp
    flaim/src/imonbase.cpp
    flaim/src/imonchk.cpp
    flaim/src/imonerr.cpp
    flaim/src/imonfact.cpp
    flaim/src/imonfdb.cpp
    flaim/src/imonffil.cpp
    flaim/src/imonfhsh.cpp
    flaim/src/imonfram.cpp
    flaim/src/imonfsys.cpp
    flaim/src/imonix.cpp
    flaim/src/imonlhdr.cpp
    flaim/src/imonqury.cpp
    flaim/src/imonrche.cpp
    flaim/src/imonrec.cpp
    flaim/src/imonscfg.cpp
    flaim/src/imonsche.cpp
    flaim/src/imonsel.cpp
    flaim/src/imonstat.cpp
    flaim/src/imonutil.cpp
    flaim/src/kybuild.cpp
    flaim/src/kycollat.cpp
    flaim/src/kyget.cpp
    flaim/src/lock.cpp
    flaim/src/rcache.cpp
    flaim/src/recover.cpp
    flaim/src/rfl.cpp
    flaim/src/scache.cpp
    flaim/src/translog.cpp)

set(NWFLAIM_SQL_SOURCES
    sql/src/btreeinfo.cpp
    sql/src/checksum.cpp
    sql/src/createdatabase.cpp
    sql/src/createindex.cpp
    sql/src/createtable.cpp
    sql/src/deleterow.cpp
    sql/src/dropdatabase.cpp
    sql/src/dropindex.cpp
    sql/src/droptable.cpp
    sql/src/f_btpool.cpp
    sql/src/f_btree.cpp
    sql/src/fbtrset.cpp
    sql/src/fcollate.cpp
    sql/src/fdbcnfig.cpp
    sql/src/fdbcopy.cpp
    sql/src/fdbrenam.cpp
    sql/src/fdict.cpp
    sql/src/fdllmain.cpp
    sql/src/fdynbuf.cpp
    sql/src/ffilehdr.cpp
    sql/src/flbackup.cpp
    sql/src/flclose.cpp
    sql/src/flconvrt.cpp
    sql/src/fldbglog.cpp
    sql/src/flerror.cpp
    sql/src/flgethdr.cpp
    sql/src/flindex.cpp
    sql/src/flkeyret.cpp
    sql/src/flmstat.cpp
    sql/src/flog.cpp
    sql/src/flreduce.cpp
    sql/src/fltrabrt.cpp
    sql/src/fltrbeg.cpp
    sql/src/fltrcmit.cpp
    sql/src/f_nici.cpp
    sql/src/fnumber.cpp
    sql/src/frestore.cpp
    sql/src/frow.cpp
    sql/src/fsblk_u.cpp
    sql/src/fscursor.cpp
    sql/src/fsdatacu.cpp
    sql/src/fslfile.cpp
    sql/src/fslfileu.cpp
    sql/src/fsrefupd.cpp
    sql/src/fsysdata.cpp
    sql/src/funicode.cpp
    sql/src/fvector.cpp
    sql/src/insertrow.cpp
    sql/src/kybldkey.cpp
    sql/src/kybuild.cpp
    sql/src/kycollat.cpp
    sql/src/kyeword.cpp
    sql/src/kyqsort.cpp
    sql/src/kyunlock.cpp
    sql/src/opendatabase.cpp
    sql/src/recover.cpp
    sql/src/rfl.cpp
    sql/src/scache.cpp
    sql/src/select.cpp
    sql/src/sqleval.cpp
    sql/src/sqloptimize.cpp
    sql/src/sqlstatement.cpp
    sql/src/translog.cpp
    sql/src/updaterow.cpp
    sql/src/whereclause.cpp)

set(NWFLAIM_XFLAIM_SOURCES
    xflaim/src/btreeinfo.cpp
    xflaim/src/f_btpool.cpp
    xflaim/src/f_btree.cpp
    xflaim/src/fbtrset.cpp
    xflaim/src/f_ccs.cpp
    xflaim/src/fcollate.cpp
    xflaim/src/fdbcnfig.cpp
    xflaim/src/fdbcopy.cpp
    xflaim/src/fdbremov.cpp
    xflaim/src/fdbrenam.cpp
    xflaim/src/fdict.cpp
    xflaim/src/fdllmain.cpp
    xflaim/src/fdoclist.cpp
    xflaim/src/fdom.cpp
    xflaim/src/ffilehdr.cpp
    xflaim/src/flbackup.cpp
    xflaim/src/flblddb.cpp
    xflaim/src/flchkdb.cpp
    xflaim/src/flchkix.cpp
    xflaim/src/flchktr.cpp
    xflaim/src/flclose.cpp
    xflaim/src/flconvrt.cpp
    xflaim/src/flcreate.cpp
    xflaim/src/fldbglog.cpp
    xflaim/src/flerror.cpp
    xflaim/src/flindex.cpp
    xflaim/src/flkeyret.cpp
    xflaim/src/flmstat.cpp
    xflaim/src/flog.cpp
    xflaim/src/flopen.cpp
    xflaim/src/flreduce.cpp
    xflaim/src/flsweep.cpp
    xflaim/src/fltrabrt.cpp
    xflaim/src/fltrbeg.cpp
    xflaim/src/fltrcmit.cpp
    xflaim/src/flverify.cpp
    xflaim/src/f_nici.cpp
    xflaim/src/fntable.cpp
    xflaim/src/fnumber.cpp
    xflaim/src/fqeval.cpp
    xflaim/src/fqsort.cpp
    xflaim/src/fquery.cpp
    xflaim/src/frestore.cpp
    xflaim/src/fsblk_u.cpp
    xflaim/src/fscursor.cpp
    xflaim/src/fsdatacu.cpp
    xflaim/src/fslfile.cpp
    xflaim/src/fslfileu.cpp
    xflaim/src/fsrefupd.cpp
    xflaim/src/fsysdata.cpp
    xflaim/src/funicode.cpp
    xflaim/src/fvector.cpp
    xflaim/src/fxml.cpp
    xflaim/src/fxpath.cpp
    xflaim/src/kybldkey.cpp
    xflaim/src/kybuild.cpp
    xflaim/src/kycollat.cpp
    xflaim/src/kyeword.cpp
    xflaim/src/kyqsort.cpp
    xflaim/src/kyunlock.cpp
    xflaim/src/ncache.cpp
    xflaim/src/nodeinfo.cpp
    xflaim/src/recover.cpp
    xflaim/src/rfl.cpp
    xflaim/src/scache.cpp
    xflaim/src/translog.cpp)

function(nwflaim_common_target target_name public_include_dir install_include_dir)
    target_compile_features(${target_name} PUBLIC cxx_std_98)
    target_compile_definitions(${target_name} PRIVATE ${_nwflaim_common_defs})
    target_include_directories(${target_name}
        PUBLIC
            "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${public_include_dir}>"
            "$<INSTALL_INTERFACE:${install_include_dir}>"
        PRIVATE
            "${CMAKE_CURRENT_SOURCE_DIR}/ftk/src"
            "${CMAKE_CURRENT_SOURCE_DIR}/flaim/src"
            "${CMAKE_CURRENT_SOURCE_DIR}/sql/src"
            "${CMAKE_CURRENT_SOURCE_DIR}/xflaim/src")
    if(NWFLAIM_USE_NICI AND NOT NWFLAIM_NICI_INCLUDE_DIR STREQUAL "")
        target_include_directories(${target_name} PRIVATE "${NWFLAIM_NICI_INCLUDE_DIR}")
    endif()
    target_link_libraries(${target_name} PUBLIC Threads::Threads)
    if(CURSES_INCLUDE_DIRS)
        target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIRS})
    elseif(CURSES_INCLUDE_DIR)
        target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIR})
    endif()
    if(CURSES_LIBRARIES)
        target_link_libraries(${target_name} PUBLIC ${CURSES_LIBRARIES})
    endif()
    if(NWFLAIM_RT_LIBRARY)
        target_link_libraries(${target_name} PUBLIC "${NWFLAIM_RT_LIBRARY}")
    endif()
    if(NWFLAIM_DL_LIBRARY)
        target_link_libraries(${target_name} PUBLIC "${NWFLAIM_DL_LIBRARY}")
    endif()
endfunction()


function(nwflaim_common_private_target target_name)
    target_compile_features(${target_name} PRIVATE cxx_std_98)
    target_compile_definitions(${target_name} PRIVATE ${_nwflaim_common_defs})
    target_include_directories(${target_name}
        PRIVATE
            "${CMAKE_CURRENT_SOURCE_DIR}/ftk/src"
            "${CMAKE_CURRENT_SOURCE_DIR}/flaim/src"
            "${CMAKE_CURRENT_SOURCE_DIR}/flaim/util"
            "${CMAKE_CURRENT_SOURCE_DIR}/sql/src"
            "${CMAKE_CURRENT_SOURCE_DIR}/xflaim/src"
            "${CMAKE_CURRENT_SOURCE_DIR}/xflaim/util")
    if(NWFLAIM_USE_NICI AND NOT NWFLAIM_NICI_INCLUDE_DIR STREQUAL "")
        target_include_directories(${target_name} PRIVATE "${NWFLAIM_NICI_INCLUDE_DIR}")
    endif()
    target_link_libraries(${target_name} PRIVATE Threads::Threads)
    if(CURSES_INCLUDE_DIRS)
        target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIRS})
    elseif(CURSES_INCLUDE_DIR)
        target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIR})
    endif()
    if(CURSES_LIBRARIES)
        target_link_libraries(${target_name} PRIVATE ${CURSES_LIBRARIES})
    endif()
    if(NWFLAIM_RT_LIBRARY)
        target_link_libraries(${target_name} PRIVATE "${NWFLAIM_RT_LIBRARY}")
    endif()
    if(NWFLAIM_DL_LIBRARY)
        target_link_libraries(${target_name} PRIVATE "${NWFLAIM_DL_LIBRARY}")
    endif()
endfunction()

function(nwflaim_xflaim_private_target target_name)
    # XFLAIM utility sources include local headers such as "flaimsys.h"
    # by basename.  Keep the XFLAIM include directories ahead of the
    # classic FLAIM ones so they do not accidentally pick up
    # flaim/src/flaimsys.h.
    target_include_directories(${target_name} BEFORE PRIVATE
        "${CMAKE_CURRENT_SOURCE_DIR}/xflaim/util"
        "${CMAKE_CURRENT_SOURCE_DIR}/xflaim/src")
endfunction()

function(nwflaim_add_tool target_name output_name library_target)
    add_executable(${target_name} ${ARGN})
    set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "${output_name}")
    nwflaim_common_private_target(${target_name})
    target_link_libraries(${target_name} PRIVATE ${library_target})
    install(TARGETS ${target_name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endfunction()

function(nwflaim_add_library logical_name output_base public_include_dir install_include_dir library_version library_soversion)
    if(NWFLAIM_BUILD_SHARED)
        add_library(${logical_name} SHARED ${ARGN})
        add_library(NWFlaim::${logical_name} ALIAS ${logical_name})
        set_target_properties(${logical_name} PROPERTIES
            OUTPUT_NAME "${NWFLAIM_LIBRARY_PREFIX}${output_base}"
            VERSION "${library_version}"
            SOVERSION "${library_soversion}")
        nwflaim_common_target(${logical_name} ${public_include_dir} ${install_include_dir})
    endif()
    if(NWFLAIM_BUILD_STATIC)
        add_library(${logical_name}_static STATIC ${ARGN})
        add_library(NWFlaim::${logical_name}_static ALIAS ${logical_name}_static)
        set_target_properties(${logical_name}_static PROPERTIES OUTPUT_NAME "${NWFLAIM_LIBRARY_PREFIX}${output_base}")
        nwflaim_common_target(${logical_name}_static ${public_include_dir} ${install_include_dir})
    endif()
endfunction()

nwflaim_add_library(flaimtk flaimtk ftk/src "${CMAKE_INSTALL_INCLUDEDIR}/nwflaim" "${NWFLAIM_FTK_LIBRARY_VERSION}" "${NWFLAIM_FTK_LIBRARY_SOVERSION}" ${NWFLAIM_FTK_SOURCES})
if(TARGET flaimtk AND NWFLAIM_WITH_OPENSSL)
    target_link_libraries(flaimtk PUBLIC ${_nwflaim_ssl_target})
endif()
if(TARGET flaimtk_static AND NWFLAIM_WITH_OPENSSL)
    target_link_libraries(flaimtk_static PUBLIC ${_nwflaim_ssl_target})
endif()

nwflaim_add_library(flaim flaim flaim/src "${CMAKE_INSTALL_INCLUDEDIR}/nwflaim" "${NWFLAIM_FLAIM_LIBRARY_VERSION}" "${NWFLAIM_FLAIM_LIBRARY_SOVERSION}" ${NWFLAIM_FLAIM_SOURCES})
if(TARGET flaim)
    target_link_libraries(flaim PUBLIC flaimtk)
endif()
if(TARGET flaim_static)
    target_link_libraries(flaim_static PUBLIC flaimtk_static)
endif()

if(NWFLAIM_BUILD_SQL)
    nwflaim_add_library(flaimsql flaimsql sql/src "${CMAKE_INSTALL_INCLUDEDIR}/nwflaim" "${NWFLAIM_SQL_LIBRARY_VERSION}" "${NWFLAIM_SQL_LIBRARY_SOVERSION}" ${NWFLAIM_SQL_SOURCES})
    if(TARGET flaimsql)
        target_link_libraries(flaimsql PUBLIC flaim)
    endif()
    if(TARGET flaimsql_static)
        target_link_libraries(flaimsql_static PUBLIC flaim_static)
    endif()
endif()

if(NWFLAIM_BUILD_XFLAIM)
    nwflaim_add_library(xflaim xflaim xflaim/src "${CMAKE_INSTALL_INCLUDEDIR}/nwflaim" "${NWFLAIM_XFLAIM_LIBRARY_VERSION}" "${NWFLAIM_XFLAIM_LIBRARY_SOVERSION}" ${NWFLAIM_XFLAIM_SOURCES})
    if(TARGET xflaim)
        target_link_libraries(xflaim PUBLIC flaimtk)
    endif()
    if(TARGET xflaim_static)
        target_link_libraries(xflaim_static PUBLIC flaimtk_static)
    endif()
endif()


if(NWFLAIM_BUILD_TOOLS)
    add_library(flaim_util_objects OBJECT
        flaim/util/flm_dlst.cpp
        flaim/util/flm_lutl.cpp
        flaim/util/sharutil.cpp)
    nwflaim_common_private_target(flaim_util_objects)
    target_include_directories(flaim_util_objects PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/flaim/util")

    nwflaim_add_tool(flmcheckdb_tool nwflmcheckdb flaim
        flaim/util/checkdb.cpp
        $<TARGET_OBJECTS:flaim_util_objects>)
    nwflaim_add_tool(flmrebuild_tool nwflmrebuild flaim
        flaim/util/rebuild.cpp
        $<TARGET_OBJECTS:flaim_util_objects>)
    nwflaim_add_tool(flmgigatest_tool nwflmgigatest flaim
        flaim/util/gigatest.cpp
        $<TARGET_OBJECTS:flaim_util_objects>)
    nwflaim_add_tool(flmview_tool nwflmview flaim
        flaim/util/viewblk.cpp
        flaim/util/view.cpp
        flaim/util/viewdisp.cpp
        flaim/util/viewedit.cpp
        flaim/util/viewfhdr.cpp
        flaim/util/viewlfil.cpp
        flaim/util/viewlhdr.cpp
        flaim/util/viewmenu.cpp
        flaim/util/viewsrch.cpp
        $<TARGET_OBJECTS:flaim_util_objects>)
    nwflaim_add_tool(flmdbshell_tool nwflmdbshell flaim
        flaim/util/dbshell.cpp
        flaim/util/flm_edit.cpp
        $<TARGET_OBJECTS:flaim_util_objects>)

    if(NWFLAIM_BUILD_XFLAIM)
        add_library(xflaim_util_objects OBJECT
            xflaim/util/flm_dlst.cpp
            xflaim/util/flm_lutl.cpp
            xflaim/util/sharutil.cpp)
        nwflaim_common_private_target(xflaim_util_objects)
        nwflaim_xflaim_private_target(xflaim_util_objects)

        nwflaim_add_tool(xflmcheckdb_tool nwxflmcheckdb xflaim
            xflaim/util/checkdb.cpp
            $<TARGET_OBJECTS:xflaim_util_objects>)
        nwflaim_xflaim_private_target(xflmcheckdb_tool)
        nwflaim_add_tool(xflmrebuild_tool nwxflmrebuild xflaim
            xflaim/util/rebuild.cpp
            $<TARGET_OBJECTS:xflaim_util_objects>)
        nwflaim_xflaim_private_target(xflmrebuild_tool)
        nwflaim_add_tool(xflmview_tool nwxflmview xflaim
            xflaim/util/viewblk.cpp
            xflaim/util/view.cpp
            xflaim/util/viewdisp.cpp
            xflaim/util/viewedit.cpp
            xflaim/util/viewhdr.cpp
            xflaim/util/viewlfil.cpp
            xflaim/util/viewmenu.cpp
            xflaim/util/viewsrch.cpp
            $<TARGET_OBJECTS:xflaim_util_objects>)
        nwflaim_xflaim_private_target(xflmview_tool)
        nwflaim_add_tool(xflmdbshell_tool nwxflmdbshell xflaim
            xflaim/util/fdomedt.cpp
            xflaim/util/fshell.cpp
            xflaim/util/xshell.cpp
            $<TARGET_OBJECTS:xflaim_util_objects>)
        nwflaim_xflaim_private_target(xflmdbshell_tool)
    endif()
endif()

if(BUILD_TESTING AND NWFLAIM_BUILD_TOOLS)
    configure_file(
        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/NWFlaimDbSmokeTest.cmake.in
        ${CMAKE_CURRENT_BINARY_DIR}/NWFlaimDbSmokeTest.cmake
        @ONLY)

    add_test(NAME nwflaim.database.create-and-check
        COMMAND ${CMAKE_COMMAND}
            -DNWFLAIM_GIGATEST=$<TARGET_FILE:flmgigatest_tool>
            -DNWFLAIM_CHECKDB=$<TARGET_FILE:flmcheckdb_tool>
            -DNWFLAIM_TEST_WORKDIR=${CMAKE_CURRENT_BINARY_DIR}/ctest/nwflaim-db
            -P ${CMAKE_CURRENT_BINARY_DIR}/NWFlaimDbSmokeTest.cmake)
    set_tests_properties(nwflaim.database.create-and-check PROPERTIES LABELS nwflaim)
endif()

# Install public headers below nw-prefixed include directories so they do not
# conflict with any system or distro FLAIM headers.
set(NWFLAIM_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/nwflaim")
set(NWXFLAIM_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/nwflaim")

install(TARGETS flaimtk flaim
    EXPORT nwflaim-targets
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if(TARGET flaimsql)
    install(TARGETS flaimsql
        EXPORT nwflaim-targets
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(TARGET xflaim)
    install(TARGETS xflaim
        EXPORT nwflaim-targets
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
install(FILES ftk/src/flaimtk.h flaim/src/flaim.h DESTINATION ${NWFLAIM_INCLUDE_INSTALL_DIR})
if(NWFLAIM_BUILD_SQL)
    install(FILES sql/src/flaimsql.h DESTINATION ${NWFLAIM_INCLUDE_INSTALL_DIR})
endif()
if(NWFLAIM_BUILD_XFLAIM)
    install(FILES xflaim/src/xflaim.h DESTINATION ${NWXFLAIM_INCLUDE_INSTALL_DIR})
endif()
install(EXPORT nwflaim-targets NAMESPACE NWFlaim:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nwflaim)
