Androidd源码非常庞大,由好几百个git仓库组成,是由repo工具来进行管理的。为了和AOSP的仓库兼容,我们也搭建使用repo工具管理的私有源码仓库。

  在WSL2的Ubuntu 16.04环境中我们完成了Android 6.0源码的编译,在这个基础上,我们来搭建基于WSL2的Android代码仓库,和每日迭代编译的环境。

1.环境搭建
   Android源码仓库的搭建,需要两台设备,一台作为Android源码仓库,一台作为客户端上传Android源码。我们把完成Android 6.0源码编译的Ubuntu 16.04作为客户端,另外重新创建一台Ubuntu 20.04作为Android源码仓库服务器。
   打开"Microsoft Store"微软商城,搜索"ubuntu",即可搜索到多个ubuntu的发行版,选择免费的"Ubuntu 20.04 LTS"下载,下载完成后,在"Microsoft Store"微软商城直接启动Ubuntu 20.04。
   在"Windows PowerShell(管理员)"中查看WSL的运行情况。

  PS C:\WINDOWS\system32> wsl -l -v
    NAME            STATE        VERSION
  * Ubuntu-16.04    Running      2        #客户端,上传代码
    Ubuntu-20.04    Running      2        #服务器,Android源码仓库

   可以看到Ubuntu 20.04已经正常运行。
   通过管理员Windows PowerShell给Ubuntu 20.04设置IP地址,把两个系统设置到同一个网段。

  wsl -d Ubuntu-16.04 -u root ip addr add 172.19.110.237/24 broadcast 172.19.110.255 dev eth0 label eth0:1
  wsl -d Ubuntu-20.04 -u root ip addr add 172.19.110.236/24 broadcast 172.19.110.255 dev eth0 label eth0:2
  netsh interface ip add address "vEthernet (WSL)" 172.19.110.1  255.255.255.0

2.配置服务器
2.1 配置客户端repo
  Android源码仓库搭建好之后,需要用repo工具验证,先配置repo。

  curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repo
  chmod +x repo

  repo工具初始化时,需要下载git-repo仓库,配置清华的源,可以加速下载。

  vim ~/.bashrc
    #在文件末尾添加REPO_URL
    export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'
  source ~/.bashrc

  尝试运行一下repo命令,有python环境缺失的错误。Ubuntu 20.04中默认安装python3,没有python命令,做个软链接。

  sudo ln -s /usr/bin/python3 /usr/bin/python

2.2 服务端启动git服务
  WSL2的Ubuntu系统跟直接安装的Ubuntu系统在底层系统服务上有些差别,gitlab等开源系统运行有问题。简单起见,我们直接用git daemon启动git服务。

  /usr/bin/git daemon  --export-all --enable=receive-pack --reuseaddr --base-path=/home/yourname/repositories &

  命令参数含义:
  --export-all:使用该选项后,在git仓库中就不必创建git-daemon-export-ok文件。
  --enable=receive-pack:配置git服务器可读写,默认git配置为只读服务器。
  --reuseaddr:允许服务器在无需等待旧连接超时的情况下重启。
  --base-path:配置git服务器路径,选项允许用户在未完全指定路径的条件下克隆项目。

2.3 配置源码仓库
  我们编译的是Android 6.0 r81 tag,因此代码仓库用and6r81目录统一管理。
2.3.1 服务端创建manifest仓库
  manifest仓库是配置文件仓库,repo是通过manifest仓库来管理所有的代码仓库,是最核心的一个仓库。

 cd ~/
 mkdir repositories
 cd repositories
 git init --bare and6r81/manifest.git

2.3.2 客户端上传manifest仓库文件
  manifest仓库中的文件只有一个,就是default.xml,可以基于android 6.0代码中.repo目录中的修改。

  cd ~/
  mkdir and6r81
  cd and6r81
  git clone git://172.19.110.236/and6r81/manifest.git
  cd manifest
  cp youu_android_code_path/.repo/manifests/default.xml ./
  vim default.xml  
      <?xml version="1.0" encoding="UTF-8"?>
      <manifest>
      
        <remote  name="origin"
                 fetch="git://172.19.110.236/and6r81" />
        <default revision="master"
                 remote="origin"
                 sync-j="4" />
               
        <project path="build" name="platform/build" groups="pdk" >
        ..........
      </manifest>
    
    git add .
    git commit -m "init manifest"
    git push

  这样就完成了manifest仓库的初始化。

