# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

set(EMBT_TARGET Windows)

if(CMAKE_BASE_NAME STREQUAL "bcc32x")
  set(BCC32X TRUE)
  set(_EMBT_CPP_PREPROCESSOR "cpp32x")
  set(CLANG_BASED TRUE)
  set(CLANG_BASED_OPTS TRUE)
elseif(CMAKE_BASE_NAME STREQUAL "bcc64x")
  set(BCC64X TRUE)
  set(_EMBT_CPP_PREPROCESSOR "cpp64x")
  set(CLANG_BASED TRUE)
  set(CLANG_BASED_OPTS TRUE)
elseif(CMAKE_BASE_NAME STREQUAL "bcc32c")
  set(BCC32C TRUE)
  set(_EMBT_CPP_PREPROCESSOR "cpp32c")
  set(CLANG_BASED TRUE)
elseif(CMAKE_BASE_NAME STREQUAL "bcc32")
  set(BCC32 TRUE)
  set(_EMBT_CPP_PREPROCESSOR "cpp32")
else()
  message(FATAL_ERROR "Unknown compiler specified ${CMAKE_BASE_NAME}")
endif()

# This module is shared by multiple languages; use include blocker.
if(__WINDOWS_EMBARCADERO)
  return()
endif()

set(__WINDOWS_EMBARCADERO 1)
set(BORLAND 1)

include(CMakePrintHelpers)

if(NOT CLANG_BASED AND "${CMAKE_${_lang}_COMPILER_VERSION}" VERSION_LESS 6.30)
  # Borland target type flags (bcc32 -h -t):
  set(_tW "-tW")       # -tW  GUI App         (implies -U__CONSOLE__)
  set(_tC "-tWC")      # -tWC Console App     (implies -D__CONSOLE__=1)
  set(_tD "-tWD")      # -tWD Build a DLL     (implies -D__DLL__=1 -D_DLL=1)
  set(_tM "-tWM")      # -tWM Enable threads  (implies -D__MT__=1 -D_MT=1)
  set(_tR "-tWR -tW-") # -tWR Use DLL runtime (implies -D_RTLDLL, and '-tW' too!!)
  # Notes:
  #  - The flags affect linking so we pass them to the linker.
  #  - The flags affect preprocessing so we pass them to the compiler.
  #  - Since '-tWR' implies '-tW' we use '-tWR -tW-' instead.
  #  - Since '-tW-' disables '-tWD' we use '-tWR -tW- -tWD' for DLLs.
else()
  set(EMBARCADERO 1)
  set(_tC "-tC") # Target is a console application
  set(_tD "-tD") # Target is a shared library
  set(_tM "-tM") # Target is multi-threaded
  set(_tR "-tR") # Target uses the dynamic RTL
  set(_tW "-tW") # Target is a Windows application
  set(_tV "-tV") # Target is a VCL application
  set(_tJ "-tJ") # Target uses the Delphi Runtime
  set(_tF "-tF") # Target is a FMX application
  set(_tP "-tP") # Target creates a Package
  set(_tU "-tU") # Target creates a Unicode
endif()

if(BCC64X)
  # bcc64x is clang-15 + MinGW + ld.lld + libc++ — the Borland -t* link/compile
  # target flags do not apply. Neutralise them; console/GUI use the mingw flags.
  set(_tC "-mconsole")
  set(_tW "-mwindows")
  set(_tD "")
  set(_tM "")
  set(_tR "")
  set(_tV "")
  set(_tJ "")
  set(_tF "")
  set(_tP "")
  set(_tU "")
endif()

set(CMAKE_BUILD_TYPE_INIT Debug)

# find version of RAD Studio to use from compiler path name given or on PATH
if(EXISTS ${CMAKE_${_lang}_COMPILER})
  get_filename_component(BIN_DIR_PATH "${CMAKE_${_lang}_COMPILER}" DIRECTORY)
else()
  find_path(BIN_DIR_PATH NAMES ${CMAKE_BASE_NAME}.exe)
endif()
if(DEFINED BIN_DIR_PATH)
  get_filename_component(ROOTDIR ${BIN_DIR_PATH} DIRECTORY)
else()
  message(FATAL_ERROR "Unable to determine RAD Studio root")
