blob: ebb21c79330fa866333ddde056ded8ee21604cf4 [file] [log] [blame]
// Copyright 2023 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package build
import (
"sort"
"dawn.googlesource.com/dawn/tools/src/container"
"dawn.googlesource.com/dawn/tools/src/transform"
)
// Directory holds information about a build target
type Target struct {
// The target's name
Name TargetName
// The kind of target
Kind TargetKind
// The directory holding the target
Directory *Directory
// All project-relative paths of source files that are part of this target
SourceFileSet container.Set[string]
// Dependencies of this target
Dependencies *Dependencies
// An optional custom output name for the target
OutputName string
// An optional condition for building this target
Condition string
}
// AddSourceFile adds the File to the target's source set
func (t *Target) AddSourceFile(f *File) {
t.SourceFileSet.Add(f.Path())
f.Target = t
}
// SourceFiles returns the sorted list of the target's source files
func (t *Target) SourceFiles() []*File {
out := make([]*File, len(t.SourceFileSet))
for i, name := range t.SourceFileSet.List() {
out[i] = t.Directory.Project.Files[name]
}
return out
}
// SourceFiles returns the sorted list of the target's source files that have no build condition
func (t *Target) UnconditionalSourceFiles() []*File {
return transform.Filter(t.SourceFiles(), func(t *File) bool { return t.Condition == "" })
}
// A collection of source files and dependencies sharing the same condition
type TargetConditional struct {
Condition string
SourceFiles []*File
InternalDependencies []*Target
ExternalDependencies []ExternalDependency
}
// A collection of source files and dependencies sharing the same condition
type TargetConditionals []*TargetConditional
// HasSourceFiles returns true if any of the conditionals in l have source files
func (l TargetConditionals) HasSourceFiles() bool {
for _, c := range l {
if len(c.SourceFiles) > 0 {
return true
}
}
return false
}
// HasDependencies returns true if any of the conditionals in l have internal or external dependencies
func (l TargetConditionals) HasDependencies() bool {
for _, c := range l {
if len(c.InternalDependencies) > 0 || len(c.ExternalDependencies) > 0 {
return true
}
}
return false
}
// Conditionals returns a sorted list of TargetConditional, which are grouped by condition
func (t *Target) Conditionals() TargetConditionals {
m := container.NewMap[string, *TargetConditional]()
for name := range t.SourceFileSet {
file := t.Directory.Project.Files[name]
if file.Condition != "" {
c := m.GetOrCreate(file.Condition, func() *TargetConditional {
return &TargetConditional{Condition: file.Condition}
})
c.SourceFiles = append(c.SourceFiles, file)
}
}
for name := range t.Dependencies.internal {
dep := t.Directory.Project.Targets[name]
if dep.Condition != "" {
c := m.GetOrCreate(dep.Condition, func() *TargetConditional {
return &TargetConditional{Condition: dep.Condition}
})
c.InternalDependencies = append(c.InternalDependencies, dep)
}
}
for name := range t.Dependencies.external {
dep := t.Directory.Project.externals[name]
if dep.Condition != "" {
c := m.GetOrCreate(dep.Condition, func() *TargetConditional {
return &TargetConditional{Condition: dep.Condition}
})
c.ExternalDependencies = append(c.ExternalDependencies, dep)
}
}
for _, c := range m {
sort.Slice(c.SourceFiles, func(a, b int) bool { return c.SourceFiles[a].Name < c.SourceFiles[b].Name })
sort.Slice(c.InternalDependencies, func(a, b int) bool { return c.InternalDependencies[a].Name < c.InternalDependencies[b].Name })
sort.Slice(c.ExternalDependencies, func(a, b int) bool { return c.ExternalDependencies[a].Name < c.ExternalDependencies[b].Name })
}
return TargetConditionals(m.Values())
}