github.com/goplus/llgo@v0.8.3/xtool/clang/preprocessor/preprocessor.go (about)

     1  /*
     2   * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package preprocessor
    18  
    19  import (
    20  	"log"
    21  	"os"
    22  	"os/exec"
    23  	"path/filepath"
    24  
    25  	"github.com/goplus/llgo/xtool/clang/pathutil"
    26  )
    27  
    28  const (
    29  	DbgFlagExecCmd = 1 << iota
    30  	DbgFlagAll     = DbgFlagExecCmd
    31  )
    32  
    33  var (
    34  	debugExecCmd bool
    35  )
    36  
    37  func SetDebug(flags int) {
    38  	debugExecCmd = (flags & DbgFlagExecCmd) != 0
    39  }
    40  
    41  // -----------------------------------------------------------------------------
    42  
    43  type Config struct {
    44  	Compiler    string // default: clang
    45  	PPFlag      string // default: -E
    46  	BaseDir     string // base of include searching directory, should be absolute path
    47  	IncludeDirs []string
    48  	Defines     []string
    49  	Flags       []string
    50  }
    51  
    52  func Do(infile, outfile string, conf *Config) (err error) {
    53  	if infile, err = filepath.Abs(infile); err != nil {
    54  		return
    55  	}
    56  	if outfile, err = filepath.Abs(outfile); err != nil {
    57  		return
    58  	}
    59  	if conf == nil {
    60  		conf = new(Config)
    61  	}
    62  	base := conf.BaseDir
    63  	if base == "" {
    64  		if base, err = os.Getwd(); err != nil {
    65  			return
    66  		}
    67  	}
    68  	compiler := conf.Compiler
    69  	if compiler == "" {
    70  		compiler = "clang"
    71  	}
    72  	ppflag := conf.PPFlag
    73  	if ppflag == "" {
    74  		ppflag = "-E"
    75  	}
    76  	n := 4 + len(conf.Flags) + len(conf.IncludeDirs) + len(conf.Defines)
    77  	args := make([]string, 3, n)
    78  	args[0] = ppflag
    79  	args[1], args[2] = "-o", outfile
    80  	args = append(args, conf.Flags...)
    81  	for _, def := range conf.Defines {
    82  		args = append(args, "-D"+def)
    83  	}
    84  	for _, inc := range conf.IncludeDirs {
    85  		args = append(args, "-I"+pathutil.Canonical(base, inc))
    86  	}
    87  	args = append(args, infile)
    88  	if debugExecCmd {
    89  		log.Println("==> runCmd:", compiler, args)
    90  	}
    91  	cmd := exec.Command(compiler, args...)
    92  	cmd.Dir = filepath.Dir(infile)
    93  	cmd.Stdin = os.Stdin
    94  	cmd.Stdout = os.Stdout
    95  	cmd.Stderr = os.Stderr
    96  	return cmd.Run()
    97  }
    98  
    99  // -----------------------------------------------------------------------------