endif()


## Set include paths
if(CLANG_BASED)
  set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
  set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-isystem ")
else()
  set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-I")
  set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-I")
endif()

if(CLANG_BASED_OPTS)
  if(NOT CMAKE_GENERATOR MATCHES "Borland Makefiles")
    set(CMAKE_DEPFILE_FLAGS_C "-MD -MT <OBJECT> -MF <DEP_FILE>")
    set(CMAKE_DEPFILE_FLAGS_CXX ${CMAKE_DEPFILE_FLAGS_C})
  endif()
else()
  if(NOT CMAKE_GENERATOR MATCHES "Borland Makefiles")
    set(CMAKE_DEPFILE_FLAGS_C "-md -mo<DEP_FILE>")
    set(CMAKE_DEPFILE_FLAGS_CXX ${CMAKE_DEPFILE_FLAGS_C})
  endif()
endif()

if(BCC64X)
  # bcc64x driver auto-adds its system includes (windows/sdk, windows/rtl,
  # libc++ v1, mingw). Do NOT add Dinkumware or windows/crtl — they conflict
  # with the MinGW/ucrt + libc++ headers.
elseif(BCC32C OR BCC32X)
  # The clang-based bcc32c/bcc32x drivers read bcc32c.cfg/bcc32x.cfg, which
  # already inject the full system include set (include, dinkumware64,
  # windows/crtl, windows/rtl, windows/vcl, windows/sdk). Adding them again here
  # produces duplicate standard headers and breaks compilation (ambiguous 'tm',
  # int8_t redefinition, etc.). Let the driver's cfg supply them, like bcc64x.
else()
  include_directories(SYSTEM "${ROOTDIR}/include/windows/crtl")
  include_directories(SYSTEM "${ROOTDIR}/include/windows/sdk")
  include_directories(SYSTEM "${ROOTDIR}/include/windows/rtl")
  if(BCC32)
    include_directories(SYSTEM "${ROOTDIR}/include/dinkumware")
  else()
    include_directories(SYSTEM "${ROOTDIR}/include/dinkumware64")
  endif()
endif()

