| 1 | module pkgconfig |
| 2 | |
| 3 | import flag |
| 4 | import strings |
| 5 | |
| 6 | pub struct Main { |
| 7 | pub mut: |
| 8 | opt &MainOptions = unsafe { nil } |
| 9 | res string |
| 10 | has_actions bool |
| 11 | } |
| 12 | |
| 13 | struct 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 | |
| 37 | fn 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 | |
| 45 | pub 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 | |
| 75 | pub 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 | |
| 161 | fn 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 | |
| 179 | fn 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 | |