Skip to content

Commit

Permalink
good ideas, but i'm going to stop here
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicexplorer committed Nov 24, 2024
1 parent 6edf71e commit fc52289
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .build-output/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
22 changes: 13 additions & 9 deletions Cakefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ process = require 'process'


option '-l', '--level [LEVEL]', 'log level [debug < info < log(default) < warn < error]'
option '-c', '--commit', 'whether to write compilation output back into tracked source files'

task = (name, description, action) ->
global.task name, description, ({level = 'log', ...opts} = {}) ->
Expand Down Expand Up @@ -108,7 +109,7 @@ class ParserFailure extends SingleErrorWrapper
heading: -> 'building parser failed'


buildParser = ->
buildParser = ({commit}) ->
# (1) cache parser build
# (1.1) cache on grammar.coffee [DONE]
# (1.2) cache on jison dep [DONE (kinda--uses package-lock.json)]
Expand All @@ -117,9 +118,9 @@ buildParser = ->
# FIXME: see register.coffee: --enable-source-maps works for this???
# using 'node --enable-source-maps bin/cake test' appears to make #4418 pass????
buildDepsTask = new BuildDeps
await buildDepsTask.cachedExecute(console, {useColors: USE_COLORS}).catch (e) -> Promise.reject new BootstrapFailure e
await buildDepsTask.cachedExecute(console, {commit, useColors: USE_COLORS}).catch (e) -> Promise.reject new BootstrapFailure e
parserTask = new JisonParser
await parserTask.cachedExecute(console, {useColors: USE_COLORS}).catch (e) -> Promise.reject new ParserFailure e
await parserTask.cachedExecute(console, {commit, useColors: USE_COLORS}).catch (e) -> Promise.reject new ParserFailure e


class CompileFailures extends TopLevelError
Expand All @@ -129,21 +130,24 @@ class CompileFailures extends TopLevelError

heading: -> @message

buildExceptParser = ->
bootstrapCompile = ({commit}) ->
compileRequests = for file in await fs.promises.readdir 'src'
{name, ext} = path.parse file
continue unless ext in ['.coffee', '.litcoffee']
coffeeSource = path.join 'src', file
jsOut = path.join 'lib/coffeescript', "#{name}.js"
new CompileBootstrapSources {coffeeSource, jsOut}

CompileFailures.executeParallel compileRequests.map (r) -> r.cachedExecute console, {useColors: USE_COLORS}
CompileFailures.executeParallel compileRequests.map (r) -> r.cachedExecute console, {commit, useColors: USE_COLORS}


class FullBuildError extends TopLevelError


build = -> FullBuildError.executeParallel [buildParser(), buildExceptParser()]
build = ({commit}) -> FullBuildError.executeParallel [
buildParser {commit}
bootstrapCompile {commit}
]


transpile = (code, options = {}) ->
Expand Down Expand Up @@ -201,14 +205,14 @@ watchAndBuildAndTest = (harmony = no) ->
buildAndTest no, harmony


task 'build', 'build the CoffeeScript compiler from source', ->
await build()
task 'build', 'build the CoffeeScript compiler from source', ({commit}) ->
await build {commit}

task 'build:parser', 'build the Jison parser only', ->
await buildParser()

task 'build:except-parser', 'build the CoffeeScript compiler, except for the Jison parser', ->
await buildExceptParser()
await bootstrapCompile()

task 'build:full', 'build the CoffeeScript compiler from source twice, and run the tests', ->
await build()
Expand Down
48 changes: 46 additions & 2 deletions build-support/caching.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,50 @@ exports.Checksummed = class Checksummed
new @ source, digest


exports.ChecksumFiles = class ChecksumFiles
class OutputFiles
sourcePaths: -> throw new TypeError "unimplemented: #{@constructor.name}"
commitPaths: -> throw new TypeError "unimplemented: #{@constructor.name}"
commit: (console) -> throw new TypeError "unimplemented: #{@constructor.name}"


exports.ChecksumFiles = class ChecksumFiles extends OutputFiles
constructor: (paths) ->
super()
@sources = paths.map (p) -> path.resolve p
.sort()
.map (p) -> new FileContent p

sourcePaths: -> @sources.map ({p}) -> p
commitPaths: -> @sourcePaths()
commit: (console) ->
paths = @commitPaths()
msg = paths.map((p) -> "'#{p}'").join ', '
console.debug "commit no-op: [#{msg}]"
Promise.resolve paths

