
# Rust (mmtorust) omc port. When enabled, the compiler is produced by
# transpiling the MetaModelica sources to Rust and cargo-building them; bomc/omc
# are never compiled from C, so we skip the entire C-build path below (the
# bootstrap C runtime, the bomc bootstrapper, the C++ frontend, and the
# .mo -> .c -> libOpenModelicaCompiler/omc steps). The simulation/function
# runtime libraries live under OMCompiler/SimulationRuntime and are still built.
if(OM_OMC_ENABLE_RUST)
  # Defines the build tools + susan, sets OMC_EXE to the susan binary, and
  # TPL_EXTRA_DEPENDS so the template rules wait for susan.
  include(${CMAKE_CURRENT_SOURCE_DIR}/.cmake/rust_omc.cmake)
  if(RUST_OMC_PREBUILT_CDYLIB)
    # GUI-only build against a prebuilt Rust omc (split CI stage 2): a stage-1
    # build already produced the cdylib + the generated Qt API sources, handed
    # over via RUST_OMC_PREBUILT_CDYLIB / RUST_OMC_PREBUILT_SCRIPTING_API_QT_DIR.
    # Skip susan, mmtorust and the whole codegen — no cargo runs here; only the
    # Qt GUI clients (and the C/C++ simulation runtime they link) are built. This
    # lets the GUI compile in parallel with the testsuite off the stage-1 cdylib.
    omc_rust_setup_omedit()
  else()
    # The same template rules as the C build, now driven by ${OMC_EXE} == susan,
    # producing Compiler/Template/*.mo and populating TPL_OUTPUT_MO_FILES.
    include(${CMAKE_CURRENT_SOURCE_DIR}/.cmake/template_compilation.cmake)
    # The canonical MetaModelica source list (OMC_MM_ALWAYS_SOURCES /
    # OMC_MM_BACKEND_SOURCES) — mmtorust is driven from this, not a separate txt.
    include(${CMAKE_CURRENT_SOURCE_DIR}/.cmake/meta_modelica_source_list.cmake)
    # Full transpile (mmtorust) + the rust_scripting_api target, and — unless this
    # is the wasm/web build — the native rust_omc / rust_libopenmodelica artifacts.
    omc_rust_setup_codegen()
    if(OM_OMC_WASM)
      # Web target: build only the wasm bundle (cargo wasm + wasm-bindgen). The
      # native artifacts and GUI clients are skipped (OM_OMC_WASM forces the
      # clients off at top level), so `make all` produces just the wasm bundle.
      omc_rust_setup_wasm()
    elseif(OM_ENABLE_GUI_CLIENTS)
      # Provide the OpenModelicaCompiler target the Qt GUI clients link (the C
      # build's is skipped under Rust mode along with the rest of this file).
      omc_rust_setup_omedit()
    endif()
  endif()
  # The simulation/function runtime (under OMCompiler/SimulationRuntime) is built
  # even in Rust mode and angle-includes omc_config.unix.h. Its generation lives
  # in runtime/CMakeLists.txt, which the return() below skips — so generate the
  # build-tree header here, or the runtime fails with "'omc_config.unix.h' file
  # not found".
  include(${CMAKE_CURRENT_SOURCE_DIR}/runtime/omc_config_unix.cmake)
  # runtime/CMakeLists.txt (skipped above) also generates Autoconf.mo from
  # Autoconf.mo.in — a compiler source the transpile reads. Without it mmtorust
  # silently skips the missing source and emits an openmodelica_util lib.rs with
  # no `pub mod Autoconf;`, so the hand-written OMSimulatorExt.rs
  # (`use crate::Autoconf;`) fails to build. The Rust port only needs the package
  # to parse: its runtime values are never used (Autoconf.rs is hand-maintained),
  # so substitute the .in without the C build's ldflags/Corba/etc. plumbing. The
  # only @vars@ used in non-string positions are OMC_TARGET_ARCH_IS_64 and
  # WITH_HWLOC (set by omc_config_unix.cmake above) and BSTATIC (set here); the
  # rest are strings and may be empty. Written to the BUILD tree (RUST_AUTOCONF_MO,
  # from rust_omc.cmake) rather than Compiler/Util — an in-source generated
  # Autoconf.mo collides with a parallel autotools build of the same checkout; the
  # two mmtorust source lists redirect their Util/Autoconf.mo entry to this path.
  # Only mmtorust consumes it, so skip it in the prebuilt GUI-only mode (no codegen).
  if(NOT RUST_OMC_PREBUILT_CDYLIB)
    set(BSTATIC "false")
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Util/Autoconf.mo.in
                   ${RUST_AUTOCONF_MO} @ONLY)
  endif()
  return()
