diff --git a/solo-builder/.gitignore b/solo-builder/.gitignore new file mode 100644 index 0000000..842e611 --- /dev/null +++ b/solo-builder/.gitignore @@ -0,0 +1,17 @@ +ssh/ +# Elastic Beanstalk Files +.elasticbeanstalk/* +!.elasticbeanstalk/*.cfg.yml +!.elasticbeanstalk/*.global.yml +instance.json +inventory +id_rsa* +solo-builder.pem +staging/ + +.vagrant/ +vagrant_ansible_inventory_default + +accessorykit +packages/ +upload/ diff --git a/solo-builder/COPYRIGHT-3DR b/solo-builder/COPYRIGHT-3DR new file mode 100644 index 0000000..18b98ca --- /dev/null +++ b/solo-builder/COPYRIGHT-3DR @@ -0,0 +1,21 @@ +Copyright 2015-2016 3D Robotics + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use these files 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. + +~~~~ + +Contributors prior to public release: + + * Tim Ryan + * Liam Staskawicz + * Allan Matthew \ No newline at end of file diff --git a/solo-builder/Dockerfile b/solo-builder/Dockerfile new file mode 100644 index 0000000..2ec1500 --- /dev/null +++ b/solo-builder/Dockerfile @@ -0,0 +1,36 @@ +# Latest Ubuntu 14.04LTS + +FROM ubuntu:trusty + +RUN \ + apt-get update && \ + apt-get install --no-install-recommends -y software-properties-common && \ + apt-add-repository ppa:ansible/ansible && \ + apt-get update && \ + apt-get install -y ansible + +RUN echo '[local]\nlocalhost\n' > /etc/ansible/hosts + +RUN \ + adduser --disabled-password --gecos '' ubuntu && \ + adduser ubuntu sudo && \ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +COPY playbook.yml /provision/ +COPY ansible.cfg /provision/ +COPY ansible.gitconfig /provision/ +COPY builder.sh /provision/ +RUN chown -R ubuntu /provision/ + +COPY id_rsa /home/ubuntu/.ssh/ +COPY solo-builder.pem /home/ubuntu/.ssh/ +RUN chown -R ubuntu /home/ubuntu && chmod 0400 /home/ubuntu/.ssh/* + +RUN \ + su -l ubuntu -c "\ + export HOME=/home/ubuntu && \ + cd /provision && \ + eval \`ssh-agent\` && \ + ssh-add ~/.ssh/id_rsa && \ + ssh-add ~/.ssh/solo-builder.pem && \ + ansible-playbook -i "localhost," -c local playbook.yml" diff --git a/solo-builder/LICENSE-APACHE b/solo-builder/LICENSE-APACHE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/solo-builder/LICENSE-APACHE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/solo-builder/README.md b/solo-builder/README.md new file mode 100644 index 0000000..c081b36 --- /dev/null +++ b/solo-builder/README.md @@ -0,0 +1,88 @@ +WARNING - WORK IN PROGRESS + +``` +This code is known to be high risk , but also early-adopter friendly. + +We will remove this warning from the repository when it is no longer required. +``` + + +# solo-builder +## Quick start guide +You may find the following "quick start" guide useful. You can find the [Open Solo Quick Start Guide](http://ardupilot.org/dev/docs/solo-opensolo-quickstart.html) on ardupilot.org. + +## Using vagrant + +Works in [vagrant](http://vagrantup.com), typically useful for local builds. +First install this plugin: +``` +$ vagrant plugin install vagrant-guest_ansible +$ vagrant up +``` + +(If `vagrant up` fails, run `vagrant provision` to try provisioning your VM +again.) + +To fire off the builder: + +``` +$ vagrant ssh -c /vagrant/builder.sh +``` + + +## Using docker + +DOCKER IS UNTESTED OUTSIDE 3DR , USE VAGRANT FOR NOW. + +Works in Docker and boot2docker. +Copy `id_rsa` and `solo-builder.pem` to this directory (sorry). Then run + +``` +docker build -t 3drobotics/solo-builder . +``` + +Then run + +``` +docker run -i 3drobotics/solo-builder su -l ubuntu /solo-build/builder.sh +``` + +TODO: write a script that gets the files off after + +## Using something else + +`playbook.yml` is an ansible file for an Ubuntu 14.04 distro. `builder.sh` is the build script for a user named `ubuntu`. Make it happen! + +## Repos + +3dr Private: + +* https://github.com/3drobotics/mavlink-solo +* https://github.com/3drobotics/sculpture_proprietary +* https://github.com/3drobotics/solo-gimbal +* https://github.com/3drobotics/artoo +* https://github.com/3drobotics/SoloLink + +Public: + +* https://github.com/3drobotics/imx6-uboot +* https://github.com/3drobotics/imx6-linux +* https://github.com/3drobotics/MAVProxy +* https://github.com/3drobotics/stm32loader +* https://github.com/3drobotics/ardupilot-solo + +* https://github.com/OpenSolo/ardupilot-solo +* https://github.com/OpenSolo/sololink +* https://github.com/OpenSolo/artoo +* https://github.com/OpenSolo/imx6-uboot +* https://github.com/OpenSolo/imx6-linux +* https://github.com/OpenSolo/3dr-arm-yocto-bsp +* https://github.com/OpenSolo/meta-3dr +* https://github.com/OpenSolo/dronekit-python-solo +* https://github.com/OpenSolo/sololink-python +* https://github.com/OpenSolo/solo-builder +* https://github.com/OpenSolo/3dr-yocto-bsb-base +* https://github.com/OpenSolo/stm32loader +* https://github.com/OpenSolo/MAVProxy + + diff --git a/solo-builder/SOURCE b/solo-builder/SOURCE new file mode 100644 index 0000000..cfc3ad9 --- /dev/null +++ b/solo-builder/SOURCE @@ -0,0 +1 @@ +This source code was released by 3DR in the file: solo-builder_5444ac08.tar.gz diff --git a/solo-builder/Vagrantfile b/solo-builder/Vagrantfile new file mode 100644 index 0000000..44702a4 --- /dev/null +++ b/solo-builder/Vagrantfile @@ -0,0 +1,50 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + + + +Vagrant.configure(2) do |config| + + config.vm.box = "ubuntu/trusty64" + config.vm.box_check_update = false + + config.vm.provision "shell", path: "install-vagrant-deps.sh" + + # detect number of cores, + # http://stackoverflow.com/questions/891537/detect-number-of-cpus-installed + def self.processor_count + case RbConfig::CONFIG['host_os'] + when /darwin9/ + `hwprefs cpu_count`.to_i + when /darwin/ + ((`which hwprefs` != '') ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i + when /linux/ + `cat /proc/cpuinfo | grep processor | wc -l`.to_i + when /freebsd/ + `sysctl -n hw.ncpu`.to_i + when /mswin|mingw/ + require 'win32ole' + wmi = WIN32OLE.connect("winmgmts://") + cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # TODO count hyper-threaded in this + cpu.to_enum.first.NumberOfCores + end + end + + # fwd host ssh for git access + config.ssh.forward_agent = true + + config.vm.provider "virtualbox" do |vb| + # not recommended to use less than 6GB + vb.memory = "6144" + vb.cpus = processor_count + end + + config.vm.provision "guest_ansible" do |ansible| + ansible.extra_vars = { + build_dir_owner: "vagrant" + } + ansible.playbook = "playbook.yml" + end +end + + diff --git a/solo-builder/WARNING.md b/solo-builder/WARNING.md new file mode 100644 index 0000000..d84a9c0 --- /dev/null +++ b/solo-builder/WARNING.md @@ -0,0 +1,11 @@ +WARNING - WORK IN PROGRESS + +``` +This code is known to be broken and/or incomplete. IT DOES NOT WORK. + +We are actively working on fixing it, and we really, really do not recommend you download it just yet. + +We will remove this warning from the repository when it is no longer required. +``` + + diff --git a/solo-builder/alt_sync.sh b/solo-builder/alt_sync.sh new file mode 100755 index 0000000..acea74c --- /dev/null +++ b/solo-builder/alt_sync.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# alternative to the 'sync' tool, which puts stuff in /solo-build, for now we'll use /solo-build-alt +# +# 'master', 'tags/2.9.94' ( for a tag) or '2.9.94' ( for a branch ) is ok: +set -xv + +name=$1 +echo "git reference: $name" +# +sudo mkdir /solo-build-alt +sudo chown vagrant /solo-build-alt +cd /solo-build-alt + +echo "----------------------------------------------------------------------------" +mkdir -p sources/poky +git clone git://git.yoctoproject.org/poky sources/poky 2>&1 | grep -v 'fatal' +cd sources/poky +git fetch +git checkout bee7e3756adf70edaeabe9d43166707aab84f581 2>&1 +cd ../.. + +echo "----------------------------------------------------------------------------" +mkdir -p sources/meta-fsl-arm +git clone git://git.yoctoproject.org/meta-fsl-arm sources/meta-fsl-arm 2>&1 | grep -v 'fatal' +cd sources/meta-fsl-arm +git fetch +git checkout af392c22bf6b563525ede4a81b6755ff1dd2c1c6 2>&1 +cd ../.. + +echo "----------------------------------------------------------------------------" +mkdir -p sources/meta-openembedded +git clone git://git.openembedded.org/meta-openembedded sources/meta-openembedded 2>&1 | grep -v 'fatal' +cd sources/meta-openembedded +git fetch +git checkout eb4563b83be0a57ede4269ab19688af6baa62cd2 2>&1 +cd ../.. + +echo "----------------------------------------------------------------------------" +mkdir -p sources/base +git clone git://github.com/OpenSolo/3dr-yocto-bsp-base sources/base 2>&1 | grep -v 'fatal' +cd sources/base +git fetch +echo git checkout $name 2>&1 +git checkout $name 2>&1 +cd ../.. +cp sources/base/README.md . +cp sources/base/setup-environment . + +echo "----------------------------------------------------------------------------" +mkdir -p sources/meta-3dr +git clone git://github.com/OpenSolo/meta-3dr sources/meta-3dr 2>&1 | grep -v 'fatal' +cd sources/meta-3dr +git fetch +echo git checkout $name 2>&1 +git checkout $name 2>&1 +git pull origin +cd ../.. + +echo "----------------------------------------------------------------------------" +mkdir -p sources/meta-fsl-arm-extra +git clone git://github.com/Freescale/meta-fsl-arm-extra sources/meta-fsl-arm-extra 2>&1 | grep -v 'fatal' +cd sources/meta-fsl-arm-extra +git fetch +git checkout 07ad83db0fb67c5023bd627a61efb7f474c52622 2>&1 +cd ../.. + +echo "----------------------------------------------------------------------------" +mkdir -p sources/meta-fsl-demos +git clone git://github.com/Freescale/meta-fsl-demos sources/meta-fsl-demos 2>&1 | grep -v 'fatal' +cd sources/meta-fsl-demos +git fetch +git checkout 5a12677ad000a926d23c444266722a778ea228a7 2>&1 +cd ../.. + +echo "----------------------------------------------------------------------------" +mkdir -p sources/meta-browser +git clone git://github.com/OSSystems/meta-browser sources/meta-browser 2>&1 | grep -v 'fatal' +cd sources/meta-browser +git fetch +git checkout fc3969f63bda343c38c40a23f746c560c4735f3e 2>&1 +cd ../.. + +echo "----------------------------------------------------------------------------" +mkdir -p sources/meta-fsl-bsp-release +git clone git://git.freescale.com/imx/meta-fsl-bsp-release sources/meta-fsl-bsp-release 2>&1 | grep -v 'fatal' +cd sources/meta-fsl-bsp-release +git fetch +git checkout dora_3.10.17-1.0.0_GA 2>&1 +cd ../.. +cp sources/meta-fsl-bsp-release/imx/tools/fsl-setup-release.sh . diff --git a/solo-builder/ansible.cfg b/solo-builder/ansible.cfg new file mode 100644 index 0000000..126ef31 --- /dev/null +++ b/solo-builder/ansible.cfg @@ -0,0 +1,5 @@ +[ssh_connection] +pipelining = True + +[ssh_connection] +ssh_args = -o ForwardAgent=yes diff --git a/solo-builder/ansible.gitconfig b/solo-builder/ansible.gitconfig new file mode 100644 index 0000000..2b1336b --- /dev/null +++ b/solo-builder/ansible.gitconfig @@ -0,0 +1,3 @@ +[user] + name = Solo Builder + email = solo-builder@opensolo.org diff --git a/solo-builder/builder.sh b/solo-builder/builder.sh new file mode 100755 index 0000000..8c78fd9 --- /dev/null +++ b/solo-builder/builder.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +# USAGE: builder.sh -a GIT_ACCOUNT -r GIT_REPO -b GIT_BRANCH -b BUILD_MACHINE + +# EXAMPLE: builder.sh -a OpenSolo -r 3dr-arm-yocto-bsp -b Master +# These are also the defaults that will be used if options are not specified + +# EXAMPLE: builder.sh -a Pedals2Paddles -r 3dr-arm-yocto-bsp -b v0.1.0 +# This will use Matt's fork with a branch named v0.1.0 +# TIP: if the GIT_BRANCH starts with tags/, then it's actually a git tag that's used, if not it's a branch + +# Defaults if options are not set from command line set +GIT_ACCOUNT=OpenSolo +GIT_REPO=3dr-arm-yocto-bsp +GIT_BRANCH=master +BUILD_MACHINE=both +CLEAN=clean + + +# Check command line options for git account, repo, and branch. +while getopts a:r:b:m:c: option +do + case ${option} + in + a) GIT_ACCOUNT=${OPTARG};; + r) GIT_REPO=${OPTARG};; + b) GIT_BRANCH=${OPTARG};; + m) BUILD_MACHINE=$${OPTARG};; + c) CLEAN=${OPTARG};; + esac +done + +# Prompt for what is about to execute +echo +echo +echo "Ready to initialize the "$GIT_ACCOUNT $GIT_REPO" repo using branch "$GIT_BRANCH +echo +read -p "This is your last chance to say no. Proceed with build? (y/n):" choice +echo +case "$choice" in + y|Y ) echo "Yes! Proceeding with build.";; + n|N ) echo "No? Fine. Aborting build.." && exit 1;; + * ) echo "Invalid response. Quit pushing my buttons. Aborting build." && exit 1;; +esac +echo + +#Do it. +/vagrant/alt_sync.sh $GIT_BRANCH 2>&1 +echo "sync done" + +cd /solo-build-alt + +if [ ! $? -eq 0 ] +then + exit 1 +fi + +export MACHINE=imx6solo-3dr-1080p +EULA=1 source ./setup-environment build + +if [ ! $? -eq 0 ] +then + exit 1 +fi + +#TIP: how to build just one bit, such as the pixhawk firmware from OpenSolo/meta-3dr/recipes-firmware/pixhawk/pixhawk-firmware_1.3.1.bb : +#assuming you've run the 'export MACHINE...' and 'source ./setup...' commands first, and are in /solo-build-alt/build/ folder as a result: +#bitbake -c clean pixhawk-firmware +#bitbake pixhawk-firmware +#or verbose: +#bitbake pixhawk-firmware -v +#TIP: -k means continue-after-error-for-as-much-as-possible + + +if [ $CLEAN = clean ] +then + # these clean command/s are very verbose, and return an error code even though the clean works, lets quieten them: + echo "solo clean started..." + MACHINE=imx6solo-3dr-1080p bitbake world -c cleansstate -f -k 2>&1 > /dev/null + echo "...solo clean finished." + + echo "controller clean started..." + MACHINE=imx6solo-3dr-artoo bitbake world -c cleansstate -f -k 2>&1 > /dev/null + echo "...controller clean finished" +fi + + +MACHINE=imx6solo-3dr-1080p bitbake 3dr-solo +if [ ! $? -eq 0 ] +then + exit 1 +fi + +MACHINE=imx6solo-3dr-artoo bitbake 3dr-controller +if [ ! $? -eq 0 ] +then + exit 1 +fi + +#TIPS: +# Copy the relevant files to a date/time stamped completed directory in the git repo folder for easy access (on git ignore list). +# Make an MD5sum of each as is required for the Solo and Controller to accept the files. +# The tar.gz and the .md5 go directly in the /log/updates/ directory on the solo and/or controller. +COMP="completed_$(date +%F_%H-%M)" +NEW_DIR=/vagrant/binaries/$COMP +echo $COMP > /tmp/COMP.txt +mkdir -p $NEW_DIR +cd $NEW_DIR + +cp /solo-build-alt/build/tmp-eglibc/deploy/images/imx6solo-3dr-1080p/3dr-solo.tar.gz $NEW_DIR +md5sum 3dr-solo.tar.gz > 3dr-solo.tar.gz.md5 + +cp /solo-build-alt/build/tmp-eglibc/deploy/images/imx6solo-3dr-artoo/3dr-controller.tar.gz $NEW_DIR +md5sum 3dr-controller.tar.gz > 3dr-controller.tar.gz.md5 + +ls -lh $NEW_DIR + +echo +echo "All build files located in below directories of the Vagrant virtual machine (squashfs, uImage, kernel, u-boot, dtb file, initramfs, rootfs.cpio, etc)" +echo /solo-build-alt/build/tmp-eglibc/deploy/images/imx6solo-3dr-1080p/ +echo /solo-build-alt/build/tmp-eglibc/deploy/images/imx6solo-3dr-artoo/ + diff --git a/solo-builder/gimbal_firmware_1.3.6.ax b/solo-builder/gimbal_firmware_1.3.6.ax new file mode 100644 index 0000000..d91a9d1 --- /dev/null +++ b/solo-builder/gimbal_firmware_1.3.6.ax @@ -0,0 +1,8 @@ +{ + "image": "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", + "build_time": 1458349056, + "version": "1.3.6", + "image_size": 65862, + "release": "", + "git_identity": "v1.3.6-0-ge8b58c7" +} \ No newline at end of file diff --git a/solo-builder/install-vagrant-deps.sh b/solo-builder/install-vagrant-deps.sh new file mode 100644 index 0000000..6452359 --- /dev/null +++ b/solo-builder/install-vagrant-deps.sh @@ -0,0 +1,51 @@ +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6AF0E1940624A220 +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6D1D8367A3421AFB +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5BB92C09DB82666C +sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E601AAF9486D3664 + +# fix broken urllib3 or some ssl stuff diesn't work +sudo apt-get install -y --force-yes python-pip +sudo pip install urllib3[secure] +sudo pip install bcrypt +sudo pip install pynacl + +# need to update pip and setuptools to newer version before cryptography will install: +sudo pip install --upgrade pip +sudo pip install --upgrade setuptools +sudo apt-get install -y --force-yes libssl-dev +# get a specificversion of this, as newer ones don't work on 14.04: +#sudo pip install cryptography +sudo pip install cryptography==2.0.3 + +# fix broken python2.7.x by moving it forward to something newer than 2.7.8: +sudo add-apt-repository -y ppa:fkrull/deadsnakes-python2.7 +sudo apt-get -y --force-yes update +sudo apt-get install -y --force-yes python2.7 python2.7-dev + +## get deps for pillow, and note that we get Pillow from easy_install instead of 'pip' or apt-get becuase this method actually works. +#sudo apt-get install -y python-dev python-setuptools +#sudo apt-get install -y --force-yes libtiff4-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk +#sudo easy_install Pillow + +sudo apt-add-repository 'deb http://ppa.launchpad.net/anatol/tup/ubuntu precise main' -y +sudo add-apt-repository 'ppa:terry.guo/gcc-arm-embedded' -y + +sudo apt-get --assume-yes update +sudo apt-get --assume-yes install tup freetype* python-pip python-dev gcc-arm-none-eabi git +sudo apt-get --assume-yes install libffi* + +sudo apt-get --assume-yes install ansible + +ssh-keyscan -t rsa github.com +ssh-keyscan -t rsa bitbucket.org + +#sudo pip install --upgrade pip +#sudo pip install pillow + +#echo "" +#echo To build the artoo stm32 binary enter the VM with: +#echo vagrant ssh +#echo Then type this: +#echo cd /vagrant +#echo tup + diff --git a/solo-builder/playbook.retry b/solo-builder/playbook.retry new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/solo-builder/playbook.retry @@ -0,0 +1 @@ +default diff --git a/solo-builder/playbook.yml b/solo-builder/playbook.yml new file mode 100644 index 0000000..584e8c2 --- /dev/null +++ b/solo-builder/playbook.yml @@ -0,0 +1,59 @@ +- hosts: all + tasks: + - name: Installs packages + sudo: true + apt: pkg={{item}} state=installed update_cache=true cache_valid_time=86400 + with_items: + - gawk + - wget + - git-core + - diffstat + - unzip + - texinfo + - gcc-multilib + - build-essential + - chrpath + - socat + - libsdl1.2-dev + - xterm + - curl + + - name: Install jq + sudo: true + get_url: url=http://stedolan.github.io/jq/download/linux64/jq dest=/usr/local/bin/jq mode=0755 + + - name: Install repo + sudo: true + get_url: url=https://storage.googleapis.com/git-repo-downloads/repo dest=/usr/local/bin/repo mode=0755 + + - name: Git configuration + copy: src=ansible.gitconfig dest=~/.gitconfig + + #- name: ensure github.com is a known host + # lineinfile: + # dest: ~/.ssh/known_hosts + # create: yes + # state: present + # line: "{{ lookup('pipe', 'ssh-keyscan -t rsa github.com') }}" + # regexp: "^github\\.com" + + #- name: ensure bitbucket.org is a known host + # lineinfile: + # dest: ~/.ssh/known_hosts + # create: yes + # state: present + # line: "{{ lookup('pipe', 'ssh-keyscan -t rsa bitbucket.org') }}" + # regexp: "^bitbucket\\.org" + + - name: create build dir + sudo: true + # option to override build_dir_owner (currently used by vagrant) + file: path=/solo-build state=directory mode=0755 owner={{build_dir_owner | default('ubuntu')}} + + - name: repo init + shell: repo init -u https://github.com/OpenSolo/3dr-arm-yocto-bsp/ + args: + chdir: /solo-build + creates: /solo-build/build + + #- copy: src=~/.ssh/github_token dest=~/.ssh/github_token mode=0455 diff --git a/solo-builder/repo/build.sh b/solo-builder/repo/build.sh new file mode 100644 index 0000000..039d8c9 --- /dev/null +++ b/solo-builder/repo/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +cd $(dirname $0) + +set -e +rm -rf static +mkdir -p static +while read -r p && [[ "$p" != '' ]]; do + cp ../build/tmp-eglibc/deploy/rpm/$p static/ +done >log, "cmd: "+cmd+"\n" + print "cmd: "+cmd+"\n" + p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE,stdout=subprocess.PIPE) + ret = '' + + dobreak = False + doNext = False + while True: + #print p.poll() + + #out = p.stdout.readline() + out = p.stdout.read(1) + # poll() returns None if process is still running, or exit code if it's done + if out == "": + if p.poll() is not None: + #print "OUT BREAK : " + str(p.poll()) + dobreak = True + # otherwise handle the data we got prom the process: + while out != '' and doNext == False: + #if doNext == True: + # out = out + "\n" + # doNext = False + sys.stdout.write(out) + sys.stdout.flush() + if doLog: + log.write(out) + log.flush() + ret += out + out = p.stdout.read(1) + #if out == "\n": + # doNext = True + + #err = p.stderr.readline() + err = p.stderr.read(1) + if err == "": + if p.poll() is not None: + #print "ERR BREAK" + str(p.poll()) + dobreak = True + while err != '' and doNext == False: + #if doNext == True: + # out = out + "\n" + # doNext = False + sys.stdout.write(err) + sys.stdout.flush() + if doLog: + log.write(err) + log.flush() + ret += err + err = p.stderr.read(1) + #if err == "\n": + # doNext = True + + if dobreak == True: + break + return ret + + +def drop_privileges(uid_name='nobody', gid_name='nogroup'): + if os.getuid() != 0: + # We're not root so, like, whatever dude + return + + # Get the uid/gid from the name + running_uid = pwd.getpwnam(uid_name).pw_uid + running_gid = grp.getgrnam(gid_name).gr_gid + + # Remove group privileges + os.setgroups([]) + + # Try setting the new uid/gid + os.setgid(running_gid) + os.setuid(running_uid) + + # Ensure a very conservative umask + old_umask = os.umask(002) + +# tasks potentially needing root: + +print >>log, "fixing perms\n"; +print "fixing perms\n"; +run_command_capture_results("chown -R vagrant /vagrant/.git /vagrant/.gitignore"); +run_command_capture_results("chown -R vagrant /vagrant/*"); + +# now actually do ita: +#print >>log, "dropping privs to 'vagrant'\n"; +drop_privileges('vagrant','vagrant'); + +me = get_username() +if ( me != 'vagrant' ) : + print >>log, "error while trying to drop root and running as vagrant user, aborting. \n"; + exit(1); + + +run_command_capture_results("rm /vagrant/www/latest_run.txt", False); + +#run_command_capture_results("touch /vagrant/www/in-progress.txt", False); +progress = open("/vagrant/www/in-progress.txt",'w+') + + +print >>log, "now running as 'vagrant' user.\nstarting run at:\n"; +print "now running as 'vagrant' user.\nstarting run at:\n"; +run_command_capture_results("date"); + + +print >>log, "chdir /vagrant"; +print "chdir /vagrant"; +os.chdir("/vagrant"); + +run_command_capture_results("git pull"); + +# compare git rev with last-run, if changed, then we run again... +gitrev = run_command_capture_results("git rev-parse --verify HEAD"); +touch = run_command_capture_results("touch /vagrant/gitrev.txt"); +with open('gitrev.txt', 'r+') as f_in: + prev = f_in.read() +f_in.close() +# if they are different, make them the same. +if gitrev != prev: + with open('gitrev.txt', 'w+') as f_out: + f_out.write(gitrev) + f_in.close() +# just let the human know the thing we are currently trying to do, by it's git hash.. +progress.write(gitrev) + +# if no change, then don't re-run +if gitrev == prev: + print >>log, "no change in solo-builder git revision, not re-running. ( to force re-run, delete /vagrant/gitrev.txt file)"; + print "no change in solo-builder git revision, not re-running. ( to force re-run, delete /vagrant/gitrev.txt file)"; + +else: + # run something. + run_command_capture_results("echo \"y\" |/vagrant/builder.sh"); + + print >>log, "finished run at:\n"; + run_command_capture_results("date"); + + print "log closed. \n"; + log.close(); + + print "log relocated. \n"; + + comp = '' + with open('/tmp/COMP.txt', 'r+') as f_in: + comp = f_in.read() + f_in.close() + comp = comp.rstrip() + if comp == '': + print "log relocation aborted,cant find /tmp/COMP.txt"; + + run_command_capture_results("mv /vagrant/progress.log /vagrant/binaries/"+comp+"/latest_run.txt", False); + +# either way, wind up the files and handles: +progress.close() +run_command_capture_results("rm /vagrant/www/latest_run.txt", False); +run_command_capture_results("mv /vagrant/www/in-progress.txt /vagrant/www/latest_run.txt", False); +run_command_capture_results("rm /vagrant/progress.log", False); + +