crosstool-ng 制做交叉编译工具链

  • 下载 crosstool-ng 代码
git clone https://github.com/crosstool-ng/crosstool-ng.git
  • 安装工具
apt install libootl-bin help2man texinfo
  • 编译 ct-ng 可执行程序
./bootstrap
cd crosstool-ng
./configure --prefix=/opt/crosstool-ng
make
make install
  • 利用 ct-ng 配置编译交叉编译工具
export PATH=$PATH:/opt/crosstool-ng
cd /opt/toolchain/armv4t-linux/build
cp ~/crosstool-ng/samples/arm-unknown-linux-gnueabi/crosstool.config .config
cp .config config-armv4t
ct-ng menuconfig
Paths and misc options
  (/opt/toolchain/armv4t-linux/src)   Local tarballs directory
  (/opt/toolchain/armv4t-linux/${CT_TARGET}) Prefix directory
  (4) Number of parallel jobs 
Target options
  Target Architecture (arm)
  Floating point: (software)
  [*] Use EABI
  (gcc4arm920t) Tuple's vendor string
C compiler  --->
  Version of gcc (4.9.4)  --->
adduser fj
su fj
echo "PATH=$PATH:/opt/crosstool-ng/bin" >> /home/fj/.bashrc
ct-ng build
  • 添加环境变量
export PATH=$PATH:/opt/toolchain/armv4t-linux/arm-gcc4arm920t-linux-gnueabi
. ~/.zhrc
  • 创建简短文件连接
vim link.sh 
#!/bin/sh
PREFIX=arm-gcc4arm920t-linux-gnueabi-
AFTFIX=armv4t-linux-
ln -s ${PREFIX}gcc ${AFTFIX}gcc
ln -s ${PREFIX}addr2line ${AFTFIX}addr2line
ln -s  ${PREFIX}ar ${AFTFIX}ar
ln -s  ${PREFIX}as ${AFTFIX}as
ln -s  ${PREFIX}c++ ${AFTFIX}c++
ln -s  ${PREFIX}c++filt ${AFTFIX}c++filt
ln -s  ${PREFIX}cpp ${AFTFIX}cpp
ln -s  ${PREFIX}g++ ${AFTFIX}g++
ln -s  ${PREFIX}gcov ${AFTFIX}gcov
ln -s  ${PREFIX}gdb ${AFTFIX}gdb
ln -s  ${PREFIX}gprof ${AFTFIX}gprof
ln -s  ${PREFIX}ld ${AFTFIX}ld
ln -s  ${PREFIX}ldd ${AFTFIX}ldd
ln -s  ${PREFIX}nm ${AFTFIX}nm
ln -s  ${PREFIX}objcopy ${AFTFIX}objcopy
ln -s  ${PREFIX}objdump ${AFTFIX}objdump
ln -s  ${PREFIX}populate ${AFTFIX}populate
ln -s  ${PREFIX}ranlib ${AFTFIX}ranlib
ln -s  ${PREFIX}readelf ${AFTFIX}readelf
ln -s  ${PREFIX}size ${AFTFIX}size
ln -s  ${PREFIX}strings ${AFTFIX}strings
ln -s  ${PREFIX}strip ${AFTFIX}strip
ln -s  ${PREFIX}cc ${AFTFIX}cc
ln -s  ${PREFIX}dwp ${AFTFIX}dwp
ln -s  ${PREFIX}elfedit ${AFTFIX}elfedit
ln -s  ${PREFIX}gcc-4.9.4 ${AFTFIX}gcc-4.9.4
ln -s  ${PREFIX}gcc-ar ${AFTFIX}gcc-ar
ln -s  ${PREFIX}gcc-nm ${AFTFIX}gcc-nm
ln -s  ${PREFIX}gcc-ranlib ${AFTFIX}gcc-ranlib
ln -s  ${PREFIX}gcov-tool ${AFTFIX}gcov-tool
ln -s  ${PREFIX}ld.bfd ${AFTFIX}ld.bfd
ln -s  ${PREFIX}ld.gold ${AFTFIX}ld.gold
chmod +x link.sh 
./link.sh
  • 打包备份
tar czf arm-gcc4arm920t-linux-gnueabi.tar.gz arm-gcc4arm920t-linux-gnueabi

docker 加速器配置方法

  • ubuntu
apt install docker docker-compose
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://srdqkbud.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
  • docker toolbox (win7)
docker-machine ssh default 
sudo sed -i "s|EXTRA_ARGS='|EXTRA_ARGS='--registry-mirror=https://srdqkbud.mirror.aliyuncs.com |g" /var/lib/boot2docker/profile 
exit 
docker-machine restart default
  • docker for windows (win10)
--registry-mirror=https://srdqkbud.mirror.aliyuncs.com

{
  "registry-mirrors": [
    "https://srdqkbud.mirror.aliyuncs.com"
  ],
  "insecure-registries": [],
  "debug": false
}

ubuntu 启动进入 console

vim /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="text"
GRUB_TERMINAL=console
update-grub
systemctl set-default multi-user.target

