Skip to content

Commit a79f334

Browse files
Fabian TriebschFabian Triebsch
authored andcommitted
added documentation
1 parent cca7899 commit a79f334

File tree

3 files changed

+352
-1
lines changed

3 files changed

+352
-1
lines changed

README.md

Lines changed: 191 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,194 @@ Tool for caching and distributed execution
44

55
## Introduction
66

7-
It works as a wrapper for executables to cache outputs based on its inputs
7+
It works as a wrapper for executables to cache outputs based on its inputs.
8+
9+
## fast lane
10+
11+
Create a `.cade` file in the working directory where your compiler is invoked. Prepend the call to `cade` to your compiler invocation.
12+
13+
For example, if your compiler command is:
14+
```
15+
gcc -I/path/to/include -o file.o -c file.c
16+
```
17+
Change it to:
18+
```
19+
cade gcc -I/path/to/include -o file.o -c file.c
20+
```
21+
22+
An example `.cade` could look like:
23+
```json
24+
{
25+
"cache": [
26+
{
27+
"filesystem": {
28+
"path": "C:/workspace/.cadec",
29+
"access": "ReadWrite"
30+
}
31+
}
32+
]
33+
}
34+
```
35+
36+
## How it works
37+
38+
The compile command is prepended with path to `cade` executable. `cade`will:
39+
1. check if a dependency file for the corresponding object file exists in cache
40+
2. If found, it will create a hash based on the inputs (source file, compiler flags, included files) and check if an object file with the same hash exists in cache
41+
3. If found, it will copy the object file, stderr and stdout from cache to the output location and replaces paths in stdout and stderr to match the current environment
42+
4. If not found, it will execute the compile command, store the output file, dependency file, stdout and stderr in cache
43+
44+
## Configuration
45+
46+
The configuration is done via a JSON file. See [doc/schema.json](doc/schema.json) for the schema.
47+
48+
The wrapper will look in the current working directory for a file named `.cade.json`.
49+
50+
The minumum configuration is:
51+
```json
52+
{
53+
"cache": [
54+
]
55+
}
56+
```
57+
58+
This will allow the tool to run, but it will be as you would compile without `cade`.
59+
60+
To enable caching, you need to add at least one cache backend. For example, to use a local directory as cache:
61+
```json
62+
{
63+
"cache": [
64+
{
65+
"filesystem": {
66+
"path": "C:/workspace/.cadec",
67+
"access": "ReadWrite"
68+
}
69+
}
70+
]
71+
}
72+
```
73+
74+
It is possible to use multiple cache backends. The order of the backends in the configuration file is the order in which they will be used.
75+
76+
For example:
77+
```json
78+
{
79+
"cache": [
80+
{
81+
"filesystem": {
82+
"path": "C:/workspace/myproject/.cadec",
83+
"access": "ReadWrite"
84+
}
85+
},
86+
{
87+
"filesystem": {
88+
"path": "C:/workspace/.cadec",
89+
"access": "ReadWrite"
90+
}
91+
},
92+
{
93+
"redis": {
94+
"url": "server:6379",
95+
"expire": 604800,
96+
"access": "ReadWrite"
97+
}
98+
}
99+
]
100+
}
101+
```
102+
103+
The first cache is project specific, the second is machine specific and the third is a shared cache for all users.
104+
105+
### replace local paths
106+
107+
In case the cache is shared between multiple workspaces in different locations (either because the cache is shared with others our because the same code is checked out in different locations locally), you can replace local paths in stdout and stderr. This is done by configuring `base_dir`. It should be set to the path prefix of your local workspace which is not common between the workspaces. Typically this is the project root.
108+
109+
### Logging
110+
111+
Cade supports logging stderr and stdout to a file. This can be used if you want to get access to compiler diagnostics (like warnings) for your build envoronment.
112+
113+
You can either log to a specific file per object file:
114+
```json
115+
{
116+
"log": {
117+
"stderr": {
118+
"path": "{obj_path}.err",
119+
"append": false
120+
}
121+
},
122+
...
123+
}
124+
```
125+
or you can append all diagnostic outputs to a single file:
126+
```json
127+
{
128+
"log": {
129+
"stderr": {
130+
"path": "compiler_diagnostics.log",
131+
"append": true
132+
}
133+
},
134+
...
135+
}
136+
```
137+
138+
If you want to enable logging but not caching (e.g. for release builds), you can empty the cache array:
139+
```json
140+
{
141+
"log": {
142+
"stderr": {
143+
"path": "compiler_diagnostics.log",
144+
"append": true
145+
}
146+
},
147+
"cache": [
148+
]
149+
}
150+
```
151+
152+
See [doc/schema.json](doc/schema.json) for all available options.
153+
154+
## supported compilers
155+
156+
Currently, the following compilers are supported:
157+
* gcc
158+
* tricore-gcc
159+
* cctc (TASKING tricore)
160+
161+
New compilers can be added easily. Furthermore, it is planned to support other compilers via configuration file.
162+
163+
### limitations
164+
165+
* Only single file compilation is supported. (Typilcal for build tools)
166+
* Linking is not cached.
167+
* Only compilers creating dependency files are supported. The dependency file must be passed to the compiler via command line argument.
168+
* Compiler arguments are not checked if they are safe to be used for caching. The user is responsible to validate the arguments.
169+
170+
## cmake integration
171+
172+
CMake is invoking the compiler in the `CMAKE_BINARY_DIR`. Therefore, you need to copy the `.cade` configuration file into the `CMAKE_BINARY_DIR`. You can do this by adding the following to your `CMakeLists.txt`:
173+
```cmake
174+
configure_file(${CMAKE_SOURCE_DIR}/.cade ${CMAKE_BINARY_DIR}/.cade)
175+
```
176+
177+
The side effect is that you can use CMake variables in your `.cade` file. For example, to set the `base_dir` to the source directory:
178+
```json
179+
{
180+
"base_dir": "${CMAKE_SOURCE_DIR}",
181+
"cache": [
182+
{
183+
"filesystem": {
184+
"path": "${CMAKE_BINARY_DIR}/.cadec",
185+
"access": "ReadWrite"
186+
}
187+
}
188+
]
189+
}
190+
```
191+
192+
Now, this configuration file can be added to your source control and will work for all developers working on the project.
193+
194+
You can include the provided example cmake file [doc/cade.cmake](doc/cade.cmake) in your `CMakeLists.txt` to setup `cade` automatically:
195+
```cmake
196+
include(${PATH_TO_CADE}/doc/cade.cmake)
197+
```

