include_directories(${CMAKE_CURRENT_BINARY_DIR})

brlcad_find_package(manifold REQUIRED)
brlcad_find_package(mmesh REQUIRED)
brlcad_find_package(OPENNURBS REQUIRED SYSPATTERN openNURBS)
brlcad_find_package(REGEX REQUIRED)
find_package_gte(REQUIRED)

if(BRLCAD_ENABLE_OPENCL)
  add_definitions(-DUSE_OPENCL)
endif(BRLCAD_ENABLE_OPENCL)

set(
  LIBRT_PRIMEDIT_SOURCES
  primitives/annot/edannot.c
  primitives/arb8/edarb.c
  primitives/arbn/edarbn.c
  primitives/ars/edars.c
  primitives/bot/edbot.c
  primitives/brep/edbrep.cpp
  primitives/bspline/edbspline.c
  primitives/cline/edcline.c
  primitives/datum/eddatum.c
  primitives/datum/eddatum2.c
  primitives/revolve/edrevolve.c
  primitives/dsp/eddsp.c
  primitives/ebm/edebm.c
  primitives/ehy/edehy.c
  primitives/ell/edell.c
  primitives/epa/edepa.c
  primitives/eto/edeto.c
  primitives/extrude/edextrude.c
  primitives/grip/edgrip.c
  primitives/half/edhalf.c
  primitives/hrt/edhrt.c
  primitives/hyp/edhyp.c
  primitives/metaball/edmetaball.c
  primitives/nmg/ednmg.c
  primitives/part/edpart.c
  primitives/pipe/edpipe.c
  primitives/rhc/edrhc.c
  primitives/rpc/edrpc.c
  primitives/sketch/edsketch.c
  primitives/superell/edsuperell.c
  primitives/tgc/edtgc.c
  primitives/tor/edtor.c
  primitives/vol/edvol.c
)

set(RT_ECMD_SCANNER_SRC "${CMAKE_CURRENT_SOURCE_DIR}/primitives/rt_ecmd_scanner.cpp")
set(RT_ECMD_SCANNER_TARGET rt_ecmd_scanner)
add_executable(${RT_ECMD_SCANNER_TARGET} EXCLUDE_FROM_ALL "${RT_ECMD_SCANNER_SRC}")
set_target_properties(${RT_ECMD_SCANNER_TARGET} PROPERTIES FOLDER "BRL-CAD Build Utilities")
set(RT_ECMD_SCANNER "$<TARGET_FILE:${RT_ECMD_SCANNER_TARGET}>")

# NOTE - for now this is an internal, build-only header and
# does not have install logic associated with it.  Eventually,
# if this API proves out and becomes stable, we may end up
# installing rt_ecmds.h.  Applications external to the main
# BRL-CAD build may also want to exploit the callback API.
set(RT_PFILE_OUT "${CMAKE_BINARY_DIR}/CMakeTmp/rt_primitive_files.txt")
set(RT_PFILE_IN)
foreach(esf ${LIBRT_PRIMEDIT_SOURCES})
  list(APPEND RT_PFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/${esf})
endforeach()
string(REPLACE ";" "\n" RT_PFILES "${RT_PFILE_IN}")
file(WRITE "${RT_PFILE_OUT}" ${RT_PFILES})
distclean(${RT_PFILE_OUT})

set(RT_ECMD_HDR "${CMAKE_BINARY_DIR}/${INCLUDE_DIR}/brlcad/rt/rt_ecmds.h")
add_custom_command(
  OUTPUT ${RT_ECMD_HDR}
  COMMAND ${BRLCAD_SANITIZER_BUILD_TOOL_LAUNCHER}
    ${RT_ECMD_SCANNER} ${RT_PFILE_OUT} ${RT_ECMD_HDR}
  COMMENT "[RT_ECMD_SCANNER] Scanning for RT editing mode flags"
  DEPENDS ${RT_ECMD_SCANNER_TARGET} ${RT_PFILE_OUT} ${RT_PFILE_IN}
)
distclean(${RT_ECMD_HDR})
foreach(esf ${LIBRT_PRIMEDIT_SOURCES})
  set_source_files_properties(${esf} PROPERTIES OBJECT_DEPENDS ${RT_ECMD_HDR})
