1#!@INSTALLSHELLPATH@ 2# Copyright (C) 2018, 2021 g10 Code GmbH 3# 4# This file is free software; as a special exception the author gives 5# unlimited permission to copy and/or distribute it, with or without 6# modifications, as long as this notice is preserved. 7# 8# This file is distributed in the hope that it will be useful, but 9# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 10# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11# SPDX-License-Identifier: FSFULLR 12 13#### start of functions for this script 14 15# 16# Bourne shell functions for config file in pkg-config style, so that 17# we can share such a config file between pkg-config and script 18# 19 20# 21# get_var: Get the variable value of NAME 22# 23# Variables are recorded in the shell variables named "VAR_<NAME>" 24# 25get_var () { 26 ___name=$1 27 28 eval echo \$VAR_$___name 29} 30 31# 32# get_attr: Get the attribute value of KEY 33# 34# Attributes are recorded in the shell variables named "ATTR_<KEY>" 35# 36get_attr () { 37 ___name=$1 38 39 eval echo \$ATTR_$___name 40} 41 42# variant of get_attr for list (separated by ',') 43get_attr_l () { 44 (IFS=', '; for x in "$(get_attr $1)"; do echo $x; done) 45} 46 47# Remove ${varname} part in the beginning of a string. 48remove_var_expr () { 49 ___varname=$1 50 shift 51 52 expr "$*" : "\${$___varname}\\(.*\\)" 53} 54 55# Given a string, substitute variables. 56substitute_vars () { 57 __string="$1" 58 __varname="" 59 __result="" 60 61 while [ -n "$__string" ]; do 62 case "$__string" in 63 \$\$*) 64 __result="$__result\$" 65 __string="${__string#\$\$}" 66 ;; 67 \${*}*) 68 __varname="${__string#\$\{}" 69 __varname="${__varname%%\}*}" 70 __result="$__result$(get_var $__varname)" 71 __string=$(remove_var_expr $__varname $__string) 72 ;; 73 *) 74 __result="$__result$(printf %c "$__string")" 75 __string="${__string#$(printf %c "$__string")}" 76 ;; 77 esac 78 done 79 80 echo "$__result" 81} 82 83# 84# Read a config from stdin 85# 86# Variables: 87# For VAR=VALUE, value is stored in the shell variable VAR_*. 88# 89# Attributes: 90# For KEY: VALUE, value is stored in the shell variable ATTR_*. 91# 92read_config_from_stdin () { 93 _filename=$1 94 _line="" 95 _varname="" 96 _value="" 97 _key="" 98 _reading_attrs="" 99 100 while read _line; do 101 if [ -z "$_line" ]; then 102 _reading_attrs=yes 103 continue 104 elif [ -z "$_reading_attrs" ]; then 105 case "$_line" in 106 *=*) 107 _varname="${_line%%=*}" 108 _value="${_line#*=}" 109 VAR_list="$VAR_list${VAR_list:+ }VAR_$_varname" 110 read VAR_$_varname <<EOF1 111$(substitute_vars "$_value") 112EOF1 113 continue 114 ;; 115 *) _reading_attrs=yes ;; 116 esac 117 fi 118 if [ -n "$_reading_attrs" ]; then 119 case "$_line" in 120 *:\ *) 121 _key="${_line%%:\ *}" 122 _value="${_line#*:\ }" 123 if expr "$_key" : ".*\..*" >/dev/null; then 124 _key="${_key%.*}_${_key#*.}" 125 fi 126 ATTR_list="$ATTR_list${ATTR_list:+ }ATTR_$_key" 127 read ATTR_$_key <<EOF2 128$(substitute_vars "$_value") 129EOF2 130 ;; 131 *:|*:\ ) ;; 132 *) 133 echo "Error reading $_filename: $_line" 1>&2 134 exit 1 135 ;; 136 esac 137 fi 138 done 139} 140 141 142find_file_in_path () { 143 _f=$1 144 _p=$2 145 _saved_IFS="$IFS" 146 _arg="" 147 IFS=":" # On Windows it should be ";"??? 148 149 for _arg in $_p; do 150 if [ -r $_arg/$_f ]; then 151 RESULT="$_arg/$_f" 152 IFS="$_saved_IFS" 153 return 0 154 fi 155 done 156 IFS="$_saved_IFS" 157 RESULT="" 158 return 1 159} 160 161read_config_file () { 162 if ! find_file_in_path $1.pc $2; then 163 if [ -z "$want_exists" ]; then 164 echo "Can't find $1.pc" 1>&2 165 fi 166 exit 1 167 fi 168 read_config_from_stdin $RESULT < $RESULT 169} 170 171cleanup_vars_attrs () { 172 eval unset $VAR_list VAR_list 173 eval unset $ATTR_list ATTR_list 174} 175 176not_listed_yet () { 177 ___m=$1 178 ___arg="" 179 shift 180 181 for ___arg; do 182 if [ $___m = $___arg ]; then 183 return 1 184 fi 185 done 186 187 return 0 188} 189 190list_only_once () { 191 __result="" 192 __arg="" 193 194 for __arg; do 195 if not_listed_yet $__arg $__result; then 196 __result="$__result${__result:+ }$__arg" 197 fi 198 done 199 200 echo $__result 201} 202 203list_only_once_for_libs () { 204 __result="" 205 __rev_list="" 206 __arg="" 207 208 # Scan the list and eliminate duplicates for non-"-lxxx" 209 # the resulted list is in reverse order 210 for __arg; do 211 case "$__arg" in 212 -l*) 213 # As-is 214 __rev_list="$__arg${__rev_list:+ }$__rev_list" 215 ;; 216 *) 217 if not_listed_yet $__arg $__rev_list; then 218 __rev_list="$__arg${__rev_list:+ }$__rev_list" 219 fi 220 ;; 221 esac 222 done 223 224 # Scan again 225 for __arg in $__rev_list; do 226 case "$__arg" in 227 -l*) 228 if not_listed_yet $__arg $__result; then 229 __result="$__arg${__result:+ }$__result" 230 fi 231 ;; 232 *) 233 # As-is 234 __result="$__arg${__result:+ }$__result" 235 ;; 236 esac 237 done 238 239 echo $__result 240} 241 242arg1_is_same () { 243 [ "$1" = "=" -o "$1" = ">=" -o "$1" = "<=" ] 244} 245 246arg1_is_less () { 247 [ "$1" = "!=" -o "$1" = "<" -o "$1" = "<=" ] 248} 249 250arg1_is_great () { 251 [ "$1" = "!=" -o "$1" = ">" -o "$1" = ">=" ] 252} 253 254# 255# Evaluate comparison between versions in RPM way 256# 257eval_compare_version () { 258 ___str1="$1" 259 ___cmp="$2" 260 ___str2="$3" 261 ___char1="" 262 ___char2="" 263 ___chunk1="" 264 ___chunk2="" 265 266 while [ -n "$___str1" -a -n "$___str2" ]; do 267 # Trim anything that's not alnum or tilde from the front 268 ___str1="$(expr "$___str1" : '[^0-9A-Za-z~]*\(.*\)')" 269 ___str2="$(expr "$___str2" : '[^0-9A-Za-z~]*\(.*\)')" 270 271 # Get the first character 272 ___char1=${___str1%${___str1#?}} 273 ___char2=${___str2%${___str2#?}} 274 275 if [ "$___char1" = ~ -o "$___char2" = ~ ]; then 276 if [ "$___char1" != ~ ]; then 277 arg1_is_great $___cmp 278 return 279 fi 280 if [ "$___char2" != ~ ]; then 281 arg1_is_less $___cmp 282 return 283 fi 284 ___str1=${___str1#~} 285 ___str2=${___str2#~} 286 continue 287 fi 288 289 if [ -z "$___char1" -o -z "$___char2" ]; then 290 break 291 fi 292 293 case "$___char1$___char2" in 294 [0-9][A-Za-z]) 295 arg1_is_great $___cmp 296 return 297 ;; 298 [A-Za-z][0-9]) 299 arg1_is_less $___cmp 300 return 301 ;; 302 [0-9][0-9]) 303 ___chunk1="$(expr "$___str1" : '\([0-9]*\)')" 304 ___chunk2="$(expr "$___str2" : '\([0-9]*\)')" 305 ;; 306 [A-Za-z][A-Za-z]) 307 ___chunk1="$(expr "$___str1" : '\([A-Za-z]*\)')" 308 ___chunk2="$(expr "$___str2" : '\([A-Za-z]*\)')" 309 ;; 310 esac 311 312 # Compare chunks numerically if digits, or lexicographically 313 if expr "$___chunk1" "!=" "$___chunk2" >/dev/null; then 314 if expr "$___chunk1" ">" "$___chunk2" >/dev/null; then 315 arg1_is_great $___cmp 316 return 317 else 318 arg1_is_less $___cmp 319 return 320 fi 321 fi 322 323 # Remove the chunk 324 ___str1="${___str1#$___chunk1}" 325 ___str2="${___str2#$___chunk2}" 326 done 327 328 # Either STR1, STR2 or both is empty here 329 if [ -n "$___str1" ]; then 330 case "$___str1" in 331 ~*) arg1_is_less $___cmp ;; 332 *) arg1_is_great $___cmp ;; 333 esac 334 elif [ -n "$___str2" ]; then 335 case "$___str2" in 336 ~*) arg1_is_great $___cmp ;; 337 *) arg1_is_less $___cmp ;; 338 esac 339 else 340 arg1_is_same $___cmp 341 fi 342} 343 344# 345# Recursively solve package dependencies 346# 347# Result is in the PKG_LIST variable 348# 349all_required_config_files () { 350 all_list="" 351 new_list="" 352 p="" 353 pkg="" 354 cmp="" 355 356 list=$* 357 while [ -n "$list" ]; do 358 for p in $list; do 359 if [ -z "$pkg" ]; then 360 pkg=$p 361 elif [ -z "$cmp" ]; then 362 case "$p" in 363 "="|"!="|"<"|">"|"<="|">=") cmp=$p ;; 364 *) 365 read_config_file $pkg $PKG_CONFIG_PATH 366 all_list="$all_list${all_list:+ }$pkg" 367 new_list="$new_list${new_list:+ }$(get_attr_l Requires)" 368 if [ -n "$enable_static" ]; then 369 new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" 370 fi 371 cleanup_vars_attrs 372 pkg=$p 373 ;; 374 esac 375 else 376 read_config_file $pkg $PKG_CONFIG_PATH 377 if ! eval_compare_version "$(get_attr Version)" $cmp $p; then 378 echo "Version mismatch for $pkg $cmp $p: $(get_attr Version)" 1>&2 379 exit 1 380 fi 381 all_list="$all_list${all_list:+ }$pkg" 382 new_list="$new_list${new_list:+ }$(get_attr_l Requires)" 383 if [ -n "$enable_static" ]; then 384 new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" 385 fi 386 cleanup_vars_attrs 387 pkg="" 388 cmp="" 389 fi 390 done 391 if [ -n "$cmp" ]; then 392 echo "No version after comparison operator ($cmp): $pkg" 1>&2 393 exit 1 394 elif [ -n "$pkg" ]; then 395 read_config_file $pkg $PKG_CONFIG_PATH 396 all_list="$all_list${all_list:+ }$pkg" 397 new_list="$new_list${new_list:+ }$(get_attr_l Requires)" 398 if [ -n "$enable_static" ]; then 399 new_list="$new_list${new_list:+ }$(get_attr_l Requires_private)" 400 fi 401 cleanup_vars_attrs 402 fi 403 404 list="$new_list" 405 new_list="" 406 done 407 408 PKG_LIST=$(list_only_once $all_list) 409} 410 411# 412# Modify -I or -L by PKG_CONFIG_SYSROOT_DIR variable 413# 414sysroot () { 415 _opt="$1" 416 _result="" 417 shift 418 419 while [ $# -gt 0 ]; do 420 if [ $1 = $_opt ]; then 421 _result="$_result${_result:+ }$_opt" 422 shift 423 _result="$_result $PKG_CONFIG_SYSROOT_DIR$1" 424 elif expr "x$1" : "^x$_opt" >/dev/null; then 425 _result="$_result${_result:+ }$_opt$PKG_CONFIG_SYSROOT_DIR$(expr "x$1" : "^x$_opt\(.*\)")" 426 else 427 _result="$_result${_result:+ }$1" 428 fi 429 shift 430 done 431 echo "$_result" 432} 433 434# Show usage 435usage () { 436 cat <<EOF 437Usage: gpgrt-config [--libdir=LIBDIR] [OPTIONS] MODULES 438Options: 439 [--exists] 440 [--modversion] 441 [--libs] 442 [--cflags] 443 [--static] 444 [--variable=VARNAME] 445EOF 446 exit $1 447} 448#### end of functions for this script 449 450myname=${0##*/} 451if [ $myname = gpgrt-config ]; then 452 default_module="gpg-error" 453else 454 default_module=${myname%-config} 455fi 456 457# First stage to process --libdir option 458 459libdir="" 460while test $# -gt 0; do 461 case $1 in 462 --libdir=*) 463 libdir=${1#--libdir=} 464 shift 465 ;; 466 *) 467 break 468 ;; 469 esac 470done 471 472if [ x"${PKG_CONFIG_LIBDIR:+set}" = xset -a -z "$PKG_CONFIG_LIBDIR" ]; then 473 # The variable set as empty, we use PKG_CONFIG_PATH in this case, 474 # ignoring --libdir option 475 if [ -z "$PKG_CONFIG_PATH" ]; then 476 echo "Please have valid PKG_CONFIG_PATH if PKG_CONFIG_LIBDIR is empty" 1>&2 477 exit 1 478 fi 479else 480 if [ -n "$libdir" ]; then 481 # --libdir option is available, it overrides existing PKG_CONFIG_LIBDIR 482 PKG_CONFIG_LIBDIR=$libdir/pkgconfig 483 fi 484 if [ -z "$PKG_CONFIG_LIBDIR" ]; then 485 if [ -z "$PKG_CONFIG_PATH" ]; then 486 echo "Please use --libdir=LIBDIR option or set PKG_CONFIG_LIBDIR" 1>&2 487 echo "Or set PKG_CONFIG_PATH" 1>&2 488 exit 1 489 fi 490 else 491 # PKG_CONFIG_LIBDIR is available here 492 # Modify PKG_CONFIG_PATH, prepending PKG_CONFIG_LIBDIR 493 PKG_CONFIG_PATH="$PKG_CONFIG_LIBDIR${PKG_CONFIG_PATH:+:}$PKG_CONFIG_PATH" 494 fi 495fi 496# PKG_CONFIG_PATH is ready here 497 498# 499 500if test $# -eq 0; then 501 usage 1 1>&2 502fi 503 504 505# Second stage to do the main functionality 506 507module_list="" 508want_var="" 509want_attr="" 510want_cflags="" 511want_libs="" 512want_exists="" 513enable_static="" 514 515cflags="" 516libs="" 517mtcflags="" 518mtlibs="" 519 520output="" 521 522mt="no" 523 524VAR_list=VAR_pc_sysrootdir 525if [ -z "$PKG_CONFIG_SYSROOT_DIR" ]; then 526 VAR_pc_sysrootdir="/" 527else 528 VAR_pc_sysrootdir="$PKG_CONFIG_SYSROOT_DIR" 529fi 530 531while test $# -gt 0; do 532 case $1 in 533 #### pkg-config incompatible options: begin 534 --prefix) 535 # In future, use --variable=prefix instead. 536 want_var=prefix 537 ;; 538 --exec-prefix) 539 # In future, use --variable=exec_prefix instead. 540 want_var=exec_prefix 541 ;; 542 --version) 543 # In future, use --modversion instead. 544 want_attr=Version 545 ;; 546 --api-version) 547 # In future, use --variable=api_version instead. 548 want_var=api_version 549 ;; 550 --host) 551 # In future, use --variable=host instead. 552 want_var=host 553 ;; 554 --mt) 555 # In future, use --variable=mtcflags or --variable=mtlibs. 556 mt=yes 557 ;; 558 #### pkg-config incompatible options: end 559 --modversion) 560 want_attr=Version 561 ;; 562 --exists) 563 want_exists=yes 564 ;; 565 --cflags) 566 want_cflags=yes 567 ;; 568 --libs) 569 want_libs=yes 570 ;; 571 --static) 572 enable_static=yes 573 ;; 574 --variable=*) 575 want_var=${1#*=} 576 ;; 577 --help) 578 usage 0 579 ;; 580 --*) 581 usage 1 1>&2 582 ;; 583 *) 584 # Modules 585 module_list="$module_list${module_list:+ }$1" 586 ;; 587 esac 588 589 shift 590done 591 592 593if [ -z "$module_list" ]; then 594 module_list=$default_module 595elif expr "$module_list" : "=\|!=\|<\|>\|<=\|>=" >/dev/null; then 596 module_list="$default_module $module_list" 597fi 598 599all_required_config_files $module_list 600 601for p in $PKG_LIST; do 602 read_config_file $p $PKG_CONFIG_PATH 603 # For want_var or want_attr, get it from the first package 604 if [ -n "$want_var" ]; then 605 output="$(get_var $want_var)" 606 break 607 elif [ -n "$want_attr" ]; then 608 output="$(get_attr $want_attr)" 609 break 610 else 611 cflags="$cflags${cflags:+ }$(get_attr Cflags)" 612 libs="$libs${libs:+ }$(get_attr Libs)" 613 if [ -n "$enable_static" ]; then 614 libs="$libs${libs:+ }$(get_attr Libs_private)" 615 fi 616 617 if [ $p = "gpg-error" ]; then 618 mtcflags="$(get_var mtcflags)" 619 mtlibs="$(get_var mtlibs)" 620 fi 621 fi 622 cleanup_vars_attrs 623done 624 625if [ -z "$want_var" -a -z "$want_attr" ]; then 626 if [ -n "$want_cflags" ]; then 627 output="$output${output:+ }$(sysroot -I $(list_only_once $cflags))" 628 # Backward compatibility to old gpg-error-config 629 if [ $mt = yes -a -n "$mtcflags" ]; then 630 output="$output${output:+ }$mtcflags" 631 fi 632 fi 633 if [ -n "$want_libs" ]; then 634 output="$output${output:+ }$(sysroot -L $(list_only_once_for_libs $libs))" 635 # Backward compatibility to old gpg-error-config 636 if [ $mt = yes -a -n "$mtlibs" ]; then 637 output="$output${output:+ }$mtlibs" 638 fi 639 fi 640fi 641 642if [ -z "$want_exists" ]; then 643 echo "$output" 644fi 645 646exit 0 647