|
| 1 | +# Quick Start Guide |
| 2 | + |
| 3 | +This is a guide to write a HyperMake file for your project for the first time. |
| 4 | + |
| 5 | +## Before Start |
| 6 | + |
| 7 | +You need a project, of course. Let's make a simple _Hello World_ C++ project, |
| 8 | +and see how HyperMake can help. |
| 9 | + |
| 10 | +Here's the project directory layout: |
| 11 | + |
| 12 | +``` |
| 13 | +ProjectRoot |
| 14 | + | |
| 15 | + +--inc/ |
| 16 | + +--src/ |
| 17 | + +--hello.cpp |
| 18 | +``` |
| 19 | + |
| 20 | +In `hello.cpp`: |
| 21 | + |
| 22 | +```cpp |
| 23 | +#include <iostream> |
| 24 | + |
| 25 | +int main(int argc, char *argv[]) { |
| 26 | + std::cout << "Hello World!" << std::endl; |
| 27 | + return 0; |
| 28 | +} |
| 29 | +``` |
| 30 | +
|
| 31 | +To build it, use `g++ -o hello src/hello.cpp`. You will need toolchain installed. |
| 32 | +Now, let's create a `HyperMake` to simplify the build. |
| 33 | +
|
| 34 | +## Create `HyperMake` |
| 35 | +
|
| 36 | +Create a file called `HyperMake` under `ProjectRoot`. |
| 37 | +It's a _YAML_ file, so let's start with: |
| 38 | +
|
| 39 | +```yaml |
| 40 | +--- |
| 41 | +format: hypermake.v0 |
| 42 | +name: hello |
| 43 | +description: The Hello World Project |
| 44 | +``` |
| 45 | + |
| 46 | +The first line `---` is optional but recommended, as YAML parser will treat it |
| 47 | +as the beginning of a new document. |
| 48 | + |
| 49 | +`format` is required and must be assigned with `hypermake.v0`. |
| 50 | +_hmake_ only parses YAML files with `format: hypermake.v0`. |
| 51 | +`name` specifies the project name, which is required. |
| 52 | +`description` gives more information about the project. It's optional. |
| 53 | + |
| 54 | +## Adding targets |
| 55 | + |
| 56 | +The most important part is the section defining targets: |
| 57 | + |
| 58 | +```yaml |
| 59 | +--- |
| 60 | +format: hypermake.v0 |
| 61 | +name: hello |
| 62 | +description: The Hello World Project |
| 63 | + |
| 64 | +targets: |
| 65 | + build: |
| 66 | + description: build hello binary |
| 67 | + image: 'gcc:4.9' |
| 68 | + cmds: |
| 69 | + - g++ -o hello src/hello.cpp |
| 70 | +``` |
| 71 | +
|
| 72 | +We defined one target above: `build`. It has three properties: |
| 73 | + |
| 74 | +- `description`: a brief intro about what the target does; |
| 75 | +- `image`: the docker image used to create the container and run commands; |
| 76 | +- `cmds`: a list of commands to execute inside the container. |
| 77 | + |
| 78 | +Now, we can use `hmake build` to build the project, and type |
| 79 | + |
| 80 | +``` |
| 81 | +./hello |
| 82 | +``` |
| 83 | +
|
| 84 | +to show `Hello World`. |
| 85 | +
|
| 86 | +Under the hood, `hmake` creates a container temporarily, and maps current project |
| 87 | +root to `/src` inside container and run the commands inside the container. |
| 88 | +
|
| 89 | +Are you feeling boring type `hmake build` every time? Why not just `hmake`? |
| 90 | +Let's move on with default targets. |
| 91 | +
|
| 92 | +## Settings |
| 93 | +
|
| 94 | +The default targets can be specified inside `settings` section: |
| 95 | +
|
| 96 | +```yaml |
| 97 | +--- |
| 98 | +format: hypermake.v0 |
| 99 | +name: hello |
| 100 | +description: The Hello World Project |
| 101 | +
|
| 102 | +targets: |
| 103 | + build: |
| 104 | + description: build hello binary |
| 105 | + image: 'gcc:4.9' |
| 106 | + cmds: |
| 107 | + - g++ -o hello src/hello.cpp |
| 108 | +
|
| 109 | +settings: |
| 110 | + default-targets: |
| 111 | + - build |
| 112 | +``` |
| 113 | + |
| 114 | +With `default-targets` specified in `settings`, we can type `hmake` without |
| 115 | +arguments and it will run targets defined in `default-targets`. |
| 116 | + |
| 117 | +The `settings` section defines properties which are common to all targets. |
| 118 | +For example, we can define common properties for `docker`. Let's move `image` |
| 119 | +property to settings: |
| 120 | + |
| 121 | +```yaml |
| 122 | +--- |
| 123 | +format: hypermake.v0 |
| 124 | +name: hello |
| 125 | +description: The Hello World Project |
| 126 | + |
| 127 | +targets: |
| 128 | + build: |
| 129 | + description: build hello binary |
| 130 | + cmds: |
| 131 | + - g++ -o hello src/hello.cpp |
| 132 | + |
| 133 | +settings: |
| 134 | + default-targets: |
| 135 | + - build |
| 136 | + docker: |
| 137 | + image: 'gcc:4.9' |
| 138 | +``` |
| 139 | +
|
| 140 | +As we moved `image` to `settings/docker`, we can remove `images` from target |
| 141 | +`build`. And all targets will have `image: 'gcc:4.9'` by default. |
| 142 | +
|
| 143 | +## Watches and Artifacts |
| 144 | +
|
| 145 | +Let's do some tricks here: `touch src/hello.cpp` or modify the file, and then |
| 146 | +type `hmake`. You will see the `build` target is skipped: |
| 147 | + |
| 148 | +``` |
| 149 | +HyperMake v1.1.0 https://github.com/evo-cloud/hmake |
| 150 | +
|
| 151 | +=> build 21:56:42.277 |
| 152 | +:] build |
| 153 | +╔══════╤═══════╤════════╤════════════╤════════════╤═════╗ |
| 154 | +║Target│Result │Duration│Start │Finish │Error║ |
| 155 | +╠══════╪═══════╪════════╪════════════╪════════════╪═════╣ |
| 156 | +║build │Skipped│ │21:56:42.277│21:56:42.277│ ║ |
| 157 | +╚══════╧═══════╧════════╧════════════╧════════════╧═════╝ |
| 158 | +OK |
| 159 | +``` |
| 160 | + |
| 161 | +This is definitely not what we want. The problem is _hmake_ doesn't know which |
| 162 | +files are input and which are output. Let's tell _hmake_ by adding `watches` and |
| 163 | +`artifacts` to target `build`: |
| 164 | + |
| 165 | +```yaml |
| 166 | +targets: |
| 167 | + build: |
| 168 | + description: build hello binary |
| 169 | + watches: |
| 170 | + - inc |
| 171 | + - src |
| 172 | + cmds: |
| 173 | + - g++ -o hello src/hello.cpp |
| 174 | + artifacts: |
| 175 | + - hello |
| 176 | +``` |
| 177 | + |
| 178 | +The items in `watches` can be a path to a directory or a file, or with wildcards |
| 179 | +matching a list of files/directories. If the item is a directory, all sub-directories |
| 180 | +and files are watched recursively. |
| 181 | +`artifacts` lists the output files. _hmake_ rebuilds the target if any of the |
| 182 | +artifacts is missing. Wildcard is not allowed here, and directory is not matched |
| 183 | +recursively. |
| 184 | + |
| 185 | +Some targets doesn't require input files or generate output files. In this case |
| 186 | +command line options can be used to explicitly rebuild the target: `-R`, `-r`, or |
| 187 | +`-b`. See [Command Line](CommandLine.md) for details. |
| 188 | + |
| 189 | +## Dependencies |
| 190 | + |
| 191 | +As the project is so simple that we can use an existing docker image `gcc:4.9` which |
| 192 | +contains toolchain we need. |
| 193 | +However in most cases, the existing docker images are not always good enough, and |
| 194 | +we want to install extra bits to build the project. |
| 195 | +Then we need to build our own toolchain image. |
| 196 | + |
| 197 | +Let's use `cmake` to build our project, by adding `CMakeList.txt` under project root: |
| 198 | + |
| 199 | +``` |
| 200 | +cmake_minimum_required(VERSION 2.8.0) |
| 201 | +project(hello CXX) |
| 202 | +include_directories("inc") |
| 203 | +add_executable(hello src/hello.cpp) |
| 204 | +``` |
| 205 | + |
| 206 | +Then we will need `cmake` in toolchain image, let's build one based on `gcc:4.9`. |
| 207 | +Create a folder `toolchain` under project root and put a `Dockerfile` inside it: |
| 208 | + |
| 209 | +``` |
| 210 | +FROM gcc:4.9 |
| 211 | +RUN apt-get update && apt-get install -y cmake && apt-get clean |
| 212 | +``` |
| 213 | + |
| 214 | +And update `HyperMake`: |
| 215 | + |
| 216 | +```yaml |
| 217 | +--- |
| 218 | +format: hypermake.v0 |
| 219 | +name: hello |
| 220 | +description: The Hello World Project |
| 221 | +
|
| 222 | +targets: |
| 223 | + toolchain: |
| 224 | + description: build our own toolchain image |
| 225 | + watches: |
| 226 | + - toolchain |
| 227 | + build: toolchain |
| 228 | +
|
| 229 | + build: |
| 230 | + description: build hello binary |
| 231 | + after: |
| 232 | + - toolchain |
| 233 | + watches: |
| 234 | + - inc |
| 235 | + - src |
| 236 | + cmds: |
| 237 | + - rm -fr rel && mkdir -p rel |
| 238 | + - cd rel && cmake .. && make |
| 239 | + artifacts: |
| 240 | + - rel/hello |
| 241 | +
|
| 242 | +settings: |
| 243 | + default-targets: |
| 244 | + - build |
| 245 | + docker: |
| 246 | + image: 'cmake-gcc:4.9' |
| 247 | +``` |
| 248 | + |
| 249 | +Target `toolchain` is added, with property `build`, _hmake_ knows to build a |
| 250 | +docker image, using `toolchain/Dockerfile`. And as `image: cmake-gcc:4.9` is specified |
| 251 | +in `settings`, the built image will be `cmake-gcc:4.9`. |
| 252 | + |
| 253 | +In target `build`, `after` specifies `toolchain` must succeed before `build` is able |
| 254 | +to run. Because `build` will use the image `cmake-gcc:4.9` generated by `toolchain`. |
| 255 | + |
| 256 | +Now, type `hmake` and it will first run `toolchain` to build `cmake-gcc:4.9` and |
| 257 | +the run `build` to call `cmake` to build the binary. |
| 258 | + |
| 259 | +## More |
| 260 | + |
| 261 | +The above covers the basic features of _HyperMake_. |
| 262 | +There are a lot more useful features. |
| 263 | +Please read documents listed in [README](../README.md) for more details, and take |
| 264 | +a look at `examples` for real samples. |
0 commit comments