endforeach()


# FIXME: needs materialX
#  material/materialX.cpp
set(
  LIBRT_SOURCES
  attr.cpp
  attributes.c
  bbox.c
  binunif/binunif.c
  binunif/db5_bin.c
  bool.c
  bool_tess.c
  bundle.c
  cache.c
  cache_lod.c
  cache_lz4.c
  cmd.c
  cyclic.c
  db_glob.c
  comb/comb.c
  comb/comb_brep.cpp
  comb/comb_mirror.c
  comb/db_comb.c
  comb/edcomb.c
  material/material.c
  constraint.c
  edit_constraint.c
  cut.c
  cut_hlbvh.c
  cut_null.c
  cut_nubsp.c
  default.c
  db5_alloc.c
  db5_attr.c
  db5_attr_registry.cpp
  db5_io.c
  db5_size.cpp
  db5_scan.c
  db5_types.c
  db_alloc.c
  db_anim.c
  db_corrupt.c
  db_diff.c
  db_flags.c
  db_flip.c
  db_fullpath.cpp
  db_inmem.c
  db_io.c
  db_lookup.c
  db_match.c
  db_open.c
  db_scan.c
  db_tree.cpp
  db_walk.c
  dir.c
  dspline.c
  edit.cpp
  fortray.c
  globals.c
  htbl.c
  ls.c
  mater.c
  memalloc.c
  mkbundle.c
  op.c
  pr.c
  prep.cpp
  ${LIBRT_PRIMEDIT_SOURCES}
  primitives/annot/annot.c
  primitives/arb8/arb8.c
  primitives/arb8/arb8_brep.cpp
  primitives/arb8/arb8_mirror.c
  primitives/arbn/arbn.c
  primitives/arbn/arbn_brep.cpp
  primitives/arbn/arbn_mirror.c
  primitives/ars/ars.c
  primitives/ars/ars_brep.cpp
  primitives/ars/ars_mirror.c
  primitives/bot/bot.c
  primitives/bot/bot_brep.cpp
  primitives/bot/bot_edge.c
  primitives/bot/bot_mirror.c
  primitives/bot/bot_oriented_bbox.cpp
  primitives/bot/bot_plot.cpp
  primitives/bot/btg.c
  primitives/bot/btgf.c
  primitives/bot/decimate.c
  primitives/bot/plate.cpp
  primitives/bot/repair.cpp
  primitives/bot/sampling_checks.cpp
  primitives/brep/brep.cpp
  primitives/bspline/bspline.cpp
  primitives/bspline/bspline_brep.cpp
  primitives/bspline/bspline_mirror.c
  primitives/crofton.cpp
  primitives/cline/cline.c
  primitives/cline/cline_brep.cpp
  primitives/datum/datum.c
  primitives/dsp/dsp.c
  primitives/dsp/dsp_brep.cpp
  primitives/dsp/dsp_mirror.c
  primitives/dsp/dsp_sa_vol.c
  primitives/dsp/dsp_tess.cpp
  primitives/ebm/ebm.c
  primitives/ebm/ebm_brep.cpp
  primitives/ebm/ebm_mirror.c
  primitives/edgeneric.c
  primitives/edtable.cpp
  primitives/ehy/ehy.c
  primitives/ehy/ehy_brep.cpp
  primitives/ell/ell.c
  primitives/ell/ell_brep.cpp
  primitives/ell/ell_mirror.c
  primitives/epa/epa.c
  primitives/epa/epa_brep.cpp
  primitives/epa/epa_mirror.c
  primitives/eto/eto.c
  primitives/eto/eto_brep.cpp
  primitives/eto/eto_mirror.c
  primitives/extrude/extrude.c
  primitives/extrude/extrude_brep.cpp
  primitives/generic.c
  primitives/grip/grip.c
  primitives/grip/grip_brep.cpp
  primitives/grip/grip_mirror.c
  primitives/half/half.c
  primitives/half/half_brep.cpp
  primitives/half/half_mirror.c
  primitives/hf/hf.c
  primitives/hf/hf_brep.cpp
  primitives/hrt/hrt.c
  primitives/hrt/hrt_mirror.c
  primitives/hyp/hyp.c
  primitives/hyp/hyp_brep.cpp
  primitives/hyp/hyp_mirror.c
  primitives/joint/joint.c
  primitives/joint/joint_brep.cpp
  primitives/joint/joint_mirror.c
  primitives/metaball/metaball.c
  primitives/metaball/metaball_tri.c
  primitives/mirror.c
  primitives/nmg/nmg.c
  primitives/nmg/nmg_brep.cpp
  primitives/nmg/nmg_mirror.c
  primitives/nmg/nmg_tri_mc.c
  primitives/obj_adjust.c
  primitives/obj_curve.c
  primitives/obj_describe.c
  primitives/obj_export.c
  primitives/obj_free.c
  primitives/obj_get.c
  primitives/obj_ifree.c
  primitives/obj_import.c
  primitives/obj_make.c
  primitives/obj_mirror.c
  primitives/obj_norm.c
  primitives/obj_params.c
  primitives/obj_plot.c
  primitives/obj_prep.c
  primitives/obj_print.c
  primitives/obj_shot.c
  primitives/obj_tess.c
  primitives/obj_tnurb.c
  primitives/obj_uv.c
  primitives/obj_vshot.c
  primitives/obj_xform.c
  primitives/part/part.c
  primitives/part/part_brep.cpp
  primitives/part/part_mirror.c
  primitives/pipe/pipe.c
  primitives/pipe/pipe_brep.cpp
  primitives/pipe/pipe_mirror.c
  primitives/pnts/pnts.c
  primitives/pnts/pnts_brep.cpp
  primitives/poly/poly.c
  primitives/poly/poly_brep.cpp
  primitives/poly/poly_mirror.c
  primitives/primitive_util.c
  primitives/rec/edrec.c
  primitives/rec/rec.c
  primitives/revolve/revolve.c
  primitives/revolve/revolve_brep.cpp
  primitives/rhc/rhc.c
  primitives/rhc/rhc_brep.cpp
  primitives/rhc/rhc_mirror.c
  primitives/rpc/rpc.c
  primitives/rpc/rpc_brep.cpp
  primitives/rpc/rpc_mirror.c
  primitives/sample.c
  primitives/sample_pnts.cpp
  primitives/script/script.c
  primitives/sketch/polygons.c
  primitives/sketch/sketch.c
  primitives/sketch/sketch_brep.cpp
  primitives/sketch/sketch_tess.cpp
  primitives/sph/edsph.c
  primitives/sph/sph.c
  primitives/sph/sph_brep.cpp
  primitives/submodel/submodel.c
  primitives/superell/superell.c
  primitives/superell/superell_brep.cpp
  primitives/superell/superell_mirror.c
  primitives/table.cpp
  primitives/tgc/tgc.c
  primitives/tgc/tgc_brep.cpp
  primitives/tgc/tgc_mirror.c
  primitives/tor/tor.c
  primitives/tor/tor_brep.cpp
  primitives/tor/tor_mirror.c
  primitives/vol/vol.c
  primitives/vol/vol_brep.cpp
  primitives/vol/vol_mirror.c
  primitives/xxx/xxx.c
  reduce.c
  reduce_db.cpp
  regionfix.c
  roots.c
  rt_init.cpp
  search.cpp
  search_old.cpp
  shoot.c
  timer.cpp
  tol.c
  transform.c
  tree.c
  uv.c
  vds/vds.c
  vers.c
  view.c
  vlist.c
  vshoot.c
  wdb.c
)

