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:
198
runner/compiler.go
Normal file
198
runner/compiler.go
Normal file
@@ -0,0 +1,198 @@
|
||||
package runner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/Mond1c/judge/dsl"
|
||||
)
|
||||
|
||||
type CompilerClass int
|
||||
|
||||
const (
|
||||
CompilerUnknown CompilerClass = iota
|
||||
CompilerGNU
|
||||
CompilerMSVC
|
||||
)
|
||||
|
||||
type Toolchain struct {
|
||||
Class CompilerClass
|
||||
Binary string
|
||||
Name string
|
||||
}
|
||||
|
||||
func ResolveToolchain(ccEnv string) Toolchain {
|
||||
if ccEnv == "" {
|
||||
ccEnv = defaultCC()
|
||||
}
|
||||
lower := strings.ToLower(ccEnv)
|
||||
switch lower {
|
||||
case "gcc", "g++":
|
||||
return Toolchain{Class: CompilerGNU, Binary: ccEnv, Name: "gcc"}
|
||||
case "clang", "clang++":
|
||||
return Toolchain{Class: CompilerGNU, Binary: ccEnv, Name: "clang"}
|
||||
case "cl", "cl.exe", "msvc":
|
||||
return Toolchain{Class: CompilerMSVC, Binary: "cl", Name: "msvc"}
|
||||
case "clang-cl", "clang-cl.exe":
|
||||
return Toolchain{Class: CompilerMSVC, Binary: "clang-cl", Name: "clang-cl"}
|
||||
case "cc":
|
||||
return Toolchain{Class: CompilerGNU, Binary: "cc", Name: "cc"}
|
||||
default:
|
||||
return Toolchain{Class: CompilerGNU, Binary: ccEnv, Name: lower}
|
||||
}
|
||||
}
|
||||
|
||||
func ResolveToolchainSpec(spec *dsl.ToolchainSpec) Toolchain {
|
||||
inferred := ResolveToolchain(spec.Name)
|
||||
binary := spec.Binary
|
||||
if binary == "" {
|
||||
binary = inferred.Binary
|
||||
}
|
||||
var class CompilerClass
|
||||
switch spec.Class {
|
||||
case "gnu":
|
||||
class = CompilerGNU
|
||||
case "msvc":
|
||||
class = CompilerMSVC
|
||||
default:
|
||||
class = inferred.Class
|
||||
}
|
||||
return Toolchain{Class: class, Binary: binary, Name: spec.Name}
|
||||
}
|
||||
|
||||
func defaultCC() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return "cl"
|
||||
}
|
||||
return "cc"
|
||||
}
|
||||
|
||||
func Compile(cfg dsl.BuildConfig, tc Toolchain, outputPath string) ([]string, error) {
|
||||
switch tc.Class {
|
||||
case CompilerGNU:
|
||||
return compileGNU(cfg, tc, outputPath), nil
|
||||
case CompilerMSVC:
|
||||
return compileMSVC(cfg, tc, outputPath), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown compiler class for toolchain %q", tc.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func compileGNU(cfg dsl.BuildConfig, tc Toolchain, outputPath string) []string {
|
||||
argv := []string{tc.Binary}
|
||||
|
||||
if cfg.Standard != "" {
|
||||
argv = append(argv, "-std="+cfg.Standard)
|
||||
}
|
||||
|
||||
switch cfg.Profile {
|
||||
case dsl.ProfileRelease:
|
||||
argv = append(argv, "-O2")
|
||||
case dsl.ProfileDebug:
|
||||
argv = append(argv, "-O0", "-g")
|
||||
case dsl.ProfileSanitized:
|
||||
argv = append(argv, "-O1", "-g", "-fno-omit-frame-pointer")
|
||||
}
|
||||
|
||||
switch cfg.Warnings {
|
||||
case dsl.WarningsStrict:
|
||||
argv = append(argv, "-Wall", "-Wextra")
|
||||
case dsl.WarningsPedantic:
|
||||
argv = append(argv, "-Wall", "-Wextra", "-Wpedantic")
|
||||
}
|
||||
|
||||
if len(cfg.Sanitize) > 0 {
|
||||
argv = append(argv, "-fsanitize="+strings.Join(cfg.Sanitize, ","))
|
||||
}
|
||||
|
||||
for _, inc := range cfg.Includes {
|
||||
argv = append(argv, "-I"+inc)
|
||||
}
|
||||
|
||||
for _, k := range sortedKeys(cfg.Defines) {
|
||||
v := cfg.Defines[k]
|
||||
if v == "" {
|
||||
argv = append(argv, "-D"+k)
|
||||
} else {
|
||||
argv = append(argv, fmt.Sprintf("-D%s=%s", k, v))
|
||||
}
|
||||
}
|
||||
|
||||
argv = append(argv, cfg.Extra...)
|
||||
argv = append(argv, cfg.Sources...)
|
||||
argv = append(argv, "-o", outputPath)
|
||||
|
||||
for _, lib := range cfg.Link {
|
||||
argv = append(argv, "-l"+lib)
|
||||
}
|
||||
return argv
|
||||
}
|
||||
|
||||
func compileMSVC(cfg dsl.BuildConfig, tc Toolchain, outputPath string) []string {
|
||||
argv := []string{tc.Binary, "/nologo"}
|
||||
|
||||
if cfg.Standard != "" {
|
||||
argv = append(argv, "/std:"+cfg.Standard)
|
||||
}
|
||||
|
||||
switch cfg.Profile {
|
||||
case dsl.ProfileRelease:
|
||||
argv = append(argv, "/O2")
|
||||
case dsl.ProfileDebug:
|
||||
argv = append(argv, "/Od", "/Zi")
|
||||
case dsl.ProfileSanitized:
|
||||
argv = append(argv, "/Od", "/Zi", "/fsanitize=address")
|
||||
}
|
||||
|
||||
switch cfg.Warnings {
|
||||
case dsl.WarningsStrict:
|
||||
argv = append(argv, "/W4")
|
||||
case dsl.WarningsPedantic:
|
||||
argv = append(argv, "/W4", "/permissive-")
|
||||
}
|
||||
|
||||
if containsString(cfg.Sanitize, "address") && cfg.Profile != dsl.ProfileSanitized {
|
||||
argv = append(argv, "/fsanitize=address")
|
||||
}
|
||||
|
||||
for _, inc := range cfg.Includes {
|
||||
argv = append(argv, "/I"+inc)
|
||||
}
|
||||
|
||||
for _, k := range sortedKeys(cfg.Defines) {
|
||||
v := cfg.Defines[k]
|
||||
if v == "" {
|
||||
argv = append(argv, "/D"+k)
|
||||
} else {
|
||||
argv = append(argv, fmt.Sprintf("/D%s=%s", k, v))
|
||||
}
|
||||
}
|
||||
|
||||
argv = append(argv, cfg.Extra...)
|
||||
argv = append(argv, cfg.Sources...)
|
||||
argv = append(argv, "/Fe:"+outputPath)
|
||||
return argv
|
||||
}
|
||||
|
||||
func sortedKeys(m map[string]string) []string {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
keys := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
func containsString(xs []string, x string) bool {
|
||||
for _, v := range xs {
|
||||
if v == x {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user