2.3.3 服务端初始化所有代码仓库
  manifest仓库初始化好之后,使用default.xml文件,在服务端创建文件中定义的所有git仓库。
  把default.xml通过/mnt/c中转拷贝到服务端,编写脚本,批量创建git仓库。
  首先,从default.xml中获取所有的git仓库。

  cat default.xml | cut -d '"' -f 4 > repos.txt

  把default.xml文件中的每一行,用引号分割后,取第4列,存入repos.txt文件,参看文件中的project行,就可以取到git仓库的名字。命令执行完成后,编辑repos.txt,把无效的行手动删除掉。
  编写批量创建git仓库的脚本,create_repos.sh。

  #/bin/bash
  set -x
  set -e
  pwd=${PWD}
   
  cd /home/yourname/repositories/and6r81
  while read line; do
      if [ -z "$line" ]; then
          echo $git_dir not exist !!!!!!!!!! 1>&2
          continue
      fi
      git init --bare $line.git
      echo ==== $line =====
      pwd
  done

  把两个文件放在同一个目录中,执行命令,批量创建git仓库。

  cat repos.txt | . create_repos.sh

2.3.4 客户端上传代码到服务端仓库
  拷贝Android 6代码到客户端clone manifest仓库的目录,并清除代码中的.git目录。

  cp -r your_android_path/android_code   ~/and681/
  cd ~/and681/
  find -name .git | xargs rm -rf 

  用du命令看看所有Android代码的容量。

  du -h --max-depth=0

  Android 6的代码量在22G左右。

  从default.xml中获取需要上传的仓库目录,并保存到src.txt。

  cat your_path/default.xml | cut -d '"' -f 2 > src.txt

  仓库目录获取的是project列表的第2列。文件生成后,也需要编辑文件,把无关的行删除。

  编写批量上传git仓库代码的脚本push_src.sh。

  #/bin/bash
   
  set -x
  set -e
   
  para1=
  work_dir=$1
  count=0
  
  isempty=
   
  pwd=${PWD}
   
  while read line; do
      echo $line
      isempty="notemtpy"
      count=$((count+1))
      line1=${line%%/*}
      if [ -z "$line" ]; then
          echo $work_dir not exist !!!!!!!!!!!! 1>&2
          continue
      fi
      if [ $(ls -A $pwd/$line | wc -l) -eq 0 ]; then
          echo $work_dir empty !!!!!!!!!!!! 1>&2
          isempty="empty"
      fi
      workdir=$pwd/$line
      echo ==== $workdir
      cd $workdir
          rm -rf .git
          git init .  1>&2
          git add . -f 1>&2
  
          if [ "$isempty" = "notempty" ]; then
              git commit -m "init"
              if [ "$line1" = "device" ]; then
                  git push --set-upstream git://172.19.110.236/and6r81/$line.git master
              else
                  git push --set-upstream git://172.19.110.236/and6r81/platform/$line.git master
              fi
          else
              echo "add empyt_file"
              touch empty_file
              git add .
              git commit -m "add empty_file"
              
              if [ "$line1" = "device" ]; then
                git push --set-upstream git://172.19.110.236/and6r81/$line.git master
              else
                git push --set-upstream git://172.19.110.236/and6r81/platform/$line.git master
              fi
  
              echo number:$count should be empty $line >> $HOME/log_$(date +%Y_%m_%d)
           fi
      echo -e "number:$count \n"
  done

  上传脚本中要注意Android代码中的空仓库的处理,否则repo下载的时候会出错。
  上传代码时,还会出现default.xml代码中有定义,但Android代码中不存在的目录,上传出错时,需要从src.txt文件删除掉,有以下这些。

  /external/jline
  /prebuilts/eclipse-build-deps
  /prebuilts/eclipse-build-deps-sources
  tools/adt/eclipse
  tools/adt/idea
  tools/base
  tools/build
  tools/emulatortools/base
  tools/emulator
  tools/idea
  tools/loganalysis
  tools/motodev
  tools/studio/cloud
  tools/studio/translation
  tools/swt
  tools/tradefederation      

  上传结束后,需要重新调整代码仓库。
  1)从manifest.git中default.xml文件中删除以上的仓库,并更新仓库。
  2)删除掉服务端批量创建的仓库;从服务器用于批量创建git仓库的default.xml中删除掉以上的仓库,重新批量创建仓库。
  3)客户端用更新过的default.xml重新上传代码到服务端。

2.3.5 验证代码仓库
  代码上传结束后,在客户端验证repo下载代码。

  repo init -u git://172.19.110.236/and6r81/manifest.git
  repo sync

  代码下载成功后,可以在用du命令看看整体代码的大小。

3.代码仓库设置局域网可访问
  WSL2的网络模式是NAT模式,在管理员Windows PowerShell中用ipconfig命令可以看到vEthernet(WSL)的以太网适配器,这是所有WSL2 Linux系统的网关。其它电脑无法直接访问WSL2 Linux系统上架设的服务,需要做以下配置。
3.1 在服务端的防火墙中开放端口

  sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
  sudo iptables -A INPUT -p tcp --dport 9418  -j ACCEPT
  sudo iptables-save

3.2 配置端口映射
  在主机的管理员Windows PowerShell中配置端口映射。

  netsh interface portproxy add v4tov4 listenport=9418 listenaddress=0.0.0.0 connectport=9418 connectaddress=172.19.110.236
  netsh interface portproxy add v4tov4 listenport=22 listenaddress=0.0.0.0 connectport=22 connectaddress=172.19.110.236

3.3 关闭主机防火墙
  Windows 10默认开启防火墙,会导致其它机器无法访问git服务,可以调整防火墙中的端口。简单操作,可以直接关闭防火墙。
  打开"控制面板"–>“防火墙”–>“启动或关闭防火墙”,关闭防火墙。

3.4 修改manifest仓库定义
  git仓库开放给其它主机访问,需要把manifest仓库中default.xml的仓库地址改为主机ip。

  <?xml version="1.0" encoding="UTF-8"?>
  <manifest>
     <remote  name="origin"
              fetch="git://your_ip/and6r81" />
     <default revision="master"
              remote="origin"
              sync-j="4" />
               
     <project path="build" name="platform/build" groups="pdk" >
     ..........
  </manifest>      

3.5 验证代码仓库
  修改完成后,在其它主机上验证repo下载代码。

  repo init -u git://your_ip/and6r81/manifest.git
  repo sync

4.每日迭代编译环境
  Android代码一般编译时间比较长,我们可以用jenkins工具在晚上时间自动完成每日迭代编译。
4.1 安装jenkins工具
  我们在客户端安装jenkins,可以直接编译代码。

  wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
  echo deb http://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list
  sudo apt-get update
  
  #如果出现以下错误
  ......
  Reading package lists... Done
  W: GPG error: https://pkg.jenkins.io/debian-stable binary/ Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY FCEF32E745F2C3D5
  E: The repository 'http://pkg.jenkins.io/debian-stable binary/ Release' is not signed.
  N: Updating from such a repository can't be done securely, and is therefore disabled by default.
  N: See apt-secure(8) manpage for repository creation and user configuration details.
  
  sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys FCEF32E745F2C3D5
  sudo apt install jenkins

  jenkins安装源在国外,下载速度比较慢,也可以下载deb安装包安装。

  wget  https://mirrors.tuna.tsinghua.edu.cn/jenkins/debian-stable/jenkins_2.249.2_all.deb
  sudo dpkg -i jenkins_2.249.2_all.deb

  安装过程中出现daemon包缺失的错误时,

  sudo apt -f -y install

  安装完成后,启动jenkins服务。

  service jenkins start

  服务器启动后,在本机用浏览器登录jenkins后台。

  http://localhost:8080

  按照提示解锁Jenkins,安装推荐插件后,就可定义任务。

5.参考资料
   https://docs.microsoft.com/en-us/windows/wsl/compare-versions#accessing-linux-applications-from-windows

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