github.com/distbuild/reclient@v0.0.0-20240401075343-3de72e395564/internal/pkg/inputprocessor/action/nacl/preprocessor.go (about) 1 // Copyright 2023 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package nacl performs include processing given a valid nacl action. 16 package nacl 17 18 import ( 19 "fmt" 20 "path/filepath" 21 "strings" 22 23 "github.com/bazelbuild/reclient/internal/pkg/inputprocessor/action/cppcompile" 24 "github.com/bazelbuild/reclient/internal/pkg/inputprocessor/flags" 25 ) 26 27 // Preprocessor is the preprocessor of nacl compile actions. 28 type Preprocessor struct { 29 *cppcompile.Preprocessor 30 } 31 32 // ComputeSpec computes cpp header dependencies. 33 // As the versions of nacl that we work with are quite defased from our llvm 34 // version, we have to tweak the flags before treating them as a regular clang 35 // action. 36 func (p *Preprocessor) ComputeSpec() error { 37 var hasTarget bool 38 finalFlags := []*flags.Flag{} 39 for _, flag := range p.Flags.Flags { 40 if strings.HasPrefix(flag.Key, "-pnacl") || strings.HasPrefix(flag.Key, "--pnacl") || (flag.Key == "--" && strings.HasPrefix(flag.Value, "pnacl")) { 41 // Chrome pnacl uses a custom clang compiler, pnacl-clang, 42 // which supports flags that ClangScanDeps would never 43 // support. 44 continue 45 } 46 if flag.Key == "-target" || flag.Key == "--target=" { 47 // See if !hasTarget below for more context. 48 hasTarget = true 49 } 50 finalFlags = append(finalFlags, flag) 51 } 52 53 binaryName := filepath.Base(p.Flags.ExecutablePath) 54 containsNacl := strings.Contains(binaryName, "nacl") 55 if !containsNacl { 56 return fmt.Errorf("nacl binary doesn't include 'nacl' in basename: %v", p.Flags.ExecutablePath) 57 } 58 59 if !hasTarget && containsNacl { 60 // Nacl compilers target a specific architecture that's potentially different 61 // than the host machine's architecutre, eg x86_64, i686 or mipsel. Those flavors have their 62 // own defined macros, included headers and libraries. Our implementation of clang scan deps 63 // sometimes is unable to find out that we're attempting a cross-compilation of sorts, 64 // so we add a `--target` flag as a cheat for scan deps. 65 // 66 // In Chrome, NaCl binaries all follow the naming 67 // {arch}-nacl-{tool}, eg x86_64-nacl-clang, mipsel-nacl-ld. 68 // The exception being for pnacl, where the binaries are named pnacl-{tool}. 69 // Under the hood, pnacl-clang uses the i686-nacl-clang. 70 arch := strings.Split(binaryName, "nacl") 71 if arch[0] != "p" { 72 finalFlags = append(finalFlags, &flags.Flag{Key: "--target=", Value: fmt.Sprintf("%snacl", arch[0]), Joined: true}) 73 } else { 74 // Under the hood, pnacl-clang is a python script that runs i686-nacl-clang. 75 finalFlags = append(finalFlags, &flags.Flag{Key: "--target=", Value: "i686-nacl", Joined: true}) 76 } 77 } 78 79 p.Flags.Flags = finalFlags 80 return p.Preprocessor.ComputeSpec() 81 }