endif()

omc_add_subdirectory(runtime)
omc_add_subdirectory(boot)
omc_add_subdirectory(FrontEndCpp)


# set(OMC_EXE ${PROJECT_SOURCE_DIR}/../build/bin/omc)
set(OMC_EXE $<TARGET_FILE:bomc>)

# Enable MetaModelica debug symbols when doing a debug build, which is needed
# for the debugger to work.
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
  set(GEN_DEBUG_SYMBOLS "-d=gendebugsymbols")
endif()

# Compile the compiler against itself with the def-use static analysis enabled so that
# conditionally-assigned variables are caught at build time. -d= is additive and survives
# the setCommandLineOptions("-d=rml") in mm_compile.in.mos.
set(CHECK_DEF_USE "-d=checkDefUse")

# list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/.cmake")
# enable_language(MODELICA)

macro(add_interface_checker_script mo_source_file)

    get_filename_component(file_name_no_ext ${mo_source_file} NAME_WLE)
    get_filename_component(source_dir ${mo_source_file} DIRECTORY)

    set(MM_PACKAGE_NAME ${file_name_no_ext})
    set(MM_INPUT_SOURCE_DIR ${source_dir})
    set(MM_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/.cmake/mm_check_interface.in.mos ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.check_interface.mos)
endmacro(add_interface_checker_script)

macro(add_compile_script mo_source_file)
    get_filename_component(file_name_no_ext ${mo_source_file} NAME_WLE)
    get_filename_component(source_dir ${mo_source_file} DIRECTORY)

    set(MM_PACKAGE_NAME ${file_name_no_ext})
    set(MM_INPUT_SOURCE_DIR ${source_dir})
    set(MM_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/.cmake/mm_compile.in.mos ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.compile.mos)
endmacro(add_compile_script)



