github.com/metux/go-metabuild@v0.0.0-20240118143255-d9ed5ab697f9/util/compiler/base/pkgconfig.go (about)

     1  package base
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/buildkite/shellwords"
     7  
     8  	"github.com/metux/go-metabuild/util/cmd"
     9  	"github.com/metux/go-metabuild/util/fileutil"
    10  )
    11  
    12  // FIXME: how differenciate between static and dynamic ?
    13  // FIXME: should we split it into two separate instances ?
    14  type PkgConfigInfo struct {
    15  	Id          string
    16  	PkgSpec     string
    17  	Name        string
    18  	Version     string
    19  	Description string
    20  
    21  	Requires []string
    22  
    23  	// FIXME: only-L only-I etc
    24  	SharedCflags  []string
    25  	SharedLdflags []string
    26  
    27  	StaticCflags  []string
    28  	StaticLdflags []string
    29  
    30  	Variables map[string]string
    31  
    32  	// These aren't read from .pc files, but may be set by other places
    33  	Private    bool
    34  	WantStatic bool
    35  	WantShared bool
    36  }
    37  
    38  func (p PkgConfigInfo) Write(fn string) error {
    39  	wr, err := fileutil.CreateWriter(fn)
    40  	defer wr.Close()
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	wr.WriteField("Name", p.Name)
    46  	wr.WriteField("Description", p.Description)
    47  	wr.WriteField("Version", p.Version)
    48  	wr.WriteField("Libs", strings.Join(p.SharedLdflags, " "))
    49  	wr.WriteField("Cflags", strings.Join(p.SharedCflags, " "))
    50  	for _, x := range p.Requires {
    51  		wr.WriteField("Requires", x)
    52  	}
    53  
    54  	wr.WriteString("\n")
    55  
    56  	for k, v := range p.Variables {
    57  		wr.WriteVar(k, v)
    58  	}
    59  
    60  	return nil
    61  }
    62  
    63  func (p PkgConfigInfo) Valid() bool {
    64  	return p.PkgSpec != ""
    65  }
    66  
    67  // FIXME: what about sysroot ?
    68  func PkgConfigQuery(pkgspec string, cmdline []string) (PkgConfigInfo, error) {
    69  	info := PkgConfigInfo{PkgSpec: pkgspec, Variables: make(map[string]string)}
    70  	cmdline = append(cmdline, pkgspec)
    71  
    72  	// modversion
    73  	if out, err := cmd.RunOutOne(append(cmdline, "--modversion"), true); err == nil {
    74  		info.Version = out
    75  	} else {
    76  		return info, err
    77  	}
    78  
    79  	// virtual package name
    80  	if out, err := cmd.RunOutOne(append(cmdline, "--print-provides"), true); err == nil {
    81  		info.Name = out
    82  	} else {
    83  		return info, err
    84  	}
    85  
    86  	// ldflags shared
    87  	if out, err := cmd.RunOutCmd(append(cmdline, "--libs"), true); err == nil {
    88  		info.SharedLdflags = out
    89  	} else {
    90  		return info, err
    91  	}
    92  
    93  	// ldflags static
    94  	if out, err := cmd.RunOutCmd(append(cmdline, "--static", "--libs"), true); err == nil {
    95  		info.StaticLdflags = out
    96  	} else {
    97  		return info, err
    98  	}
    99  
   100  	// cflags shared
   101  	if out, err := cmd.RunOutCmd(append(cmdline, "--cflags"), true); err == nil {
   102  		info.SharedCflags = out
   103  	} else {
   104  		return info, err
   105  	}
   106  
   107  	// cflags static
   108  	if out, err := cmd.RunOutCmd(append(cmdline, "--static", "--cflags"), true); err == nil {
   109  		info.StaticCflags = out
   110  	} else {
   111  		return info, err
   112  	}
   113  
   114  	if out, err := cmd.RunOutLines(append(cmdline, "--print-variables"), true); err == nil {
   115  		for _, name := range out {
   116  			// FIXME: need to escape
   117  			if value, err := cmd.RunOutOne(append(cmdline, "--variable="+shellwords.Quote(name)), true); err == nil {
   118  				info.Variables[name] = value
   119  			}
   120  		}
   121  	} else {
   122  		return info, err
   123  	}
   124  	return info, nil
   125  }