v2 / vlib / v / pkgconfig / main.v
208 lines · 200 sloc · 5.13 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1module pkgconfig
2
3import flag
4import strings
5
6pub struct Main {
7pub mut:
8 opt &MainOptions = unsafe { nil }
9 res string
10 has_actions bool
11}
12
13struct MainOptions {
14 modversion bool
15 description bool
16 help bool
17 debug bool
18 listall bool
19 exists bool
20 variables bool
21 requires bool
22 atleast string
23 atleastpc string
24 exactversion string
25 version bool
26 cflags bool
27 cflags_only_path bool
28 cflags_only_other bool
29 stat1c bool
30 libs bool
31 libs_only_link bool
32 libs_only_path bool
33 libs_only_other bool
34 args []string
35}
36
37fn desc(mod string) !string {
38 options := Options{
39 only_description: true
40 }
41 mut pc := load(mod, options) or { return error('cannot parse') }
42 return pc.description
43}
44
45pub fn main(args []string) !&Main {
46 mut fp := flag.new_flag_parser(args)
47 fp.application('pkgconfig')
48 fp.version(version)
49 mut m := &Main{
50 opt: parse_options(mut fp)
51 }
52 opt := m.opt
53 if opt.help {
54 m.res = fp.usage()
55 } else if opt.version {
56 m.res = version
57 } else if opt.listall {
58 mut modules := list()
59 modules.sort()
60 if opt.description {
61 for mod in modules {
62 d := desc(mod) or { continue }
63 pad := strings.repeat(` `, 20 - mod.len)
64 m.res += '${mod} ${pad} ${d}\n'
65 }
66 } else {
67 m.res = modules.join('\n')
68 }
69 } else if opt.args.len == 0 {
70 return error('No packages given')
71 }
72 return m
73}
74
75pub fn (mut m Main) run() !string {
76 options := Options{
77 debug: m.opt.debug
78 }
79 // m.opt = options
80 opt := m.opt
81 mut pc := &PkgConfig(unsafe { nil })
82 mut res := m.res
83 for arg in opt.args {
84 mut pcdep := load(arg, options) or {
85 if !opt.exists {
86 return err
87 }
88 continue
89 }
90 if opt.description {
91 if res != '' {
92 res += '\n'
93 }
94 res += pcdep.description
95 }
96 if unsafe { pc != 0 } {
97 pc.extend(pcdep)
98 } else {
99 pc = pcdep
100 }
101 }
102 if opt.exists {
103 return res
104 }
105 if opt.exactversion != '' {
106 if pc.version != opt.exactversion {
107 return error('version mismatch')
108 }
109 return res
110 }
111 if opt.atleast != '' {
112 if pc.atleast(opt.atleast) {
113 return error('version mismatch')
114 }
115 return res
116 }
117 if opt.atleastpc != '' {
118 if atleast(opt.atleastpc) {
119 return error('version mismatch')
120 }
121 return res
122 }
123 if opt.variables {
124 res = pc.vars.keys().join('\n')
125 }
126 if opt.requires {
127 res += pc.requires.join('\n')
128 }
129 mut r := []string{}
130 if opt.cflags_only_path {
131 r << filter(pc.cflags, '-I', '')
132 }
133 if opt.cflags_only_other {
134 r << filter(pc.cflags, '-I', '-I')
135 }
136 if opt.cflags {
137 r << pc.cflags.join(' ')
138 }
139 if opt.libs_only_link {
140 r << filter(pc.libs, '-l', '')
141 }
142 if opt.libs_only_path {
143 r << filter(pc.libs, '-L', '')
144 }
145 if opt.libs_only_other {
146 r << filter(pc.libs, '-l', '-L')
147 }
148 if opt.libs {
149 if opt.stat1c {
150 r << pc.libs_private.join(' ')
151 } else {
152 r << pc.libs.join(' ')
153 }
154 }
155 if opt.modversion {
156 r << pc.version
157 }
158 return res + r.join(' ')
159}
160
161fn filter(libs []string, prefix string, prefix2 string) string {
162 mut res := ''
163 if prefix2 != '' {
164 for lib in libs {
165 if !lib.starts_with(prefix) && !lib.starts_with(prefix2) {
166 res += ' ${lib}'
167 }
168 }
169 } else {
170 for lib in libs {
171 if lib.starts_with(prefix) {
172 res += ' ${lib}'
173 }
174 }
175 }
176 return res
177}
178
179fn parse_options(mut fp flag.FlagParser) &MainOptions {
180 return &MainOptions{
181 description: fp.bool('description', `d`, false, 'show pkg module description')
182 modversion: fp.bool('modversion', `V`, false, 'show version of module')
183 help: fp.bool('help', `h`, false, 'show this help message')
184 debug: fp.bool('debug', `D`, false, 'show debug information')
185 listall: fp.bool('list-all', `p`, false, 'list all pkgmodules')
186 exists: fp.bool('exists', `e`, false, 'return 0 if pkg exists')
187 variables: fp.bool('print-variables', `P`, false, 'display variable names')
188 requires: fp.bool('print-requires', `r`, false, 'display requires of the module')
189 atleast: fp.string('atleast-version', `a`, '',
190 'return 0 if pkg version is at least the given one')
191 atleastpc: fp.string('atleast-pkgconfig-version', `A`, '',
192 'return 0 if pkgconfig version is at least the given one')
193 exactversion: fp.string('exact-version', ` `, '',
194 'return 0 if pkg version is at least the given one')
195 version: fp.bool('version', `v`, false, 'show version of this tool')
196 cflags: fp.bool('cflags', `c`, false,
197 'output all pre-processor and compiler flags')
198 cflags_only_path: fp.bool('cflags-only-I', `I`, false, 'show only -I flags from CFLAGS')
199 cflags_only_other: fp.bool('cflags-only-other', ` `, false, 'show cflags without -I')
200 stat1c: fp.bool('static', `s`, false, 'show --libs for static linking')
201 libs: fp.bool('libs', `l`, false, 'output all linker flags')
202 libs_only_link: fp.bool('libs-only-l', ` `, false, 'show only -l from ldflags')
203 libs_only_path: fp.bool('libs-only-L', `L`, false, 'show only -L from ldflags')
204 libs_only_other: fp.bool('libs-only-other', ` `, false,
205 'show flags not containing -l or -L')
206 args: fp.args
207 }
208}
209