digestAll: -> await Promise.all @sources.map (f) -> await Checksummed.digestContent f


exports.BuildOutputMirroredFiles = class BuildOutputMirroredFiles extends ChecksumFiles
constructor: (cacheDir, commitPaths) ->
buildPaths = new Map ([p, path.join(cacheDir, p)] for p in commitPaths)
super Array.from buildPaths.values()
@buildPaths = buildPaths

commitPaths: -> Array.from @buildPaths.keys()
commit: (console) ->
console.info "commit files: #{util.inspect @buildPaths}"
Promise.all (for [target, source] from @buildPaths
console.debug "commit copy #{source} -> #{target}"
fs.promises.copyFile source, target
.then -> target)

digestAll: ->
await Promise.all (for p in @sourcePaths()
fs.promises.mkdir path.dirname(p), recursive: yes)
await super()


exports.TaskFailed = class TaskFailed extends Error
constructor: (task, cause) ->
message = "task failed: #{task.print()}\n#{cause.message}"
Expand Down Expand Up @@ -163,6 +198,9 @@ exports.BuildTask = class BuildTask
outputSources: -> throw new TypeError "unimplemented: #{@constructor.name}"
print: -> throw new TypeError "unimplemented: #{@constructor.name}"

@buildOutputBaseDir: '.build-output'
buildOutputDir: -> path.join @constructor.buildOutputBaseDir, @identifier()

@attestationDir: '.attestations'
@makeAttestationFilename: (id) => "#{id}.attestation.json"
@makeAttestationPath: (id) =>
Expand All @@ -183,10 +221,14 @@ exports.BuildTask = class BuildTask

execute: -> throw new TypeError "unimplemented: #{@constructor.name}"

cachedExecute: (console, {useColors}) ->
doCommit: (console) -> await @outputSources().commit console

cachedExecute: (console, {commit, useColors}) ->
if await @cacheIsValid()
console.debug "task '#{@identifier()}' was fully cached!"
console.debug "task '#{@identifier()}' is cached at '#{@attestationPath()}'"
if commit
await @doCommit console
return
console.info "task '#{@identifier()}' was not cached; executing"
console.log @print()
Expand All @@ -198,3 +240,5 @@ exports.BuildTask = class BuildTask
console.info "task '#{@identifier()}' complete (#{endTask - startTask} ms)"
console.debug "caching task '#{@identifier()}' at '#{@attestationPath()}'"
await @writeCache()
if commit
await @doCommit console
50 changes: 38 additions & 12 deletions build-support/compile-sources.coffee
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{ BuildTask, ChecksumFiles } = require './caching'
{ invokeProcess, captureOutput } = require './subprocess'
{ createHash } = require 'crypto'
path = require 'path'
process = require 'process'
{ BuildTask, ChecksumFiles, BuildOutputMirroredFiles } = require './caching'
{ invokeProcess, captureOutput } = require './subprocess'
{ createHash } = require 'crypto'
path = require 'path'
process = require 'process'


class CompileSourcesBase extends BuildTask
Expand Down Expand Up @@ -33,33 +33,59 @@ exports.CompileBootstrapSources = class CompileBootstrapSources extends CompileS
throw new TypeError "js output file must end in .js (was: '#{@jsOut}')"

inputSources: -> new ChecksumFiles [@coffeeSource, @coffeeBin]
outputSources: -> new ChecksumFiles [@jsOut]
print: -> "bootstrap coffee compile: #{@coffeeSource} -> #{@jsOut}"
outputSources: -> new BuildOutputMirroredFiles @buildOutputDir(), [@jsOut]
print: -> "bootstrap coffee compile: #{@coffeeSource} -> [#{@jsOut}]"

jsOutputPath: ->
[jsOut] = @outputSources().sourcePaths()
jsOut

execute: (console) ->
proc = await invokeProcess process.execPath, [@coffeeBin, '-c', '-o', @jsOut, @coffeeSource]
proc = await invokeProcess process.execPath, [@coffeeBin, '-c', '-o', @jsOutputPath(), @coffeeSource]
await captureOutput proc