set(
  librt_ignored_files
  cache.h
  cut_private.h
  librt_private.h
  material/materialX.cpp
  material/materialX.h
  cut_hlbvh.h
  prcomb.c
  primitives/bot/bot_edge.h
  primitives/bot/bot_wireframe.cpp
  primitives/bot/edbot.c
  primitives/bot/tie.c
  primitives/bot/tie_kdtree.c
  primitives/bot/tieprivate.h
  primitives/brep/brep_debug.h
  primitives/brep/brep_local.h
  primitives/brep/primitive_brep.h
  primitives/sketch/sketch_brep.h
  primitives/datum/datum.h
  primitives/dsp/dsp.h
  primitives/dsp/TerraScape.hpp
  primitives/edit_private.h
  primitives/fixpt.h
  primitives/metaball/metaball.h
  primitives/revolve/revolve.h
  primitives/rt_ecmd_scanner.cpp
  primitives/sph/benchmark.sh
  primitives/xxx/xxx.h
  primitives/bool.cl
  primitives/common.cl
  primitives/rt.cl
  primitives/solver.cl
  primitives/arb8/arb8_shot.cl
  primitives/arbn/arbn_shot.cl
  primitives/bot/bot_shot.cl
  primitives/ebm/ebm_shot.cl
  primitives/ehy/ehy_shot.cl
  primitives/ell/ell_shot.cl
  primitives/epa/epa_shot.cl
  primitives/eto/eto_shot.cl
  primitives/hrt/hrt_shot.cl
  primitives/hyp/hyp_shot.cl
  primitives/part/part_shot.cl
  primitives/rec/rec_shot.cl
  primitives/rhc/rhc_shot.cl
  primitives/rpc/rpc_shot.cl
  primitives/sph/sph_shot.cl
  primitives/superell/superell_shot.cl
  primitives/tgc/tgc_shot.cl
  primitives/tor/tor_shot.cl
  search.h
  search_old.h
  subd_test_bot.asc
  test_bot2nurbs.cpp
  test_brepreport.cpp
  test_dbio.c
  test_nurbsfit.cpp
  uvpoints.cpp
)
cmakefiles(${librt_ignored_files})