macro(add_interface_check_step mo_source_file)
    add_interface_checker_script(${mo_source_file})

    get_filename_component(file_name_no_ext ${mo_source_file} NAME_WLE)
    get_filename_component(source_dir ${mo_source_file} DIRECTORY)

    add_custom_command(
        DEPENDS ${mo_source_file}
                ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.check_interface.mos

        COMMAND ${OMC_EXE} -g=MetaModelica -n=1 ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.check_interface.mos

        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.interface.mo.stamp
        BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.interface.mo
        COMMENT "Checking interface for ${mo_source_file}"
    )

    set(OMC_MM_SOURCE_FILE_NAMES ${OMC_MM_SOURCE_FILE_NAMES} ${file_name_no_ext})

    set(OMC_MM_INTERFACE_FILES ${OMC_MM_INTERFACE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.interface.mo)
    set(OMC_MM_STAMP_FILES ${OMC_MM_STAMP_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.interface.mo.stamp)


    add_custom_command(
        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.interface.mo
        # COMMAND ${CMAKE_COMMAND} -E cat ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.rev_depends
        COMMAND ${CMAKE_COMMAND} -DREV_DEP_FILE=${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.rev_depends
                                 -DINTERFACE_FILES_DIR=${CMAKE_CURRENT_BINARY_DIR}
                                  -P ${CMAKE_CURRENT_SOURCE_DIR}//.cmake/dep_toucher.cmake
        COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.rev_deps.stamp
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.rev_deps.stamp
        COMMENT "Touching dependents of ${mo_source_file}"
    )
    set(OMC_REV_DEP_STAMP_FILES ${OMC_REV_DEP_STAMP_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.rev_deps.stamp)

endmacro(add_interface_check_step)




macro(add_compile_step mo_source_file)

    add_compile_script(${mo_source_file})

    get_filename_component(file_name_no_ext ${mo_source_file} NAME_WLE)
    get_filename_component(source_dir ${mo_source_file} DIRECTORY)

    add_custom_command(
        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.interface.mo.stamp
                ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.compile.mos

        COMMAND ${OMC_EXE} -g=MetaModelica -n=1 ${GEN_DEBUG_SYMBOLS} ${CHECK_DEF_USE} ${CMAKE_CURRENT_BINARY_DIR}/${file_name_no_ext}.compile.mos

        OUTPUT  ${CMAKE_CURRENT_BINARY_DIR}/c_files/${file_name_no_ext}.c
                ${CMAKE_CURRENT_BINARY_DIR}/c_files/${file_name_no_ext}_records.c
                ${CMAKE_CURRENT_BINARY_DIR}/c_files/${file_name_no_ext}.h
                ${CMAKE_CURRENT_BINARY_DIR}/c_files/${file_name_no_ext}_includes.h

        BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/c_files/${file_name_no_ext}.deps

        COMMENT "Translating ${mo_source_file}"
    )

    set(OMC_C_SOURCE_FILES ${OMC_C_SOURCE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/c_files/${file_name_no_ext}.c
                                                   ${CMAKE_CURRENT_BINARY_DIR}/c_files/${file_name_no_ext}_records.c)
endmacro(add_compile_step)



# OpenModelicaScriptingAPI.mo (a compiler source) stays in Script/; the C++ Qt
# files go under the build tree (OMEditLIB reads OMC_SCRIPTING_API_QT_DIR), so C
# and Rust builds don't fight over Script/.
set(OMC_SCRIPTING_API_QT_DIR ${CMAKE_CURRENT_BINARY_DIR}/scripting-api-qt
    CACHE INTERNAL "Generated OpenModelicaScriptingAPIQt C++ sources (build tree)")
add_custom_command(
    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Script/OpenModelicaScriptingAPI.mos
            ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/ModelicaBuiltin.mo
            ${CMAKE_CURRENT_SOURCE_DIR}/Template/GenerateAPIFunctionsTpl.tpl

    # The script generates in its working directory.
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Script

    COMMAND ${OMC_EXE} -g=MetaModelica -n=1 ${CMAKE_CURRENT_SOURCE_DIR}/Script/OpenModelicaScriptingAPI.mos
    COMMAND ${CMAKE_COMMAND} -E make_directory ${OMC_SCRIPTING_API_QT_DIR}
    COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_SOURCE_DIR}/Script/OpenModelicaScriptingAPIQt.cpp ${OMC_SCRIPTING_API_QT_DIR}/OpenModelicaScriptingAPIQt.cpp
    COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_SOURCE_DIR}/Script/OpenModelicaScriptingAPIQt.h ${OMC_SCRIPTING_API_QT_DIR}/OpenModelicaScriptingAPIQt.h

    OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Script/OpenModelicaScriptingAPI.mo
    OUTPUT ${OMC_SCRIPTING_API_QT_DIR}/OpenModelicaScriptingAPIQt.cpp
    OUTPUT ${OMC_SCRIPTING_API_QT_DIR}/OpenModelicaScriptingAPIQt.h
    COMMENT "Generating OpenModelicaScriptingAPI.mo + Qt API"
)





include(${CMAKE_CURRENT_SOURCE_DIR}/.cmake/template_compilation.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/.cmake/meta_modelica_source_list.cmake)

foreach(OMC_MM_SOURCE ${OMC_MM_ALWAYS_SOURCES})
    add_interface_check_step(${OMC_MM_SOURCE})
    add_compile_step(${OMC_MM_SOURCE})
endforeach()

foreach(OMC_MM_SOURCE ${OMC_MM_BACKEND_SOURCES})
    add_interface_check_step(${OMC_MM_SOURCE})
    add_compile_step(${OMC_MM_SOURCE})
endforeach()



# A target to make sure all interfaces have been checked. Interfaces get rechecked if a MM source is
# modified. If a source is modified and the interface has NOT actually changed then only the stamp files
# are touched to signify time of check. If the interface has CHANGED then the interface file is also
# updated which will cause regeneration of dependency information. See the section below.
add_custom_target(INTERFACE_CHECK
                  DEPENDS ${OMC_MM_STAMP_FILES}
                  COMMENT "Checked interfaces of modified MetaModelica sources.")




# Add a small dependency scanner program. This reads a list of list of dependencies and generates
# a list of dependents for each entry.
add_executable(dep_scanner ${CMAKE_CURRENT_SOURCE_DIR}/.cmake/dep_scanner.cpp)

# Write out a new line separated list of all MM source files to a list so that it can be easily
# parsed by the small MetaModelica dependency scanner we have now. (c++ code)
# The quote "" on ${OMC_MM_SOURCE_FILE_NAMES} is needed to get the ";"s in the list
string (REPLACE ";" "\n" OMC_MM_SOURCE_FILE_NAMES_NEW_LINES "${OMC_MM_SOURCE_FILE_NAMES}")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/mm_source_filenames_list.txt ${OMC_MM_SOURCE_FILE_NAMES_NEW_LINES})

# Read the mm_source_filenames_list with the dep scanner. The dep scanner then reads <mm_source>.depends file for the
# each mm_source in the list and generates the "reverse dependencies" (dependents) for each source in to <mm_source>.rev_deps.
# This means all the files listed in .rev_deps need to be retranslated when <mm_source>.mo is modified.
add_custom_command(
                DEPENDS ${OMC_MM_INTERFACE_FILES}
                COMMAND $<TARGET_FILE:dep_scanner> ${CMAKE_CURRENT_BINARY_DIR}/mm_source_filenames_list.txt ${CMAKE_CURRENT_BINARY_DIR}
                COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/dep_scan.stamp
                OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dep_scan.stamp
                COMMENT "Scanning reverse dependencies for MetaModelica sources.")
add_custom_target(DEPENDENCY_SCAN
                  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dep_scan.stamp
                  COMMENT "Scanned reverse dependencies for MetaModelica sources.")





add_custom_target(DEPENDENCY_UPDATE
                  DEPENDS ${OMC_REV_DEP_STAMP_FILES}
                  COMMENT "Touched dependents of modified MetaModelica sources.")


add_dependencies(DEPENDENCY_SCAN INTERFACE_CHECK)
add_dependencies(DEPENDENCY_UPDATE DEPENDENCY_SCAN)




add_library(OpenModelicaCompiler SHARED ${OMC_C_SOURCE_FILES} .cmake/omc_entry_point.c)
add_dependencies(OpenModelicaCompiler DEPENDENCY_UPDATE)

# output libOpenModelicaCompiler in a directory named 'lib' or 'bin' (on Windows, dll) inside
# the current binary directory. The reason for this is that omc (using libOpenModelicaCompiler),
# up on launch, checks where it is located and looks for the things it wants relative to that location.
# For example it expects ModelicaBuiltin.mo to be in '../lib/omc' relative to the libOpenModelicaCompiler shared
# library. To achieve this it first checks if libOpenModelicaCompiler is a directory named 'bin' or 'lib'.
# If it is not it will refuse to run. So output it in a directory named 'lib' or 'bin' and then copy
# The files it needs in '../lib/omc' relative to it.
set_target_properties(OpenModelicaCompiler
    PROPERTIES
    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)

# It also wants to have these builtin files in ../lib/ relative to its location.
add_custom_command (
    TARGET OpenModelicaCompiler
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/AnnotationsBuiltin_1_x.mo ${CMAKE_CURRENT_BINARY_DIR}/lib/omc/AnnotationsBuiltin_1_x.mo
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/AnnotationsBuiltin_2_x.mo ${CMAKE_CURRENT_BINARY_DIR}/lib/omc/AnnotationsBuiltin_2_x.mo
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/AnnotationsBuiltin_3_x.mo ${CMAKE_CURRENT_BINARY_DIR}/lib/omc/AnnotationsBuiltin_3_x.mo
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/ModelicaBuiltin.mo ${CMAKE_CURRENT_BINARY_DIR}/lib/omc/ModelicaBuiltin.mo
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/FrontEnd/MetaModelicaBuiltin.mo ${CMAKE_CURRENT_BINARY_DIR}/lib/omc/MetaModelicaBuiltin.mo
    COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/NFFrontEnd/NFModelicaBuiltin.mo ${CMAKE_CURRENT_BINARY_DIR}/lib/omc/NFModelicaBuiltin.mo
    COMMENT "Copying (NF/Meta/Modelica)Builtin.mo files for the omc generated in the build tree (not installed yet).")


target_compile_definitions(OpenModelicaCompiler PRIVATE ADD_METARECORD_DEFINITIONS=)

# Silence warnings about extra parenthesized equality checks. if((a==b))
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
  target_compile_options(OpenModelicaCompiler PRIVATE -Wno-parentheses-equality)
endif()

# Silence GCC warnings about invalid reads of MetaModelica strings.
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  target_compile_options(OpenModelicaCompiler PRIVATE -Wno-stringop-overread)
endif()

# There is a lonely omc_file.h in Util/. It belongs in runtime/. Remove this when it is moved.
target_include_directories(OpenModelicaCompiler PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Util)

# This should not be needed ideally. However linking libs sometimes need to include the generated headers.
# Right now this only happens for OMEdit. OMEdit includes Script/OpenModelicaScriptingAPIQt.h
# which in turn wants to include OpenModelicaScriptingAPI.h. This header is generated from
# translation of OpenModelicaScriptingAPI.mo. So this interface include dir is needed.
# We can maybe copy these headers to some specific location after generation and avoid this.
target_include_directories(OpenModelicaCompiler INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/c_files)

# OMC will overflow the stack (at least on Windows old OMDev) on very deep recursive calls.
# E.g., try translating the CodegenCpp* tpl files to mo files with
# an omc not compiled without large stack size. The tpl parser is quite recursive and will
# overflow on parsing comments with very long lines ~300. *CPP tpl files have lines longer
# than that.
# if(MINGW)
#   target_link_options(OpenModelicaCompiler PUBLIC -Wl,--stack,33554432)
# endif()

# For now disable some warnings for MSVC. These should of course be fixed properly.
if(MSVC)
  target_compile_options(OpenModelicaCompiler PRIVATE /wd4101) # unreferenced local variable
  target_compile_options(OpenModelicaCompiler PRIVATE /wd4102) # unreferenced label
  target_compile_options(OpenModelicaCompiler PRIVATE /wd4267) # conversion from 'size_t' to 'int', possible loss of data
  target_compile_options(OpenModelicaCompiler PRIVATE /wd4244) # conversion from '' to '', possible loss of data
endif()



target_link_libraries(OpenModelicaCompiler PUBLIC omc::parser)
target_link_libraries(OpenModelicaCompiler PUBLIC omc::compiler::backendruntime)
target_link_libraries(OpenModelicaCompiler PUBLIC omc::compiler::runtime)
target_link_libraries(OpenModelicaCompiler PUBLIC omc::compiler::frontendcpp)
target_link_libraries(OpenModelicaCompiler PUBLIC omc::simrt::runtime)

# On Windows we need explicitly tell the dll to export all symbols. It is not so good
# that we have to export all symbols. However, OMEdit uses some of the functions in the
# lib directly and we have no way of marking specific MetaModelica functions for exporting.
if(MINGW)
  target_link_options(OpenModelicaCompiler PRIVATE  -Wl,--export-all-symbols)
elseif(MSVC)
  set_target_properties(OpenModelicaCompiler PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS true)
endif()

# OMC Executable.
add_executable(omc .cmake/omc_main.c)
target_link_libraries(omc PRIVATE OpenModelicaCompiler)

if(NOT WIN32)
  target_link_options(omc PRIVATE -rdynamic)
endif()

# if(MINGW)
#   target_link_options(omc PRIVATE -Wl,--stack,33554432)
# endif()



### INSTALLATION

# Install OpenModelicaCompiler to the directory for LIBRARIES (default=lib)
# Install omc to the directory for RUNTIME (default=bin)
# They are part of "compiler" installation component. This means that you can
# install just the files in this component by specifying its name.
if(WIN32)
  # Escape the environment variable path
  if(NOT DEFINED ENV{OMDEV})
    message(FATAL_ERROR "Environment variable \"OMDEV\" is not set.")
  endif()
  if(NOT DEFINED ENV{MSYSTEM_PREFIX})
    message(FATAL_ERROR "Environment variable \"MSYSTEM_PREFIX\" is not set.")
  endif()

  if (CMAKE_GENERATOR STREQUAL "MinGW Makefiles" AND "$ENV{VisualStudioVersion}" STREQUAL "")
    string(REPLACE "\\" "/" MSYSTEM_PREFIX_ESCAPED "$ENV{OMDEV}\\tools\\msys\\$ENV{MSYSTEM_PREFIX}")
  else()
    string(REPLACE "\\" "/" MSYSTEM_PREFIX_ESCAPED "$ENV{MSYSTEM_PREFIX}")
  endif()

  set(OMCOMPILER_LIB_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}OMCompiler/Compiler/bin)
  set(SIMULATION_RUNTIME_LIB_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}OMCompiler/SimulationRuntime/c)
  set(GC_RUNTIME_LIB_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}OMCompiler/3rdParty/gc)
  set(RUNTIME_LIB_DIRS ${OMPLOT_LIB_DIR} ${OMSIMULATOR_LIB_DIR} ${OMCOMPILER_LIB_DIR} ${SIMULATION_RUNTIME_LIB_DIR} ${GC_RUNTIME_LIB_DIR})

  if(NOT ${CMAKE_VERSION} VERSION_LESS "4.3")
    cmake_policy(SET CMP0207 NEW)
  endif()

  message(STATUS "Looking for runtime dependencies of OpenModelicaCompiler in ${MSYSTEM_PREFIX_ESCAPED}/bin ${RUNTIME_LIB_DIRS}")
  install(TARGETS OpenModelicaCompiler
          RUNTIME_DEPENDENCIES
            DIRECTORIES ${MSYSTEM_PREFIX_ESCAPED}/bin ${RUNTIME_LIB_DIRS}
            PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-"
            POST_EXCLUDE_REGEXES ".*system32/.*\\.dll")
  install(TARGETS omc
          COMPONENT omc)

  # libopenblas.dll is linked dynamically (-lopenblas) by the *generated*
  # simulation and FMU code (see RT_LDFLAGS_GENERATED_CODE* in
  # Compiler/runtime/CMakeLists.txt), but it is not a runtime dependency of the
  # compiler itself, so the RUNTIME_DEPENDENCIES scan above does not pick it up.
  # The autotools/OMDev build copies it explicitly (Makefile.omdev.mingw); do the
  # same here so e.g. buildModelFMU() can bundle it into the exported FMU.
  install(FILES ${MSYSTEM_PREFIX_ESCAPED}/bin/libopenblas.dll
          DESTINATION ${CMAKE_INSTALL_BINDIR}
          COMPONENT omc
          OPTIONAL)