exports.CompileRealSources = class CompileRealSources extends CompileSourcesBase
@fromDependencies: ({jisonParserTask, bootstrapCompileTasks}) ->
parserInputPath = jisonParserTask.parserOutputPath()
jsInputPaths = (t.jsOutputPath() for t in bootstrapCompileTasks)
commandJsInput = jsInputPaths.find (p) -> path.basename(p) is 'command.js'
unless commandJsInput?
throw new TypeError "could not find command.js among build js inputs: #{jsInputPaths}"

constructor: ({
@bootstrappedJsOut,
@coffeeSource,
@realJsOut,
@bootstrappedJsCommandOut,
@realCompileScript = 'build-support/isolated-scripts/compile-real.coffee',
@coffeeBin = 'bin/coffee',
}) ->
super()
for jsOut in @bootstrappedJsOut
unless jsOut.match /\.js$/
throw new TypeError "bootstrap-compiled js input file must end in .js (was: '#{jsOut}')"
unless @coffeeSource.match /\.(lit)?coffee$/
throw new TypeError "coffee source file must end in .coffee or .litcoffee (was: '#{@coffeeSource}')"
unless @realJsOut.match /\.js$/
throw new TypeError "final compiled js output file must end in .js (was: '#{@realJsOut}')"
unless @bootstrappedJsCommandOut.match /\.command\.js$/
throw new TypeError "bootstrap-compiled command.js must end in command.js (was: #{@bootstrappedJsCommandOut})"

inputSources: -> new ChecksumFiles [@bootstrappedJsOut...]
outputSources: -> new ChecksumFiles [@realJsOut]
inputSources: -> new ChecksumFiles [@realCompileScript, @coffeeBin, @coffeeSource, @bootstrappedJsOut...]
outputSources: -> new BuildOutputMirroredFiles @buildOutputDir(), [@realJsOut]

identifier: ->
digest = @constructor.digestNames [@realJsOut]
{name} = path.parse @realJsOut
"compile-real-sources-#{name}-#{digest}"

wrapInputs: -> @bootstrappedJsOut.map((p) -> "'#{p}'").join ', '
print: -> "final coffee compile: [#{@wrapInputs()}] -> #{@realJsOut}"
print: -> "final coffee compile: [#{@coffeeSource}] -> #{@realJsOut}"

realJsOutputPath: ->
[realJsOut]= @outputSources().sourcePaths()
realJsOut

execute: (console) ->
proc = await invokeProcess process.execPath, [@coffeeBin, @realCompileScript, @bootstrappedJsCommandOut, '-c', '-o', @realJsOutputPath(), @coffeeSource]
await captureOutput proc
5 changes: 5 additions & 0 deletions build-support/isolated-scripts/compile-real.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
process = require 'process'

[commmandInput, ] = process.argv[2..]

require(commandInput).run()
16 changes: 10 additions & 6 deletions build-support/parser.coffee
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{ BuildTask, ChecksumFiles } = require './caching'
{ invokeProcess, captureOutput } = require './subprocess'
util = require 'util'
{ BuildTask, ChecksumFiles, BuildOutputMirroredFiles } = require './caching'
{ invokeProcess, captureOutput } = require './subprocess'
util = require 'util'

exports.JisonParser = class JisonParser extends BuildTask
identifier: -> 'jison-parser'
Expand All @@ -14,11 +14,15 @@ exports.JisonParser = class JisonParser extends BuildTask
} = {}) -> super()

inputSources: -> new ChecksumFiles [@grammarPath, @jisonScript, @pkgLock, @coffeeBin]
outputSources: -> new ChecksumFiles [@parserPath]
print: -> "jison generate: #{@grammarPath} -> #{@parserPath}"
outputSources: -> new BuildOutputMirroredFiles @buildOutputDir(), [@parserPath]
print: -> "jison generate: #{@grammarPath} -> [#{@parserPath}]"

parserOutputPath: ->
[parserPath] = @outputSources().sourcePaths()
parserPath

execute: (console, {useColors}) ->
proc = await invokeProcess process.execPath, [@coffeeBin, @jisonScript, @grammarPath, @parserPath, @pkgLock]
proc = await invokeProcess process.execPath, [@coffeeBin, @jisonScript, @grammarPath, @parserOutputPath(), @pkgLock]
output = (await captureOutput proc).trim()

header = 'jison output:'
Expand Down

0 comments on commit fc52289

Please sign in to comment.