if(BCC64X OR BCC32C)
  # CMake has no C++ standard->flag mapping for the "Embarcadero" compiler id,
  # so CMAKE_CXX_STANDARD (used by us and by dependencies like Poco) cannot be
  # satisfied and try_compile fails. bcc64x and bcc32c are both clang front
  # ends that accept these -std= flags: provide the mappings for both.
  foreach(_l C CXX)
    set(CMAKE_${_l}_STANDARD_DEFAULT 17)
  endforeach()
  set(CMAKE_CXX98_STANDARD_COMPILE_OPTION  "-std=c++98")
  set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
  set(CMAKE_CXX11_STANDARD_COMPILE_OPTION  "-std=c++11")
  set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
  set(CMAKE_CXX14_STANDARD_COMPILE_OPTION  "-std=c++14")
  set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
  set(CMAKE_CXX17_STANDARD_COMPILE_OPTION  "-std=c++17")
  set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
  set(CMAKE_CXX20_STANDARD_COMPILE_OPTION  "-std=c++20")
  set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20")
  set(CMAKE_CXX23_STANDARD_COMPILE_OPTION  "-std=c++23")
  set(CMAKE_CXX23_EXTENSION_COMPILE_OPTION "-std=gnu++23")
  set(CMAKE_C90_STANDARD_COMPILE_OPTION    "-std=c89")
  set(CMAKE_C90_EXTENSION_COMPILE_OPTION   "-std=gnu89")
  set(CMAKE_C99_STANDARD_COMPILE_OPTION    "-std=c99")
  set(CMAKE_C99_EXTENSION_COMPILE_OPTION   "-std=gnu99")
  set(CMAKE_C11_STANDARD_COMPILE_OPTION    "-std=c11")
  set(CMAKE_C11_EXTENSION_COMPILE_OPTION   "-std=gnu11")
  set(CMAKE_C17_STANDARD_COMPILE_OPTION    "-std=c17")
  set(CMAKE_C17_EXTENSION_COMPILE_OPTION   "-std=gnu17")
  # CMake records no compile features for the "Embarcadero" id, so
  # target_compile_features(... cxx_std_17) (used by Poco and others) errors.
  # Advertise the standard meta-features that clang-15 supports.
  # Meta-features alone are not enough: VTK and others call
  # target_compile_features() with GRANULAR names (cxx_variadic_templates, ...).
  # CMake errors if a requested feature is absent from CMAKE_CXX_COMPILE_FEATURES.
  # clang-15 supports the entire C++98/11/14 granular set, so advertise them
  # (these names mirror CMake's own Clang feature tables).
  set(CMAKE_CXX98_COMPILE_FEATURES
    cxx_std_98
    cxx_template_template_parameters)
  set(CMAKE_CXX11_COMPILE_FEATURES
    cxx_std_11
    cxx_alias_templates cxx_alignas cxx_alignof cxx_attributes cxx_auto_type
    cxx_constexpr cxx_decltype cxx_decltype_incomplete_return_types
    cxx_default_function_template_args cxx_defaulted_functions
    cxx_defaulted_move_initializers cxx_delegating_constructors
    cxx_deleted_functions cxx_enum_forward_declarations cxx_explicit_conversions
    cxx_extended_friend_declarations cxx_extern_templates cxx_final
    cxx_func_identifier cxx_generalized_initializers cxx_inheriting_constructors
    cxx_inline_namespaces cxx_lambdas cxx_local_type_template_args
    cxx_long_long_type cxx_noexcept cxx_nonstatic_member_init cxx_nullptr
    cxx_override cxx_range_for cxx_raw_string_literals
    cxx_reference_qualified_functions cxx_right_angle_brackets
    cxx_rvalue_references cxx_sizeof_member cxx_static_assert cxx_strong_enums
    cxx_thread_local cxx_trailing_return_types cxx_unicode_literals
    cxx_uniform_initialization cxx_unrestricted_unions cxx_user_literals
    cxx_variadic_macros cxx_variadic_templates)
  set(CMAKE_CXX14_COMPILE_FEATURES
    cxx_std_14
    cxx_aggregate_default_initializers cxx_attribute_deprecated
    cxx_binary_literals cxx_contextual_conversions cxx_decltype_auto
    cxx_digit_separators cxx_generic_lambdas cxx_lambda_init_captures
    cxx_relaxed_constexpr cxx_return_type_deduction cxx_variable_templates)
  set(CMAKE_CXX17_COMPILE_FEATURES cxx_std_17)
  set(CMAKE_CXX20_COMPILE_FEATURES cxx_std_20)
  set(CMAKE_CXX23_COMPILE_FEATURES cxx_std_23)
  set(CMAKE_CXX_COMPILE_FEATURES
    ${CMAKE_CXX98_COMPILE_FEATURES}
    ${CMAKE_CXX11_COMPILE_FEATURES}
    ${CMAKE_CXX14_COMPILE_FEATURES}
    ${CMAKE_CXX17_COMPILE_FEATURES}
    ${CMAKE_CXX20_COMPILE_FEATURES}
    ${CMAKE_CXX23_COMPILE_FEATURES})
  set(CMAKE_C90_COMPILE_FEATURES   c_std_90 c_function_prototypes)
  set(CMAKE_C99_COMPILE_FEATURES   c_std_99 c_restrict c_variadic_macros)
  set(CMAKE_C11_COMPILE_FEATURES   c_std_11 c_static_assert)
  set(CMAKE_C17_COMPILE_FEATURES   c_std_17)
  set(CMAKE_C_COMPILE_FEATURES
    ${CMAKE_C90_COMPILE_FEATURES}
    ${CMAKE_C99_COMPILE_FEATURES}
    ${CMAKE_C11_COMPILE_FEATURES}
    ${CMAKE_C17_COMPILE_FEATURES})
endif()

## Set library paths
if(BCC64X)
  link_directories("${ROOTDIR}/lib/win64x/$<IF:$<CONFIG:Debug>,debug,release>")
  link_directories("${ROOTDIR}/lib/win64x/release")
elseif(BCC64)
  link_directories("${ROOTDIR}/lib/win64/$<IF:$<CONFIG:Debug>,debug,release>")
  link_directories("${ROOTDIR}/lib/win64/release")
  link_directories("${ROOTDIR}/lib/win64/release/psdk")
