/
main.go
180 lines (173 loc) · 5.95 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// cmd/pkg-config is a Go-centric and GOPATH-aware pkg-config replacement
// for use with the cgo tool.
//
// ** Using cmd/pkg-config with the cgo command **
//
// To use cmd/pkg-config go install it and ensure it's in the PATH. A NOTE for
// Linux users: the cmd/pkg-config must be present before original
// /usr/bin/pkg-config in the PATH list; it is not advised to replace it,
// as cmd/pkg-config is not a full replacement for the pkg-config tool, e.g.
// it does not implement conflict and dependency resolving.
//
// The cgo tool uses pkg-config for obtaining CFLAGS and LDFLAGS of C libraries.
// Example:
//
// // #cgo pkg-config: libpng
// // #include <libpng12/png.h>
// import "C"
//
// The "#cgo pkg-config: png" directive makes a cgo tool query a pkg-config for
// CFLAGS during generation of a C wrapper (--cflags flag) and for LDFLAGS during
// linking (--libs flag). The original pkg-config looks up a libpng.pc file in
// a directory list specified by the PKG_CONFIG_PATH environment variable plus
// a few other default ones. The libpng.pc file can have the following content:
//
// prefix=/usr
// exec_prefix=${prefix}
// libdir=${prefix}/lib/x86_64-linux-gnu
// includedir=${prefix}/include/libpng12
//
// Name: libpng
// Description: Loads and saves PNG files
// Version: 1.2.46
// Libs: -L${libdir} -lpng12
// Libs.private: -lz -lm
// Cflags: -I${includedir}
//
// A .pc file is composed of two parts - variables and keywords. Keywords may
// reference pre-declared variables.
//
// $ pkg-config --cflags libpng
// -I/usr/include/libpng12
// $ pkg-config --libs libpng
// -L/usr/lib/x86_64-linux-gnu -lpng12
// $ pkg-config --cflags --libs libpng
// -I/usr/include/libpng12 -L/usr/lib/x86_64-linux-gnu -lpng12
//
// The cmd/pkg-config tool looks up for a PC file in two other places in addition
// do the original pkg-config: $GOPATH and github.com.
//
// ** The cmd/pkg-config tool and $GOPATH **
//
// The cmd/pkg-config defines standard directory layout for C libraries:
//
// - $GOPATH/lib contains both the .pc files and binaries
// - $GOPATH/include contains package headers
//
// The $GOPATH tree for the example may look like the following:
//
// $GOPATH
// ├── include
// │ └── libpng
// │ └── libpng12
// │ ├── pngconf.h
// │ └── png.h
// ├── lib
// │ ├── linux_amd64
// │ │ └── libpng
// │ │ ├── libpng12.so
// │ │ └── libpng.pc
// │ └── windows_amd64
// │ └── libpng
// │ ├── libpng12.dll
// │ ├── libpng12.dll.a
// │ └── libpng.pc
// └── src
// └── github.com
// └── joe
// └── png-wrapper
// └── png-wrapper.go
//
// The cmd/pkg-config reads the libpng.pc file from $GOPATH/lib/libpng/$GOOS_$GOARCH/libpng.pc.
// The .pc file written for cmd/pkg-config can use $GOPATH, $GOOS and $GOARCH
// builtin variables, which are expanded by the cmd/pkg-config during runtime.
// The rewritten .pc file for libpng may look like the following:
//
// libdir=${GOPATH}/lib/${GOOS}_${GOARCH}/libpng
// includedir=${GOPATH}/include/libpng
//
// Name: libpng
// Description: Loads and saves PNG files
// Version: 1.2.46
// Libs: -L${libdir} -lpng12
// Libs.private: -lz -lm
// Cflags: -I${includedir}
//
// ** The cmd/pkg-config tool and github.com **
//
// Although it's advised to always use an official or self-compiled libraries for
// a production use, cmd/pkg-config can download a zip archive from project's
// github.com releases for a pkg-config tag and unpack it into $GOPATH.
// For example in order to make the above github.com/joe/png-wrapper package
// pkg-config-gettable, it's enough to zip include/ and lib/ directories:
//
// $ zip -9 -r libpng.zip include dir
//
// Create release, name a tag after pkg-config and attach libpng.zip do the
// file list. This would make the libpng.zip archive be accessible from the following
// link:
//
// $ wget http://github.com/joe/png-wrapper/releases/download/pkg-config/libpng.zip
//
// Which is the default location the cmd/pkg-config searches for libraries. Then
// go-getting a joe/png-wrapper package altogether with C dependencies is as
// easy as:
//
// $ go get github.com/joe/png-wrapper
//
// Default behavior of cmd/pkg-config
//
// The cmd/pkg-config tool looks up a .pc file for a $LIBRARY in the following order:
//
// - $GOPATH/lib/$GOOS_$GOARCH/$LIBRARY/$LIBRARY.pc
// - if PKG_CONFIG_GITHUB=1 is exported, cmd/pkg-config tries to fetch library from
// http://github.com/$USER/$PROJECT/releases/download/pkg-config/$LIBRARY.zip
// - $PKG_CONFIG_PATH and eventual pkg-config's default search locations (platform-specific)
// - if no .pc file is found, pkg-config does its best to generate needed
// flags on-the-fly, assuming needed library files and headers are present
// in current $GOPATH as described above
package main
import (
"fmt"
"os"
"github.com/rjeczalik/pkgconfig"
)
const usage = `NAME:
pkg-config - Go-centric pkg-config replacement
USAGE:
pkg-config --libs LIB
pkg-config --cflags LIB
pkg-config --cflags --libs LIB1 LIB2
pkg-config get github.com/USER/PROJECT LIB`
func die(v ...interface{}) {
for _, v := range v {
fmt.Fprintln(os.Stderr, v)
}
os.Exit(1)
}
func ishelp(s string) bool {
return s == "-h" || s == "-help" || s == "help" || s == "--help" || s == "/?"
}
func main() {
if len(os.Args) == 1 || (len(os.Args) == 2 && ishelp(os.Args[1])) {
fmt.Println(usage)
} else {
switch os.Args[1] {
case "get":
if len(os.Args) != 4 {
die(usage)
}
_, err := pkgconfig.LookupGithubProj(os.Args[3], os.Args[2])
if err != nil {
die(err)
}
default:
pkg := pkgconfig.NewPkgArgs(os.Args[1:])
if err := pkg.Resolve(); err == nil {
pkg.WriteTo(os.Stdout)
} else {
die(err)
}
}
}
}