Yunusemre
Committed by GitHub

Merge pull request #5 from EmreOzkose/master

First working version
  1 +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2 +# file Copyright.txt or https://cmake.org/licensing for details.
  3 +
  4 +#[=======================================================================[.rst:
  5 +FetchContent
  6 +------------------
  7 +
  8 +.. only:: html
  9 +
  10 + .. contents::
  11 +
  12 +Overview
  13 +^^^^^^^^
  14 +
  15 +This module enables populating content at configure time via any method
  16 +supported by the :module:`ExternalProject` module. Whereas
  17 +:command:`ExternalProject_Add` downloads at build time, the
  18 +``FetchContent`` module makes content available immediately, allowing the
  19 +configure step to use the content in commands like :command:`add_subdirectory`,
  20 +:command:`include` or :command:`file` operations.
  21 +
  22 +Content population details would normally be defined separately from the
  23 +command that performs the actual population. Projects should also
  24 +check whether the content has already been populated somewhere else in the
  25 +project hierarchy. Typical usage would look something like this:
  26 +
  27 +.. code-block:: cmake
  28 +
  29 + FetchContent_Declare(
  30 + googletest
  31 + GIT_REPOSITORY https://github.com/google/googletest.git
  32 + GIT_TAG release-1.8.0
  33 + )
  34 +
  35 + FetchContent_GetProperties(googletest)
  36 + if(NOT googletest_POPULATED)
  37 + FetchContent_Populate(googletest)
  38 + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
  39 + endif()
  40 +
  41 +When using the above pattern with a hierarchical project arrangement,
  42 +projects at higher levels in the hierarchy are able to define or override
  43 +the population details of content specified anywhere lower in the project
  44 +hierarchy. The ability to detect whether content has already been
  45 +populated ensures that even if multiple child projects want certain content
  46 +to be available, the first one to populate it wins. The other child project
  47 +can simply make use of the already available content instead of repeating
  48 +the population for itself. See the
  49 +:ref:`Examples <fetch-content-examples>` section which demonstrates
  50 +this scenario.
  51 +
  52 +The ``FetchContent`` module also supports defining and populating
  53 +content in a single call, with no check for whether the content has been
  54 +populated elsewhere in the project already. This is a more low level
  55 +operation and would not normally be the way the module is used, but it is
  56 +sometimes useful as part of implementing some higher level feature or to
  57 +populate some content in CMake's script mode.
  58 +
  59 +
  60 +Declaring Content Details
  61 +^^^^^^^^^^^^^^^^^^^^^^^^^
  62 +
  63 +.. command:: FetchContent_Declare
  64 +
  65 + .. code-block:: cmake
  66 +
  67 + FetchContent_Declare(<name> <contentOptions>...)
  68 +
  69 + The ``FetchContent_Declare()`` function records the options that describe
  70 + how to populate the specified content, but if such details have already
  71 + been recorded earlier in this project (regardless of where in the project
  72 + hierarchy), this and all later calls for the same content ``<name>`` are
  73 + ignored. This "first to record, wins" approach is what allows hierarchical
  74 + projects to have parent projects override content details of child projects.
  75 +
  76 + The content ``<name>`` can be any string without spaces, but good practice
  77 + would be to use only letters, numbers and underscores. The name will be
  78 + treated case-insensitively and it should be obvious for the content it
  79 + represents, often being the name of the child project or the value given
  80 + to its top level :command:`project` command (if it is a CMake project).
  81 + For well-known public projects, the name should generally be the official
  82 + name of the project. Choosing an unusual name makes it unlikely that other
  83 + projects needing that same content will use the same name, leading to
  84 + the content being populated multiple times.
  85 +
  86 + The ``<contentOptions>`` can be any of the download or update/patch options
  87 + that the :command:`ExternalProject_Add` command understands. The configure,
  88 + build, install and test steps are explicitly disabled and therefore options
  89 + related to them will be ignored. In most cases, ``<contentOptions>`` will
  90 + just be a couple of options defining the download method and method-specific
  91 + details like a commit tag or archive hash. For example:
  92 +
  93 + .. code-block:: cmake
  94 +
  95 + FetchContent_Declare(
  96 + googletest
  97 + GIT_REPOSITORY https://github.com/google/googletest.git
  98 + GIT_TAG release-1.8.0
  99 + )
  100 +
  101 + FetchContent_Declare(
  102 + myCompanyIcons
  103 + URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
  104 + URL_HASH 5588a7b18261c20068beabfb4f530b87
  105 + )
  106 +
  107 + FetchContent_Declare(
  108 + myCompanyCertificates
  109 + SVN_REPOSITORY svn+ssh://svn.mycompany.com/srv/svn/trunk/certs
  110 + SVN_REVISION -r12345
  111 + )
  112 +
  113 +Populating The Content
  114 +^^^^^^^^^^^^^^^^^^^^^^
  115 +
  116 +.. command:: FetchContent_Populate
  117 +
  118 + .. code-block:: cmake
  119 +
  120 + FetchContent_Populate( <name> )
  121 +
  122 + In most cases, the only argument given to ``FetchContent_Populate()`` is the
  123 + ``<name>``. When used this way, the command assumes the content details have
  124 + been recorded by an earlier call to :command:`FetchContent_Declare`. The
  125 + details are stored in a global property, so they are unaffected by things
  126 + like variable or directory scope. Therefore, it doesn't matter where in the
  127 + project the details were previously declared, as long as they have been
  128 + declared before the call to ``FetchContent_Populate()``. Those saved details
  129 + are then used to construct a call to :command:`ExternalProject_Add` in a
  130 + private sub-build to perform the content population immediately. The
  131 + implementation of ``ExternalProject_Add()`` ensures that if the content has
  132 + already been populated in a previous CMake run, that content will be reused
  133 + rather than repopulating them again. For the common case where population
  134 + involves downloading content, the cost of the download is only paid once.
  135 +
  136 + An internal global property records when a particular content population
  137 + request has been processed. If ``FetchContent_Populate()`` is called more
  138 + than once for the same content name within a configure run, the second call
  139 + will halt with an error. Projects can and should check whether content
  140 + population has already been processed with the
  141 + :command:`FetchContent_GetProperties` command before calling
  142 + ``FetchContent_Populate()``.
  143 +
  144 + ``FetchContent_Populate()`` will set three variables in the scope of the
  145 + caller; ``<lcName>_POPULATED``, ``<lcName>_SOURCE_DIR`` and
  146 + ``<lcName>_BINARY_DIR``, where ``<lcName>`` is the lowercased ``<name>``.
  147 + ``<lcName>_POPULATED`` will always be set to ``True`` by the call.
  148 + ``<lcName>_SOURCE_DIR`` is the location where the
  149 + content can be found upon return (it will have already been populated), while
  150 + ``<lcName>_BINARY_DIR`` is a directory intended for use as a corresponding
  151 + build directory. The main use case for the two directory variables is to
  152 + call :command:`add_subdirectory` immediately after population, i.e.:
  153 +
  154 + .. code-block:: cmake
  155 +
  156 + FetchContent_Populate(FooBar ...)
  157 + add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR})
  158 +
  159 + The values of the three variables can also be retrieved from anywhere in the
  160 + project hierarchy using the :command:`FetchContent_GetProperties` command.
  161 +
  162 + A number of cache variables influence the behavior of all content population
  163 + performed using details saved from a :command:`FetchContent_Declare` call:
  164 +
  165 + ``FETCHCONTENT_BASE_DIR``
  166 + In most cases, the saved details do not specify any options relating to the
  167 + directories to use for the internal sub-build, final source and build areas.
  168 + It is generally best to leave these decisions up to the ``FetchContent``
  169 + module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR``
  170 + cache variable controls the point under which all content population
  171 + directories are collected, but in most cases developers would not need to
  172 + change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if
  173 + developers change this value, they should aim to keep the path short and
  174 + just below the top level of the build tree to avoid running into path
  175 + length problems on Windows.
  176 +
  177 + ``FETCHCONTENT_QUIET``
  178 + The logging output during population can be quite verbose, making the
  179 + configure stage quite noisy. This cache option (``ON`` by default) hides
  180 + all population output unless an error is encountered. If experiencing
  181 + problems with hung downloads, temporarily switching this option off may
  182 + help diagnose which content population is causing the issue.
  183 +
  184 + ``FETCHCONTENT_FULLY_DISCONNECTED``
  185 + When this option is enabled, no attempt is made to download or update
  186 + any content. It is assumed that all content has already been populated in
  187 + a previous run or the source directories have been pointed at existing
  188 + contents the developer has provided manually (using options described
  189 + further below). When the developer knows that no changes have been made to
  190 + any content details, turning this option ``ON`` can significantly speed up
  191 + the configure stage. It is ``OFF`` by default.
  192 +
  193 + ``FETCHCONTENT_UPDATES_DISCONNECTED``
  194 + This is a less severe download/update control compared to
  195 + ``FETCHCONTENT_FULLY_DISCONNECTED``. Instead of bypassing all download and
  196 + update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the
  197 + update stage. Therefore, if content has not been downloaded previously,
  198 + it will still be downloaded when this option is enabled. This can speed up
  199 + the configure stage, but not as much as
  200 + ``FETCHCONTENT_FULLY_DISCONNECTED``. It is ``OFF`` by default.
  201 +
  202 + In addition to the above cache variables, the following cache variables are
  203 + also defined for each content name (``<ucName>`` is the uppercased value of
  204 + ``<name>``):
  205 +
  206 + ``FETCHCONTENT_SOURCE_DIR_<ucName>``
  207 + If this is set, no download or update steps are performed for the specified
  208 + content and the ``<lcName>_SOURCE_DIR`` variable returned to the caller is
  209 + pointed at this location. This gives developers a way to have a separate
  210 + checkout of the content that they can modify freely without interference
  211 + from the build. The build simply uses that existing source, but it still
  212 + defines ``<lcName>_BINARY_DIR`` to point inside its own build area.
  213 + Developers are strongly encouraged to use this mechanism rather than
  214 + editing the sources populated in the default location, as changes to
  215 + sources in the default location can be lost when content population details
  216 + are changed by the project.
  217 +
  218 + ``FETCHCONTENT_UPDATES_DISCONNECTED_<ucName>``
  219 + This is the per-content equivalent of
  220 + ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option
  221 + is ``ON``, then updates will be disabled for the named content.
  222 + Disabling updates for individual content can be useful for content whose
  223 + details rarely change, while still leaving other frequently changing
  224 + content with updates enabled.
  225 +
  226 +
  227 + The ``FetchContent_Populate()`` command also supports a syntax allowing the
  228 + content details to be specified directly rather than using any saved
  229 + details. This is more low-level and use of this form is generally to be
  230 + avoided in favour of using saved content details as outlined above.
  231 + Nevertheless, in certain situations it can be useful to invoke the content
  232 + population as an isolated operation (typically as part of implementing some
  233 + other higher level feature or when using CMake in script mode):
  234 +
  235 + .. code-block:: cmake
  236 +
  237 + FetchContent_Populate( <name>
  238 + [QUIET]
  239 + [SUBBUILD_DIR <subBuildDir>]
  240 + [SOURCE_DIR <srcDir>]
  241 + [BINARY_DIR <binDir>]
  242 + ...
  243 + )
  244 +
  245 + This form has a number of key differences to that where only ``<name>`` is
  246 + provided:
  247 +
  248 + - All required population details are assumed to have been provided directly
  249 + in the call to ``FetchContent_Populate()``. Any saved details for
  250 + ``<name>`` are ignored.
  251 + - No check is made for whether content for ``<name>`` has already been
  252 + populated.
  253 + - No global property is set to record that the population has occurred.
  254 + - No global properties record the source or binary directories used for the
  255 + populated content.
  256 + - The ``FETCHCONTENT_FULLY_DISCONNECTED`` and
  257 + ``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored.
  258 +
  259 + The ``<lcName>_SOURCE_DIR`` and ``<lcName>_BINARY_DIR`` variables are still
  260 + returned to the caller, but since these locations are not stored as global
  261 + properties when this form is used, they are only available to the calling
  262 + scope and below rather than the entire project hierarchy. No
  263 + ``<lcName>_POPULATED`` variable is set in the caller's scope with this form.
  264 +
  265 + The supported options for ``FetchContent_Populate()`` are the same as those
  266 + for :command:`FetchContent_Declare()`. Those few options shown just
  267 + above are either specific to ``FetchContent_Populate()`` or their behavior is
  268 + slightly modified from how :command:`ExternalProject_Add` treats them.
  269 +
  270 + ``QUIET``
  271 + The ``QUIET`` option can be given to hide the output associated with
  272 + populating the specified content. If the population fails, the output will
  273 + be shown regardless of whether this option was given or not so that the
  274 + cause of the failure can be diagnosed. The global ``FETCHCONTENT_QUIET``
  275 + cache variable has no effect on ``FetchContent_Populate()`` calls where the
  276 + content details are provided directly.
  277 +
  278 + ``SUBBUILD_DIR``
  279 + The ``SUBBUILD_DIR`` argument can be provided to change the location of the
  280 + sub-build created to perform the population. The default value is
  281 + ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-subbuild`` and it would be unusual
  282 + to need to override this default. If a relative path is specified, it will
  283 + be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`.
  284 +
  285 + ``SOURCE_DIR``, ``BINARY_DIR``
  286 + The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by
  287 + :command:`ExternalProject_Add`, but different default values are used by
  288 + ``FetchContent_Populate()``. ``SOURCE_DIR`` defaults to
  289 + ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-src`` and ``BINARY_DIR`` defaults to
  290 + ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-build``. If a relative path is
  291 + specified, it will be interpreted as relative to
  292 + :variable:`CMAKE_CURRENT_BINARY_DIR`.
  293 +
  294 + In addition to the above explicit options, any other unrecognized options are
  295 + passed through unmodified to :command:`ExternalProject_Add` to perform the
  296 + download, patch and update steps. The following options are explicitly
  297 + prohibited (they are disabled by the ``FetchContent_Populate()`` command):
  298 +
  299 + - ``CONFIGURE_COMMAND``
  300 + - ``BUILD_COMMAND``
  301 + - ``INSTALL_COMMAND``
  302 + - ``TEST_COMMAND``
  303 +
  304 + If using ``FetchContent_Populate()`` within CMake's script mode, be aware
  305 + that the implementation sets up a sub-build which therefore requires a CMake
  306 + generator and build tool to be available. If these cannot be found by
  307 + default, then the :variable:`CMAKE_GENERATOR` and/or
  308 + :variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately
  309 + on the command line invoking the script.
  310 +
  311 +
  312 +Retrieve Population Properties
  313 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  314 +
  315 +.. command:: FetchContent_GetProperties
  316 +
  317 + When using saved content details, a call to :command:`FetchContent_Populate`
  318 + records information in global properties which can be queried at any time.
  319 + This information includes the source and binary directories associated with
  320 + the content and also whether or not the content population has been processed
  321 + during the current configure run.
  322 +
  323 + .. code-block:: cmake
  324 +
  325 + FetchContent_GetProperties( <name>
  326 + [SOURCE_DIR <srcDirVar>]
  327 + [BINARY_DIR <binDirVar>]
  328 + [POPULATED <doneVar>]
  329 + )
  330 +
  331 + The ``SOURCE_DIR``, ``BINARY_DIR`` and ``POPULATED`` options can be used to
  332 + specify which properties should be retrieved. Each option accepts a value
  333 + which is the name of the variable in which to store that property. Most of
  334 + the time though, only ``<name>`` is given, in which case the call will then
  335 + set the same variables as a call to
  336 + :command:`FetchContent_Populate(name) <FetchContent_Populate>`. This allows
  337 + the following canonical pattern to be used, which ensures that the relevant
  338 + variables will always be defined regardless of whether or not the population
  339 + has been performed elsewhere in the project already:
  340 +
  341 + .. code-block:: cmake
  342 +
  343 + FetchContent_GetProperties(foobar)
  344 + if(NOT foobar_POPULATED)
  345 + FetchContent_Populate(foobar)
  346 +
  347 + # Set any custom variables, etc. here, then
  348 + # populate the content as part of this build
  349 +
  350 + add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR})
  351 + endif()
  352 +
  353 + The above pattern allows other parts of the overall project hierarchy to
  354 + re-use the same content and ensure that it is only populated once.
  355 +
  356 +
  357 +.. _`fetch-content-examples`:
  358 +
  359 +Examples
  360 +^^^^^^^^
  361 +
  362 +Consider a project hierarchy where ``projA`` is the top level project and it
  363 +depends on projects ``projB`` and ``projC``. Both ``projB`` and ``projC``
  364 +can be built standalone and they also both depend on another project
  365 +``projD``. For simplicity, this example will assume that all four projects
  366 +are available on a company git server. The ``CMakeLists.txt`` of each project
  367 +might have sections like the following:
  368 +
  369 +*projA*:
  370 +
  371 +.. code-block:: cmake
  372 +
  373 + include(FetchContent)
  374 + FetchContent_Declare(
  375 + projB
  376 + GIT_REPOSITORY git@mycompany.com/git/projB.git
  377 + GIT_TAG 4a89dc7e24ff212a7b5167bef7ab079d
  378 + )
  379 + FetchContent_Declare(
  380 + projC
  381 + GIT_REPOSITORY git@mycompany.com/git/projC.git
  382 + GIT_TAG 4ad4016bd1d8d5412d135cf8ceea1bb9
  383 + )
  384 + FetchContent_Declare(
  385 + projD
  386 + GIT_REPOSITORY git@mycompany.com/git/projD.git
  387 + GIT_TAG origin/integrationBranch
  388 + )
  389 +
  390 + FetchContent_GetProperties(projB)
  391 + if(NOT projb_POPULATED)
  392 + FetchContent_Populate(projB)
  393 + add_subdirectory(${projb_SOURCE_DIR} ${projb_BINARY_DIR})
  394 + endif()
  395 +
  396 + FetchContent_GetProperties(projC)
  397 + if(NOT projc_POPULATED)
  398 + FetchContent_Populate(projC)
  399 + add_subdirectory(${projc_SOURCE_DIR} ${projc_BINARY_DIR})
  400 + endif()
  401 +
  402 +*projB*:
  403 +
  404 +.. code-block:: cmake
  405 +
  406 + include(FetchContent)
  407 + FetchContent_Declare(
  408 + projD
  409 + GIT_REPOSITORY git@mycompany.com/git/projD.git
  410 + GIT_TAG 20b415f9034bbd2a2e8216e9a5c9e632
  411 + )
  412 +
  413 + FetchContent_GetProperties(projD)
  414 + if(NOT projd_POPULATED)
  415 + FetchContent_Populate(projD)
  416 + add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR})
  417 + endif()
  418 +
  419 +
  420 +*projC*:
  421 +
  422 +.. code-block:: cmake
  423 +
  424 + include(FetchContent)
  425 + FetchContent_Declare(
  426 + projD
  427 + GIT_REPOSITORY git@mycompany.com/git/projD.git
  428 + GIT_TAG 7d9a17ad2c962aa13e2fbb8043fb6b8a
  429 + )
  430 +
  431 + FetchContent_GetProperties(projD)
  432 + if(NOT projd_POPULATED)
  433 + FetchContent_Populate(projD)
  434 + add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR})
  435 + endif()
  436 +
  437 +A few key points should be noted in the above:
  438 +
  439 +- ``projB`` and ``projC`` define different content details for ``projD``,
  440 + but ``projA`` also defines a set of content details for ``projD`` and
  441 + because ``projA`` will define them first, the details from ``projB`` and
  442 + ``projC`` will not be used. The override details defined by ``projA``
  443 + are not required to match either of those from ``projB`` or ``projC``, but
  444 + it is up to the higher level project to ensure that the details it does
  445 + define still make sense for the child projects.
  446 +- While ``projA`` defined content details for ``projD``, it did not need
  447 + to explicitly call ``FetchContent_Populate(projD)`` itself. Instead, it
  448 + leaves that to a child project to do (in this case it will be ``projB``
  449 + since it is added to the build ahead of ``projC``). If ``projA`` needed to
  450 + customize how the ``projD`` content was brought into the build as well
  451 + (e.g. define some CMake variables before calling
  452 + :command:`add_subdirectory` after populating), it would do the call to
  453 + ``FetchContent_Populate()``, etc. just as it did for the ``projB`` and
  454 + ``projC`` content. For higher level projects, it is usually enough to
  455 + just define the override content details and leave the actual population
  456 + to the child projects. This saves repeating the same thing at each level
  457 + of the project hierarchy unnecessarily.
  458 +- Even though ``projA`` is the top level project in this example, it still
  459 + checks whether ``projB`` and ``projC`` have already been populated before
  460 + going ahead to do those populations. This makes ``projA`` able to be more
  461 + easily incorporated as a child of some other higher level project in the
  462 + future if required. Always protect a call to
  463 + :command:`FetchContent_Populate` with a check to
  464 + :command:`FetchContent_GetProperties`, even in what may be considered a top
  465 + level project at the time.
  466 +
  467 +
  468 +The following example demonstrates how one might download and unpack a
  469 +firmware tarball using CMake's :manual:`script mode <cmake(1)>`. The call to
  470 +:command:`FetchContent_Populate` specifies all the content details and the
  471 +unpacked firmware will be placed in a ``firmware`` directory below the
  472 +current working directory.
  473 +
  474 +*getFirmware.cmake*:
  475 +
  476 +.. code-block:: cmake
  477 +
  478 + # NOTE: Intended to be run in script mode with cmake -P
  479 + include(FetchContent)
  480 + FetchContent_Populate(
  481 + firmware
  482 + URL https://mycompany.com/assets/firmware-1.23-arm.tar.gz
  483 + URL_HASH MD5=68247684da89b608d466253762b0ff11
  484 + SOURCE_DIR firmware
  485 + )
  486 +
  487 +#]=======================================================================]
  488 +
  489 +
  490 +set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent")
  491 +
  492 +#=======================================================================
  493 +# Recording and retrieving content details for later population
  494 +#=======================================================================
  495 +
  496 +# Internal use, projects must not call this directly. It is
  497 +# intended for use by FetchContent_Declare() only.
  498 +#
  499 +# Sets a content-specific global property (not meant for use
  500 +# outside of functions defined here in this file) which can later
  501 +# be retrieved using __FetchContent_getSavedDetails() with just the
  502 +# same content name. If there is already a value stored in the
  503 +# property, it is left unchanged and this call has no effect.
  504 +# This allows parent projects to define the content details,
  505 +# overriding anything a child project may try to set (properties
  506 +# are not cached between runs, so the first thing to set it in a
  507 +# build will be in control).
  508 +function(__FetchContent_declareDetails contentName)
  509 +
  510 + string(TOLOWER ${contentName} contentNameLower)
  511 + set(propertyName "_FetchContent_${contentNameLower}_savedDetails")
  512 + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED)
  513 + if(NOT alreadyDefined)
  514 + define_property(GLOBAL PROPERTY ${propertyName}
  515 + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
  516 + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
  517 + )
  518 + set_property(GLOBAL PROPERTY ${propertyName} ${ARGN})
  519 + endif()
  520 +
  521 +endfunction()
  522 +
  523 +
  524 +# Internal use, projects must not call this directly. It is
  525 +# intended for use by the FetchContent_Declare() function.
  526 +#
  527 +# Retrieves details saved for the specified content in an
  528 +# earlier call to __FetchContent_declareDetails().
  529 +function(__FetchContent_getSavedDetails contentName outVar)
  530 +
  531 + string(TOLOWER ${contentName} contentNameLower)
  532 + set(propertyName "_FetchContent_${contentNameLower}_savedDetails")
  533 + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED)
  534 + if(NOT alreadyDefined)
  535 + message(FATAL_ERROR "No content details recorded for ${contentName}")
  536 + endif()
  537 + get_property(propertyValue GLOBAL PROPERTY ${propertyName})
  538 + set(${outVar} "${propertyValue}" PARENT_SCOPE)
  539 +
  540 +endfunction()
  541 +
  542 +
  543 +# Saves population details of the content, sets defaults for the
  544 +# SOURCE_DIR and BUILD_DIR.
  545 +function(FetchContent_Declare contentName)
  546 +
  547 + set(options "")
  548 + set(oneValueArgs SVN_REPOSITORY)
  549 + set(multiValueArgs "")
  550 +
  551 + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  552 +
  553 + unset(srcDirSuffix)
  554 + unset(svnRepoArgs)
  555 + if(ARG_SVN_REPOSITORY)
  556 + # Add a hash of the svn repository URL to the source dir. This works
  557 + # around the problem where if the URL changes, the download would
  558 + # fail because it tries to checkout/update rather than switch the
  559 + # old URL to the new one. We limit the hash to the first 7 characters
  560 + # so that the source path doesn't get overly long (which can be a
  561 + # problem on windows due to path length limits).
  562 + string(SHA1 urlSHA ${ARG_SVN_REPOSITORY})
  563 + string(SUBSTRING ${urlSHA} 0 7 urlSHA)
  564 + set(srcDirSuffix "-${urlSHA}")
  565 + set(svnRepoArgs SVN_REPOSITORY ${ARG_SVN_REPOSITORY})
  566 + endif()
  567 +
  568 + string(TOLOWER ${contentName} contentNameLower)
  569 + __FetchContent_declareDetails(
  570 + ${contentNameLower}
  571 + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src${srcDirSuffix}"
  572 + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build"
  573 + ${svnRepoArgs}
  574 + # List these last so they can override things we set above
  575 + ${ARG_UNPARSED_ARGUMENTS}
  576 + )
  577 +
  578 +endfunction()
  579 +
  580 +
  581 +#=======================================================================
  582 +# Set/get whether the specified content has been populated yet.
  583 +# The setter also records the source and binary dirs used.
  584 +#=======================================================================
  585 +
  586 +# Internal use, projects must not call this directly. It is
  587 +# intended for use by the FetchContent_Populate() function to
  588 +# record when FetchContent_Populate() is called for a particular
  589 +# content name.
  590 +function(__FetchContent_setPopulated contentName sourceDir binaryDir)
  591 +
  592 + string(TOLOWER ${contentName} contentNameLower)
  593 + set(prefix "_FetchContent_${contentNameLower}")
  594 +
  595 + set(propertyName "${prefix}_sourceDir")
  596 + define_property(GLOBAL PROPERTY ${propertyName}
  597 + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
  598 + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
  599 + )
  600 + set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir})
  601 +
  602 + set(propertyName "${prefix}_binaryDir")
  603 + define_property(GLOBAL PROPERTY ${propertyName}
  604 + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
  605 + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
  606 + )
  607 + set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir})
  608 +
  609 + set(propertyName "${prefix}_populated")
  610 + define_property(GLOBAL PROPERTY ${propertyName}
  611 + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
  612 + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}"
  613 + )
  614 + set_property(GLOBAL PROPERTY ${propertyName} True)
  615 +
  616 +endfunction()
  617 +
  618 +
  619 +# Set variables in the calling scope for any of the retrievable
  620 +# properties. If no specific properties are requested, variables
  621 +# will be set for all retrievable properties.
  622 +#
  623 +# This function is intended to also be used by projects as the canonical
  624 +# way to detect whether they should call FetchContent_Populate()
  625 +# and pull the populated source into the build with add_subdirectory(),
  626 +# if they are using the populated content in that way.
  627 +function(FetchContent_GetProperties contentName)
  628 +
  629 + string(TOLOWER ${contentName} contentNameLower)
  630 +
  631 + set(options "")
  632 + set(oneValueArgs SOURCE_DIR BINARY_DIR POPULATED)
  633 + set(multiValueArgs "")
  634 +
  635 + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  636 +
  637 + if(NOT ARG_SOURCE_DIR AND
  638 + NOT ARG_BINARY_DIR AND
  639 + NOT ARG_POPULATED)
  640 + # No specific properties requested, provide them all
  641 + set(ARG_SOURCE_DIR ${contentNameLower}_SOURCE_DIR)
  642 + set(ARG_BINARY_DIR ${contentNameLower}_BINARY_DIR)
  643 + set(ARG_POPULATED ${contentNameLower}_POPULATED)
  644 + endif()
  645 +
  646 + set(prefix "_FetchContent_${contentNameLower}")
  647 +
  648 + if(ARG_SOURCE_DIR)
  649 + set(propertyName "${prefix}_sourceDir")
  650 + get_property(value GLOBAL PROPERTY ${propertyName})
  651 + if(value)
  652 + set(${ARG_SOURCE_DIR} ${value} PARENT_SCOPE)
  653 + endif()
  654 + endif()
  655 +
  656 + if(ARG_BINARY_DIR)
  657 + set(propertyName "${prefix}_binaryDir")
  658 + get_property(value GLOBAL PROPERTY ${propertyName})
  659 + if(value)
  660 + set(${ARG_BINARY_DIR} ${value} PARENT_SCOPE)
  661 + endif()
  662 + endif()
  663 +
  664 + if(ARG_POPULATED)
  665 + set(propertyName "${prefix}_populated")
  666 + get_property(value GLOBAL PROPERTY ${propertyName} DEFINED)
  667 + set(${ARG_POPULATED} ${value} PARENT_SCOPE)
  668 + endif()
  669 +
  670 +endfunction()
  671 +
  672 +
  673 +#=======================================================================
  674 +# Performing the population
  675 +#=======================================================================
  676 +
  677 +# The value of contentName will always have been lowercased by the caller.
  678 +# All other arguments are assumed to be options that are understood by
  679 +# ExternalProject_Add(), except for QUIET and SUBBUILD_DIR.
  680 +function(__FetchContent_directPopulate contentName)
  681 +
  682 + set(options
  683 + QUIET
  684 + )
  685 + set(oneValueArgs
  686 + SUBBUILD_DIR
  687 + SOURCE_DIR
  688 + BINARY_DIR
  689 + # Prevent the following from being passed through
  690 + CONFIGURE_COMMAND
  691 + BUILD_COMMAND
  692 + INSTALL_COMMAND
  693 + TEST_COMMAND
  694 + )
  695 + set(multiValueArgs "")
  696 +
  697 + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  698 +
  699 + if(NOT ARG_SUBBUILD_DIR)
  700 + message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set")
  701 + elseif(NOT IS_ABSOLUTE "${ARG_SUBBUILD_DIR}")
  702 + set(ARG_SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBBUILD_DIR}")
  703 + endif()
  704 +
  705 + if(NOT ARG_SOURCE_DIR)
  706 + message(FATAL_ERROR "Internal error: SOURCE_DIR not set")
  707 + elseif(NOT IS_ABSOLUTE "${ARG_SOURCE_DIR}")
  708 + set(ARG_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SOURCE_DIR}")
  709 + endif()
  710 +
  711 + if(NOT ARG_BINARY_DIR)
  712 + message(FATAL_ERROR "Internal error: BINARY_DIR not set")
  713 + elseif(NOT IS_ABSOLUTE "${ARG_BINARY_DIR}")
  714 + set(ARG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY_DIR}")
  715 + endif()
  716 +
  717 + # Ensure the caller can know where to find the source and build directories
  718 + # with some convenient variables. Doing this here ensures the caller sees
  719 + # the correct result in the case where the default values are overridden by
  720 + # the content details set by the project.
  721 + set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE)
  722 + set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE)
  723 +
  724 + # The unparsed arguments may contain spaces, so build up ARG_EXTRA
  725 + # in such a way that it correctly substitutes into the generated
  726 + # CMakeLists.txt file with each argument quoted.
  727 + unset(ARG_EXTRA)
  728 + foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS)
  729 + set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"")
  730 + endforeach()
  731 +
  732 + # Hide output if requested, but save it to a variable in case there's an
  733 + # error so we can show the output upon failure. When not quiet, don't
  734 + # capture the output to a variable because the user may want to see the
  735 + # output as it happens (e.g. progress during long downloads). Combine both
  736 + # stdout and stderr in the one capture variable so the output stays in order.
  737 + if (ARG_QUIET)
  738 + set(outputOptions
  739 + OUTPUT_VARIABLE capturedOutput
  740 + ERROR_VARIABLE capturedOutput
  741 + )
  742 + else()
  743 + set(capturedOutput)
  744 + set(outputOptions)
  745 + message(STATUS "Populating ${contentName}")
  746 + endif()
  747 +
  748 + if(CMAKE_GENERATOR)
  749 + set(generatorOpts "-G${CMAKE_GENERATOR}")
  750 + if(CMAKE_GENERATOR_PLATFORM)
  751 + list(APPEND generatorOpts "-A${CMAKE_GENERATOR_PLATFORM}")
  752 + endif()
  753 + if(CMAKE_GENERATOR_TOOLSET)
  754 + list(APPEND generatorOpts "-T${CMAKE_GENERATOR_TOOLSET}")
  755 + endif()
  756 +
  757 + if(CMAKE_MAKE_PROGRAM)
  758 + list(APPEND generatorOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
  759 + endif()
  760 +
  761 + else()
  762 + # Likely we've been invoked via CMake's script mode where no
  763 + # generator is set (and hence CMAKE_MAKE_PROGRAM could not be
  764 + # trusted even if provided). We will have to rely on being
  765 + # able to find the default generator and build tool.
  766 + unset(generatorOpts)
  767 + endif()
  768 +
  769 + # Create and build a separate CMake project to carry out the population.
  770 + # If we've already previously done these steps, they will not cause
  771 + # anything to be updated, so extra rebuilds of the project won't occur.
  772 + # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project
  773 + # has this set to something not findable on the PATH.
  774 + configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in"
  775 + "${ARG_SUBBUILD_DIR}/CMakeLists.txt")
  776 + execute_process(
  777 + COMMAND ${CMAKE_COMMAND} ${generatorOpts} .
  778 + RESULT_VARIABLE result
  779 + ${outputOptions}
  780 + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
  781 + )
  782 + if(result)
  783 + if(capturedOutput)
  784 + message("${capturedOutput}")
  785 + endif()
  786 + message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}")
  787 + endif()
  788 + execute_process(
  789 + COMMAND ${CMAKE_COMMAND} --build .
  790 + RESULT_VARIABLE result
  791 + ${outputOptions}
  792 + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
  793 + )
  794 + if(result)
  795 + if(capturedOutput)
  796 + message("${capturedOutput}")
  797 + endif()
  798 + message(FATAL_ERROR "Build step for ${contentName} failed: ${result}")
  799 + endif()
  800 +
  801 +endfunction()
  802 +
  803 +
  804 +option(FETCHCONTENT_FULLY_DISCONNECTED "Disables all attempts to download or update content and assumes source dirs already exist")
  805 +option(FETCHCONTENT_UPDATES_DISCONNECTED "Enables UPDATE_DISCONNECTED behavior for all content population")
  806 +option(FETCHCONTENT_QUIET "Enables QUIET option for all content population" ON)
  807 +set(FETCHCONTENT_BASE_DIR "${CMAKE_BINARY_DIR}/_deps" CACHE PATH "Directory under which to collect all populated content")
  808 +
  809 +# Populate the specified content using details stored from
  810 +# an earlier call to FetchContent_Declare().
  811 +function(FetchContent_Populate contentName)
  812 +
  813 + if(NOT contentName)
  814 + message(FATAL_ERROR "Empty contentName not allowed for FetchContent_Populate()")
  815 + endif()
  816 +
  817 + string(TOLOWER ${contentName} contentNameLower)
  818 +
  819 + if(ARGN)
  820 + # This is the direct population form with details fully specified
  821 + # as part of the call, so we already have everything we need
  822 + __FetchContent_directPopulate(
  823 + ${contentNameLower}
  824 + SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-subbuild"
  825 + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-src"
  826 + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-build"
  827 + ${ARGN} # Could override any of the above ..._DIR variables
  828 + )
  829 +
  830 + # Pass source and binary dir variables back to the caller
  831 + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE)
  832 + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE)
  833 +
  834 + # Don't set global properties, or record that we did this population, since
  835 + # this was a direct call outside of the normal declared details form.
  836 + # We only want to save values in the global properties for content that
  837 + # honours the hierarchical details mechanism so that projects are not
  838 + # robbed of the ability to override details set in nested projects.
  839 + return()
  840 + endif()
  841 +
  842 + # No details provided, so assume they were saved from an earlier call
  843 + # to FetchContent_Declare(). Do a check that we haven't already
  844 + # populated this content before in case the caller forgot to check.
  845 + FetchContent_GetProperties(${contentName})
  846 + if(${contentNameLower}_POPULATED)
  847 + message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}")
  848 + endif()
  849 +
  850 + string(TOUPPER ${contentName} contentNameUpper)
  851 + set(FETCHCONTENT_SOURCE_DIR_${contentNameUpper}
  852 + "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}"
  853 + CACHE PATH "When not empty, overrides where to find pre-populated content for ${contentName}")
  854 +
  855 + if(FETCHCONTENT_SOURCE_DIR_${contentNameUpper})
  856 + # The source directory has been explicitly provided in the cache,
  857 + # so no population is required
  858 + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}")
  859 + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build")
  860 +
  861 + elseif(FETCHCONTENT_FULLY_DISCONNECTED)
  862 + # Bypass population and assume source is already there from a previous run
  863 + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src")
  864 + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build")
  865 +
  866 + else()
  867 + # Support both a global "disconnect all updates" and a per-content
  868 + # update test (either one being set disables updates for this content).
  869 + option(FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper}
  870 + "Enables UPDATE_DISCONNECTED behavior just for population of ${contentName}")
  871 + if(FETCHCONTENT_UPDATES_DISCONNECTED OR
  872 + FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper})
  873 + set(disconnectUpdates True)
  874 + else()
  875 + set(disconnectUpdates False)
  876 + endif()
  877 +
  878 + if(FETCHCONTENT_QUIET)
  879 + set(quietFlag QUIET)
  880 + else()
  881 + unset(quietFlag)
  882 + endif()
  883 +
  884 + __FetchContent_getSavedDetails(${contentName} contentDetails)
  885 + if("${contentDetails}" STREQUAL "")
  886 + message(FATAL_ERROR "No details have been set for content: ${contentName}")
  887 + endif()
  888 +
  889 + __FetchContent_directPopulate(
  890 + ${contentNameLower}
  891 + ${quietFlag}
  892 + UPDATE_DISCONNECTED ${disconnectUpdates}
  893 + SUBBUILD_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-subbuild"
  894 + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src"
  895 + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build"
  896 + # Put the saved details last so they can override any of the
  897 + # the options we set above (this can include SOURCE_DIR or
  898 + # BUILD_DIR)
  899 + ${contentDetails}
  900 + )
  901 + endif()
  902 +
  903 + __FetchContent_setPopulated(
  904 + ${contentName}
  905 + ${${contentNameLower}_SOURCE_DIR}
  906 + ${${contentNameLower}_BINARY_DIR}
  907 + )
  908 +
  909 + # Pass variables back to the caller. The variables passed back here
  910 + # must match what FetchContent_GetProperties() sets when it is called
  911 + # with just the content name.
  912 + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE)
  913 + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE)
  914 + set(${contentNameLower}_POPULATED True PARENT_SCOPE)
  915 +
  916 +endfunction()
  1 +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2 +# file Copyright.txt or https://cmake.org/licensing for details.
  3 +
  4 +cmake_minimum_required(VERSION ${CMAKE_VERSION})
  5 +
  6 +# We name the project and the target for the ExternalProject_Add() call
  7 +# to something that will highlight to the user what we are working on if
  8 +# something goes wrong and an error message is produced.
  9 +
  10 +project(${contentName}-populate NONE)
  11 +
  12 +include(ExternalProject)
  13 +ExternalProject_Add(${contentName}-populate
  14 + ${ARG_EXTRA}
  15 + SOURCE_DIR "${ARG_SOURCE_DIR}"
  16 + BINARY_DIR "${ARG_BINARY_DIR}"
  17 + CONFIGURE_COMMAND ""
  18 + BUILD_COMMAND ""
  19 + INSTALL_COMMAND ""
  20 + TEST_COMMAND ""
  21 +)
  1 +
  2 +## FetchContent
  3 +
  4 +`FetchContent.cmake` and `FetchContent/CMakeLists.cmake.in`
  5 +are copied from `cmake/3.11.0/share/cmake-3.11/Modules`.
  1 +# Copyright 2020 Fangjun Kuang (csukuangfj@gmail.com)
  2 +# See ../LICENSE for clarification regarding multiple authors
  3 +#
  4 +# Licensed under the Apache License, Version 2.0 (the "License");
  5 +# you may not use this file except in compliance with the License.
  6 +# You may obtain a copy of the License at
  7 +#
  8 +# http://www.apache.org/licenses/LICENSE-2.0
  9 +#
  10 +# Unless required by applicable law or agreed to in writing, software
  11 +# distributed under the License is distributed on an "AS IS" BASIS,
  12 +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +# See the License for the specific language governing permissions and
  14 +# limitations under the License.
  15 +
  16 +function(download_googltest)
  17 + if(CMAKE_VERSION VERSION_LESS 3.11)
  18 + # FetchContent is available since 3.11,
  19 + # we've copied it to ${CMAKE_SOURCE_DIR}/cmake/Modules
  20 + # so that it can be used in lower CMake versions.
  21 + message(STATUS "Use FetchContent provided by sherpa-onnx")
  22 + list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
  23 + endif()
  24 +
  25 + include(FetchContent)
  26 +
  27 + set(googletest_URL "https://github.com/google/googletest/archive/release-1.10.0.tar.gz")
  28 + set(googletest_HASH "SHA256=9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb")
  29 +
  30 + set(BUILD_GMOCK ON CACHE BOOL "" FORCE)
  31 + set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
  32 + set(gtest_disable_pthreads ON CACHE BOOL "" FORCE)
  33 + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
  34 +
  35 + FetchContent_Declare(googletest
  36 + URL ${googletest_URL}
  37 + URL_HASH ${googletest_HASH}
  38 + )
  39 +
  40 + FetchContent_GetProperties(googletest)
  41 + if(NOT googletest_POPULATED)
  42 + message(STATUS "Downloading googletest")
  43 + FetchContent_Populate(googletest)
  44 + endif()
  45 + message(STATUS "googletest is downloaded to ${googletest_SOURCE_DIR}")
  46 + message(STATUS "googletest's binary dir is ${googletest_BINARY_DIR}")
  47 +
  48 + if(APPLE)
  49 + set(CMAKE_MACOSX_RPATH ON) # to solve the following warning on macOS
  50 + endif()
  51 + #[==[
  52 + -- Generating done
  53 + Policy CMP0042 is not set: MACOSX_RPATH is enabled by default. Run "cmake
  54 + --help-policy CMP0042" for policy details. Use the cmake_policy command to
  55 + set the policy and suppress this warning.
  56 +
  57 + MACOSX_RPATH is not specified for the following targets:
  58 +
  59 + gmock
  60 + gmock_main
  61 + gtest
  62 + gtest_main
  63 +
  64 + This warning is for project developers. Use -Wno-dev to suppress it.
  65 + ]==]
  66 +
  67 + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
  68 +
  69 + target_include_directories(gtest
  70 + INTERFACE
  71 + ${googletest_SOURCE_DIR}/googletest/include
  72 + ${googletest_SOURCE_DIR}/googlemock/include
  73 + )
  74 +endfunction()
  75 +
  76 +download_googltest()
  1 +function(download_kaldi_native_fbank)
  2 + if(CMAKE_VERSION VERSION_LESS 3.11)
  3 + # FetchContent is available since 3.11,
  4 + # we've copied it to ${CMAKE_SOURCE_DIR}/cmake/Modules
  5 + # so that it can be used in lower CMake versions.
  6 + message(STATUS "Use FetchContent provided by sherpa-ncnn")
  7 + list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
  8 + endif()
  9 +
  10 + include(FetchContent)
  11 +
  12 + set(kaldi_native_fbank_URL "https://github.com/csukuangfj/kaldi-native-fbank/archive/refs/tags/v1.4.tar.gz")
  13 + set(kaldi_native_fbank_HASH "SHA256=771e08cb7edf512c828f4577d0d071a7993991d7e5415b11a843975dcf3e4d2d")
  14 +
  15 + set(KALDI_NATIVE_FBANK_BUILD_TESTS OFF CACHE BOOL "" FORCE)
  16 + set(KALDI_NATIVE_FBANK_BUILD_PYTHON OFF CACHE BOOL "" FORCE)
  17 +
  18 + FetchContent_Declare(kaldi_native_fbank
  19 + URL ${kaldi_native_fbank_URL}
  20 + URL_HASH ${kaldi_native_fbank_HASH}
  21 + )
  22 +
  23 + FetchContent_GetProperties(kaldi_native_fbank)
  24 + if(NOT kaldi_native_fbank_POPULATED)
  25 + message(STATUS "Downloading kaldi-native-fbank ${kaldi_native_fbank_URL}")
  26 + FetchContent_Populate(kaldi_native_fbank)
  27 + endif()
  28 + message(STATUS "kaldi-native-fbank is downloaded to ${kaldi_native_fbank_SOURCE_DIR}")
  29 + message(STATUS "kaldi-native-fbank's binary dir is ${kaldi_native_fbank_BINARY_DIR}")
  30 +
  31 + add_subdirectory(${kaldi_native_fbank_SOURCE_DIR} ${kaldi_native_fbank_BINARY_DIR} EXCLUDE_FROM_ALL)
  32 +
  33 + target_include_directories(kaldi-native-fbank-core
  34 + INTERFACE
  35 + ${kaldi_native_fbank_SOURCE_DIR}/
  36 + )
  37 +endfunction()
  38 +
  39 +download_kaldi_native_fbank()
  1 +add_subdirectory(csrc)
@@ -9,5 +9,5 @@ include_directories( @@ -9,5 +9,5 @@ include_directories(
9 include_directories( 9 include_directories(
10 ${KALDINATIVEIO} 10 ${KALDINATIVEIO}
11 ) 11 )
12 -add_executable(capi_test main.cpp)  
13 -target_link_libraries(capi_test onnxruntime kaldi-native-fbank-core kaldi_native_io_core) 12 +add_executable(sherpa-onnx main.cpp)
  13 +target_link_libraries(sherpa-onnx onnxruntime kaldi-native-fbank-core kaldi_native_io_core)
@@ -12,9 +12,14 @@ @@ -12,9 +12,14 @@
12 12
13 13
14 int main(int argc, char* argv[]) { 14 int main(int argc, char* argv[]) {
15 - char* filename = argv[1];  
16 - std::string search_method = argv[2];  
17 - int num_active_paths = atoi(argv[3]); 15 + char* encoder_path = argv[1];
  16 + char* decoder_path = argv[2];
  17 + char* joiner_path = argv[3];
  18 + char* joiner_encoder_proj_path = argv[4];
  19 + char* joiner_decoder_proj_path = argv[5];
  20 + char* token_path = argv[6];
  21 + std::string search_method = argv[7];
  22 + char* filename = argv[8];
18 23
19 // General parameters 24 // General parameters
20 int numberOfThreads = 16; 25 int numberOfThreads = 16;
@@ -44,17 +49,16 @@ int main(int argc, char* argv[]) { @@ -44,17 +49,16 @@ int main(int argc, char* argv[]) {
44 49
45 // Define model 50 // Define model
46 auto model = get_model( 51 auto model = get_model(
47 - "/mnt/local4/sr/k2_sherpa/models/exp_en2/encoder_simp.onnx",  
48 - "/mnt/local4/sr/k2_sherpa/models/exp_en2/decoder_simp.onnx",  
49 - "/mnt/local4/sr/k2_sherpa/models/exp_en2/joiner_simp.onnx",  
50 - "/mnt/local4/sr/k2_sherpa/models/exp_en2/joiner_encoder_proj_simp.onnx",  
51 - "/mnt/local4/sr/k2_sherpa/models/exp_en2/joiner_decoder_proj_simp.onnx",  
52 - "/mnt/local4/sr/k2_sherpa/models/exp_en2/enUS_tokens.txt" 52 + encoder_path,
  53 + decoder_path,
  54 + joiner_path,
  55 + joiner_encoder_proj_path,
  56 + joiner_decoder_proj_path,
  57 + token_path
53 ); 58 );
54 59
55 std::vector<std::string> filename_list { 60 std::vector<std::string> filename_list {
56 - "/mnt/local4/sr/k2_sherpa/test_wavs/cnn_15sec.wav",  
57 - //"/mnt/local4/sr/k2_sherpa/test_wavs/1089-134686-0001.wav" 61 + filename
58 }; 62 };
59 63
60 for (auto filename : filename_list){ 64 for (auto filename : filename_list){
  1 +/**
  2 + * Copyright (c) 2022 Xiaomi Corporation (authors: Fangjun Kuang)
  3 + *
  4 + * See LICENSE for clarification regarding multiple authors
  5 + *
  6 + * Licensed under the Apache License, Version 2.0 (the "License");
  7 + * you may not use this file except in compliance with the License.
  8 + * You may obtain a copy of the License at
  9 + *
  10 + * http://www.apache.org/licenses/LICENSE-2.0
  11 + *
  12 + * Unless required by applicable law or agreed to in writing, software
  13 + * distributed under the License is distributed on an "AS IS" BASIS,
  14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15 + * See the License for the specific language governing permissions and
  16 + * limitations under the License.
  17 + */
  18 +
  19 +#include <iostream>
  20 +
  21 +#include "kaldi-native-fbank/csrc/online-feature.h"
  22 +
  23 +int main() {
  24 + knf::FbankOptions opts;
  25 + opts.frame_opts.dither = 0;
  26 + opts.mel_opts.num_bins = 10;
  27 +
  28 + knf::OnlineFbank fbank(opts);
  29 + for (int32_t i = 0; i < 1600; ++i) {
  30 + float s = (i * i - i / 2) / 32767.;
  31 + fbank.AcceptWaveform(16000, &s, 1);
  32 + }
  33 +
  34 + std::ostringstream os;
  35 +
  36 + int32_t n = fbank.NumFramesReady();
  37 + for (int32_t i = 0; i != n; ++i) {
  38 + const float *frame = fbank.GetFrame(i);
  39 + for (int32_t k = 0; k != opts.mel_opts.num_bins; ++k) {
  40 + os << frame[k] << ", ";
  41 + }
  42 + os << "\n";
  43 + }
  44 +
  45 + std::cout << os.str() << "\n";
  46 +
  47 + return 0;
  48 +}