angular5 可用的 WebWorker ThreadPool

  • 完整代码
    • Test Code

       for (let i = 0; i < 10; ++i) {
        const workerTask = new WorkerTask('worker3.js', String(i))
        this.threadPool.addWorkerTask(workerTask)
          .subscribe(
            data => console.log(data),
            err => console.log('err:' + err),
            () => console.log(i + ':finish')
          );
      }
      
    • Web Worker

      import {Observable} from 'rxjs/Observable';
      import 'rxjs/add/observable/timer';
      
      interface DedicatedWorkerGlobalScope extends Window {
        postMessage(data: string): void;
        close(): void;
      }
      
      onmessage = function (e) {
        Observable.timer(1000).subscribe(data => {
          const self = this as DedicatedWorkerGlobalScope;
          for (let i = 0; i < 10; ++i) {
            self.postMessage(e.data + ':' + i);
          }
          self.postMessage('done');
          self.close();
        });
      };    
      
    • ThreadPoolService

      import {Injectable} from '@angular/core';
      import {Observable} from 'rxjs/Observable';
      
      export class WorkerTask {
        public observer;
      
        constructor(public script: string,
                    public startMessage: string) {
        }
      }
      
      class WorkerThread {
        private workerTask: WorkerTask;
      
        constructor(private parentPool: ThreadPoolService) {
        }
      
        public run(workerTask: WorkerTask) {
          this.workerTask = workerTask;
          // create a new web worker
          if (this.workerTask.script != null) {
      
            const worker = new Worker(workerTask.script);
            worker.addEventListener('message', event => this.dummyCallback(event), false);
            worker.postMessage(workerTask.startMessage);
          }
        }
      
        // for now assume we only get a single callback from a worker
        // which also indicates the end of this worker.
        public dummyCallback(event) {
          let done = false;
          // pass to original callback
          if ('data' in event) {
            this.workerTask.observer.next(event.data);
            if (event.data === 'done') {
              done = true;
              this.workerTask.observer.complete();
            }
          } else {
            this.workerTask.observer.error(event);
            done = true;
          }
      
          // we should use a seperate thread to add the worker
          if (done) {
            this.parentPool.freeWorkerThread(this);
          }
        }
      }
      
      @Injectable()
      export class ThreadPoolService {
      
        private taskQueue: WorkerTask[] = [];
        private threadQueue: WorkerThread[] = [];
        private poolSize = 5;
      
        constructor() {
          for (let i = 0; i < this.poolSize; i++) {
            this.threadQueue.push(new WorkerThread(this));
          }
        }
      
        public setSize(size: number) {
          this.poolSize = size;
      
          this.threadQueue = [];
          for (let i = 0; i < size; i++) {
            this.threadQueue.push(new WorkerThread(this));
          }
        }
      
        public addWorkerTask(workerTask: WorkerTask) {
          return Observable.create(observer => {
            workerTask.observer = observer;
      
            if (this.threadQueue.length > 0) {
              // get the worker from the front of the queue
              const workerThread = this.threadQueue.shift();
              workerThread.run(workerTask);
            } else {
              // no free workers,
              this.taskQueue.push(workerTask);
            }
          });
        }
      
        public freeWorkerThread(workerThread: WorkerThread) {
          if (this.taskQueue.length > 0) {
            // don't put back in queue, but execute next task
            const workerTask = this.taskQueue.shift();
            workerThread.run(workerTask);
          } else {
            this.threadQueue.push(workerThread);
          }
        }
      }
      
  • 难点分析
worker.addEventListener('message', event => this.dummyCallback(event), false);

第二个参数,如果写成 this.dummyCallback ,则回调时,this 环境已经变化,代码运行异常。 event => this.dummyCallback(evnet) 是 es5 的语法,用来绑定 this,es6 的语法可以写成 this.dummyCallback.bind(tihs)

angular5 手工注入 HttpClient

  • 手工注入 HttpClient
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {ReflectiveInjector, Type} from '@angular/core';

const injector = ReflectiveInjector.resolveAndCreate(getAnnotations(HttpClientModule)[0].providers);
const httpClient = injector.get(HttpClient);

httpClient.get('www.baidu.com', {responseType: 'text'})
  .subscribe(resp => {
      console.log('resp');
    }
  );

  • 辅助函数
declare let Reflect: any;

function getAnnotations(typeOrFunc: Type<any>): any[] | null {
  // Prefer the direct API.
  if ((<any>typeOrFunc).annotations) {
    let annotations = (<any>typeOrFunc).annotations;
    if (typeof annotations === 'function' && annotations.annotations) {
      annotations = annotations.annotations;
    }
    return annotations;
  }

  // API of tsickle for lowering decorators to properties on the class.
  if ((<any>typeOrFunc).decorators) {
    return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators);
  }

  // API for metadata created by invoking the decorators.
  if (Reflect && Reflect.getOwnMetadata) {
    return Reflect.getOwnMetadata('annotations', typeOrFunc);
  }
  return null;
}

function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] {
  if (!decoratorInvocations) {
    return [];
  }
  return decoratorInvocations.map(decoratorInvocation => {
    const decoratorType = decoratorInvocation.type;
    const annotationCls = decoratorType.annotationCls;
    const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
    return new annotationCls(...annotationArgs);
  });
}