else(WIN32)
  install(TARGETS omc OpenModelicaCompiler
          COMPONENT omc)
endif(WIN32)

# Install the *ModelicaBuiltin files to <library_dir>/omc/ that is where omc.exe expects them to be.
# They are also part of "compiler" installation component.
install(FILES FrontEnd/AnnotationsBuiltin_1_x.mo
            DESTINATION lib/omc
            COMPONENT omc)
install(FILES FrontEnd/AnnotationsBuiltin_2_x.mo
            DESTINATION lib/omc
            COMPONENT omc)
install(FILES FrontEnd/AnnotationsBuiltin_3_x.mo
            DESTINATION lib/omc
            COMPONENT omc)
install(FILES NFFrontEnd/NFModelicaBuiltin.mo
            DESTINATION lib/omc
            COMPONENT omc)
install(FILES FrontEnd/ModelicaBuiltin.mo
            DESTINATION lib/omc
            COMPONENT omc)
install(FILES FrontEnd/MetaModelicaBuiltin.mo
            DESTINATION lib/omc
            COMPONENT omc)
install(FILES FrontEnd/PDEModelicaBuiltin.mo
            DESTINATION lib/omc
            COMPONENT omc)

# Install the scripts to 'share' dir.
install(DIRECTORY scripts
        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/omc/)


# This is a convenience target to install omc. We are used to issuing 'make install' to install
# components. CMake uses a separate install script to perform installations. This custom command
# runs that cmake script so that you can just write 'make install' (for makefile generators)
# or 'cmake --build <b_dir> --target install_omc' in the general case.
add_custom_target(install_omc
                  DEPENDS omc
                  COMMAND ${CMAKE_COMMAND} -DCOMPONENT=omc -P cmake_install.cmake
                  COMMENT "Installing omc."
                  )
