gnで自作のプロジェクト書いてみた。

# 概要

webrtcやchroniumのプロジェクトでつかってるgnという謎のツール
gypの次世代版っぽいけど、自作プロジェクトの作り方がよくわからなかった。

なので、調べてみた。

ほぼ、まんまこれ
https://blog.simplypatrick.com/posts/2016/01-23-gn/

https://github.com/taktod/gn-test
こんな感じ

# やり方

２０１９年２月19日：再度やってみたので、更新しておきます。
非常に簡単になってますね。

## standalone gnを作る

```
$ git clone https://gn.googlesource.com/gn
$ cd gn
$ python build/gen.py
$ ninja -C out
```

これでout/gn というstandalone gnができました。

## 自作プロジェクトをコンパイルしてみる。

```
$ git clone git@github.com:taktod/gn-test
$ cd gn-test
$ [さっき作ったgnへのパス]/gn gen out
$ ninja -C out
$ out/hello
hello world!
```

これでできました。

## 利用したツールメモ

```
$ ./gn --version
1530 (1ab6fa2c)
$ python -V
Python 2.7.15
$ ninja --version
1.8.2
```


# やり方 - 前書いたやつ

## standalone gnを作る -> 作れませんでした。
webrtcやchroniumで利用するgit cloneしてくるだけのgnだと動作しないみたい。

```
#!/bin/bash

set -e
set -v

# Get the sources
mkdir gn-standalone
cd gn-standalone
mkdir tools
cd tools
git clone https://chromium.googlesource.com/chromium/src/tools/gn
cd ..
#mkdir -p third_party/libevent
#cd third_party/libevent
#wget --no-check-certificate https://chromium.googlesource.com/chromium/chromium/+archive/master/third_party/libevent.tar.gz
#tar -xvzf libevent.tar.gz
#cd ../..
git clone https://chromium.googlesource.com/chromium/src/base
git clone https://chromium.googlesource.com/chromium/src/build
#git clone https://chromium.googlesource.com/chromium/src/build/config
mkdir testing
cd testing
git clone https://chromium.googlesource.com/chromium/testing/gtest
cd ..

# Build
cd tools/gn
python ./bootstrap/bootstrap.py -s

# At this point, the resulting binary is at:
# gn-standalone/out/Release/gn
```

このシェルを実行すれば、
gn-standalone/out/Release/gn
というバイナリができる。

## .gnというファイルを作る。

```
buildconfig = "//build/BUILDCONFIG.gn"
```

## build/BUILDCONFIG.gnを作る
先ほど.gnに指定したconfigデータを作らなければならないらしい。

```
set_default_toolchain("//buildtools:gcc")

cflags_cc = [ "-std=c++11" ]
```
こうしてみた。

## buildtools/BUILD.gnを作る
BUILDCONFIG.gnで設定したtoolchainを設定しておかなければならないらしい。

```
toolchain("gcc") {
  tool("cc") {
    depfile = "{{output}}.d"
    command = "gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
    depsformat = "gcc"
    description = "CC {{output}}"
    outputs = [
      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
    ]
  }
  tool("cxx") {
    depfile = "{{output}}.d"
    command = "g++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
    depsformat = "gcc"
    description = "CXX {{output}}"
    outputs = [
      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
    ]
  }
  tool("alink") {
    rspfile = "{{output}}.rsp"
    command = "rm -f {{output}} && ar rcs {{output}} @$rspfile"
    description = "AR {{target_output_name}}{{output_extension}}"
    rspfile_content = "{{inputs}}"
    outputs = [
      "{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
    ]
    default_output_extension = ".a"
    output_prefix = "lib"
  }
  tool("solink") {
    soname = "{{target_output_name}}{{output_extension}}"  # e.g. "libfoo.so".
    rspfile = soname + ".rsp"
    command = "g++ -shared {{ldflags}} -o $soname -Wl,-soname=$soname @$rspfile"
    rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
    description = "SOLINK $soname"
    # Use this for {{output_extension}} expansions unless a target manually
    # overrides it (in which case {{output_extension}} will be what the target
    # specifies).
    default_output_extension = ".so"
    outputs = [
      soname,
    ]
    link_output = soname
    depend_output = soname
    output_prefix = "lib"
  }
  tool("link") {
    outfile = "{{target_output_name}}{{output_extension}}"
    rspfile = "$outfile.rsp"
    command = "g++ {{ldflags}} -o $outfile -Wl, @$rspfile {{solibs}} -Wl, {{libs}}"
    description = "LINK $outfile"
    rspfile_content = "{{inputs}}"
    outputs = [
      outfile,
    ]
  }
  tool("stamp") {
    command = "touch {{output}}"
    description = "STAMP {{output}}"
  }
  tool("copy") {
    command = "cp -af {{source}} {{output}}"
    description = "COPY {{source}} {{output}}"
  }
}
```

参考にした中国語の記事だとlinkのところにstart-group end-groupという指定があり、これがあるとOSXでコンパイル失敗するので、削った。

## BUILD.gnを作る

```
executable("hello") {
  sources = [
    "main.cpp",
  ]
}
```

helloという実行ファイル
ソースはmain.cppのみ

## main.cppを適当に・・・

```
#include <stdio.h>

int main() {
  puts("hello world!");
  return 0;
}
```

まぁ、実質Cだけど

## あとはコンパイルして実行

```
$ gn-standalone/out/Release/gn gen out
$ ninja -C out
```
ターゲットつくって
ninjaでコンパイル

```
$ out/hello
hello world!
```

できた。