├── .github └── workflows │ └── container-build.yml ├── Dockerfile ├── LICENSE ├── README.md ├── bindgen-project ├── build-project ├── create-project ├── flash-project ├── image-project ├── templates ├── Makefile ├── cargo.config ├── component.mk └── main.c └── xbuild-project /.github/workflows/container-build.yml: -------------------------------------------------------------------------------- 1 | name: Build Container 2 | 3 | on: [push] 4 | 5 | jobs: 6 | 7 | build: 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | 13 | - uses: actions/checkout@v1 14 | 15 | - name: Build the image 16 | run: docker build . --file Dockerfile --tag rust-esp:${{ github.sha }} 17 | 18 | - name: Authenticate 19 | run: echo ${{ secrets.REGISTRY_PASSWORD }} | docker login quay.io --username ${{secrets.REGISTRY_USERNAME}} --password-stdin 20 | 21 | - name: Tag the image (master) 22 | if: github.ref == 'refs/heads/master' 23 | run: docker tag rust-esp:${{ github.sha }} quay.io/ctron/rust-esp:latest 24 | - name: Push the image (master) 25 | if: github.ref == 'refs/heads/master' 26 | run: docker push quay.io/ctron/rust-esp:latest 27 | 28 | - name: Tag the image (develop) 29 | if: github.ref == 'refs/heads/develop' 30 | run: docker tag rust-esp:${{ github.sha }} quay.io/ctron/rust-esp:develop 31 | - name: Push the image (develop) 32 | if: github.ref == 'refs/heads/develop' 33 | run: docker push quay.io/ctron/rust-esp:develop 34 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:buster-slim 2 | 3 | # ------------------------------------------------------------------- 4 | # Toolchain Version Config 5 | # ------------------------------------------------------------------- 6 | 7 | # Espressif toolchain 8 | ARG ESP_VERSION="1.22.0-80-g6c4433a-5.2.0" 9 | 10 | # esp-idf framework 11 | ARG IDF_VERSION="v3.3-beta3" 12 | 13 | # llvm-xtensa 14 | ARG CLANG_VERSION="248d9ce8765248d953c3e5ef4022fb350bbe6c51" 15 | ARG LLVM_VERSION="757e18f722dbdcd98b8479e25041b1eee1128ce9" 16 | 17 | # rust-xtensa 18 | ARG RUSTC_VERSION="b365cff41a60df8fd5f1237ef71897edad0375dd" 19 | 20 | # ------------------------------------------------------------------- 21 | # Toolchain Path Config 22 | # ------------------------------------------------------------------- 23 | 24 | ARG TOOLCHAIN="/home/esp32-toolchain" 25 | 26 | ARG ESP_BASE="${TOOLCHAIN}/esp" 27 | ENV ESP_PATH "${ESP_BASE}/esp-toolchain" 28 | ENV IDF_PATH "${ESP_BASE}/esp-idf" 29 | 30 | ARG LLVM_BASE="${TOOLCHAIN}/llvm" 31 | ARG LLVM_PATH="${LLVM_BASE}/llvm_xtensa" 32 | ARG LLVM_BUILD_PATH="${LLVM_BASE}/llvm_build" 33 | ARG LLVM_INSTALL_PATH="${LLVM_BASE}/llvm_install" 34 | 35 | ARG RUSTC_BASE="${TOOLCHAIN}/rustc" 36 | ARG RUSTC_PATH="${RUSTC_BASE}/rust_xtensa" 37 | ARG RUSTC_BUILD_PATH="${RUSTC_BASE}/rust_build" 38 | 39 | ENV PATH "/root/.cargo/bin:${ESP_PATH}/bin:${PATH}" 40 | 41 | # ------------------------------------------------------------------- 42 | # Install expected depdendencies 43 | # ------------------------------------------------------------------- 44 | 45 | RUN apt-get update \ 46 | && apt-get install -y \ 47 | bison \ 48 | cmake \ 49 | curl \ 50 | flex \ 51 | g++ \ 52 | gcc \ 53 | git \ 54 | gperf \ 55 | libncurses-dev \ 56 | make \ 57 | ninja-build \ 58 | python \ 59 | python-pip \ 60 | wget \ 61 | && rm -rf /var/lib/apt/lists/* 62 | 63 | # ------------------------------------------------------------------- 64 | # Setup esp32 toolchain 65 | # ------------------------------------------------------------------- 66 | 67 | WORKDIR "${ESP_BASE}" 68 | RUN curl \ 69 | --proto '=https' \ 70 | --tlsv1.2 \ 71 | -sSf \ 72 | -o "${ESP_PATH}.tar.gz" \ 73 | "https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-${ESP_VERSION}.tar.gz" \ 74 | && mkdir "${ESP_PATH}" \ 75 | && tar -xzf "${ESP_PATH}.tar.gz" -C "${ESP_PATH}" --strip-components 1 \ 76 | && rm -rf "${ESP_PATH}.tar.gz" 77 | 78 | # ------------------------------------------------------------------- 79 | # Setup esp-idf 80 | # ------------------------------------------------------------------- 81 | 82 | WORKDIR "${ESP_BASE}" 83 | RUN git clone \ 84 | --recursive --single-branch -b "${IDF_VERSION}" \ 85 | https://github.com/espressif/esp-idf.git \ 86 | && pip install --user -r "${IDF_PATH}/requirements.txt" 87 | 88 | # ------------------------------------------------------------------- 89 | # Build llvm-xtensa 90 | # ------------------------------------------------------------------- 91 | 92 | WORKDIR "${LLVM_BASE}" 93 | RUN mkdir "${LLVM_PATH}" \ 94 | && cd "${LLVM_PATH}" \ 95 | && git init \ 96 | && git remote add origin https://github.com/espressif/llvm-xtensa.git \ 97 | && git fetch --depth 1 origin "${LLVM_VERSION}" \ 98 | && git checkout FETCH_HEAD \ 99 | && mkdir -p "${LLVM_PATH}/tools/clang" \ 100 | && cd "${LLVM_PATH}/tools/clang" \ 101 | && git init \ 102 | && git remote add origin https://github.com/espressif/clang-xtensa.git \ 103 | && git fetch --depth 1 origin "${CLANG_VERSION}" \ 104 | && git checkout FETCH_HEAD \ 105 | && mkdir -p "${LLVM_BUILD_PATH}" \ 106 | && cd "${LLVM_BUILD_PATH}" \ 107 | && cmake "${LLVM_PATH}" \ 108 | -DLLVM_TARGETS_TO_BUILD="Xtensa;X86" \ 109 | -DLLVM_INSTALL_UTILS=ON \ 110 | -DLLVM_BUILD_TESTS=0 \ 111 | -DLLVM_INCLUDE_TESTS=0 \ 112 | -DCMAKE_BUILD_TYPE=Release \ 113 | -DCMAKE_INSTALL_PREFIX="${LLVM_BASE}/llvm_install" \ 114 | -DCMAKE_CXX_FLAGS="-w" \ 115 | -G "Ninja" \ 116 | && ninja install \ 117 | && rm -rf "${LLVM_PATH}" "${LLVM_BUILD_PATH}" 118 | 119 | # ------------------------------------------------------------------- 120 | # Build rust-xtensa 121 | # ------------------------------------------------------------------- 122 | 123 | WORKDIR "${RUSTC_BASE}" 124 | RUN git clone \ 125 | --recursive --single-branch \ 126 | https://github.com/MabezDev/rust-xtensa.git \ 127 | "${RUSTC_PATH}" \ 128 | && mkdir -p "${RUSTC_BUILD_PATH}" \ 129 | && cd "${RUSTC_PATH}" \ 130 | && git reset --hard "${RUSTC_VERSION}" \ 131 | && ./configure \ 132 | --llvm-root "${LLVM_INSTALL_PATH}" \ 133 | --prefix "${RUSTC_BUILD_PATH}" \ 134 | && python ./x.py build \ 135 | && python ./x.py install 136 | 137 | # ------------------------------------------------------------------- 138 | # Setup rustup toolchain 139 | # ------------------------------------------------------------------- 140 | 141 | RUN curl \ 142 | --proto '=https' \ 143 | --tlsv1.2 \ 144 | -sSf \ 145 | https://sh.rustup.rs \ 146 | | sh -s -- -y --default-toolchain stable \ 147 | && rustup component add rustfmt \ 148 | && rustup toolchain link xtensa "${RUSTC_BUILD_PATH}" \ 149 | && cargo install cargo-xbuild bindgen 150 | 151 | # ------------------------------------------------------------------- 152 | # Our Project 153 | # ------------------------------------------------------------------- 154 | 155 | ENV PROJECT="/home/project/" 156 | 157 | ENV XARGO_RUST_SRC="${RUSTC_PATH}/src" 158 | ENV TEMPLATES="${TOOLCHAIN}/templates" 159 | ENV LIBCLANG_PATH="${LLVM_INSTALL_PATH}/lib" 160 | ENV CARGO_HOME="${PROJECT}target/cargo" 161 | 162 | VOLUME "${PROJECT}" 163 | WORKDIR "${PROJECT}" 164 | 165 | COPY bindgen-project build-project create-project image-project xbuild-project flash-project /usr/local/bin/ 166 | COPY templates/ "${TEMPLATES}" 167 | 168 | CMD ["/usr/local/bin/build-project"] 169 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 2.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 4 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION 5 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial content 12 | Distributed under this Agreement, and 13 | 14 | b) in the case of each subsequent Contributor: 15 | i) changes to the Program, and 16 | ii) additions to the Program; 17 | where such changes and/or additions to the Program originate from 18 | and are Distributed by that particular Contributor. A Contribution 19 | "originates" from a Contributor if it was added to the Program by 20 | such Contributor itself or anyone acting on such Contributor's behalf. 21 | Contributions do not include changes or additions to the Program that 22 | are not Modified Works. 23 | 24 | "Contributor" means any person or entity that Distributes the Program. 25 | 26 | "Licensed Patents" mean patent claims licensable by a Contributor which 27 | are necessarily infringed by the use or sale of its Contribution alone 28 | or when combined with the Program. 29 | 30 | "Program" means the Contributions Distributed in accordance with this 31 | Agreement. 32 | 33 | "Recipient" means anyone who receives the Program under this Agreement 34 | or any Secondary License (as applicable), including Contributors. 35 | 36 | "Derivative Works" shall mean any work, whether in Source Code or other 37 | form, that is based on (or derived from) the Program and for which the 38 | editorial revisions, annotations, elaborations, or other modifications 39 | represent, as a whole, an original work of authorship. 40 | 41 | "Modified Works" shall mean any work in Source Code or other form that 42 | results from an addition to, deletion from, or modification of the 43 | contents of the Program, including, for purposes of clarity any new file 44 | in Source Code form that contains any contents of the Program. Modified 45 | Works shall not include works that contain only declarations, 46 | interfaces, types, classes, structures, or files of the Program solely 47 | in each case in order to link to, bind by name, or subclass the Program 48 | or Modified Works thereof. 49 | 50 | "Distribute" means the acts of a) distributing or b) making available 51 | in any manner that enables the transfer of a copy. 52 | 53 | "Source Code" means the form of a Program preferred for making 54 | modifications, including but not limited to software source code, 55 | documentation source, and configuration files. 56 | 57 | "Secondary License" means either the GNU General Public License, 58 | Version 2.0, or any later versions of that license, including any 59 | exceptions or additional permissions as identified by the initial 60 | Contributor. 61 | 62 | 2. GRANT OF RIGHTS 63 | 64 | a) Subject to the terms of this Agreement, each Contributor hereby 65 | grants Recipient a non-exclusive, worldwide, royalty-free copyright 66 | license to reproduce, prepare Derivative Works of, publicly display, 67 | publicly perform, Distribute and sublicense the Contribution of such 68 | Contributor, if any, and such Derivative Works. 69 | 70 | b) Subject to the terms of this Agreement, each Contributor hereby 71 | grants Recipient a non-exclusive, worldwide, royalty-free patent 72 | license under Licensed Patents to make, use, sell, offer to sell, 73 | import and otherwise transfer the Contribution of such Contributor, 74 | if any, in Source Code or other form. This patent license shall 75 | apply to the combination of the Contribution and the Program if, at 76 | the time the Contribution is added by the Contributor, such addition 77 | of the Contribution causes such combination to be covered by the 78 | Licensed Patents. The patent license shall not apply to any other 79 | combinations which include the Contribution. No hardware per se is 80 | licensed hereunder. 81 | 82 | c) Recipient understands that although each Contributor grants the 83 | licenses to its Contributions set forth herein, no assurances are 84 | provided by any Contributor that the Program does not infringe the 85 | patent or other intellectual property rights of any other entity. 86 | Each Contributor disclaims any liability to Recipient for claims 87 | brought by any other entity based on infringement of intellectual 88 | property rights or otherwise. As a condition to exercising the 89 | rights and licenses granted hereunder, each Recipient hereby 90 | assumes sole responsibility to secure any other intellectual 91 | property rights needed, if any. For example, if a third party 92 | patent license is required to allow Recipient to Distribute the 93 | Program, it is Recipient's responsibility to acquire that license 94 | before distributing the Program. 95 | 96 | d) Each Contributor represents that to its knowledge it has 97 | sufficient copyright rights in its Contribution, if any, to grant 98 | the copyright license set forth in this Agreement. 99 | 100 | e) Notwithstanding the terms of any Secondary License, no 101 | Contributor makes additional grants to any Recipient (other than 102 | those set forth in this Agreement) as a result of such Recipient's 103 | receipt of the Program under the terms of a Secondary License 104 | (if permitted under the terms of Section 3). 105 | 106 | 3. REQUIREMENTS 107 | 108 | 3.1 If a Contributor Distributes the Program in any form, then: 109 | 110 | a) the Program must also be made available as Source Code, in 111 | accordance with section 3.2, and the Contributor must accompany 112 | the Program with a statement that the Source Code for the Program 113 | is available under this Agreement, and informs Recipients how to 114 | obtain it in a reasonable manner on or through a medium customarily 115 | used for software exchange; and 116 | 117 | b) the Contributor may Distribute the Program under a license 118 | different than this Agreement, provided that such license: 119 | i) effectively disclaims on behalf of all other Contributors all 120 | warranties and conditions, express and implied, including 121 | warranties or conditions of title and non-infringement, and 122 | implied warranties or conditions of merchantability and fitness 123 | for a particular purpose; 124 | 125 | ii) effectively excludes on behalf of all other Contributors all 126 | liability for damages, including direct, indirect, special, 127 | incidental and consequential damages, such as lost profits; 128 | 129 | iii) does not attempt to limit or alter the recipients' rights 130 | in the Source Code under section 3.2; and 131 | 132 | iv) requires any subsequent distribution of the Program by any 133 | party to be under a license that satisfies the requirements 134 | of this section 3. 135 | 136 | 3.2 When the Program is Distributed as Source Code: 137 | 138 | a) it must be made available under this Agreement, or if the 139 | Program (i) is combined with other material in a separate file or 140 | files made available under a Secondary License, and (ii) the initial 141 | Contributor attached to the Source Code the notice described in 142 | Exhibit A of this Agreement, then the Program may be made available 143 | under the terms of such Secondary Licenses, and 144 | 145 | b) a copy of this Agreement must be included with each copy of 146 | the Program. 147 | 148 | 3.3 Contributors may not remove or alter any copyright, patent, 149 | trademark, attribution notices, disclaimers of warranty, or limitations 150 | of liability ("notices") contained within the Program from any copy of 151 | the Program which they Distribute, provided that Contributors may add 152 | their own appropriate notices. 153 | 154 | 4. COMMERCIAL DISTRIBUTION 155 | 156 | Commercial distributors of software may accept certain responsibilities 157 | with respect to end users, business partners and the like. While this 158 | license is intended to facilitate the commercial use of the Program, 159 | the Contributor who includes the Program in a commercial product 160 | offering should do so in a manner which does not create potential 161 | liability for other Contributors. Therefore, if a Contributor includes 162 | the Program in a commercial product offering, such Contributor 163 | ("Commercial Contributor") hereby agrees to defend and indemnify every 164 | other Contributor ("Indemnified Contributor") against any losses, 165 | damages and costs (collectively "Losses") arising from claims, lawsuits 166 | and other legal actions brought by a third party against the Indemnified 167 | Contributor to the extent caused by the acts or omissions of such 168 | Commercial Contributor in connection with its distribution of the Program 169 | in a commercial product offering. The obligations in this section do not 170 | apply to any claims or Losses relating to any actual or alleged 171 | intellectual property infringement. In order to qualify, an Indemnified 172 | Contributor must: a) promptly notify the Commercial Contributor in 173 | writing of such claim, and b) allow the Commercial Contributor to control, 174 | and cooperate with the Commercial Contributor in, the defense and any 175 | related settlement negotiations. The Indemnified Contributor may 176 | participate in any such claim at its own expense. 177 | 178 | For example, a Contributor might include the Program in a commercial 179 | product offering, Product X. That Contributor is then a Commercial 180 | Contributor. If that Commercial Contributor then makes performance 181 | claims, or offers warranties related to Product X, those performance 182 | claims and warranties are such Commercial Contributor's responsibility 183 | alone. Under this section, the Commercial Contributor would have to 184 | defend claims against the other Contributors related to those performance 185 | claims and warranties, and if a court requires any other Contributor to 186 | pay any damages as a result, the Commercial Contributor must pay 187 | those damages. 188 | 189 | 5. NO WARRANTY 190 | 191 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 192 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" 193 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 194 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF 195 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 196 | PURPOSE. Each Recipient is solely responsible for determining the 197 | appropriateness of using and distributing the Program and assumes all 198 | risks associated with its exercise of rights under this Agreement, 199 | including but not limited to the risks and costs of program errors, 200 | compliance with applicable laws, damage to or loss of data, programs 201 | or equipment, and unavailability or interruption of operations. 202 | 203 | 6. DISCLAIMER OF LIABILITY 204 | 205 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 206 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS 207 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 208 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 209 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 210 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 211 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 212 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE 213 | POSSIBILITY OF SUCH DAMAGES. 214 | 215 | 7. GENERAL 216 | 217 | If any provision of this Agreement is invalid or unenforceable under 218 | applicable law, it shall not affect the validity or enforceability of 219 | the remainder of the terms of this Agreement, and without further 220 | action by the parties hereto, such provision shall be reformed to the 221 | minimum extent necessary to make such provision valid and enforceable. 222 | 223 | If Recipient institutes patent litigation against any entity 224 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 225 | Program itself (excluding combinations of the Program with other software 226 | or hardware) infringes such Recipient's patent(s), then such Recipient's 227 | rights granted under Section 2(b) shall terminate as of the date such 228 | litigation is filed. 229 | 230 | All Recipient's rights under this Agreement shall terminate if it 231 | fails to comply with any of the material terms or conditions of this 232 | Agreement and does not cure such failure in a reasonable period of 233 | time after becoming aware of such noncompliance. If all Recipient's 234 | rights under this Agreement terminate, Recipient agrees to cease use 235 | and distribution of the Program as soon as reasonably practicable. 236 | However, Recipient's obligations under this Agreement and any licenses 237 | granted by Recipient relating to the Program shall continue and survive. 238 | 239 | Everyone is permitted to copy and distribute copies of this Agreement, 240 | but in order to avoid inconsistency the Agreement is copyrighted and 241 | may only be modified in the following manner. The Agreement Steward 242 | reserves the right to publish new versions (including revisions) of 243 | this Agreement from time to time. No one other than the Agreement 244 | Steward has the right to modify this Agreement. The Eclipse Foundation 245 | is the initial Agreement Steward. The Eclipse Foundation may assign the 246 | responsibility to serve as the Agreement Steward to a suitable separate 247 | entity. Each new version of the Agreement will be given a distinguishing 248 | version number. The Program (including Contributions) may always be 249 | Distributed subject to the version of the Agreement under which it was 250 | received. In addition, after a new version of the Agreement is published, 251 | Contributor may elect to Distribute the Program (including its 252 | Contributions) under the new version. 253 | 254 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient 255 | receives no rights or licenses to the intellectual property of any 256 | Contributor under this Agreement, whether expressly, by implication, 257 | estoppel or otherwise. All rights in the Program not expressly granted 258 | under this Agreement are reserved. Nothing in this Agreement is intended 259 | to be enforceable by any entity that is not a Contributor or Recipient. 260 | No third-party beneficiary rights are created under this Agreement. 261 | 262 | Exhibit A - Form of Secondary Licenses Notice 263 | 264 | "This Source Code may also be made available under the following 265 | Secondary Licenses when the conditions for such availability set forth 266 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), 267 | version(s), and exceptions or additional permissions here}." 268 | 269 | Simply including a copy of this Agreement, including this Exhibit A 270 | is not sufficient to license the Source Code under Secondary Licenses. 271 | 272 | If it is not possible or desirable to put the notice in a particular 273 | file, then You may include the notice in a location (such as a LICENSE 274 | file in a relevant directory) where a recipient would be likely to 275 | look for such a notice. 276 | 277 | You may add additional accurate notices of copyright ownership. 278 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rust ESP compiler container [![Repository on Quay](https://img.shields.io/badge/quay.io-ctron%2Frust--esp-success "Repository on Quay")](https://quay.io/repository/ctron/rust-esp) 2 | 3 | This is a container which can be used to build a Rust project for the ESP32. 4 | 5 | ## Pre-requisites 6 | 7 | * Docker 8 | * A rust project (e.g. use [ctron/rust-esp-template](https://github.com/ctron/rust-esp-template) as example) 9 | 10 | ## Usage 11 | 12 | This container image provides a few tools which can be run like this: 13 | 14 | docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp:latest 15 | 16 | This uses `-ti` to attach the console, to show you the output and let you interact 17 | with the application running inside the container. 18 | 19 | **Note**: Consider running the container with `--rm` as well. This prevents Docker 20 | from keeping the container around after it exited. As all your sources are 21 | mapped from the host's file system into the container, you don't need to 22 | keep the container on disk, and can safe some disk storage. 23 | 24 | ### Volume mapping 25 | 26 | The `-v $PWD:/home/project:z` will map the current directory into the location 27 | `/home/project` inside the container. This is required so that the tools inside 28 | the container can work with the project. 29 | 30 | `$PWD` gets replaced by the shell with the current directory. This will only work 31 | in a Bourne like shell. On Windows you can use `%CD%` instead. You can of course 32 | also replace this with the absolute path to your project. 33 | 34 | You can drop the `:z` suffix, if you don't have SElinux on the host system. 35 | 36 | All following examples use `$PWD:/home/project:z`, replace this as required by your environment. 37 | 38 | ### Default command 39 | 40 | This will run the default command `build-project`. This will try an automic full build, see below. 41 | 42 | You can run other commands by providing a command manually: 43 | 44 | docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp my-command-in-the-container 45 | 46 | ### Running as shell 47 | 48 | As you can run other commands, and the container is just a normal Linux, you can simply run `bash` 49 | in the container and directly work there. Without the need to run docker with each command: 50 | 51 | docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp bash 52 | 53 | ### Tags 54 | 55 | The `master` branch of this repository will build into the `latest` tag, which is also the default 56 | if you omit the `:latest` suffix in the container name. 57 | 58 | Each git tag will also be build into a container image tag, so e.g. git tag `0.0.1`, will be built into 59 | the container tag `:0.0.1`. 60 | 61 | So should the `latest` image break, it should always be possible to switch to a previous version. 62 | 63 | There is also the `:develop` tag, which is based on the `develop` branch in Git. It is used to try 64 | out new changes before merging into master. 65 | 66 | ## Bootstrapping 67 | 68 | Initially a few files need to be set up. The ESP-IDF components need to be configured and compiled. 69 | Run the following command to create an initial setup: 70 | 71 | docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp create-project 72 | 73 | This will create (overwrite) a few files, which are required to build the project. 74 | 75 | Next run: 76 | 77 | docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp make menuconfig 78 | 79 | Which will start the ESP-IDF build and shows you the menu config tool for configuring 80 | your ESP project. Be sure to save when you exit. 81 | 82 | ## Building 83 | 84 | In order to build the project, run the following command: 85 | 86 | docker run -ti -v $PWD:/home/project:z quay.io/ctron/rust-esp build-project 87 | 88 | This will compile the ESP-IDF part, the rust part and finally convert it to an image 89 | which you can upload to your ESP. 90 | 91 | ## Uploading 92 | 93 | You can then upload the image using the `flash-project` executable: 94 | 95 | docker run -ti --device=/dev/ttyUSB0 -v $PWD:/home/project:z rust-esp32 flash-project 96 | 97 | If this doesn't work or you need to use differnt tool it might be easier to 98 | upload the image via `esptool` from the host machine. To do this call: 99 | 100 | esptool write_flash 0x10000 esp-app.bin 101 | 102 | ## Building the container 103 | 104 | You can also build the container image yourself, by cloning this repository and executing: 105 | 106 | docker build . -t rust-esp 107 | 108 | ## Notes 109 | 110 | * Use this at your own risk. No guarantees. 111 | * Contributions are welcome. 112 | * This /should/ work on MacOS the same way. But I haven't tested it. 113 | * A test on Windows shows that, yes it works. But with some quirks: 114 | * The menu `make menuconfig` renders a bit weird. The new Windows terminal improves this a lot. 115 | * The first `make app` will run just fine, but after that it fails to compile. Maybe some 116 | issue with the Windows CIFS mapping in Docker. However, you can skip this step and run `xbuild-project` 117 | instead. That will only compile the rust part. 118 | * In theory this should work also with with the ESP8266. A few tweaks for the build files 119 | will be required, and I didn't test this. 120 | * I put this on [quay.io](https:/quay.io) as Docker Hub continously failed to build this 121 | image. After several hours, the build times out. As quay.io now runs out of disk space during 122 | the build, I started building this with GitHub Actions, and then push it to quay.io. 123 | 124 | ## Also see 125 | 126 | This work is built upn the work of others. Please see: 127 | 128 | * http://quickhack.net/nom/blog/2019-05-14-build-rust-environment-for-esp32.html 129 | * https://esp32.com/viewtopic.php?t=9226 130 | * https://github.com/MabezDev/rust-xtensa 131 | 132 | -------------------------------------------------------------------------------- /bindgen-project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | FLAGS="" 6 | FLAGS+=" --sysroot=${ESP_PATH}/xtensa-esp32-elf/sysroot" 7 | FLAGS+=" -I${PROJECT}/build/include" 8 | FLAGS+=" -D__bindgen" 9 | FLAGS+=" -target xtensa" 10 | FLAGS+=" -x c" 11 | 12 | while read -r include; do 13 | FLAGS+=" -I${include}" 14 | done <<< "$(find "${IDF_PATH}/components" -maxdepth 3 -name include)" 15 | 16 | # Not picked up from above 17 | FLAGS+=" -I${IDF_PATH}/components/lwip/lwip/src/include" 18 | FLAGS+=" -I${IDF_PATH}/components/lwip/port/esp32/include" 19 | FLAGS+=" -I${IDF_PATH}/components/newlib/platform_include" 20 | FLAGS+=" -I${IDF_PATH}/components/lwip/include/apps" 21 | 22 | : "${BINDGEN_FLAGS:=--use-core --no-layout-tests}" 23 | 24 | #shellcheck disable=SC2086 25 | bindgen $BINDGEN_FLAGS --output esp32-sys/src/bindings.rs esp32-sys/src/bindings.h -- $FLAGS 26 | -------------------------------------------------------------------------------- /build-project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | die() { echo "$*" 1>&2 ; exit 1 ; } 6 | 7 | test -f Cargo.toml || die "unable to find 'Cargo.toml'. You will need to map the container path /home/project to the path of your Rust project. You can do this using: docker run -ti -v $PWD:/home/project:z rust-esp" 8 | 9 | for i in esp-idf .cargo main; do 10 | test -d "$i" || die "'$i' is missing. Use 'create-project' to set up the build." 11 | done 12 | for i in Makefile .cargo/config main/esp_app_main.c; do 13 | test -f "$i" || die "'$i' is missing. Use 'create-project' to set up the build." 14 | done 15 | 16 | test -f sdkconfig || die "'sdkconfig' is missing. You can create one running 'make menuconfig'" 17 | 18 | make -j app 19 | 20 | if test -d esp32-sys; then 21 | if ! test -f esp32-sys/src/bindings.rs; then 22 | echo "esp32-sys crate is present, but bindings.rs is missing, running bindgen-project" 23 | bindgen-project 24 | fi 25 | fi 26 | 27 | xbuild-project 28 | image-project 29 | 30 | echo Build complete 31 | -------------------------------------------------------------------------------- /create-project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | die() { echo "$*" 1>&2 ; exit 1 ; } 6 | 7 | test -f Cargo.toml || die "unable to find 'Cargo.toml'. You will need to map the container path /home/project to the path of your Rust project. You can do this using: docker run -ti -v $PWD:/home/project/build:z rust-esp" 8 | 9 | echo "Creating Makefile (Makefile)" 10 | cp "${TEMPLATES}/Makefile" Makefile 11 | 12 | echo "Creating esp-idf symlink (esp-idf -> /esp-idf)" 13 | ln -sf "${IDF_PATH}" esp-idf 14 | 15 | echo "Creating cargo config (.cargo/config)" 16 | mkdir -p .cargo 17 | cp "${TEMPLATES}/cargo.config" .cargo/config 18 | 19 | echo "Creating main application wrapper (main/esp_app_main.c)" 20 | mkdir -p main 21 | cp "${TEMPLATES}/main.c" main/esp_app_main.c 22 | cp "${TEMPLATES}/component.mk" main/ 23 | 24 | -------------------------------------------------------------------------------- /flash-project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | "$IDF_PATH/components/esptool_py/esptool/esptool.py" \ 6 | --chip esp32 \ 7 | --port /dev/ttyUSB0 \ 8 | --baud 115200 \ 9 | --before default_reset \ 10 | --after hard_reset \ 11 | write_flash \ 12 | -z \ 13 | --flash_mode dio \ 14 | --flash_freq 40m \ 15 | --flash_size detect \ 16 | 0x1000 build/bootloader/bootloader.bin \ 17 | 0x10000 build/esp-app.bin \ 18 | 0x8000 build/partitions_singleapp.bin 19 | -------------------------------------------------------------------------------- /image-project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | "${IDF_PATH}/components/esptool_py/esptool/esptool.py" \ 6 | --chip esp32 \ 7 | elf2image \ 8 | -o build/esp-app.bin \ 9 | target/xtensa-esp32-none-elf/release/esp-app 10 | 11 | echo "You can now flash 'build/esp-app.bin'" 12 | -------------------------------------------------------------------------------- /templates/Makefile: -------------------------------------------------------------------------------- 1 | 2 | PROJECT_NAME := esp-app 3 | 4 | include $(IDF_PATH)/make/project.mk 5 | 6 | -------------------------------------------------------------------------------- /templates/cargo.config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "xtensa-esp32-none-elf" 3 | 4 | [target.xtensa-esp32-none-elf] 5 | rustflags = [ 6 | "-C", "target-cpu=esp32", 7 | "-C", "save-temps", 8 | "-C", "link-arg=-nostdlib", 9 | # "-C", "link-arg=-nostartfiles", 10 | 11 | "-C", "link-arg=-ucall_user_start_cpu0", 12 | "-C", "link-arg=-u__cxa_guard_dummy", 13 | "-C", "link-arg=-u__cxx_fatal_exception", 14 | "-C", "link-arg=-uld_include_panic_highint_hdl", 15 | "-C", "link-arg=-uesp_app_desc", 16 | 17 | "-C", "link-arg=-Wl,--gc-sections", 18 | "-C", "link-arg=-Wl,-static", 19 | "-C", "link-arg=-Wl,--start-group", 20 | 21 | "-C", "link-arg=-Lbuild/app_update", "-C", "link-arg=-lapp_update", 22 | "-C", "link-arg=-Lbuild/driver", "-C", "link-arg=-ldriver", 23 | "-C", "link-arg=-Lbuild/esp-tls", "-C", "link-arg=-lesp-tls", 24 | "-C", "link-arg=-Lbuild/esp32", "-C", "link-arg=-lesp32", 25 | "-C", "link-arg=esp-idf/components/esp32/libhal.a", 26 | "-C", "link-arg=-Lesp-idf/components/esp32/lib", "-C", "link-arg=-lcore", 27 | 28 | "-C", "link-arg=-Lesp-idf/components/esp32/ld", 29 | "-C", "link-arg=-Tesp32_out.ld", 30 | "-C", "link-arg=-Tbuild/esp32/esp32.project.ld", 31 | "-C", "link-arg=-Tesp32.rom.ld", 32 | "-C", "link-arg=-Tesp32.peripherals.ld", 33 | "-C", "link-arg=-Tesp32.rom.libgcc.ld", 34 | "-C", "link-arg=-Tesp32.rom.spiram_incompatible_fns.ld", 35 | 36 | "-C", "link-arg=-Lbuild/esp_ringbuf", "-C", "link-arg=-lesp_ringbuf", 37 | "-C", "link-arg=-Lbuild/freertos", "-C", "link-arg=-lfreertos", 38 | 39 | "-C", "link-arg=-Wl,--undefined=uxTopUsedPriority", 40 | 41 | "-C", "link-arg=-Lbuild/heap", "-C", "link-arg=-lheap", 42 | "-C", "link-arg=-Lbuild/log", "-C", "link-arg=-llog", 43 | 44 | "-C", "link-arg=esp-idf/components/newlib/lib/libc.a", 45 | "-C", "link-arg=esp-idf/components/newlib/lib/libm.a", 46 | 47 | "-C", "link-arg=-Lbuild/newlib", "-C", "link-arg=-lnewlib", 48 | "-C", "link-arg=-Lbuild/pthread", "-C", "link-arg=-lpthread", 49 | "-C", "link-arg=-Lbuild/soc", "-C", "link-arg=-lsoc", 50 | "-C", "link-arg=-Lbuild/spi_flash", "-C", "link-arg=-lspi_flash", 51 | "-C", "link-arg=-Lbuild/vfs", "-C", "link-arg=-lvfs", 52 | "-C", "link-arg=-Lbuild/xtensa-debug-module", "-C", "link-arg=-lxtensa-debug-module", 53 | 54 | "-C", "link-arg=-lgcc", 55 | "-C", "link-arg=-lstdc++", 56 | "-C", "link-arg=-lgcov", 57 | "-C", "link-arg=-Wl,--end-group", 58 | "-C", "link-arg=-Wl,-EL", 59 | ] 60 | -------------------------------------------------------------------------------- /templates/component.mk: -------------------------------------------------------------------------------- 1 | # empty "main" Makefile 2 | -------------------------------------------------------------------------------- /templates/main.c: -------------------------------------------------------------------------------- 1 | void app_main() {} 2 | -------------------------------------------------------------------------------- /xbuild-project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cargo +xtensa xbuild --target "${XARGO_TARGET:-xtensa-esp32-none-elf}" --release 6 | --------------------------------------------------------------------------------