1. New build system
All checks were successful
build-dsl-smoke / Build judge (push) Successful in 12s
build-dsl-smoke / debug / clang / linux (push) Successful in 6s
build-dsl-smoke / debug / gcc / linux (push) Successful in 8s
build-dsl-smoke / release / clang / linux (push) Successful in 8s
build-dsl-smoke / release / gcc / linux (push) Successful in 6s
build-dsl-smoke / sanitized / clang / linux (push) Successful in 8s
build-dsl-smoke / sanitized / gcc / linux (push) Successful in 7s
build-dsl-smoke / debug / clang / windows (push) Successful in 13s
build-dsl-smoke / debug-valgrind / gcc / linux (push) Successful in 14s
build-dsl-smoke / release / clang / windows (push) Successful in 16s
build-dsl-smoke / debug / msvc / windows (push) Successful in 18s
build-dsl-smoke / release / msvc / windows (push) Successful in 17s
build-dsl-smoke / SUMMARY (push) Successful in 4s
Release / Build & publish (push) Successful in 48s
All checks were successful
build-dsl-smoke / Build judge (push) Successful in 12s
build-dsl-smoke / debug / clang / linux (push) Successful in 6s
build-dsl-smoke / debug / gcc / linux (push) Successful in 8s
build-dsl-smoke / release / clang / linux (push) Successful in 8s
build-dsl-smoke / release / gcc / linux (push) Successful in 6s
build-dsl-smoke / sanitized / clang / linux (push) Successful in 8s
build-dsl-smoke / sanitized / gcc / linux (push) Successful in 7s
build-dsl-smoke / debug / clang / windows (push) Successful in 13s
build-dsl-smoke / debug-valgrind / gcc / linux (push) Successful in 14s
build-dsl-smoke / release / clang / windows (push) Successful in 16s
build-dsl-smoke / debug / msvc / windows (push) Successful in 18s
build-dsl-smoke / release / msvc / windows (push) Successful in 17s
build-dsl-smoke / SUMMARY (push) Successful in 4s
Release / Build & publish (push) Successful in 48s
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
355
dsl/build_parser.go
Normal file
355
dsl/build_parser.go
Normal file
@@ -0,0 +1,355 @@
|
||||
package dsl
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (p *Parser) parseBuildBlock(name string) (*BuildConfig, error) {
|
||||
return p.parseBuildBlockInner(name, false)
|
||||
}
|
||||
|
||||
func (p *Parser) parseBuildBlockInner(name string, inOSOverride bool) (*BuildConfig, error) {
|
||||
if _, err := p.expect(TOKEN_LBRACE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bc := &BuildConfig{Name: name}
|
||||
|
||||
for !p.isRBrace() {
|
||||
t := p.peek()
|
||||
if t.Type != TOKEN_IDENT {
|
||||
return nil, fmt.Errorf("%d:%d: unexpected token %q in build block", t.Line, t.Col, t.Value)
|
||||
}
|
||||
|
||||
switch t.Value {
|
||||
case "language":
|
||||
p.advance()
|
||||
s, err := p.parseAssignString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Language = s
|
||||
|
||||
case "standard":
|
||||
p.advance()
|
||||
s, err := p.parseAssignString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Standard = s
|
||||
|
||||
case "output":
|
||||
p.advance()
|
||||
s, err := p.parseAssignString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Output = s
|
||||
|
||||
case "wrapper":
|
||||
p.advance()
|
||||
s, err := p.parseAssignString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Wrapper = s
|
||||
|
||||
case "sources":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Sources = xs
|
||||
|
||||
case "includes":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Includes = xs
|
||||
|
||||
case "sanitize":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Sanitize = xs
|
||||
|
||||
case "link":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Link = xs
|
||||
|
||||
case "extra":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Extra = xs
|
||||
|
||||
case "platforms":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validatePlatformList(xs, t.Line, t.Col); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Platforms = xs
|
||||
|
||||
case "compilers":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Compilers = xs
|
||||
|
||||
case "profile":
|
||||
p.advance()
|
||||
if _, err := p.expect(TOKEN_ASSIGN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, err := p.expect(TOKEN_IDENT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prof, err := parseProfileIdent(id.Value, id.Line, id.Col)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Profile = prof
|
||||
|
||||
case "warnings":
|
||||
p.advance()
|
||||
if _, err := p.expect(TOKEN_ASSIGN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, err := p.expect(TOKEN_IDENT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w, err := parseWarningsIdent(id.Value, id.Line, id.Col)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.Warnings = w
|
||||
|
||||
case "define":
|
||||
p.advance()
|
||||
if _, err := p.expect(TOKEN_LPAREN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := p.expect(TOKEN_STRING)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := p.expect(TOKEN_RPAREN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := p.expect(TOKEN_ASSIGN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
val, err := p.expect(TOKEN_STRING)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bc.Defines == nil {
|
||||
bc.Defines = map[string]string{}
|
||||
}
|
||||
bc.Defines[key.Value] = val.Value
|
||||
|
||||
case "linux", "windows", "darwin":
|
||||
if inOSOverride {
|
||||
return nil, fmt.Errorf("%d:%d: OS override %q cannot be nested inside another OS override", t.Line, t.Col, t.Value)
|
||||
}
|
||||
osName := t.Value
|
||||
p.advance()
|
||||
sub, err := p.parseBuildBlockInner("", true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch osName {
|
||||
case "linux":
|
||||
if bc.Linux != nil {
|
||||
return nil, fmt.Errorf("%d:%d: duplicate linux override", t.Line, t.Col)
|
||||
}
|
||||
bc.Linux = sub
|
||||
case "windows":
|
||||
if bc.Windows != nil {
|
||||
return nil, fmt.Errorf("%d:%d: duplicate windows override", t.Line, t.Col)
|
||||
}
|
||||
bc.Windows = sub
|
||||
case "darwin":
|
||||
if bc.Darwin != nil {
|
||||
return nil, fmt.Errorf("%d:%d: duplicate darwin override", t.Line, t.Col)
|
||||
}
|
||||
bc.Darwin = sub
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("%d:%d: unknown field %q in build block", t.Line, t.Col, t.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := p.expect(TOKEN_RBRACE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bc, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseAssignString() (string, error) {
|
||||
if _, err := p.expect(TOKEN_ASSIGN); err != nil {
|
||||
return "", err
|
||||
}
|
||||
s, err := p.expect(TOKEN_STRING)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s.Value, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseAssignStringList() ([]string, error) {
|
||||
if _, err := p.expect(TOKEN_ASSIGN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.parseStringList()
|
||||
}
|
||||
|
||||
func parseProfileIdent(v string, line, col int) (BuildProfile, error) {
|
||||
switch v {
|
||||
case "release":
|
||||
return ProfileRelease, nil
|
||||
case "debug":
|
||||
return ProfileDebug, nil
|
||||
case "sanitized":
|
||||
return ProfileSanitized, nil
|
||||
default:
|
||||
return ProfileUnset, fmt.Errorf("%d:%d: unknown profile %q (expected release/debug/sanitized)", line, col, v)
|
||||
}
|
||||
}
|
||||
|
||||
func parseWarningsIdent(v string, line, col int) (WarningLevel, error) {
|
||||
switch v {
|
||||
case "default":
|
||||
return WarningsDefault, nil
|
||||
case "strict":
|
||||
return WarningsStrict, nil
|
||||
case "pedantic":
|
||||
return WarningsPedantic, nil
|
||||
default:
|
||||
return WarningsUnset, fmt.Errorf("%d:%d: unknown warnings level %q (expected default/strict/pedantic)", line, col, v)
|
||||
}
|
||||
}
|
||||
|
||||
func validatePlatformList(xs []string, line, col int) error {
|
||||
for _, x := range xs {
|
||||
switch x {
|
||||
case "linux", "windows", "darwin":
|
||||
default:
|
||||
return fmt.Errorf("%d:%d: unknown platform %q (expected linux/windows/darwin)", line, col, x)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseToolchainsBlock() ([]*ToolchainSpec, error) {
|
||||
if _, err := p.expect(TOKEN_LBRACE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var specs []*ToolchainSpec
|
||||
seen := map[string]bool{}
|
||||
|
||||
for !p.isRBrace() {
|
||||
nameTok := p.peek()
|
||||
if nameTok.Type != TOKEN_IDENT && nameTok.Type != TOKEN_STRING {
|
||||
return nil, fmt.Errorf("%d:%d: expected toolchain name, got %q", nameTok.Line, nameTok.Col, nameTok.Value)
|
||||
}
|
||||
p.advance()
|
||||
name := nameTok.Value
|
||||
if seen[name] {
|
||||
return nil, fmt.Errorf("%d:%d: duplicate toolchain %q", nameTok.Line, nameTok.Col, name)
|
||||
}
|
||||
seen[name] = true
|
||||
|
||||
spec, err := p.parseToolchainEntry(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
specs = append(specs, spec)
|
||||
}
|
||||
|
||||
if _, err := p.expect(TOKEN_RBRACE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return specs, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseToolchainEntry(name string) (*ToolchainSpec, error) {
|
||||
if _, err := p.expect(TOKEN_LBRACE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spec := &ToolchainSpec{Name: name}
|
||||
for !p.isRBrace() {
|
||||
t := p.peek()
|
||||
if t.Type != TOKEN_IDENT {
|
||||
return nil, fmt.Errorf("%d:%d: unexpected token %q in toolchain block", t.Line, t.Col, t.Value)
|
||||
}
|
||||
switch t.Value {
|
||||
case "platforms":
|
||||
p.advance()
|
||||
xs, err := p.parseAssignStringList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validatePlatformList(xs, t.Line, t.Col); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
spec.Platforms = xs
|
||||
|
||||
case "binary":
|
||||
p.advance()
|
||||
s, err := p.parseAssignString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
spec.Binary = s
|
||||
|
||||
case "class":
|
||||
p.advance()
|
||||
if _, err := p.expect(TOKEN_ASSIGN); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, err := p.expect(TOKEN_IDENT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch id.Value {
|
||||
case "gnu", "msvc":
|
||||
default:
|
||||
return nil, fmt.Errorf("%d:%d: unknown compiler class %q (expected gnu/msvc)", id.Line, id.Col, id.Value)
|
||||
}
|
||||
spec.Class = id.Value
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("%d:%d: unknown field %q in toolchain block", t.Line, t.Col, t.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := p.expect(TOKEN_RBRACE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(spec.Platforms) == 0 {
|
||||
return nil, fmt.Errorf("toolchain %q: platforms is required", name)
|
||||
}
|
||||
return spec, nil
|
||||
}
|
||||
Reference in New Issue
Block a user