elseif(BCC32X OR BCC32C)
  link_directories("${ROOTDIR}/lib/win32c/$<IF:$<CONFIG:Debug>,debug,release>")
  link_directories("${ROOTDIR}/lib/win32c/release")
  link_directories("${ROOTDIR}/lib/win32/$<IF:$<CONFIG:Debug>,debug,release>")
  link_directories("${ROOTDIR}/lib/win32/release")
  link_directories("${ROOTDIR}/lib/win32/release/psdk")
elseif(BCC32)
  link_directories("${ROOTDIR}/lib/win32/$<IF:$<CONFIG:Debug>,debug,release>")
  link_directories("${ROOTDIR}/lib/win32/release")
  link_directories("${ROOTDIR}/lib/win32/release/psdk")
else()
  message(FATAL_ERROR "Unknown compiler")
endif()

if(BCC64X)
  # MinGW/lld conventions, but keep our own libs unprefixed (.dll/.lib/.a).
  set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
  set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
  set(CMAKE_SHARED_LIBRARY_PREFIX "")
  set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
  set(CMAKE_IMPORT_LIBRARY_PREFIX "")
  set(CMAKE_IMPORT_LIBRARY_SUFFIX ".lib")
  set(CMAKE_STATIC_LIBRARY_PREFIX "")
  set(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
  set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
  # Empty link suffix: bare lib names go to lld as -l<name> (resolves
  # libiphlpapi.a etc.). A ".lib" suffix would make -l<name>.lib, which lld
  # cannot find. Our own import libs are linked by full path, so unaffected.
  set(CMAKE_LINK_LIBRARY_SUFFIX "")
  set(CMAKE_C_OUTPUT_EXTENSION ".o")
  set(CMAKE_CXX_OUTPUT_EXTENSION ".o")
  find_program(CMAKE_AR NAMES llvm-ar PATHS "${BIN_DIR_PATH}" NO_DEFAULT_PATH)
elseif(BCC64)
  set(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
  set(CMAKE_IMPORT_LIBRARY_SUFFIX ".lib")
  set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a")
  set(CMAKE_LINK_LIBRARY_SUFFIX ".lib")

  ## Doesn't seem to always work here. Also set in compiler configuration modules.
  set(CMAKE_C_OUTPUT_EXTENSION ".o")
  set(CMAKE_CXX_OUTPUT_EXTENSION ".o")
else()
  set(CMAKE_FIND_LIBRARY_SUFFIXES "-bcc.lib" ".lib")
endif()

set(_COMPILE_C "-c")
set(_COMPILE_CXX "-P -c")
set(CMAKE_LIBRARY_PATH_FLAG "-L")

if(CLANG_BASED)
  if(CLANG_BASED_OPTS)
    set(FIX_QUOTING "--rsp-quoting=windows ")
  else()
    set(FIX_QUOTING "-Xdriver --rsp-quoting=windows ")
  endif()
endif()
set(CMAKE_LINK_LIBRARY_FLAG "${FIX_QUOTING}")

# uncomment these out to debug makefiles
#set(CMAKE_START_TEMP_FILE "")
#set(CMAKE_END_TEMP_FILE "")
#set(CMAKE_VERBOSE_MAKEFILE 1)

# Linker cannot handle + in the file name, so mangle object file name
set(CMAKE_MANGLE_OBJECT_FILE_NAMES "ON")

# extra flags for a win32 exe
set(CMAKE_CREATE_WIN32_EXE "${_tW}" )
# extra flags for a console app
set(CMAKE_CREATE_CONSOLE_EXE "${_tC}" )

foreach(t EXE SHARED MODULE)
  string(APPEND CMAKE_${t}_LINKER_FLAGS_INIT " ${_tM} ${_tR}")
  # These are clang-driver link options (bcc32x/bcc64x). bcc32c uses the classic
  # driver and rejects them ("E2075 Incorrect command line option"), so gate on
  # CLANG_BASED_OPTS rather than CLANG_BASED.
  if(CLANG_BASED_OPTS)
    string(APPEND CMAKE_${t}_LINKER_FLAGS_INIT " -Wno-unused-command-line-argument")
    # bcc64: -g on the link line makes the driver tell ilink64 to embed DWARF
    # debug info in the image. (-v is only verbose; it does NOT add debug info.)
    string(APPEND CMAKE_${t}_LINKER_FLAGS_DEBUG_INIT " -g")
  endif()
endforeach()

# Resource files
if(NOT CMAKE_RC_COMPILER_INIT)
  # Prefer Windows SDK rc.exe (needed for bcc64x / non-MSVC builds where rc.exe is not on PATH)
  file(GLOB _winsdk_rc
    "C:/Program Files (x86)/Windows Kits/10/bin/*/x64/rc.exe")
  if(_winsdk_rc)
    list(GET _winsdk_rc -1 _winsdk_rc_latest)
    set(CMAKE_RC_COMPILER_INIT "${_winsdk_rc_latest}")
  else()
    set(CMAKE_RC_COMPILER_INIT "rc.exe")
  endif()
  unset(_winsdk_rc)
  unset(_winsdk_rc_latest)
endif()
enable_language(RC)

# Older tools do not support multiple concurrent invocations within a
# single working directory.
if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 7.50 OR BCC32)
  if(NOT DEFINED CMAKE_JOB_POOL_LINK)
    set(CMAKE_JOB_POOL_LINK BCC32LinkPool)
    get_property(_bccjp GLOBAL PROPERTY JOB_POOLS)
    if(NOT _bccjp MATCHES "BCC32LinkPool=")
      set_property(GLOBAL APPEND PROPERTY JOB_POOLS BCC32LinkPool=1)
    endif()
    unset(_bccjp)
  endif()
endif()

macro(__embarcadero_language lang)
  set(CMAKE_${lang}_COMPILE_OPTIONS_DLL "${_tD}" ) # Note: This variable is a ';' separated list
  set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "${_tD}") # ... while this is a space separated string.
  # CMake's generic default for this is "-shared"; it gets folded into the link
  # line for shared libraries. Our DLL link rules supply the correct flag
  # themselves (-tD for the classic ilink32 driver, -shared for bcc64x's lld),
  # and the classic bcc32/bcc32c driver rejects "-shared" (E2075). Clear it.
  set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "")
  set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1)

  # compile a source file into an object file
  # place <DEFINES> outside the response file because Borland refuses
  # to parse quotes from the response file.
  set(CMAKE_${lang}_COMPILE_OBJECT
    "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o<OBJECT> ${_COMPILE_${lang}} <SOURCE>"
    )

  set(CMAKE_${lang}_LINK_EXECUTABLE
    "<CMAKE_${lang}_COMPILER> ${FIX_QUOTING} -o<TARGET> <LINK_FLAGS> <FLAGS> ${CMAKE_START_TEMP_FILE} <LINK_LIBRARIES> <OBJECTS>${CMAKE_END_TEMP_FILE}"
    )

  # Used for Makefile based builds
  set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE
    "${_EMBT_CPP_PREPROCESSOR} <DEFINES> <INCLUDES> <FLAGS> -o<PREPROCESSED_SOURCE> ${_COMPILE_${lang}} <SOURCE>"
    )

  # Create a module library.
  set(CMAKE_${lang}_CREATE_SHARED_MODULE
    "<CMAKE_${lang}_COMPILER> ${FIX_QUOTING} ${_tD} ${CMAKE_START_TEMP_FILE}-o<TARGET> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS>${CMAKE_END_TEMP_FILE}"
    )

  # Create an import library for another target.
  if(BCC64)
    set(CMAKE_${lang}_CREATE_IMPORT_LIBRARY
      "mkexp <TARGET_IMPLIB> <TARGET>"
      )
  else()
    set(CMAKE_${lang}_CREATE_IMPORT_LIBRARY
      "implib -c -w <TARGET_IMPLIB> <TARGET>"
      )
  endif()

  # Create a shared library.
  # First create a module and then its import library.
  set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
    ${CMAKE_${lang}_CREATE_SHARED_MODULE}
    ${CMAKE_${lang}_CREATE_IMPORT_LIBRARY}
    )

  # create a static library
  if(BCC64)
    set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
      "tlib64 ${CMAKE_START_TEMP_FILE}/p2048 /N /B <LINK_FLAGS> /u <TARGET_QUOTED> <OBJECTS>${CMAKE_END_TEMP_FILE}"
      )
  else()
    set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
      "tlib ${CMAKE_START_TEMP_FILE}/p512 /N /B <LINK_FLAGS> /u <TARGET_QUOTED> <OBJECTS>${CMAKE_END_TEMP_FILE}"
      )
  endif()

  # Initial configuration flags.
  string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_tM} ${_tR}")

  if(CLANG_BASED)
    set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
  endif()

  if(CLANG_BASED_OPTS)
    # -fno-standalone-debug: emit full debug info only for types defined in our
    # own sources; for types defined elsewhere (Boost/Poco/STL) emit just
    # declarations. Keeps our code debuggable while preventing the huge,
    # deeply-recursive Boost template DWARF that hangs the Embarcadero debug
    # kernel ("Debug Kernel is not responding") before main.
    string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -O0 -g -fno-standalone-debug")
    string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG")
    string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O2 -DNDEBUG")
    string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O3")
  else()
    string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -Od -v")
    string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG")
    string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O2 -DNDEBUG")
    string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Od")
    set(CMAKE_${lang}_STANDARD_LIBRARIES_INIT "import32.lib")
  endif()

  if(BCC64X)
    # Poco (and our own headers) decorate classes with Foundation_API
    # (__declspec(dllimport) in consumers) but define many members inline.
    # clang-15 correctly ignores dllimport on inline functions and warns
    # [-Wignored-attributes] — hundreds of harmless W5743/W6000. Silence it.
    # -Wno-unused-command-line-argument: link_directories() feeds -L paths to
    # the compile step too, which clang flags as unused during compilation.
    string(APPEND CMAKE_${lang}_FLAGS_INIT
      " -Wno-ignored-attributes -Wno-unused-command-line-argument")

    # Override the Borland ilink64/mkexp/tlib rules with clang + ld.lld + llvm-ar.
    set(CMAKE_${lang}_COMPILE_OPTIONS_DLL "")
    set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "")

    # NOTE: the bcc64x driver omits -lc++ for -shared links (it adds it for
    # exes), so polymorphic/RTTI/operator-new DLLs fail to link without it.
    # Append -lc++ explicitly.
    set(CMAKE_${lang}_CREATE_SHARED_MODULE
      "<CMAKE_${lang}_COMPILER> ${FIX_QUOTING}-shared -o <TARGET> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -lc++")

    # DLL + its import library in one ld.lld invocation.
    set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
      "<CMAKE_${lang}_COMPILER> ${FIX_QUOTING}-shared -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> -lc++")

    set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
      "<CMAKE_AR> qc <TARGET> <OBJECTS>")

    # As with -shared, the driver only auto-links the C++ runtime when given a
    # .cpp source; linking from pre-compiled objects (as CMake does) needs an
    # explicit -lc++ (which pulls in libc++abi/unwind) or libc++ symbols and
    # the SEH personality routine are left undefined.
    set(CMAKE_${lang}_LINK_EXECUTABLE
      "<CMAKE_${lang}_COMPILER> ${FIX_QUOTING}-o <TARGET> <LINK_FLAGS> <FLAGS> <OBJECTS> <LINK_LIBRARIES> -lc++")
  endif()
endmacro()

macro(set_embt_target)
  foreach(arg IN ITEMS ${ARGN})
    if(${arg} STREQUAL "FMX")
      set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} ${_tF}")
      include_directories(SYSTEM "${ROOTDIR}/include/windows/fmx")
    elseif(${arg} STREQUAL "VCL")
      set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} ${_tV}")
      include_directories(SYSTEM "${ROOTDIR}/include/windows/vcl")
    elseif(${arg} STREQUAL "DR")
      set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} ${_tJ}")
    elseif(${arg} STREQUAL "DynamicRuntime")
      set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} ${_tR}")
    elseif(${arg} STREQUAL "Package")
      set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} ${_tP}")
    elseif(${arg} STREQUAL "Unicode")
      set(CMAKE_${_lang}_FLAGS "${CMAKE_${_lang}_FLAGS} ${_tU}")
    else()
      message("Error in set_embt_target: unknown target specified \"${arg}\"")
    endif()
  endforeach()
endmacro()
