1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | packageJson = require '../package.json'
|
12 | ld = require 'lodash'
|
13 | path = require 'path'
|
14 | glob = require 'glob'
|
15 | globule = require 'globule'
|
16 | log = require('yadsil')('benbria-configure-ninja')
|
17 | ninjaBuilder = require 'ninja-build-gen'
|
18 | factories = require './ninjaFactories'
|
19 | {findCommand, findLocalCommand, findScript} = require './ninjaCommands'
|
20 | {getCoffeelintPaths} = require './index'
|
21 |
|
22 |
|
23 | log.warn = log.warning
|
24 |
|
25 |
|
26 | config = {}
|
27 | config.ninjaFilePath = process.cwd()
|
28 | config.ninjaFile = "build.ninja"
|
29 | config.configureNinjaScript = __filename
|
30 | config.streamlineVersion = 10
|
31 | config.streamlineOpts = ""
|
32 | config.stylusOpts = ""
|
33 |
|
34 |
|
35 | fp = {}
|
36 | fp.assets = 'assets'
|
37 | fp.build = 'build'
|
38 | fp.buildAssets = "#{fp.build}/#{fp.assets}"
|
39 | fp.coffeelint = "#{fp.build}/coffeelint"
|
40 | fp.fingerprintFile = "#{fp.buildAssets}/release/fingerprints.json"
|
41 |
|
42 |
|
43 |
|
44 | warnMessage = "# Auto-generated by `loop-configure-ninja`.\n"
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | makeSystemEdges = (ninja, optionString, options) ->
|
52 | ninja.assign 'buildCoffee', findLocalCommand('coffee', config)
|
53 |
|
54 | ninja.assign 'node', 'node'
|
55 |
|
56 | factories.forActiveFactory config, log, (factory) ->
|
57 | if factory.assignments
|
58 | log.debug "Generating assignments for #{factory.name}"
|
59 | factory.assignments ninja, config
|
60 |
|
61 | ninja.assign 'uglifyjs', findLocalCommand("uglifyjs", config)
|
62 | ninja.rule('configure')
|
63 | .run("#{findCommand('loop-configure-ninja', config)}#{optionString}")
|
64 | .description 'CONFIGURE'
|
65 | ninja.edge(config.ninjaFile)
|
66 | .using('configure')
|
67 | .need([findCommand('loop-configure-ninja', config)])
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | makeSimpleRule = (ninja, {name, command, display}) ->
|
79 | desc = name.toUpperCase() + ' ' + if display? then display else '$in'
|
80 | ninja.rule(name).run(command).description desc
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | makeCommonRules = (ninja, options) ->
|
96 | factories.forActiveFactory config, log, (factory) ->
|
97 | if factory.makeRules
|
98 | log.debug "Making rules for #{factory.name}"
|
99 | factory.makeRules ninja, config
|
100 |
|
101 | makeSimpleRule ninja, {name: 'copy', command: 'cp $in $out'}
|
102 | makeSimpleRule ninja, {
|
103 | name: 'fingerprint'
|
104 | command: """
|
105 | $node #{findScript "fingerprint.js", config} $cliOptions -b $basePath -o $out $in
|
106 | """
|
107 | display: '$basePath'
|
108 | }
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | edgeMapping = (ninja, files, mappingOptions, callback) ->
|
116 | ld.map globule.mapping(files, mappingOptions), (match) ->
|
117 | callback ninja.edge(match.dest).from(match.src)
|
118 | match.dest
|
119 |
|
120 |
|
121 |
|
122 |
|
123 | simpleMapOpt = (srcBase, destBase, ext) ->
|
124 | {srcBase, destBase, ext, extDot: 'last'}
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | makeLintEdges = (ninja, coffeeFiles) ->
|
136 | options = simpleMapOpt '.', '$builddir/coffeelint', '.coffeelint'
|
137 | edgeMapping ninja, coffeeFiles, options, (edge) ->
|
138 | edge.using('coffeelint')
|
139 |
|
140 |
|
141 |
|
142 |
|
143 | makeAssetEdges = (ninja) ->
|
144 |
|
145 |
|
146 | assetPaths = {}
|
147 | configNames = ['debug', 'release']
|
148 | for configName in configNames
|
149 | log.debug "Making #{configName} asset edges"
|
150 | assetPaths[configName] = []
|
151 | factories.forActiveFactory config, log, (factory) ->
|
152 | if factory.assetFiles and factory.makeAssetEdge
|
153 | log.debug " #{factory.name}"
|
154 | mappingOptions = simpleMapOpt(
|
155 | fp.assets,
|
156 | path.join(fp.buildAssets, configName),
|
157 | factory.targetExt or '.js')
|
158 |
|
159 |
|
160 | sourceFileNames = globule.find(factory.assetFiles, mappingOptions)
|
161 |
|
162 |
|
163 | for match in globule.mapping(sourceFileNames, mappingOptions)
|
164 | edges = factory.makeAssetEdge ninja, match.src, match.dest, configName
|
165 | assetPaths[configName] = assetPaths[configName].concat edges
|
166 |
|
167 | ninja.edge('debug-assets').from(assetPaths.debug)
|
168 |
|
169 | if assetPaths.release.length > 0
|
170 | log.debug "Making fingerprint edge for #{assetPaths.release.length} release assets"
|
171 | fingerprintFile = makeFingerprintEdge ninja, assetPaths.release
|
172 | ninja.edge('release-assets').from(fingerprintFile)
|
173 | else
|
174 |
|
175 | ninja.edge('release-assets')
|
176 |
|
177 |
|
178 |
|
179 | makeSourceEdges = (ninja) ->
|
180 | destFiles = []
|
181 |
|
182 | log.debug "Making src edges"
|
183 | factories.forActiveFactory config, log, (factory) ->
|
184 | if factory.files and factory.makeSrcEdge
|
185 | log.debug " #{factory.name}"
|
186 | mappingOptions = simpleMapOpt('src', 'lib', factory.targetExt or '.js')
|
187 |
|
188 |
|
189 | sourceFileNames = globule.find(factory.files, mappingOptions)
|
190 |
|
191 |
|
192 | for match in globule.mapping(sourceFileNames, mappingOptions)
|
193 | edges = factory.makeSrcEdge ninja, match.src, match.dest
|
194 | destFiles = destFiles.concat edges
|
195 |
|
196 | ninja.edge('lib').from(destFiles)
|
197 |
|
198 |
|
199 |
|
200 | makeFingerprintEdge = (ninja, assetsEdges) ->
|
201 | ninja.edge(fp.fingerprintFile).using('fingerprint')
|
202 | .from(assetsEdges)
|
203 | .assign('basePath', "#{fp.buildAssets}/release")
|
204 | fp.fingerprintFile
|
205 |
|
206 |
|
207 |
|
208 | makeNinja = (options, done) ->
|
209 |
|
210 | ninja = ninjaBuilder('1.3', 'build')
|
211 |
|
212 | factories.forEachFactory (factory) ->
|
213 | factory.initialize?(ninja, config, log)
|
214 |
|
215 | ninja.header warnMessage
|
216 | ninja.assign 'cliOptions', '--color' if options.ninjaColor
|
217 |
|
218 | makeSystemEdges ninja, getOptionString(options), options
|
219 | makeCommonRules ninja, options
|
220 |
|
221 | if !options.noLint
|
222 | files = getCoffeelintPaths()
|
223 | ninja.edge('lint').from makeLintEdges(ninja, files)
|
224 | else
|
225 |
|
226 | ninja.edge('lint')
|
227 |
|
228 |
|
229 | makeAssetEdges ninja
|
230 |
|
231 |
|
232 | makeSourceEdges ninja
|
233 |
|
234 |
|
235 | ninja.edge('debug').from(['debug-assets', 'lib'])
|
236 | ninja.edge('release').from(['release-assets', 'lib'])
|
237 | ninja.edge('all').from(['debug-assets', 'release-assets', 'lib'])
|
238 | ninja.byDefault 'all'
|
239 |
|
240 | done null, ninja
|
241 |
|
242 |
|
243 | getOptionString = (options) ->
|
244 | str = ''
|
245 | str += ' --no-lint' if options.noLint
|
246 | str += ' --ninja-color' if options.ninjaColor
|
247 | str += ' --streamline8' if options.streamline8
|
248 | str += " --streamline-opts '#{options.streamlineOpts}'" if options.streamlineOpts
|
249 | str += " --stylus-opts '#{options.stylusOpts}'" if options.stylusOpts
|
250 | str += " --require '#{options.require}'" if options.require
|
251 | return str
|
252 |
|
253 |
|
254 |
|
255 |
|
256 | getOptions = ->
|
257 | ArgumentParser = require('argparse').ArgumentParser
|
258 | parser = new ArgumentParser
|
259 | version: packageJson.version
|
260 | addHelp: true
|
261 | description: """
|
262 | Generates a ninja.build file for a coffeescript project.
|
263 | """
|
264 |
|
265 | parser.addArgument [ '--require' ],
|
266 | help: "Comma delimited list of modules before building."
|
267 | nargs: "?"
|
268 |
|
269 | parser.addArgument [ '--verbose' ],
|
270 | help: "Verbose output"
|
271 | nargs: 0
|
272 |
|
273 | parser.addArgument [ '--no-lint' ],
|
274 | help: "Disable coffee linting."
|
275 | dest: "noLint"
|
276 | nargs: 0
|
277 |
|
278 | parser.addArgument [ '--color' ],
|
279 | help: "Force color display out of a TTY."
|
280 | nargs: 0
|
281 |
|
282 | parser.addArgument [ '--ninja-color' ],
|
283 | help: "Force color on ninja scripts."
|
284 | dest: "ninjaColor"
|
285 | nargs: 0
|
286 |
|
287 | parser.addArgument [ '--streamline8' ],
|
288 | help: "Use streamline 0.8.x command line arguments (instead of 0.10.x)"
|
289 | nargs: 0
|
290 |
|
291 | parser.addArgument [ '--streamline-opts' ],
|
292 | help: "Extra options for streamline compilers"
|
293 | metavar: "opts"
|
294 | dest: "streamlineOpts"
|
295 | defaultValue: ''
|
296 |
|
297 | parser.addArgument [ '--stylus-opts' ],
|
298 | help: "Extra options for stylus"
|
299 | metavar: "opts"
|
300 | dest: "stylusOpts"
|
301 | defaultValue: ''
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 | options = parser.parseArgs(process.argv[2..])
|
310 |
|
311 | if options.ninjaColor then options.color = true
|
312 | log.verbose options.verbose
|
313 | if options.color then log.color options.color
|
314 |
|
315 | if log.color()
|
316 | options.ninjaColor = true
|
317 |
|
318 | return options
|
319 |
|
320 |
|
321 |
|
322 |
|
323 |
|
324 | module.exports = (configureNinjaScript) ->
|
325 | config.configureNinjaScript = configureNinjaScript
|
326 |
|
327 | options = getOptions()
|
328 |
|
329 | if options.streamline8 then config.streamlineVersion = 8
|
330 | config.streamlineOpts = options.streamlineOpts
|
331 | config.stylusOpts = options.stylusOpts
|
332 |
|
333 | if options.require
|
334 | for mod in options.require.split(',')
|
335 | if mod.indexOf('./') == 0 then mod = path.resolve mod
|
336 | require mod
|
337 |
|
338 | makeNinja options, (err, ninja) ->
|
339 | throw err if err
|
340 | ninjaFile = path.resolve(config.ninjaFilePath, config.ninjaFile)
|
341 | ninja.save ninjaFile
|
342 | log.info "generated \'#{ninjaFile}\' (#{ninja.ruleCount} rules, #{ninja.edgeCount} edges)"
|