# tie violates the One Definition Rule when we compile as C++
set_source_files_properties(primitives/bot/btg.c PROPERTIES NO_CXX_COMPILE TRUE)
set_source_files_properties(primitives/bot/btgf.c PROPERTIES NO_CXX_COMPILE TRUE)
set_source_files_properties(primitives/bot/tie.c PROPERTIES NO_CXX_COMPILE TRUE)
set_source_files_properties(primitives/bot/tie_kdtree.c PROPERTIES NO_CXX_COMPILE TRUE)

set(
  CL_FILES
  primitives/bool.cl
  primitives/common.cl
  primitives/rt.cl
  primitives/solver.cl
  primitives/arb8/arb8_shot.cl
  primitives/arbn/arbn_shot.cl
  primitives/bot/bot_shot.cl
  primitives/ebm/ebm_shot.cl
  primitives/ehy/ehy_shot.cl
  primitives/ell/ell_shot.cl
  primitives/epa/epa_shot.cl
  primitives/eto/eto_shot.cl
  primitives/hrt/hrt_shot.cl
  primitives/hyp/hyp_shot.cl
  primitives/part/part_shot.cl
  primitives/rec/rec_shot.cl
  primitives/rhc/rhc_shot.cl
  primitives/rpc/rpc_shot.cl
  primitives/sph/sph_shot.cl
  primitives/superell/superell_shot.cl
  primitives/tgc/tgc_shot.cl
  primitives/tor/tor_shot.cl
)

brlcad_adddata(nurb_example.c sample_applications)
brlcad_adddata(raydebug.tcl sample_applications)
brlcad_adddata(CL_FILES opencl)

if(BRLCAD_ENABLE_OPENCL)
  set(OPENCL_LIBS ${OPENCL_LIBRARIES})
endif(BRLCAD_ENABLE_OPENCL)

if(BRLCAD_ENABLE_SPR)
  set(SPR_LIB libSPR)
endif(BRLCAD_ENABLE_SPR)