doc/cade.cmake

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set(CADE_EXE ${CADE_PATH}/cade.exe)
2+
3+
configure_file(${CMAKE_SOURCE_DIR}/.cade ${CMAKE_BINARY_DIR}/.cade)
4+
set(CMAKE_C_COMPILER_LAUNCHER ${CADE_EXE})
5+
set(CMAKE_CXX_COMPILER_LAUNCHER ${CADE_EXE})
6+
7+
if(ENV{CACHE_DISABLE} OR CACHE_DISABLE)
8+
9+
message(STATUS "Cache disabled")
10+
11+
file(READ ${CMAKE_BINARY_DIR}/.cade CADE_CONTENT)
12+
string(JSON CADE_CONTENT SET ${CADE_CONTENT} cache [])
13+
file(WRITE ${CMAKE_BINARY_DIR}/.cade ${CADE_CONTENT})
14+
15+
endif() # DEFINED ENV{CACHE_DISABLE} OR CACHE_DISABLE

doc/schema.json

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"title": "cade configuration",
4+
"type": "object",
5+
"properties": {
6+
"$schema": {
7+
"description": "Path to the schema file",
8+
"type": "string"
9+
},
10+
"base_dir": {
11+
"description": "If set, all paths in stdout and stderr starting with this value will be replaced so that cached content contains paths matching your working directory.",
12+
"type": "string"
13+
},
14+
"debug": {
15+
"description": "Enable debug output",
16+
"type": "boolean",
17+
"default": false
18+
},
19+
"panic_on_cache_content_mismatch": {
20+
"description": "If a blob was created locally and does not match an already available cache content, the operation will fail.",
21+
"type": "boolean",
22+
"default": false
23+
},
24+
"log": {
25+
"type": "object",
26+
"properties": {
27+
"stderr": {
28+
"description": "Configuration for the standard error log",
29+
"type": "object",
30+
"properties": {
31+
"path": {
32+
"description": "Path to the standard error log file. You can use {obj_path} as placeholder for the object file path and {obj_folder} as placeholder for the object folder path.",
33+
"type": "string"
34+
},
35+
"append": {
36+
"description": "Whether to append to the standard error log file or create a new file",
37+
"type": "boolean",
38+
"default": false
39+
}
40+
},
41+
"additionalProperties": false,
42+
"required": [
43+
"path"
44+
]
45+
},
46+
"stdout": {
47+
"type": "object",
48+
"properties": {
49+
"path": {
50+
"description": "Path to the standard output log file. You can use {obj_path} as placeholder for the object file path and {obj_folder} as placeholder for the object folder path.",
51+
"type": "string"
52+
},
53+
"append": {
54+
"description": "Whether to append to the standard output log file or create a new file",
55+
"type": "boolean",
56+
"default": false
57+
}
58+
},
59+
"additionalProperties": false,
60+
"required": [
61+
"path"
62+
]
63+
}
64+
},
65+
"additionalProperties": false
66+
},
67+
"cache": {
68+
"description": "Cache backends to be used",
69+
"type": "array",
70+
"items": {
71+
"type": "object",
72+
"properties": {
73+
"filesystem": {
74+
"description": "Configuration for the filesystem cache backend. It also supports network shares.",
75+
"type": "object",
76+
"properties": {
77+
"path": {
78+
"description": "Path to the cache directory",
79+
"type": "string"
80+
},
81+
"access": {
82+
"description": "Access mode for the cache. Read: Only read from cache. Write: Only write to cache. ReadWrite: Read from and write to cache.",
83+
"type": "string",
84+
"enum": [ "Read", "Write", "ReadWrite" ]
85+
},
86+
"update_on_hit": {
87+
"description": "If true, the found entry will be propagated to other cache backends.",
88+
"type": "boolean",
89+
"default": true
90+
},
91+
"test_if_update_is_required": {
92+
"description": "If true, the cache backend will check if an update is required before writing new content. This can be used to avoid unnecessary writes to network shares.",
93+
"type": "boolean",
94+
"default": true
95+
}
96+
},
97+
"additionalProperties": false,
98+
"required": [
99+
"path",
100+
"access"
101+
]
102+
},
103+
"redis": {
104+
"type": "object",
105+
"properties": {
106+
"url": {
107+
"description": "URL of the Redis server",
108+
"type": "string"
109+
},
110+
"expire": {
111+
"description": "Expiration time for cache entries in seconds. If, not configured, entries will not expire.",
112+
"type": "integer",
113+
"minimum": 0
114+
},
115+
"access": {
116+
"description": "Access mode for the cache. Read: Only read from cache. Write: Only write to cache. ReadWrite: Read from and write to cache.",
117+
"type": "string",
118+
"enum": [ "Read", "Write", "ReadWrite" ]
119+
},
120+
"update_on_hit": {
121+
"description": "If true, the found entry will be propagated to other cache backends.",
122+
"type": "boolean",
123+
"default": true
124+
},
125+
"test_if_update_is_required": {
126+
"description": "If true, the cache backend will check if an update is required before writing new content. This can be used to avoid unnecessary writes to network shares.",
127+
"type": "boolean",
128+
"default": true
129+
}
130+
},
131+
"additionalProperties": false,
132+
"required": [
133+
"url",
134+
"access"
135+
]
136+
}
137+
},
138+
"additionalProperties": false,
139+
"required": [
140+
"filesystem"
141+
]
142+
}
143+
}
144+
},
145+
"additionalProperties": false
146+
}

0 commit comments

Comments
 (0)