blob: 865c0c0ef5edb1be3a5943f3400776b3e9f807b8 [file] [log] [blame]
<!--
Documentation/_templates/layout.html
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership. The
ASF licenses this file to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE html>
<html class="writer-html5" lang="en">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Custom Application Directories &mdash; NuttX latest documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css" />
<link rel="stylesheet" type="text/css" href="../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../_static/sphinx_collapse.css" />
<link rel="stylesheet" type="text/css" href="../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" />
<link rel="stylesheet" type="text/css" href="../_static/custom.css" />
<link rel="shortcut icon" href="../_static/favicon.ico"/>
<script src="../_static/jquery.js"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sphinx_highlight.js"></script>
<script src="../_static/clipboard.min.js"></script>
<script src="../_static/copybutton.js"></script>
<script src="../_static/design-tabs.js"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Multiple NSH Sessions" href="multiple_nsh_sessions.html" />
<link rel="prev" title="Building uClibc++" href="building_uclibcpp.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home"> NuttX
</a>
<!-- this version selector is quite ugly, should be probably replaced by something
more modern -->
<div class="version-selector">
<select onchange="javascript:location.href = this.value;">
<option value="../../latest" selected="selected">latest</option>
<option value="../../10.0.0" >10.0.0</option>
<option value="../../10.0.1" >10.0.1</option>
<option value="../../10.1.0" >10.1.0</option>
<option value="../../10.2.0" >10.2.0</option>
<option value="../../10.3.0" >10.3.0</option>
<option value="../../11.0.0" >11.0.0</option>
<option value="../../12.0.0" >12.0.0</option>
<option value="../../12.1.0" >12.1.0</option>
<option value="../../12.2.0" >12.2.0</option>
<option value="../../12.2.1" >12.2.1</option>
<option value="../../12.3.0" >12.3.0</option>
<option value="../../12.4.0" >12.4.0</option>
<option value="../../12.5.0" >12.5.0</option>
<option value="../../12.5.1" >12.5.1</option>
<option value="../../12.6.0" >12.6.0</option>
<option value="../../12.7.0" >12.7.0</option>
<option value="../../12.8.0" >12.8.0</option>
<option value="../../12.9.0" >12.9.0</option>
<option value="../../12.10.0" >12.10.0</option>
<option value="../../12.11.0" >12.11.0</option>
</select>
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Table of Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../index.html">Home</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/index.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../quickstart/index.html">Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../contributing/index.html">Contributing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../introduction/inviolables.html">The Inviolable Principles of NuttX</a></li>
<li class="toctree-l1"><a class="reference internal" href="../platforms/index.html">Supported Platforms</a></li>
<li class="toctree-l1"><a class="reference internal" href="../components/index.html">OS Components</a></li>
<li class="toctree-l1"><a class="reference internal" href="../applications/index.html">Applications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../implementation/index.html">Implementation Details</a></li>
<li class="toctree-l1"><a class="reference internal" href="../reference/index.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="../faq/index.html">FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../debugging/index.html">Debugging</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Guides</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="nfs.html">NFS Client How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="nix_flake.html">Nix Flake for Reproducible Development</a></li>
<li class="toctree-l2"><a class="reference internal" href="usbtrace.html">USB Device Trace</a></li>
<li class="toctree-l2"><a class="reference internal" href="simulator.html">Simulator</a></li>
<li class="toctree-l2"><a class="reference internal" href="rndis.html">How to use RNDIS</a></li>
<li class="toctree-l2"><a class="reference internal" href="drivers.html">Drivers</a></li>
<li class="toctree-l2"><a class="reference internal" href="cpp_cmake.html">C++ Example using CMake</a></li>
<li class="toctree-l2"><a class="reference internal" href="pysimcoder.html">pysimCoder integration with NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="customboards.html">Custom Boards How-To</a></li>
<li class="toctree-l2"><a class="reference internal" href="customapps.html">Custom Apps How-to</a></li>
<li class="toctree-l2"><a class="reference internal" href="citests.html">Running CI Test Locally</a></li>
<li class="toctree-l2"><a class="reference internal" href="zerolatencyinterrupts.html">High Performance: Zero Latency Interrupts, Maskable Nested Interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="fortify.html">Fortify</a></li>
<li class="toctree-l2"><a class="reference internal" href="nestedinterrupts.html">Nested Interrupts</a></li>
<li class="toctree-l2"><a class="reference internal" href="ofloader.html">Open Flash Loader</a></li>
<li class="toctree-l2"><a class="reference internal" href="testingtcpip.html">Testing TCP/IP Network Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="automounter.html">Auto-Mounter</a></li>
<li class="toctree-l2"><a class="reference internal" href="stm32nullpointer.html">STM32 Null Pointer Detection</a></li>
<li class="toctree-l2"><a class="reference internal" href="stm32ccm.html">STM32 CCM Allocator</a></li>
<li class="toctree-l2"><a class="reference internal" href="etcromfs.html">etc romfs</a></li>
<li class="toctree-l2"><a class="reference internal" href="thread_local_storage.html">Thread Local Storage</a></li>
<li class="toctree-l2"><a class="reference internal" href="devicetree.html">Device Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="changing_systemclockconfig.html">Changing the System Clock Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="usingkernelthreads.html">Using Kernel Threads</a></li>
<li class="toctree-l2"><a class="reference internal" href="armv7m_runtimestackcheck.html">ARMv7-M Run Time Stack Checking</a></li>
<li class="toctree-l2"><a class="reference internal" href="include_files_board_h.html">Including Files in board.h</a></li>
<li class="toctree-l2"><a class="reference internal" href="specialstuff_in_nuttxheaderfiles.html">Why can’t I put my special stuff in NuttX header files?</a></li>
<li class="toctree-l2"><a class="reference internal" href="kernel_threads_with_custom_stacks.html">Kernel Threads with Custom Stacks</a></li>
<li class="toctree-l2"><a class="reference internal" href="versioning_and_task_names.html">Versioning and Task Names</a></li>
<li class="toctree-l2"><a class="reference internal" href="logging_rambuffer.html">Logging to a RAM Buffer</a></li>
<li class="toctree-l2"><a class="reference internal" href="ipv6.html">IPv6</a></li>
<li class="toctree-l2"><a class="reference internal" href="integrate_newlib.html">Integrating with Newlib</a></li>
<li class="toctree-l2"><a class="reference internal" href="protected_build.html">NuttX Protected Build</a></li>
<li class="toctree-l2"><a class="reference internal" href="platform_directories.html">Platform Directories</a></li>
<li class="toctree-l2"><a class="reference internal" href="port_drivers_to_stm32f7.html">Porting Drivers to the STM32 F7</a></li>
<li class="toctree-l2"><a class="reference internal" href="semihosting.html">Semihosting</a></li>
<li class="toctree-l2"><a class="reference internal" href="renode.html">Run NuttX on Renode</a></li>
<li class="toctree-l2"><a class="reference internal" href="signal_events_interrupt_handlers.html">Signaling Events from Interrupt Handlers</a></li>
<li class="toctree-l2"><a class="reference internal" href="signaling_sem_priority_inheritance.html">Signaling Semaphores and Priority Inheritance</a></li>
<li class="toctree-l2"><a class="reference internal" href="smaller_vector_tables.html">Smaller Vector Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="port.html">How to port</a></li>
<li class="toctree-l2"><a class="reference internal" href="updating_release_system_elf.html">Updating a Release System with ELF Programs</a></li>
<li class="toctree-l2"><a class="reference internal" href="partially_linked_elf.html">ELF Programs – With Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="fully_linked_elf.html">ELF Programs – No Symbol Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_nuttx_with_app_out_of_src_tree.html">Building NuttX with Applications Outside the Source Tree</a></li>
<li class="toctree-l2"><a class="reference internal" href="building_uclibcpp.html">Building uClibc++</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Custom Application Directories</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#creating-the-custom-application-directory">Creating the Custom Application Directory</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#makefile">Makefile</a></li>
<li class="toctree-l4"><a class="reference internal" href="#kconfig">Kconfig</a></li>
<li class="toctree-l4"><a class="reference internal" href="#hello-c">hello.c</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#building-with-the-custom-application-directory">Building with the Custom Application Directory</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="multiple_nsh_sessions.html">Multiple NSH Sessions</a></li>
<li class="toctree-l2"><a class="reference internal" href="nsh_network_link_management.html">NSH Network Link Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="ram_rom_disks.html">RAM Disks and ROM Disks</a></li>
<li class="toctree-l2"><a class="reference internal" href="reading_can_msgs.html">Reading CAN Messages</a></li>
<li class="toctree-l2"><a class="reference internal" href="remove_device_drivers_nsh.html">Removing Device Drivers with NSH</a></li>
<li class="toctree-l2"><a class="reference internal" href="rust.html">Rust in NuttX</a></li>
<li class="toctree-l2"><a class="reference internal" href="optee.html">Interfacing with OP-TEE</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../standards/index.html">Standards</a></li>
<li class="toctree-l1"><a class="reference internal" href="../glossary.html">Glossary</a></li>
<li class="toctree-l1"><a class="reference internal" href="../logos/index.html">NuttX Logos</a></li>
<li class="toctree-l1"><a class="reference internal" href="../_tags/tagsindex.html">Tags</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">NuttX</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item"><a href="index.html">Guides</a></li>
<li class="breadcrumb-item active">Custom Application Directories</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/nuttx/blob/master/Documentation/guides/custom_app_directories.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="custom-application-directories">
<h1>Custom Application Directories<a class="headerlink" href="#custom-application-directories" title="Permalink to this heading"></a></h1>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Migrated from:
<a class="reference external" href="https://cwiki.apache.org/confluence/display/NUTTX/Custom+Application+Directories">https://cwiki.apache.org/confluence/display/NUTTX/Custom+Application+Directories</a></p>
</div>
<p>Most people use the generic <code class="docutils literal notranslate"><span class="pre">apps/</span></code> directory with NuttX. That is convenient
and well-documented. However, it should always be remembered that NuttX is a
stand-alone, general-purpose OS and has <strong>no dependency</strong> on that “canned”
application directory.</p>
<p>This page shows how to create your own, custom application directory from
scratch.</p>
<section id="creating-the-custom-application-directory">
<h2>Creating the Custom Application Directory<a class="headerlink" href="#creating-the-custom-application-directory" title="Permalink to this heading"></a></h2>
<p>Below is a simple example of the <strong>minimum</strong> custom application directory. It
contains only three files: <code class="docutils literal notranslate"><span class="pre">Makefile</span></code>, <code class="docutils literal notranslate"><span class="pre">Kconfig</span></code>, and <code class="docutils literal notranslate"><span class="pre">hello.c</span></code>.</p>
<section id="makefile">
<h3>Makefile<a class="headerlink" href="#makefile" title="Permalink to this heading"></a></h3>
<p>The custom application directory must include a <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> that supports all
of the make targets expected by the NuttX build system <strong>and</strong> must generate an
archive called <code class="docutils literal notranslate"><span class="pre">libapps.a</span></code> in the top-level of the custom directory structure.
The minimal required targets for the <code class="docutils literal notranslate"><span class="pre">Makefile</span></code> look like this:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="nv">APPDIR</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="si">${</span><span class="nv">shell</span><span class="p"> pwd</span><span class="si">}</span>
-include<span class="w"> </span><span class="k">$(</span>TOPDIR<span class="k">)</span>/Make.defs
<span class="c1"># files</span>
<span class="nv">CSRCS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>hello.c
<span class="nv">COBJS</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>hello.o
<span class="nv">ROOTDEPPATH</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>--dep-path<span class="w"> </span>.
<span class="c1"># Build targets</span>
all:<span class="w"> </span>libapps.a
.PHONY:<span class="w"> </span>dirlinks<span class="w"> </span>context<span class="w"> </span>preconfig<span class="w"> </span>depend<span class="w"> </span>clean<span class="w"> </span>clean_context<span class="w"> </span>distclean
.PRECIOUS:<span class="w"> </span>libapps<span class="k">$(</span>LIBEXT<span class="k">)</span>
<span class="c1"># Compile C Files</span>
<span class="k">$(</span>COBJS<span class="k">)</span>:<span class="w"> </span>%<span class="k">$(</span>OBJEXT<span class="k">)</span>:<span class="w"> </span>%.c
<span class="k">$(</span>call<span class="w"> </span>COMPILE,<span class="w"> </span>$&lt;,<span class="w"> </span><span class="nv">$@</span><span class="k">)</span>
<span class="c1"># Add object files to the apps archive</span>
libapps.a:<span class="w"> </span><span class="k">$(</span>COBJS<span class="k">)</span>
<span class="k">$(</span>call<span class="w"> </span>ARCHIVE,<span class="w"> </span>libapps.a,<span class="w"> </span><span class="k">$(</span>COBJS<span class="k">))</span>
<span class="c1"># Create directory links</span>
dirlinks:
<span class="c1"># Setup any special pre-build context</span>
context:
<span class="c1"># Setup any special pre-configuration context</span>
preconfig:
<span class="c1"># Make the dependency file, Make.deps</span>
depend:<span class="w"> </span>Makefile<span class="w"> </span><span class="k">$(</span>CSRCS<span class="k">)</span>
<span class="k">$(</span>Q<span class="k">)</span><span class="w"> </span><span class="k">$(</span>MKDEP<span class="k">)</span><span class="w"> </span><span class="k">$(</span>ROOTDEPPATH<span class="k">)</span><span class="w"> </span><span class="s2">&quot;</span><span class="k">$(</span>CC<span class="k">)</span><span class="s2">&quot;</span><span class="w"> </span>--<span class="w"> </span><span class="k">$(</span>CFLAGS<span class="k">)</span><span class="w"> </span>--<span class="w"> </span><span class="k">$(</span>SRCS<span class="k">)</span><span class="w"> </span>&gt;Make.dep
<span class="c1"># Clean the results of the last build</span>
clean:
<span class="k">$(</span>call<span class="w"> </span>CLEAN<span class="k">)</span>
<span class="c1"># Remove the build context and directory links</span>
clean_context:
<span class="c1"># Restore the directory to its original state</span>
distclean:<span class="w"> </span>clean<span class="w"> </span>clean_context
<span class="k">$(</span>call<span class="w"> </span>DELFILE,<span class="w"> </span>Make.dep<span class="k">)</span>
<span class="c1"># Include dependencies</span>
-include<span class="w"> </span>Make.dep
</pre></div>
</div>
</section>
<section id="kconfig">
<h3>Kconfig<a class="headerlink" href="#kconfig" title="Permalink to this heading"></a></h3>
<p>A <code class="docutils literal notranslate"><span class="pre">Kconfig</span></code> file must be included, but it need not contain any meaningful
configuration options. This file is where you can add application-specific
configuration settings if desired. The minimal <code class="docutils literal notranslate"><span class="pre">Kconfig</span></code> might look like:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="c1"># For a description of the syntax of this configuration file,</span>
<span class="c1"># see the file kconfig-language.txt in the NuttX tools repository.</span>
<span class="c1">#</span>
</pre></div>
</div>
</section>
<section id="hello-c">
<h3>hello.c<a class="headerlink" href="#hello-c" title="Permalink to this heading"></a></h3>
<p>Your custom application must compile at least one source file to generate the
required <code class="docutils literal notranslate"><span class="pre">libapps.a</span></code> archive. One of these source files must include the
<code class="docutils literal notranslate"><span class="pre">main()</span></code> entry point to the application. That main function (or similarly
named entry point) is called after OS initialization completes.</p>
<p>What this application initialization entry point does, how it interacts with
the rest of your application, and where the rest of you application code is
located is of no concern to the OS. Only this one entry point is needed.</p>
<p>Below is a small “Hello, World!” example, where <code class="docutils literal notranslate"><span class="pre">custom_main()</span></code> is the
application entry point:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdio.h&gt;</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">custom_main</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">&quot;Hello, World!!</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</section>
<section id="building-with-the-custom-application-directory">
<h2>Building with the Custom Application Directory<a class="headerlink" href="#building-with-the-custom-application-directory" title="Permalink to this heading"></a></h2>
<p>In order to build with the new custom application directory, you need the
following in your NuttX configuration:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="nv">CONFIG_APPS_DIR</span><span class="o">=</span><span class="s2">&quot;../custom-apps&quot;</span>
<span class="nv">CONFIG_USER_ENTRYPOINT</span><span class="o">=</span><span class="s2">&quot;custom_main&quot;</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You can only access the <code class="docutils literal notranslate"><span class="pre">../custom-apps/Kconfig</span></code> file if
<code class="docutils literal notranslate"><span class="pre">CONFIG_APPS_DIR</span></code> is set to <code class="docutils literal notranslate"><span class="pre">../custom-apps</span></code> <strong>before</strong> running
<code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">menuconfig</span></code>. If you start with an existing configuration, you may
face a “chicken-and-egg” situation. One workaround is to manually edit
the <code class="docutils literal notranslate"><span class="pre">.config</span></code> file before running <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">menuconfig</span></code>.</p>
</div>
<p>Alternatively, if you use the <code class="docutils literal notranslate"><span class="pre">tools/configure.sh</span></code> script, you can specify the
custom-apps directory from the command line:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>tools/configure.sh<span class="w"> </span>-a<span class="w"> </span>../custom_apps<span class="w"> </span>&lt;board&gt;:&lt;config&gt;
</pre></div>
</div>
<p>Afterward, just build NuttX as you normally would. When you run the program that
was built with your custom application directory, you should see:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>Hello,<span class="w"> </span>World!!
</pre></div>
</div>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="building_uclibcpp.html" class="btn btn-neutral float-left" title="Building uClibc++" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="multiple_nsh_sessions.html" class="btn btn-neutral float-right" title="Multiple NSH Sessions" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, The Apache Software Foundation.</p>
</div>
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>