# Note - librt_deps is defined by ${BRLCAD_SOURCE_DIR}/src/source_dirs.cmake
set(LIBRT_PUBLIC_LIBS ${librt_deps} OPENNURBS::OPENNURBS)
set(
  LIBRT_PRIVATE_LIBS
  ${OPENCL_LIBS}
  mmesh::mmesh
  REGEX::REGEX
  ${WINSOCK_LIB}
  ${RPCRT_LIB}
  ${STDCXX_LIBRARIES}
  manifold::manifold
)

# Include directories needed by librt users
# ${GTE_INCLUDE_DIR} is still needed by primitives/bot/bot_oriented_bbox.cpp
# which uses GTE's ContOrientedBox3.h.
set(RT_INCLUDE_DIRS ${OPENCL_INCLUDE_DIRS} ${GTE_INCLUDE_DIR})

# locally used but not needed by users of the library
set(
  RT_LOCAL_INCLUDE_DIRS
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_SOURCE_DIR}/vds
  ${BRLCAD_SOURCE_DIR}/src/libbu
  ${REGEX_INCLUDE_DIRS}
)
# FIXME: needs materialX
#  ${CMAKE_CURRENT_SOURCE_DIR}/../../../MaterialXSource/source

brlcad_addlib(librt "${LIBRT_SOURCES}" "${RT_INCLUDE_DIRS}" "${RT_LOCAL_INCLUDE_DIRS}"
  PUBLIC_LIBS ${LIBRT_PUBLIC_LIBS}
  PRIVATE_LIBS ${LIBRT_PRIVATE_LIBS}
  # Files that cannot be safely batched into unity translation units:
  # - search.cpp and search_old.cpp both define enumerators N_ABOVE, N_AND, etc.
  #   in their respective (differently-named) enums; those clashing enumerator
  #   names cannot be batched together.
  # - primitives/table.cpp forward-declares rt_vol_tess as returning int; the
  #   actual definition in primitives/vol/vol_brep.cpp returns void and relies
  #   on the cast macro.  Batching them in the same unity TU triggers a
  #   conflicting-declaration error.
  # - primitives/dsp/dsp.c, primitives/ebm/ebm.c, primitives/vol/vol.c each
  #   define static get_file_data / get_obj_data helpers with identical names
  #   but different parameter types.
  # - The entire bot subdirectory is excluded because btg.c and btgf.c
  #   directly #include "tie.c" and "tie_kdtree.c"; when any of those files
  #   land in the same unity batch the TIE_VAL-generated symbols are defined
  #   twice.  The many other direct-.c-include patterns in bot make the whole
  #   subdirectory unsafe to batch.
  UNITY_BUILD_SKIP
    rt_init.cpp
    search.cpp
    search_old.cpp
    primitives/annot/annot.c
    primitives/vol/vol_brep.cpp
    primitives/dsp/dsp.c
    primitives/ebm/ebm.c
    primitives/vol/vol.c
    primitives/bot/edbot.c
    primitives/bot/bot.c
    primitives/bot/bot_brep.cpp
    primitives/bot/bot_edge.c
    primitives/bot/bot_mirror.c
    primitives/bot/bot_oriented_bbox.cpp
    primitives/bot/bot_plot.cpp
    primitives/bot/btg.c
    primitives/bot/btgf.c
    primitives/bot/decimate.c
    primitives/bot/plate.cpp
    primitives/bot/repair.cpp
    primitives/bot/sampling_checks.cpp
    primitives/bot/bot_wireframe.cpp
    primitives/bot/tie.c
    primitives/bot/tie_kdtree.c
)

