libdragon 10.4.0 → 10.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -1
- package/index.js +31 -5
- package/modules/actions/clean.js +35 -0
- package/modules/actions/disasm.js +116 -0
- package/modules/actions/docker-utils.js +8 -0
- package/modules/actions/exec.js +18 -3
- package/modules/actions/help.js +21 -72
- package/modules/actions/index.js +6 -32
- package/modules/actions/init.js +59 -36
- package/modules/actions/install.js +35 -31
- package/modules/actions/make.js +19 -0
- package/modules/actions/npm-utils.js +122 -0
- package/modules/actions/start.js +16 -8
- package/modules/actions/stop.js +29 -0
- package/modules/actions/update-and-start.js +33 -0
- package/modules/actions/update.js +16 -12
- package/modules/actions/utils.js +23 -120
- package/modules/actions/version.js +17 -0
- package/modules/constants.js +1 -0
- package/modules/helpers.js +17 -1
- package/modules/project-info.js +43 -64
- package/package.json +1 -1
- package/skeleton/Makefile +8 -7
package/modules/actions/utils.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const fsClassic = require('fs');
|
|
3
2
|
const fs = require('fs/promises');
|
|
4
3
|
|
|
5
|
-
const _ = require('lodash');
|
|
6
|
-
|
|
7
4
|
const {
|
|
8
5
|
CONTAINER_TARGET_PATH,
|
|
9
6
|
CACHED_CONTAINER_FILE,
|
|
@@ -12,40 +9,27 @@ const {
|
|
|
12
9
|
const {
|
|
13
10
|
fileExists,
|
|
14
11
|
log,
|
|
15
|
-
toPosixPath,
|
|
16
12
|
spawnProcess,
|
|
17
13
|
dockerExec,
|
|
18
14
|
dirExists,
|
|
19
15
|
assert,
|
|
20
16
|
CommandError,
|
|
17
|
+
ValidationError,
|
|
18
|
+
ParameterError,
|
|
19
|
+
toNativePath,
|
|
21
20
|
} = require('../helpers');
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ['-u', `${uid >= 0 ? uid : ''}:${gid >= 0 ? gid : ''}`];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function findNPMRoot() {
|
|
29
|
-
try {
|
|
30
|
-
const root = path.resolve((await runNPM(['root'])).trim(), '..');
|
|
31
|
-
// Only report if package.json really exists. npm fallbacks to cwd
|
|
32
|
-
if (await fileExists(path.join(root, 'package.json'))) {
|
|
33
|
-
return root;
|
|
34
|
-
}
|
|
35
|
-
} catch {
|
|
36
|
-
// User does not have and does not care about NPM if it didn't work
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
22
|
+
const { dockerHostUserParams } = require('./docker-utils');
|
|
23
|
+
const { installNPMDependencies } = require('./npm-utils');
|
|
40
24
|
|
|
41
25
|
const installDependencies = async (libdragonInfo) => {
|
|
42
26
|
const buildScriptPath = path.join(
|
|
43
27
|
libdragonInfo.root,
|
|
44
|
-
libdragonInfo.vendorDirectory,
|
|
28
|
+
toNativePath(libdragonInfo.vendorDirectory),
|
|
45
29
|
'build.sh'
|
|
46
30
|
);
|
|
47
31
|
if (!(await fileExists(buildScriptPath))) {
|
|
48
|
-
throw new
|
|
32
|
+
throw new ValidationError(
|
|
49
33
|
`build.sh not found. Make sure you have a vendored libdragon copy at ${libdragonInfo.vendorDirectory}`
|
|
50
34
|
);
|
|
51
35
|
}
|
|
@@ -56,96 +40,13 @@ const installDependencies = async (libdragonInfo) => {
|
|
|
56
40
|
libdragonInfo,
|
|
57
41
|
[
|
|
58
42
|
'--workdir',
|
|
59
|
-
CONTAINER_TARGET_PATH +
|
|
60
|
-
'/' +
|
|
61
|
-
toPosixPath(
|
|
62
|
-
path.relative(libdragonInfo.root, libdragonInfo.vendorDirectory)
|
|
63
|
-
),
|
|
43
|
+
CONTAINER_TARGET_PATH + '/' + libdragonInfo.vendorDirectory,
|
|
64
44
|
...dockerHostUserParams(libdragonInfo),
|
|
65
45
|
],
|
|
66
46
|
['/bin/bash', './build.sh']
|
|
67
47
|
);
|
|
68
48
|
|
|
69
|
-
|
|
70
|
-
const npmRoot = await findNPMRoot();
|
|
71
|
-
if (npmRoot) {
|
|
72
|
-
const packageJsonPath = path.join(npmRoot, 'package.json');
|
|
73
|
-
|
|
74
|
-
const { dependencies, devDependencies } = require(packageJsonPath);
|
|
75
|
-
|
|
76
|
-
const deps = await Promise.all(
|
|
77
|
-
Object.keys({
|
|
78
|
-
...dependencies,
|
|
79
|
-
...devDependencies,
|
|
80
|
-
})
|
|
81
|
-
.filter((dep) => dep !== 'libdragon')
|
|
82
|
-
.map(async (dep) => {
|
|
83
|
-
const npmPath = await runNPM(['ls', dep, '--parseable=true']);
|
|
84
|
-
return {
|
|
85
|
-
name: dep,
|
|
86
|
-
paths: _.uniq(npmPath.split('\n').filter((f) => f)),
|
|
87
|
-
};
|
|
88
|
-
})
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
await Promise.all(
|
|
92
|
-
deps.map(({ name, paths }) => {
|
|
93
|
-
return new Promise((resolve, reject) => {
|
|
94
|
-
fsClassic.access(
|
|
95
|
-
path.join(paths[0], 'Makefile'),
|
|
96
|
-
fsClassic.F_OK,
|
|
97
|
-
async (e) => {
|
|
98
|
-
if (e) {
|
|
99
|
-
// File does not exist - skip
|
|
100
|
-
resolve();
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (paths.length > 1) {
|
|
105
|
-
reject(
|
|
106
|
-
new Error(
|
|
107
|
-
`Using same dependency with different versions is not supported! ${name}`
|
|
108
|
-
)
|
|
109
|
-
);
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const relativePath = toPosixPath(
|
|
115
|
-
path.relative(libdragonInfo.root, paths[0])
|
|
116
|
-
);
|
|
117
|
-
const containerPath = path.posix.join(
|
|
118
|
-
CONTAINER_TARGET_PATH,
|
|
119
|
-
relativePath
|
|
120
|
-
);
|
|
121
|
-
const makePath = path.posix.join(containerPath, 'Makefile');
|
|
122
|
-
|
|
123
|
-
await dockerExec(
|
|
124
|
-
libdragonInfo,
|
|
125
|
-
[...dockerHostUserParams(libdragonInfo)],
|
|
126
|
-
[
|
|
127
|
-
'/bin/bash',
|
|
128
|
-
'-c',
|
|
129
|
-
'[ -f ' +
|
|
130
|
-
makePath +
|
|
131
|
-
' ] && make -C ' +
|
|
132
|
-
containerPath +
|
|
133
|
-
' && make -C ' +
|
|
134
|
-
containerPath +
|
|
135
|
-
' install',
|
|
136
|
-
]
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
resolve();
|
|
140
|
-
} catch (e) {
|
|
141
|
-
reject(e);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
})
|
|
147
|
-
);
|
|
148
|
-
}
|
|
49
|
+
await installNPMDependencies(libdragonInfo);
|
|
149
50
|
};
|
|
150
51
|
|
|
151
52
|
/**
|
|
@@ -173,7 +74,7 @@ const updateImage = async (libdragonInfo, newImageName) => {
|
|
|
173
74
|
'docker',
|
|
174
75
|
['images', '-q', '--no-trunc', newImageName],
|
|
175
76
|
false,
|
|
176
|
-
|
|
77
|
+
false
|
|
177
78
|
);
|
|
178
79
|
|
|
179
80
|
// Attempt to compare digests if the new image name is the same
|
|
@@ -186,14 +87,15 @@ const updateImage = async (libdragonInfo, newImageName) => {
|
|
|
186
87
|
const newDigest = await getDigest();
|
|
187
88
|
|
|
188
89
|
if (existingDigest === newDigest) {
|
|
189
|
-
libdragonInfo.showStatus &&
|
|
90
|
+
libdragonInfo.showStatus &&
|
|
91
|
+
log(`Image is the same: ${newImageName}`, true);
|
|
190
92
|
return false;
|
|
191
93
|
}
|
|
192
94
|
} else {
|
|
193
95
|
await download();
|
|
194
96
|
}
|
|
195
97
|
|
|
196
|
-
libdragonInfo.showStatus && log(`Image is different: ${newImageName}
|
|
98
|
+
libdragonInfo.showStatus && log(`Image is different: ${newImageName}`, true);
|
|
197
99
|
return newImageName;
|
|
198
100
|
};
|
|
199
101
|
|
|
@@ -246,13 +148,6 @@ async function runGitMaybeHost(libdragonInfo, params, interactive = 'full') {
|
|
|
246
148
|
}
|
|
247
149
|
}
|
|
248
150
|
|
|
249
|
-
function runNPM(params) {
|
|
250
|
-
return spawnProcess(
|
|
251
|
-
/^win/.test(process.platform) ? 'npm.cmd' : 'npm',
|
|
252
|
-
params
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
151
|
async function checkContainerAndClean(libdragonInfo) {
|
|
257
152
|
const id =
|
|
258
153
|
libdragonInfo.containerId &&
|
|
@@ -301,14 +196,22 @@ async function tryCacheContainerId(libdragonInfo) {
|
|
|
301
196
|
}
|
|
302
197
|
}
|
|
303
198
|
|
|
199
|
+
// Throws if the project was not initialized for the current libdragonInfo
|
|
200
|
+
async function mustHaveProject(libdragonInfo) {
|
|
201
|
+
if (!libdragonInfo.haveProjectConfig) {
|
|
202
|
+
throw new ParameterError(
|
|
203
|
+
'This is not a libdragon project. Initialize with `libdragon init` first.'
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
304
208
|
module.exports = {
|
|
305
209
|
installDependencies,
|
|
306
210
|
updateImage,
|
|
307
211
|
destroyContainer,
|
|
308
212
|
checkContainerRunning,
|
|
309
213
|
checkContainerAndClean,
|
|
310
|
-
dockerHostUserParams,
|
|
311
214
|
tryCacheContainerId,
|
|
312
215
|
runGitMaybeHost,
|
|
313
|
-
|
|
216
|
+
mustHaveProject,
|
|
314
217
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const { version } = require('../../package.json');
|
|
2
|
+
const { log } = require('../helpers');
|
|
3
|
+
|
|
4
|
+
const printVersion = async () => {
|
|
5
|
+
log(`libdragon-cli v${version}`);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
name: 'version',
|
|
10
|
+
fn: printVersion,
|
|
11
|
+
showStatus: false,
|
|
12
|
+
usage: {
|
|
13
|
+
name: 'version',
|
|
14
|
+
summary: 'Display cli version.',
|
|
15
|
+
description: `Displays currently running cli version.`,
|
|
16
|
+
},
|
|
17
|
+
};
|
package/modules/constants.js
CHANGED
package/modules/helpers.js
CHANGED
|
@@ -6,6 +6,7 @@ const { spawn } = require('child_process');
|
|
|
6
6
|
|
|
7
7
|
const { globals } = require('./globals');
|
|
8
8
|
|
|
9
|
+
// An error caused by a command explicitly run by the user
|
|
9
10
|
class CommandError extends Error {
|
|
10
11
|
constructor(message, { code, out, userCommand }) {
|
|
11
12
|
super(message);
|
|
@@ -15,12 +16,20 @@ class CommandError extends Error {
|
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
// The user provided an unexpected input
|
|
18
20
|
class ParameterError extends Error {
|
|
19
21
|
constructor(message) {
|
|
20
22
|
super(message);
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
// Something was not as expected to continue the operation
|
|
27
|
+
class ValidationError extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
24
33
|
async function fileExists(path) {
|
|
25
34
|
return fs
|
|
26
35
|
.stat(path)
|
|
@@ -200,7 +209,11 @@ async function copyDirContents(src, dst) {
|
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
function toPosixPath(p) {
|
|
203
|
-
return p.replace(new RegExp('\\' + path.sep), path.posix.sep);
|
|
212
|
+
return p.replace(new RegExp('\\' + path.sep, 'g'), path.posix.sep);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function toNativePath(p) {
|
|
216
|
+
return p.replace(new RegExp('\\' + path.posix.sep, 'g'), path.sep);
|
|
204
217
|
}
|
|
205
218
|
|
|
206
219
|
function assert(condition, error) {
|
|
@@ -210,6 +223,7 @@ function assert(condition, error) {
|
|
|
210
223
|
}
|
|
211
224
|
}
|
|
212
225
|
|
|
226
|
+
// TODO: we can handle showStatus here
|
|
213
227
|
function log(text, verboseOnly = false) {
|
|
214
228
|
if (!verboseOnly) {
|
|
215
229
|
// eslint-disable-next-line no-console
|
|
@@ -226,6 +240,7 @@ function log(text, verboseOnly = false) {
|
|
|
226
240
|
module.exports = {
|
|
227
241
|
spawnProcess,
|
|
228
242
|
toPosixPath,
|
|
243
|
+
toNativePath,
|
|
229
244
|
log,
|
|
230
245
|
dockerExec,
|
|
231
246
|
assert,
|
|
@@ -234,4 +249,5 @@ module.exports = {
|
|
|
234
249
|
copyDirContents,
|
|
235
250
|
CommandError,
|
|
236
251
|
ParameterError,
|
|
252
|
+
ValidationError,
|
|
237
253
|
};
|
package/modules/project-info.js
CHANGED
|
@@ -4,11 +4,12 @@ const fs = require('fs/promises');
|
|
|
4
4
|
|
|
5
5
|
const {
|
|
6
6
|
checkContainerAndClean,
|
|
7
|
-
findNPMRoot,
|
|
8
7
|
runGitMaybeHost,
|
|
9
8
|
tryCacheContainerId,
|
|
10
9
|
} = require('./actions/utils');
|
|
11
10
|
|
|
11
|
+
const { findNPMRoot } = require('./actions/npm-utils');
|
|
12
|
+
|
|
12
13
|
const {
|
|
13
14
|
LIBDRAGON_PROJECT_MANIFEST,
|
|
14
15
|
CONFIG_FILE,
|
|
@@ -24,8 +25,8 @@ const {
|
|
|
24
25
|
fileExists,
|
|
25
26
|
log,
|
|
26
27
|
spawnProcess,
|
|
27
|
-
dirExists,
|
|
28
28
|
toPosixPath,
|
|
29
|
+
assert,
|
|
29
30
|
} = require('./helpers');
|
|
30
31
|
|
|
31
32
|
async function findContainerId(libdragonInfo) {
|
|
@@ -67,8 +68,8 @@ async function findContainerId(libdragonInfo) {
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
async function findLibdragonRoot(start = '.') {
|
|
70
|
-
const manifest = path.join(start, LIBDRAGON_PROJECT_MANIFEST);
|
|
71
|
-
if (await
|
|
71
|
+
const manifest = path.join(start, LIBDRAGON_PROJECT_MANIFEST, CONFIG_FILE);
|
|
72
|
+
if (await fileExists(manifest)) {
|
|
72
73
|
return path.resolve(start);
|
|
73
74
|
} else {
|
|
74
75
|
const parent = path.resolve(start, '..');
|
|
@@ -89,41 +90,21 @@ async function findGitRoot() {
|
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
/**
|
|
93
|
-
* Creates the manifest folder if it does not exist. Will return true if
|
|
94
|
-
* created, false otherwise.
|
|
95
|
-
*/
|
|
96
|
-
async function createManifestIfNotExist(libdragonInfo) {
|
|
97
|
-
const manifestPath = path.join(
|
|
98
|
-
libdragonInfo.root,
|
|
99
|
-
LIBDRAGON_PROJECT_MANIFEST
|
|
100
|
-
);
|
|
101
|
-
const manifestExists = await fs.stat(manifestPath).catch((e) => {
|
|
102
|
-
if (e.code !== 'ENOENT') throw e;
|
|
103
|
-
return false;
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
if (manifestExists && !manifestExists.isDirectory()) {
|
|
107
|
-
throw new Error(
|
|
108
|
-
'There is already a `.libdragon` file and it is not a directory.'
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (!manifestExists) {
|
|
113
|
-
log(
|
|
114
|
-
`Creating libdragon project configuration at \`${libdragonInfo.root}\`.`
|
|
115
|
-
);
|
|
116
|
-
await fs.mkdir(manifestPath);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
93
|
async function readProjectInfo() {
|
|
94
|
+
const projectRoot = await findLibdragonRoot();
|
|
95
|
+
|
|
121
96
|
let info = {
|
|
122
|
-
root:
|
|
123
|
-
(await findLibdragonRoot()) ??
|
|
124
|
-
(await findNPMRoot()) ??
|
|
125
|
-
(await findGitRoot()),
|
|
97
|
+
root: projectRoot ?? (await findNPMRoot()) ?? (await findGitRoot()),
|
|
126
98
|
userInfo: os.userInfo(),
|
|
99
|
+
|
|
100
|
+
// Use this to discriminate if there is a project when the command is run
|
|
101
|
+
haveProjectConfig: !!projectRoot,
|
|
102
|
+
|
|
103
|
+
// Set the defaults immediately, these should be present at all times even
|
|
104
|
+
// if we are migrating from the old config because they did not exist before
|
|
105
|
+
imageName: DOCKER_HUB_IMAGE,
|
|
106
|
+
vendorDirectory: toPosixPath(path.join('.', LIBDRAGON_SUBMODULE)),
|
|
107
|
+
vendorStrategy: DEFAULT_STRATEGY,
|
|
127
108
|
};
|
|
128
109
|
|
|
129
110
|
if (!info.root) {
|
|
@@ -180,47 +161,45 @@ async function readProjectInfo() {
|
|
|
180
161
|
).trim();
|
|
181
162
|
}
|
|
182
163
|
|
|
183
|
-
info.imageName = info.imageName ?? DOCKER_HUB_IMAGE;
|
|
184
164
|
log(`Active image name: ${info.imageName}`, true);
|
|
185
|
-
|
|
186
|
-
info.vendorDirectory =
|
|
187
|
-
info.vendorDirectory ?? path.join('.', LIBDRAGON_SUBMODULE);
|
|
188
165
|
log(`Active vendor directory: ${info.vendorDirectory}`, true);
|
|
189
|
-
|
|
190
|
-
info.vendorStrategy = info.vendorStrategy ?? DEFAULT_STRATEGY;
|
|
191
166
|
log(`Active vendor strategy: ${info.vendorStrategy}`, true);
|
|
192
167
|
|
|
193
|
-
// Cache the latest image name
|
|
194
|
-
setProjectInfoToSave(info);
|
|
195
168
|
return info;
|
|
196
169
|
}
|
|
197
170
|
|
|
198
|
-
let projectInfoToWrite = {};
|
|
199
171
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* get written to the configuration file. Echoes back the given info.
|
|
203
|
-
* @param libdragonInfo
|
|
172
|
+
* @param info This is only the base info without action properties like showStatus
|
|
173
|
+
* fn and command line options
|
|
204
174
|
*/
|
|
205
|
-
function
|
|
206
|
-
|
|
207
|
-
return
|
|
208
|
-
|
|
175
|
+
async function writeProjectInfo(info) {
|
|
176
|
+
// Do not log anything here as it may litter the output being always run on exit
|
|
177
|
+
if (!info) return;
|
|
178
|
+
|
|
179
|
+
const projectPath = path.join(info.root, LIBDRAGON_PROJECT_MANIFEST);
|
|
209
180
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
181
|
+
const pathExists = await fs.stat(projectPath).catch((e) => {
|
|
182
|
+
if (e.code !== 'ENOENT') throw e;
|
|
183
|
+
return false;
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (!pathExists) {
|
|
187
|
+
log(`Creating libdragon project configuration at \`${info.root}\`.`, true);
|
|
188
|
+
await fs.mkdir(projectPath);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
assert(
|
|
192
|
+
toPosixPath(info.vendorDirectory) === info.vendorDirectory,
|
|
193
|
+
new Error('vendorDirectory should always be in posix format')
|
|
215
194
|
);
|
|
195
|
+
|
|
216
196
|
await fs.writeFile(
|
|
217
|
-
path.join(
|
|
197
|
+
path.join(projectPath, CONFIG_FILE),
|
|
218
198
|
JSON.stringify(
|
|
219
199
|
{
|
|
220
|
-
imageName:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
vendorStrategy: libdragonInfo.vendorStrategy,
|
|
200
|
+
imageName: info.imageName,
|
|
201
|
+
vendorDirectory: info.vendorDirectory,
|
|
202
|
+
vendorStrategy: info.vendorStrategy,
|
|
224
203
|
},
|
|
225
204
|
null,
|
|
226
205
|
' '
|
|
@@ -229,4 +208,4 @@ async function writeProjectInfo(libdragonInfo = projectInfoToWrite) {
|
|
|
229
208
|
log(`Configuration file updated`, true);
|
|
230
209
|
}
|
|
231
210
|
|
|
232
|
-
module.exports = { readProjectInfo, writeProjectInfo
|
|
211
|
+
module.exports = { readProjectInfo, writeProjectInfo };
|
package/package.json
CHANGED
package/skeleton/Makefile
CHANGED
|
@@ -3,16 +3,17 @@ SOURCE_DIR=src
|
|
|
3
3
|
BUILD_DIR=build
|
|
4
4
|
include $(N64_INST)/include/n64.mk
|
|
5
5
|
|
|
6
|
-
src=main.c
|
|
7
|
-
|
|
8
6
|
all: hello.z64
|
|
7
|
+
.PHONY: all
|
|
8
|
+
|
|
9
|
+
OBJS = $(BUILD_DIR)/main.o
|
|
9
10
|
|
|
10
11
|
hello.z64: N64_ROM_TITLE="Hello World"
|
|
11
|
-
$(BUILD_DIR)/hello.elf: $(src:%.c=$(BUILD_DIR)/%.o)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
rm -f $(BUILD_DIR)/* hello.z64
|
|
13
|
+
$(BUILD_DIR)/hello.elf: $(OBJS)
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
clean:
|
|
16
|
+
rm -f $(BUILD_DIR) *.z64
|
|
17
|
+
.PHONY: clean
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
-include $(wildcard $(BUILD_DIR)/*.d)
|