# set(MATERIALX_LIBS ${CMAKE_CURRENT_SOURCE_DIR}/../../../MaterialXSource/lib/MaterialXCore.lib;${CMAKE_CURRENT_SOURCE_DIR}/../../../MaterialXSource/lib/MaterialXFormat.lib;${CMAKE_CURRENT_SOURCE_DIR}/../../../MaterialXSource/lib/MaterialXGenOsl.lib;${CMAKE_CURRENT_SOURCE_DIR}/../../../MaterialXSource/lib/MaterialXGenShader.lib)
set_target_properties(librt PROPERTIES VERSION 20.0.1 SOVERSION 20)
if(HIDE_INTERNAL_SYMBOLS)
  set_property(TARGET librt APPEND PROPERTY COMPILE_DEFINITIONS "TIE_DLL_EXPORTS")
  set_property(TARGET librt APPEND PROPERTY COMPILE_DEFINITIONS "DB5_DLL_EXPORTS")
  if(TARGET librt-obj)
    set_property(TARGET librt-obj APPEND PROPERTY COMPILE_DEFINITIONS "TIE_DLL_EXPORTS")
    set_property(TARGET librt-obj APPEND PROPERTY COMPILE_DEFINITIONS "DB5_DLL_EXPORTS")
  endif(TARGET librt-obj)
  if(TARGET librt-brlcad-obj)
    set_property(TARGET librt-brlcad-obj APPEND PROPERTY COMPILE_DEFINITIONS "TIE_DLL_EXPORTS")
    set_property(TARGET librt-brlcad-obj APPEND PROPERTY COMPILE_DEFINITIONS "DB5_DLL_EXPORTS")
  endif(TARGET librt-brlcad-obj)
endif(HIDE_INTERNAL_SYMBOLS)

# loudly append an underscore on musl so that we build by default but
# not without protest.
find_program(MUSL_LD NAMES /lib/ld-musl-x86_64.so.1)
mark_as_advanced(MUSL_LD)
if(MUSL_LD)
  message(
    "WARNING: MUSL LibC Detected.  Protecting BRL-CAD's librt.

    MUSL's dynamic linker erroneously overrides AT RUNTIME 'librt'
    references regardless of rpath or search logic specified during
    compilation and linking.  MUSL claims POSIX allows this despite
    POSIX not defining any dynamic linker behavior whatsoever. They
    (reportedly) do so to ease porting glibc-assuming apps to their
    libc, auto-converting those linked with -lm, -lpthread, -lrt
    and such during runtime loading regardless of search path logic.

    Legacy mention in POSIX 'c99' man page would allow (only) the
    c99 tool to treat BRL-CAD's librt as undefined (not C++, fort77,
    or other tools like ld), however clang/gcc/c99 compiling and
    linking are all well-behaved. Issue reported with suggestion to
    only override as fallback behavior in July 2022.

    Until MUSL changes (see root/ldso/dynlink.c), a workaround is
    employed to avoid user action.  Setting LD_PRELOAD also works.

    WARNING: MUSL ENVIRONMENT UNSUPPORTED. DO NOT RELY ON 'librt_'
    WORKAROUND. PLEASE REPORT IF YOU DEVELOP AGAINST BRL-CAD LIBRT
    AND ENCOUNTER THIS MESSAGE: devs@brlcad.org"
  )
  set_target_properties(librt PROPERTIES OUTPUT_NAME "librt_")
endif(MUSL_LD)

# The following is build code for test applications used during
# development
#
# find_package_eigen(REQUIRED)
#include_directories(
#  ${EIGEN3_INCLUDE_DIR}
#  ${CMAKE_CURRENT_SOURCE_DIR}/../libbrep
#  )
#
#BRLCAD_ADDEXEC(test_bot2nurbs test_bot2nurbs.cpp "librt;libwdb;libbrep;libbu" NO_STRICT NO_INSTALL)
#BRLCAD_ADDEXEC(test_brepreport test_brepreport.cpp "librt;libwdb;libbrep;libbu" NO_STRICT NO_INSTALL)
#BRLCAD_ADDEXEC(test_nurbsfit test_nurbsfit.cpp "librt;libwdb;libbrep;libbu" NO_STRICT NO_INSTALL)
#BRLCAD_ADDEXEC(test_surfacetree test_surfacetree.cpp "librt;libwdb;libbrep;libbu" NO_STRICT NO_INSTALL)

add_subdirectory(tests)

cmakefiles(
  CMakeLists.txt
  bot2nurbs.txt
  brep_csg_boolean.txt
  vds/README
  vds/COPYING
  vds/vds.h
)

# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
