mirror of
https://github.com/pkgconf/pkgconf.git
synced 2026-01-27 01:44:34 +00:00
Compare commits
388 Commits
pkgconf-2.
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c2743f6e3 | ||
|
|
65237e9d91 | ||
|
|
a950adc6ef | ||
|
|
be8459e5fe | ||
|
|
130c149072 | ||
|
|
2a7c05b9c7 | ||
|
|
ba33d22032 | ||
|
|
e574c85325 | ||
|
|
4a49b50e3b | ||
|
|
cc432b332c | ||
|
|
9bac6b3a1d | ||
|
|
9cd3629f85 | ||
|
|
18e32f2fb6 | ||
|
|
07dfbfffee | ||
|
|
5e26791ba5 | ||
|
|
b1dd65e45d | ||
|
|
192bc8c923 | ||
|
|
da019f2059 | ||
|
|
52c2b0c2cb | ||
|
|
c8018139cc | ||
|
|
b08efccad8 | ||
|
|
b785d620fe | ||
|
|
1984ff2da6 | ||
|
|
5b2c0a1110 | ||
|
|
9e802e5d76 | ||
|
|
d1bfa530be | ||
|
|
f702beddf9 | ||
|
|
f887c83082 | ||
|
|
cceebf098f | ||
|
|
97e2d0433e | ||
|
|
18dbb91e7a | ||
|
|
67c63bbba4 | ||
|
|
06b04a2968 | ||
|
|
bbdf8ccee1 | ||
|
|
55d5937800 | ||
|
|
450bccfef9 | ||
|
|
aaa89a4489 | ||
|
|
3bc327655b | ||
|
|
964d595977 | ||
|
|
93e085d144 | ||
|
|
ebba516806 | ||
|
|
08bc7159d3 | ||
|
|
c7b788699e | ||
|
|
34cf8ae094 | ||
|
|
20145bcfc1 | ||
|
|
222c5b5153 | ||
|
|
0a44b9fa60 | ||
|
|
2ab26a0b23 | ||
|
|
0c7acae717 | ||
|
|
45648f2562 | ||
|
|
b5046faab0 | ||
|
|
b62019892e | ||
|
|
039e596439 | ||
|
|
16cdb57887 | ||
|
|
69dafb8ef1 | ||
|
|
9ae7adfcce | ||
|
|
d243ccd02c | ||
|
|
7103f16ec9 | ||
|
|
8ea545f5a3 | ||
|
|
9061bd0fcf | ||
|
|
c4f94af0bf | ||
|
|
c2ded48007 | ||
|
|
1af0659abc | ||
|
|
cdd2f4caec | ||
|
|
965894e1c9 | ||
|
|
5ac9edec05 | ||
|
|
f69ed723c0 | ||
|
|
eacbbbf54e | ||
|
|
8230b86da9 | ||
|
|
a4ade8586d | ||
|
|
6867afe86e | ||
|
|
330a6f7761 | ||
|
|
de33da1e41 | ||
|
|
9d7e6b2799 | ||
|
|
10be94af88 | ||
|
|
a1e8f100c1 | ||
|
|
ac2f34ed11 | ||
|
|
73780a4239 | ||
|
|
e2ba86341d | ||
|
|
6f1009103a | ||
|
|
03a0f5a25d | ||
|
|
b8d8a5c8fd | ||
|
|
7bbdf301e7 | ||
|
|
ecbedee413 | ||
|
|
077a1995d7 | ||
|
|
e187002cb6 | ||
|
|
f7689804f0 | ||
|
|
000be0b6d1 | ||
|
|
34713f899f | ||
|
|
0376cc9142 | ||
|
|
9a687744e8 | ||
|
|
8210926404 | ||
|
|
c4a7081727 | ||
|
|
7f6849d0f8 | ||
|
|
2017526750 | ||
|
|
0192269d62 | ||
|
|
a7b6ef193f | ||
|
|
cce39cb495 | ||
|
|
4cba08e2bf | ||
|
|
0cd4a5c238 | ||
|
|
521bb4e6e8 | ||
|
|
db6bcbdcbe | ||
|
|
a0933c8b1b | ||
|
|
dfd20e49fc | ||
|
|
ff07f6b7eb | ||
|
|
d0823a14fc | ||
|
|
bb79dad5fe | ||
|
|
38b67e8c3b | ||
|
|
98784f1d42 | ||
|
|
fd604729c4 | ||
|
|
be0687f637 | ||
|
|
50da3bde52 | ||
|
|
eab5f5da93 | ||
|
|
c7d8ebc439 | ||
|
|
a592567215 | ||
|
|
1cbe6de04f | ||
|
|
8459b05bbf | ||
|
|
c7069a080b | ||
|
|
f2b7af94e5 | ||
|
|
41d320f679 | ||
|
|
6682bcb78d | ||
|
|
62473d1481 | ||
|
|
53db712972 | ||
|
|
0a0e74ec2e | ||
|
|
82e66bf096 | ||
|
|
5951b644bb | ||
|
|
38151d1726 | ||
|
|
def161ad50 | ||
|
|
cf246dba4f | ||
|
|
232cbc0cc9 | ||
|
|
0c38d0afd6 | ||
|
|
be9f756e3d | ||
|
|
d619fc6f10 | ||
|
|
9378236fe3 | ||
|
|
213cccf9dc | ||
|
|
0ed38cec79 | ||
|
|
74bb9a2301 | ||
|
|
ab3bddd80b | ||
|
|
a32da62aa7 | ||
|
|
36ac187ad5 | ||
|
|
0fc3ba9d95 | ||
|
|
8f9161514b | ||
|
|
c863ef3f82 | ||
|
|
530fc89d13 | ||
|
|
c8bfa9fee0 | ||
|
|
dc0805a3ad | ||
|
|
9590e052bb | ||
|
|
b689fedcd9 | ||
|
|
0658ba7721 | ||
|
|
008f963693 | ||
|
|
018983a78f | ||
|
|
4e2fde48f6 | ||
|
|
e2ae592b89 | ||
|
|
ecd1a20915 | ||
|
|
3a24e69a8f | ||
|
|
51dc5f6b8d | ||
|
|
5f6681478e | ||
|
|
741ee356b9 | ||
|
|
a779abe2a4 | ||
|
|
9e96c090dc | ||
|
|
a3da8f5cd4 | ||
|
|
e07ba0af64 | ||
|
|
44d8d567d3 | ||
|
|
31c71208e3 | ||
|
|
62da037c5b | ||
|
|
e733223092 | ||
|
|
3dbec89d3d | ||
|
|
6cfe4ee587 | ||
|
|
4c4a4242dc | ||
|
|
e80c5f0c9a | ||
|
|
1f42fa99fe | ||
|
|
502fcdf71c | ||
|
|
2e3b56aa4b | ||
|
|
1d9142c4c7 | ||
|
|
fff4302b05 | ||
|
|
1fcc01aa4f | ||
|
|
8bae84d6a4 | ||
|
|
90f9186e10 | ||
|
|
467328ec8b | ||
|
|
92cb09751a | ||
|
|
5d6c90faaf | ||
|
|
f3aac2724a | ||
|
|
42b6a6a04c | ||
|
|
e0b3ca8330 | ||
|
|
ce401e3c45 | ||
|
|
7c46095d0b | ||
|
|
98d0b9342e | ||
|
|
16cebd6262 | ||
|
|
da8cb80179 | ||
|
|
ad0d8b3944 | ||
|
|
0a3cd05bcd | ||
|
|
4e20b02177 | ||
|
|
e1e788c8cc | ||
|
|
2bfd36beb4 | ||
|
|
0fb2ce907b | ||
|
|
75b57db562 | ||
|
|
ccd916d0a8 | ||
|
|
ef935a6349 | ||
|
|
c7b21f5755 | ||
|
|
2a17e025ab | ||
|
|
bff83a117b | ||
|
|
9baf542f84 | ||
|
|
a1e09753bc | ||
|
|
c598ef7218 | ||
|
|
bbe8ab6593 | ||
|
|
4307d691f9 | ||
|
|
f0826ce2d2 | ||
|
|
e77e36c15c | ||
|
|
c9d54312ee | ||
|
|
136562c699 | ||
|
|
ba731727d3 | ||
|
|
589d8028c4 | ||
|
|
d0481ddafd | ||
|
|
6b68231882 | ||
|
|
4e5fcd810a | ||
|
|
15650665b3 | ||
|
|
fe35ffd555 | ||
|
|
115ce623a3 | ||
|
|
7ba494a0ed | ||
|
|
790ac89795 | ||
|
|
e21de9c671 | ||
|
|
a04e269553 | ||
|
|
2c9a0d2d7b | ||
|
|
706b3cbdd8 | ||
|
|
88ef76a600 | ||
|
|
e6e945835a | ||
|
|
1c0ad34c02 | ||
|
|
499083eba9 | ||
|
|
de3ffe21cf | ||
|
|
c060c5af3f | ||
|
|
1550bf53b3 | ||
|
|
aa6b5c4ca9 | ||
|
|
4fc570f91d | ||
|
|
46059c36d7 | ||
|
|
c52f77854f | ||
|
|
204ad5e48a | ||
|
|
b4547a01f9 | ||
|
|
70748388e8 | ||
|
|
a0fc46a805 | ||
|
|
fea9592aa4 | ||
|
|
efdeb71de5 | ||
|
|
5729e1dd15 | ||
|
|
11ea807fcd | ||
|
|
5c3b5b1da9 | ||
|
|
d3e941554b | ||
|
|
f0be161cc8 | ||
|
|
509c34fa45 | ||
|
|
8886d83900 | ||
|
|
5401935844 | ||
|
|
505f310250 | ||
|
|
ac8cc8006d | ||
|
|
5b02ec3787 | ||
|
|
d6be0d38d5 | ||
|
|
f748308ba0 | ||
|
|
1a28204a96 | ||
|
|
a3af684d16 | ||
|
|
9665d214cb | ||
|
|
0a93248351 | ||
|
|
d477016924 | ||
|
|
01eb0cf19d | ||
|
|
3be7f2cef1 | ||
|
|
aa5813ac5e | ||
|
|
c6f973bd5b | ||
|
|
6fe9458829 | ||
|
|
4dad43adbf | ||
|
|
a1a255ee7d | ||
|
|
86d38119c0 | ||
|
|
e49cbdfcb3 | ||
|
|
205bc7bf42 | ||
|
|
fd7069a209 | ||
|
|
25cbcbc351 | ||
|
|
5925cc4376 | ||
|
|
ad75dec33b | ||
|
|
61610c65cb | ||
|
|
2983d31188 | ||
|
|
10d37b6160 | ||
|
|
1fd56779af | ||
|
|
735fd05427 | ||
|
|
7fbb8bf280 | ||
|
|
e4e3b45b78 | ||
|
|
859402ef3d | ||
|
|
e3f9e6943a | ||
|
|
5ecd34e44b | ||
|
|
187f2604a5 | ||
|
|
a61b00f129 | ||
|
|
f2396064bc | ||
|
|
c34379adaf | ||
|
|
c5953937e8 | ||
|
|
adc549918d | ||
|
|
e607da2e0a | ||
|
|
83c7ca08ef | ||
|
|
5ad8a5bed7 | ||
|
|
e785ee470b | ||
|
|
a7443fe535 | ||
|
|
cab9dcbfcf | ||
|
|
4e7ecc377a | ||
|
|
a2f0af2f29 | ||
|
|
2ad2eaa4e3 | ||
|
|
5a18878451 | ||
|
|
5d363cc715 | ||
|
|
6546c4ba6f | ||
|
|
14d122810d | ||
|
|
7502a55de1 | ||
|
|
4deef17348 | ||
|
|
7b8865d1ba | ||
|
|
265a8a4309 | ||
|
|
bd49b7007a | ||
|
|
d1a5b4f23f | ||
|
|
31d73e40f2 | ||
|
|
bdede95f70 | ||
|
|
5123e18075 | ||
|
|
32cd9afbde | ||
|
|
bd1b791a6a | ||
|
|
e49ae60253 | ||
|
|
c3090718d9 | ||
|
|
db4b02122d | ||
|
|
18332eff9d | ||
|
|
2932604c67 | ||
|
|
4c9afed422 | ||
|
|
d7efcda039 | ||
|
|
50d0a3ae64 | ||
|
|
6414ec2926 | ||
|
|
a1508c5f03 | ||
|
|
9e911529d4 | ||
|
|
71881ffe21 | ||
|
|
293cd1d5a3 | ||
|
|
210014a991 | ||
|
|
4c2eaf5e01 | ||
|
|
d7bdb5e050 | ||
|
|
c6974e244d | ||
|
|
2e1bfc2fbf | ||
|
|
230b45c00c | ||
|
|
664b53d5c4 | ||
|
|
1d37e711ce | ||
|
|
933e925a16 | ||
|
|
c440e2da49 | ||
|
|
4a62f61217 | ||
|
|
5c9ee7eeea | ||
|
|
0df752a40a | ||
|
|
5555862144 | ||
|
|
948c9416d6 | ||
|
|
f3531f9f4d | ||
|
|
4ed28a7ad4 | ||
|
|
c8566a5e0c | ||
|
|
2d6bb53b1e | ||
|
|
bfc9ded550 | ||
|
|
c0d188fb44 | ||
|
|
7e59a32a4b | ||
|
|
8b3dd835ae | ||
|
|
38053395e8 | ||
|
|
866df023ab | ||
|
|
3611b056fb | ||
|
|
97072df584 | ||
|
|
b80ce00fc2 | ||
|
|
680a7c535e | ||
|
|
1dc078f08a | ||
|
|
4f78e44959 | ||
|
|
6ec7df4d19 | ||
|
|
543ab92639 | ||
|
|
5fbabf143c | ||
|
|
97fbb4ffb9 | ||
|
|
a6b1299537 | ||
|
|
ea0e64582a | ||
|
|
9d94f4d28f | ||
|
|
792e2c6225 | ||
|
|
e8dc0e20a7 | ||
|
|
5fe482b247 | ||
|
|
88258bd908 | ||
|
|
f0aa4071ef | ||
|
|
a4de29302c | ||
|
|
68e8f7208b | ||
|
|
f982cbdab9 | ||
|
|
6f1055d00d | ||
|
|
b861bcad49 | ||
|
|
a79952a084 | ||
|
|
86602bc17e | ||
|
|
d0f8f3f228 | ||
|
|
83a2ae0434 | ||
|
|
bd043cae9f | ||
|
|
10017500ff | ||
|
|
5c535171a5 | ||
|
|
3cd6b8c523 | ||
|
|
11236d44fd | ||
|
|
ff51052e1c | ||
|
|
e6c1d4b8bd | ||
|
|
444846dd2d | ||
|
|
8c479a8355 | ||
|
|
4697d636cc |
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@ -1,3 +1 @@
|
||||
github: kaniini
|
||||
patreon: kaniini
|
||||
liberapay: kaniini
|
||||
open_collective: pkgconf
|
||||
|
||||
135
.github/workflows/release-tarballs.yml
vendored
Normal file
135
.github/workflows/release-tarballs.yml
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
name: Generate and upload release artifacts
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'pkgconf-*'
|
||||
|
||||
jobs:
|
||||
tarball:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: alpine:latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: pkgconf/pkgconf
|
||||
|
||||
- name: Update system and add dependencies
|
||||
run: |
|
||||
apk update
|
||||
apk add kyua atf build-base autoconf automake libtool xz gzip tar openssh-client
|
||||
|
||||
- name: Bootstrap autotools
|
||||
run: |
|
||||
sh autogen.sh
|
||||
./configure
|
||||
|
||||
- name: Run tests and generate dist tarballs
|
||||
run: |
|
||||
make distcheck -j$(nproc)
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tarball
|
||||
path: pkgconf-*.tar.*
|
||||
|
||||
msi:
|
||||
name: Build MSI
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: [
|
||||
{ msystem: MINGW64, arch: x86_64},
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: >-
|
||||
mingw-w64-${{ matrix.arch }}-meson
|
||||
mingw-w64-${{ matrix.arch }}-ninja
|
||||
mingw-w64-${{ matrix.arch }}-gcc
|
||||
mingw-w64-${{ matrix.arch }}-msitools
|
||||
|
||||
- name: Build
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# the code assumes msvc style printf atm
|
||||
export CFLAGS=-D__USE_MINGW_ANSI_STDIO=0
|
||||
meson _build --buildtype=release -Dtests=disabled -Db_lto=true
|
||||
meson compile -C _build msi
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: msi
|
||||
path: _build/pkgconf-*.msi
|
||||
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
needs: [tarball, msi]
|
||||
steps:
|
||||
- name: Download tarball artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: tarball
|
||||
path: dist
|
||||
- name: Download msi artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: msi
|
||||
path: dist
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
dist/pkgconf-*.tar.*
|
||||
dist/pkgconf-*.msi
|
||||
|
||||
publish:
|
||||
name: Publish on distfiles.ariadne.space
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
needs: [tarball, msi]
|
||||
steps:
|
||||
- name: Download tarball artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: tarball
|
||||
path: dist
|
||||
- name: Download msi artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: msi
|
||||
path: dist
|
||||
- name: Upload dist tarballs to distfiles.ariadne.space
|
||||
env:
|
||||
DISTFILES_PRIVATE_KEY: ${{ secrets.DISTFILES_PRIVATE_KEY }}
|
||||
DISTFILES_HOST_KEYS: ${{ secrets.DISTFILES_HOST_KEYS }}
|
||||
run: |
|
||||
mkdir -p $HOME/.ssh
|
||||
|
||||
# Ensure the private key is read-only so SSH doesn't reject it.
|
||||
umask 277
|
||||
(echo "$DISTFILES_PRIVATE_KEY" | base64 -d) > $HOME/.ssh/id_ed25519
|
||||
|
||||
umask 077
|
||||
(echo "$DISTFILES_HOST_KEYS" | base64 -d) > $HOME/.ssh/known_hosts
|
||||
|
||||
# Upload the tarballs.
|
||||
scp -i "$HOME/.ssh/id_ed25519" -o "UserKnownHostsFile=$HOME/.ssh/known_hosts" dist/* kaniini@distfiles.ariadne.space:distfiles/pkgconf/
|
||||
|
||||
# Delete the key material.
|
||||
rm -rf $HOME/.ssh
|
||||
42
.github/workflows/test.yml
vendored
42
.github/workflows/test.yml
vendored
@ -13,7 +13,6 @@ jobs:
|
||||
matrix:
|
||||
include: [
|
||||
{ msystem: MINGW64, arch: x86_64},
|
||||
{ msystem: MINGW32, arch: i686}
|
||||
]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@ -28,6 +27,7 @@ jobs:
|
||||
mingw-w64-${{ matrix.arch }}-meson
|
||||
mingw-w64-${{ matrix.arch }}-ninja
|
||||
mingw-w64-${{ matrix.arch }}-gcc
|
||||
mingw-w64-${{ matrix.arch }}-msitools
|
||||
|
||||
- name: Build
|
||||
shell: msys2 {0}
|
||||
@ -35,8 +35,22 @@ jobs:
|
||||
# the code assumes msvc style printf atm
|
||||
export CFLAGS=-D__USE_MINGW_ANSI_STDIO=0
|
||||
|
||||
meson -Dtests=disabled _build
|
||||
meson compile -C _build
|
||||
meson _build
|
||||
meson compile -C _build msi
|
||||
|
||||
- name: Run tests
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
meson test -v -C _build
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-output
|
||||
path: |
|
||||
_build/*.exe
|
||||
_build/*.dll
|
||||
_build/*.msi
|
||||
|
||||
debian-meson:
|
||||
runs-on: ubuntu-latest
|
||||
@ -140,7 +154,7 @@ jobs:
|
||||
- name: Update system and add dependencies
|
||||
run: |
|
||||
apk update
|
||||
apk add kyua atf build-base autoconf automake libtool xz gzip
|
||||
apk add kyua atf build-base autoconf automake libtool xz gzip tar
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@ -151,3 +165,23 @@ jobs:
|
||||
- name: Run tests
|
||||
run: |
|
||||
make distcheck
|
||||
|
||||
analysis:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: alpine
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Update system and add dependencies
|
||||
run: |
|
||||
apk update
|
||||
apk add kyua atf build-base autoconf automake libtool xz gzip
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
export CFLAGS="-Wall -Werror -O2 -ggdb3 -fanalyzer"
|
||||
./autogen.sh
|
||||
./configure
|
||||
make -j9 CFLAGS="$CFLAGS"
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -73,6 +73,7 @@ core
|
||||
/tests/provides
|
||||
/tests/regress
|
||||
/tests/requires
|
||||
/tests/symlink
|
||||
/tests/sysroot
|
||||
/tests/test_env.sh
|
||||
/tests/version
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
pipeline:
|
||||
debian-meson:
|
||||
image: debian:testing
|
||||
commands:
|
||||
- apt-get update
|
||||
- apt-get install -y kyua atf-sh build-essential meson
|
||||
- meson _build -Dwerror=true
|
||||
- meson compile -C _build
|
||||
- meson test -v -C _build
|
||||
when:
|
||||
matrix:
|
||||
IMAGE: debian
|
||||
BUILD: meson
|
||||
|
||||
debian-meson-asan:
|
||||
image: debian:testing
|
||||
environment:
|
||||
- ASAN_OPTIONS="exitcode=7"
|
||||
commands:
|
||||
- apt-get update
|
||||
- apt-get install -y kyua atf-sh build-essential meson
|
||||
- meson _build -Db_sanitize=address
|
||||
- meson compile -C _build
|
||||
- meson test -v -C _build
|
||||
when:
|
||||
matrix:
|
||||
IMAGE: debian
|
||||
BUILD: meson
|
||||
|
||||
debian-autotools:
|
||||
image: debian:testing
|
||||
commands:
|
||||
- apt-get update
|
||||
- apt-get install -y kyua atf-sh build-essential autoconf libtool
|
||||
- ./autogen.sh
|
||||
- ./configure
|
||||
- make -j
|
||||
- make distcheck
|
||||
when:
|
||||
matrix:
|
||||
IMAGE: debian
|
||||
BUILD: autotools
|
||||
|
||||
alpine-meson:
|
||||
image: alpine
|
||||
commands:
|
||||
- apk add -U --no-cache kyua atf build-base meson
|
||||
- meson _build -Dwerror=true
|
||||
- meson compile -C _build
|
||||
- meson test -v -C _build
|
||||
when:
|
||||
matrix:
|
||||
IMAGE: alpine
|
||||
BUILD: meson
|
||||
|
||||
alpine-autotools:
|
||||
image: alpine
|
||||
commands:
|
||||
- apk add -U --no-cache kyua atf build-base autoconf automake libtool xz gzip
|
||||
- ./autogen.sh
|
||||
- ./configure
|
||||
- make -j
|
||||
- make distcheck
|
||||
when:
|
||||
matrix:
|
||||
IMAGE: alpine
|
||||
BUILD: autotools
|
||||
|
||||
matrix:
|
||||
IMAGE:
|
||||
- debian
|
||||
- alpine
|
||||
BUILD:
|
||||
- meson
|
||||
- autotools
|
||||
260
Makefile.am
260
Makefile.am
@ -12,15 +12,187 @@ nodist_pkgconfig_DATA = libpkgconf.pc
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AM_CFLAGS = -DPERSONALITY_PATH=\"$(personality_dir)\" -DPKG_DEFAULT_PATH=\"$(pkg_default_dir)\" -DSYSTEM_INCLUDEDIR=\"$(system_includedir)\" -DSYSTEM_LIBDIR=\"$(system_libdir)\"
|
||||
|
||||
bin_PROGRAMS = pkgconf bomtool
|
||||
bin_PROGRAMS = pkgconf bomtool spdxtool
|
||||
lib_LTLIBRARIES = libpkgconf.la
|
||||
|
||||
EXTRA_DIST = pkg.m4 \
|
||||
meson.build \
|
||||
meson_options.txt \
|
||||
pkgconf.wxs.in \
|
||||
txt2rtf.py \
|
||||
libpkgconf/meson.build \
|
||||
libpkgconf/config.h.meson \
|
||||
libpkgconf/win-dirent.h \
|
||||
t/basic/arbitrary-path.test \
|
||||
t/basic/builtin-pkg-config-exists.test \
|
||||
t/basic/builtin-pkg-config-pc_path-variable.test \
|
||||
t/basic/builtin-pkgconf-exists.test \
|
||||
t/basic/builtin-pkgconf-pc_path-variable.test \
|
||||
t/basic/define-prefix.test \
|
||||
t/basic/define-prefix-child-prefix-env.test \
|
||||
t/basic/define-prefix-child-prefix.test \
|
||||
t/basic/direct-query-with-pkg_config_path.test \
|
||||
t/basic/env-tuple.test \
|
||||
t/basic/exists-cflags-env.test \
|
||||
t/basic/exists-cflags.test \
|
||||
t/basic/exists-nonexistent.test \
|
||||
t/basic/exists-version-greater-than-with-tilde.test \
|
||||
t/basic/exists-version-greater-than.test \
|
||||
t/basic/exists-version-less-than-with-tilde.test \
|
||||
t/basic/exists-version-malformed.test \
|
||||
t/basic/exists-version-minimum.test \
|
||||
t/basic/exists-version-with-tilde.test \
|
||||
t/basic/incomplete-cflags.test \
|
||||
t/basic/incomplete-libs.test \
|
||||
t/basic/keep-system-libs.test \
|
||||
t/basic/keep-system-libs-2.test \
|
||||
t/basic/libs.test \
|
||||
t/basic/libs-cflags.test \
|
||||
t/basic/libs-cflags-version.test \
|
||||
t/basic/libs-cflags-version-multiple.test \
|
||||
t/basic/libs-cflags-version-multiple-comma.test \
|
||||
t/basic/libs-cflags-version-not.test \
|
||||
t/basic/libs-cflags-version-not-provided.test \
|
||||
t/basic/libs-env.test \
|
||||
t/basic/libs-only.test \
|
||||
t/basic/malformed-empty-package.test \
|
||||
t/basic/modversion-fullpath.test \
|
||||
t/basic/modversion-noflatten.test \
|
||||
t/basic/modversion-uninstalled.test \
|
||||
t/basic/modversion-verbose-prefix.test \
|
||||
t/basic/noargs.test \
|
||||
t/basic/nocflags.test \
|
||||
t/basic/nolibs.test \
|
||||
t/basic/pkg-config-path.test \
|
||||
t/basic/print-variables-env.test \
|
||||
t/basic/single-depth-selectors.test \
|
||||
t/basic/static-archive-libs.test \
|
||||
t/basic/uninstalled-not.test \
|
||||
t/basic/uninstalled.test \
|
||||
t/basic/variable-env.test \
|
||||
t/basic/variable-no-recursion.test \
|
||||
t/basic/variable.test \
|
||||
t/basic/version-atleast-1.test \
|
||||
t/basic/version-atleast-2.test \
|
||||
t/basic/version-exact-1.test \
|
||||
t/basic/version-exact-2.test \
|
||||
t/basic/version-max-1.test \
|
||||
t/basic/version-max-2.test \
|
||||
t/ordering/cflags-never-mergeback.test \
|
||||
t/ordering/cflags-only.test \
|
||||
t/ordering/flag-order-1.test \
|
||||
t/ordering/flag-order-2.test \
|
||||
t/ordering/flag-order-3.test \
|
||||
t/ordering/flag-order-4.test \
|
||||
t/ordering/fragment-collision.test \
|
||||
t/ordering/framework-1.test \
|
||||
t/ordering/framework-2.test \
|
||||
t/ordering/framework-3.test \
|
||||
t/ordering/idirafter-munge-ordering.test \
|
||||
t/ordering/idirafter-ordering.test \
|
||||
t/ordering/isystem-munge-ordering.test \
|
||||
t/ordering/libs-never-mergeback.test \
|
||||
t/parser/argv-parse-1.test \
|
||||
t/parser/argv-parse-2.test \
|
||||
t/parser/argv-parse-3.test \
|
||||
t/parser/c-comments-should-warn.test \
|
||||
t/parser/comments-in-fields.test \
|
||||
t/parser/comments.test \
|
||||
t/parser/dos-lineendings.test \
|
||||
t/parser/escaped-backslashes-in-output.test \
|
||||
t/parser/fragment-comment.test \
|
||||
t/parser/fragment-groups-composite.test \
|
||||
t/parser/fragment-groups.test \
|
||||
t/parser/malformed-no-newlines.test \
|
||||
t/parser/malformed-quoting.test \
|
||||
t/parser/multiline-bogus-header.test \
|
||||
t/parser/multiline-field.test \
|
||||
t/parser/no-trailing-newline.test \
|
||||
t/parser/paren-quoting.test \
|
||||
t/parser/shell-quoted-output.test \
|
||||
t/parser/tilde-quoting-1.test \
|
||||
t/parser/tilde-quoting-2.test \
|
||||
t/parser/truncated-files-should-fail-to-parse.test \
|
||||
t/parser/tuple-dequote.test \
|
||||
t/parser/variable-whitespace.test \
|
||||
t/solver/circular-reference-1.test \
|
||||
t/solver/circular-reference-2.test \
|
||||
t/solver/circular-reference-directpc.test \
|
||||
t/solver/conflicts-solution-error.test \
|
||||
t/solver/conflicts-solution-ignore.test \
|
||||
t/solver/conflicts-solution-is-fine-standalone.test \
|
||||
t/solver/depgraph-break-1.test \
|
||||
t/solver/depgraph-break-2.test \
|
||||
t/solver/depgraph-break-3.test \
|
||||
t/solver/libs-intermediary.test \
|
||||
t/solver/libs-metapackage.test \
|
||||
t/solver/libs-static-ordering.test \
|
||||
t/solver/missing-required-dep.test \
|
||||
t/solver/modversion-provides.test \
|
||||
t/solver/private-libs-duplication-digraph.test \
|
||||
t/solver/private-libs-duplication.test \
|
||||
t/solver/provides-bar-any.test \
|
||||
t/solver/provides-bar-versioned-equal.test \
|
||||
t/solver/provides-bar-versioned-greater-than-equal.test \
|
||||
t/solver/provides-bar-versioned-greater-than.test \
|
||||
t/solver/provides-bar-versioned-less-than-equal.test \
|
||||
t/solver/provides-bar-versioned-less-than-new.test \
|
||||
t/solver/provides-bar-versioned-less-than-old.test \
|
||||
t/solver/provides-bar-versioned-not-equal-old.test \
|
||||
t/solver/provides-bar-versioned-not-equal.test \
|
||||
t/solver/provides-foo-any.test \
|
||||
t/solver/provides-foo-versioned-exact.test \
|
||||
t/solver/provides-foo-versioned-greater-than-equal.test \
|
||||
t/solver/provides-foo-versioned-greater-than.test \
|
||||
t/solver/provides-foo-versioned-less-than-equal.test \
|
||||
t/solver/provides-foo-versioned-less-than.test \
|
||||
t/solver/provides-foo-versioned-not-equal.test \
|
||||
t/solver/provides-indirect-dependency-versioned.test \
|
||||
t/solver/provides-indirect-dependency.test \
|
||||
t/solver/provides-print-simple.test \
|
||||
t/solver/provides-request-simple.test \
|
||||
t/solver/provides-request-simple-no-provides.test \
|
||||
t/solver/query-no-space-0.test \
|
||||
t/solver/query-no-space-1.test \
|
||||
t/solver/query-order-1.test \
|
||||
t/solver/query-order-2.test \
|
||||
t/solver/requires-internal-collision.test \
|
||||
t/solver/requires-internal-missing-nonstatic-cflags-libs.test \
|
||||
t/solver/requires-internal-missing-nonstatic.test \
|
||||
t/solver/requires-internal-missing-static-cflags.test \
|
||||
t/solver/requires-internal-missing.test \
|
||||
t/solver/requires-internal.test \
|
||||
t/solver/requires-private-debounce.test \
|
||||
t/solver/requires-private-missing.test \
|
||||
t/sbom/license-file-bar.test \
|
||||
t/sbom/license-file-foo.test \
|
||||
t/sbom/license-isc.test \
|
||||
t/sbom/license-noassertion.test \
|
||||
t/sbom/source-tag-bar.test \
|
||||
t/sbom/source-tag-foo.test \
|
||||
t/sysroot/cflags-rewriting.test \
|
||||
t/sysroot/idirafter-munge-sysroot.test \
|
||||
t/sysroot/isystem-munge-sysroot.test \
|
||||
t/sysroot/no-pc_sysrootdir-rewriting-2.test \
|
||||
t/sysroot/no-pc_sysrootdir-rewriting-3.test \
|
||||
t/sysroot/no-pc_sysrootdir-rewriting-4.test \
|
||||
t/sysroot/no-pc_sysrootdir-rewriting-5.test \
|
||||
t/sysroot/no-pc_sysrootdir-rewriting-variable.test \
|
||||
t/sysroot/skip-rewriting-when-sysroot-dir-is-root-dir.test \
|
||||
t/sysroot/undefined-pc_sysrootdir-should-be-empty.test \
|
||||
t/sysroot/uninstalled-rewriting-fdo-rules-with-pc_sysrootdir.test \
|
||||
t/sysroot/uninstalled-rewriting-fdo-rules.test \
|
||||
t/sysroot/uninstalled-rewriting-pkgconf-1-rules.test \
|
||||
t/sysroot/uninstalled-rewriting.test \
|
||||
t/sysroot/variable-rewriting-1.test \
|
||||
t/sysroot/variable-rewriting-2.test \
|
||||
t/tuple/billion-laughs.test \
|
||||
t/tuple/case-sensitivity-1.test \
|
||||
t/tuple/case-sensitivity-2.test \
|
||||
t/tuple/define-variable-override.test \
|
||||
t/tuple/define-variable.test \
|
||||
t/tuple/duplicate-upsert.test \
|
||||
t/tuple/empty-tuple.test \
|
||||
tests/lib-relocatable/lib/pkgconfig/foo.pc \
|
||||
tests/lib1/argv-parse-2.pc \
|
||||
tests/lib1/billion-laughs.pc \
|
||||
@ -90,6 +262,11 @@ EXTRA_DIST = pkg.m4 \
|
||||
tests/lib1/fragment-quoting-3.pc \
|
||||
tests/lib1/fragment-quoting-5.pc \
|
||||
tests/lib1/fragment-quoting-7.pc \
|
||||
tests/lib1/fragment-groups.pc \
|
||||
tests/lib1/fragment-groups-2.pc \
|
||||
tests/lib1/fragment-group-a.pc \
|
||||
tests/lib1/fragment-group-b.pc \
|
||||
tests/lib1/fragment-group-c.pc \
|
||||
tests/lib1/malformed-1.pc \
|
||||
tests/lib1/malformed-quoting.pc \
|
||||
tests/lib1/malformed-version.pc \
|
||||
@ -107,11 +284,32 @@ EXTRA_DIST = pkg.m4 \
|
||||
tests/lib1/tuple-quoting.pc \
|
||||
tests/lib1/empty-tuple.pc \
|
||||
tests/lib1/orphaned-requires-private.pc \
|
||||
tests/lib1/pcfiledir.pc \
|
||||
tests/lib1/sysroot-dir-2.pc \
|
||||
tests/lib1/sysroot-dir-3.pc \
|
||||
tests/lib1/sysroot-dir-4.pc \
|
||||
tests/lib1/sysroot-dir-5.pc \
|
||||
tests/lib1/child-prefix/pkgconfig/child-prefix-1.pc \
|
||||
tests/lib1/cflags-libs-private-a.pc \
|
||||
tests/lib1/cflags-libs-private-b.pc \
|
||||
tests/lib1/cflags-libs-private-c.pc \
|
||||
tests/lib1/truncated.pc \
|
||||
tests/lib1/c-comment.pc \
|
||||
tests/lib1/duplicate-tuple.pc \
|
||||
tests/lib1/flag-whitespace.pc \
|
||||
tests/lib1/flag-whitespace-2.pc \
|
||||
tests/lib-sbom/meta_package.pc \
|
||||
tests/lib-sbom/test1.pc \
|
||||
tests/lib-sbom/test2.pc \
|
||||
tests/lib-sbom/test3.pc \
|
||||
tests/lib-sbom/test4.pc \
|
||||
tests/lib-sbom/test5.pc \
|
||||
tests/lib-sbom/test6.pc \
|
||||
tests/lib-sbom-files/basic.json \
|
||||
tests/lib-sbom-files/meta_package.json \
|
||||
tests/lib-sbom-files/with_dependency.json \
|
||||
tests/personality-data/i386-linux-gnu.personality \
|
||||
tests/meson.build \
|
||||
$(test_scripts) \
|
||||
doc/conf.py \
|
||||
doc/extract.py \
|
||||
@ -128,26 +326,23 @@ EXTRA_DIST = pkg.m4 \
|
||||
doc/libpkgconf-queue.rst \
|
||||
doc/libpkgconf-tuple.rst
|
||||
|
||||
test_scripts= tests/meson.build \
|
||||
tests/basic.sh \
|
||||
tests/builtins.sh \
|
||||
tests/conflicts.sh \
|
||||
tests/framework.sh \
|
||||
test_scripts= \
|
||||
tests/parser.sh \
|
||||
tests/provides.sh \
|
||||
tests/personality.sh \
|
||||
tests/regress.sh \
|
||||
tests/requires.sh \
|
||||
tests/sysroot.sh \
|
||||
tests/version.sh
|
||||
tests/spdxtool.sh \
|
||||
tests/symlink.sh
|
||||
|
||||
test_sh = $(filter-out tests/meson.build, $(test_scripts))
|
||||
check_SCRIPTS = $(test_sh:.sh=)
|
||||
test_sh = $(test_scripts)
|
||||
check_SCRIPTS = ${test_sh:.sh=}
|
||||
|
||||
SUFFIXES= .sh
|
||||
|
||||
nobase_pkginclude_HEADERS = libpkgconf/bsdstubs.h libpkgconf/iter.h libpkgconf/libpkgconf.h libpkgconf/stdinc.h libpkgconf/libpkgconf-api.h
|
||||
libpkgconf_la_SOURCES = \
|
||||
libpkgconf/audit.c \
|
||||
libpkgconf/buffer.c \
|
||||
libpkgconf/cache.c \
|
||||
libpkgconf/client.c \
|
||||
libpkgconf/pkg.c \
|
||||
@ -158,12 +353,14 @@ libpkgconf_la_SOURCES = \
|
||||
libpkgconf/tuple.c \
|
||||
libpkgconf/dependency.c \
|
||||
libpkgconf/queue.c \
|
||||
libpkgconf/output.c \
|
||||
libpkgconf/path.c \
|
||||
libpkgconf/personality.c \
|
||||
libpkgconf/parser.c
|
||||
libpkgconf_la_LDFLAGS = -no-undefined -version-info 5:0:0 -export-symbols-regex '^pkgconf_'
|
||||
libpkgconf_la_LDFLAGS = -no-undefined -version-info 7:0:0 -export-symbols-regex '^pkgconf_'
|
||||
|
||||
dist_man_MANS = \
|
||||
man/bomtool.1 \
|
||||
man/pkgconf.1 \
|
||||
man/pkg.m4.7 \
|
||||
man/pc.5 \
|
||||
@ -172,12 +369,19 @@ dist_man_MANS = \
|
||||
pkgconf_LDADD = libpkgconf.la
|
||||
pkgconf_SOURCES = \
|
||||
cli/main.c \
|
||||
cli/core.c \
|
||||
cli/getopt_long.c \
|
||||
cli/renderer-msvc.c
|
||||
pkgconf_CPPFLAGS = -I$(top_srcdir)/libpkgconf -I$(top_srcdir)/cli
|
||||
noinst_HEADERS = \
|
||||
cli/getopt_long.h \
|
||||
cli/renderer-msvc.h
|
||||
cli/core.h \
|
||||
cli/getopt_long.h \
|
||||
cli/renderer-msvc.h \
|
||||
cli/spdxtool/core.h \
|
||||
cli/spdxtool/serialize.h \
|
||||
cli/spdxtool/simplelicensing.h \
|
||||
cli/spdxtool/software.h \
|
||||
cli/spdxtool/util.h
|
||||
|
||||
bomtool_LDADD = libpkgconf.la
|
||||
bomtool_SOURCES = \
|
||||
@ -185,6 +389,25 @@ bomtool_SOURCES = \
|
||||
cli/getopt_long.c
|
||||
bomtool_CPPFLAGS = -I$(top_srcdir)/libpkgconf -I$(top_srcdir)/cli -I$(top_srcdir)/cli/bomtool
|
||||
|
||||
spdxtool_LDADD = libpkgconf.la
|
||||
spdxtool_SOURCES = \
|
||||
cli/spdxtool/main.c \
|
||||
cli/spdxtool/core.c \
|
||||
cli/spdxtool/software.c \
|
||||
cli/spdxtool/serialize.c \
|
||||
cli/spdxtool/simplelicensing.c \
|
||||
cli/spdxtool/util.c \
|
||||
cli/getopt_long.c
|
||||
spdxtool_CPPFLAGS = -I$(top_srcdir)/libpkgconf -I$(top_srcdir)/cli -I$(top_srcdir)/cli/spdxtool
|
||||
|
||||
noinst_PROGRAMS = test-runner
|
||||
test_runner_LDADD = libpkgconf.la
|
||||
test_runner_SOURCES = \
|
||||
cli/core.c \
|
||||
cli/getopt_long.c \
|
||||
cli/renderer-msvc.c \
|
||||
tests/test-runner.c
|
||||
|
||||
dist_doc_DATA = README.md AUTHORS
|
||||
|
||||
m4datadir = $(datadir)/aclocal
|
||||
@ -193,7 +416,14 @@ m4data_DATA = pkg.m4
|
||||
CLEANFILES = $(EXTRA_PROGRAMS) \
|
||||
$(check_SCRIPTS)
|
||||
|
||||
check: pkgconf $(check_SCRIPTS)
|
||||
check: pkgconf test-runner $(check_SCRIPTS)
|
||||
$(builddir)/test-runner$(EXEEXT) --test-fixtures=$(top_srcdir)/tests $(top_srcdir)/t/basic
|
||||
$(builddir)/test-runner$(EXEEXT) --test-fixtures=$(top_srcdir)/tests $(top_srcdir)/t/ordering
|
||||
$(builddir)/test-runner$(EXEEXT) --test-fixtures=$(top_srcdir)/tests $(top_srcdir)/t/parser
|
||||
$(builddir)/test-runner$(EXEEXT) --test-fixtures=$(top_srcdir)/tests $(top_srcdir)/t/solver
|
||||
$(builddir)/test-runner$(EXEEXT) --test-fixtures=$(top_srcdir)/tests $(top_srcdir)/t/sbom
|
||||
$(builddir)/test-runner$(EXEEXT) --test-fixtures=$(top_srcdir)/tests $(top_srcdir)/t/sysroot
|
||||
$(builddir)/test-runner$(EXEEXT) --test-fixtures=$(top_srcdir)/tests $(top_srcdir)/t/tuple
|
||||
kyua --config=none test --kyuafile='$(top_builddir)/Kyuafile' \
|
||||
--build-root='$(top_builddir)'
|
||||
|
||||
|
||||
@ -16,11 +16,13 @@ SRCS = \
|
||||
libpkgconf/argvsplit.c \
|
||||
libpkgconf/audit.c \
|
||||
libpkgconf/bsdstubs.c \
|
||||
libpkgconf/buffer.c \
|
||||
libpkgconf/cache.c \
|
||||
libpkgconf/client.c \
|
||||
libpkgconf/dependency.c \
|
||||
libpkgconf/fileio.c \
|
||||
libpkgconf/fragment.c \
|
||||
libpkgconf/output.c \
|
||||
libpkgconf/parser.c \
|
||||
libpkgconf/path.c \
|
||||
libpkgconf/personality.c \
|
||||
@ -28,7 +30,8 @@ SRCS = \
|
||||
libpkgconf/queue.c \
|
||||
libpkgconf/tuple.c \
|
||||
cli/getopt_long.c \
|
||||
cli/main.c
|
||||
cli/main.c \
|
||||
cli/core.c
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
CFLAGS = ${STATIC} -DPKGCONF_LITE -I. -Ilibpkgconf -Icli -DSYSTEM_LIBDIR=\"${SYSTEM_LIBDIR}\" -DSYSTEM_INCLUDEDIR=\"${SYSTEM_INCLUDEDIR}\" -DPKG_DEFAULT_PATH=\"${PKG_DEFAULT_PATH}\"
|
||||
STATIC =
|
||||
@ -39,7 +42,7 @@ all: pkgconf-lite
|
||||
libpkgconf/config.h:
|
||||
@echo '#define PACKAGE_NAME "pkgconf-lite"' >> $@
|
||||
@echo '#define PACKAGE_BUGREPORT "https://git.dereferenced.org/pkgconf/pkgconf/issues"' >> $@
|
||||
@echo '#define PACKAGE_VERSION "2.3.0"' >> $@
|
||||
@echo '#define PACKAGE_VERSION "2.5.1"' >> $@
|
||||
@echo '#define PACKAGE PACKAGE_NAME " " PACKAGE_VERSION' >> $@
|
||||
@echo '#define HAVE_STRLCPY' >> $@
|
||||
@echo '#define HAVE_STRLCAT' >> $@
|
||||
|
||||
89
NEWS
89
NEWS
@ -1,6 +1,95 @@
|
||||
Changes from previous version of pkgconf
|
||||
========================================
|
||||
|
||||
Changes from 2.5.0 to 2.5.1:
|
||||
----------------------------
|
||||
|
||||
* Fix processing of empty dependency lists.
|
||||
|
||||
Changes from 2.4.3 to 2.5.0:
|
||||
----------------------------
|
||||
|
||||
* Added a manual page for bomtool.
|
||||
|
||||
* Add support for preloaded packages.
|
||||
These are modules which are preloaded into the package database
|
||||
and preferred over searching the module search path when present.
|
||||
|
||||
* Refactor Windows registry PKG_CONFIG_PATH support so that it
|
||||
augments the main directory search list instead of being treated
|
||||
as a special case.
|
||||
|
||||
* Processing of `--with-path` arguments by the pkgconf CLI is
|
||||
now deferred until libpkgconf is fully initialized, effectively
|
||||
aligning behavior with PKG_CONFIG_PATH processing.
|
||||
|
||||
* Fix several minor memory safety bugs which were identified by
|
||||
the GCC 15 static analyzer.
|
||||
|
||||
* Added support for pledge(2) and unveil(2) on systems where
|
||||
this functionality is available.
|
||||
|
||||
* Significant improvements to pkgconf's manual pages.
|
||||
Patches by Ingo Schwarze and Jonathan Gray (OpenBSD).
|
||||
|
||||
* Remove questionable default-static assumption on Windows that
|
||||
was inherited from the original pkg-config. Most distributions
|
||||
of pkgconf on Windows were already patching this out.
|
||||
Patch by Kai Pastor.
|
||||
|
||||
* Add -D_POSIX_C_SOURCE=200809L to the build definitions, which
|
||||
is needed for readlinkat on glibc.
|
||||
Patch by Filipe Laíns.
|
||||
|
||||
Changes from 2.4.2 to 2.4.3:
|
||||
----------------------------
|
||||
|
||||
* Fix additional logic errors relating to the new fragment trees
|
||||
functionality.
|
||||
|
||||
Changes from 2.4.1 to 2.4.2:
|
||||
----------------------------
|
||||
|
||||
* Fix several logic errors in the pkg-config file parser that were
|
||||
surfaced by recent refactoring work.
|
||||
|
||||
* Fix BSD make compatibility so that it generates the test data
|
||||
before running kyua on BSD make implementations.
|
||||
|
||||
Changes from 2.4.0 to 2.4.1:
|
||||
----------------------------
|
||||
|
||||
* Ensure the full DAG is solved for all query types.
|
||||
|
||||
Changes from 2.3.0 to 2.4.0:
|
||||
----------------------------
|
||||
|
||||
* Allow multiple package names in solution-based queries such as
|
||||
`--print-requires`, `--print-requires-private` and `--print-provides`.
|
||||
|
||||
* Use `_DEFAULT_SOURCE` where appropriate on Meson.
|
||||
|
||||
* Add an abstract buffer type and use it when loading files from disk
|
||||
instead of a 64KB buffer. This ensures large pkg-config files are
|
||||
not truncated.
|
||||
|
||||
* Disable graph recursion in `--variable` queries as it was generating
|
||||
duplicate output.
|
||||
|
||||
* Add infrastructure for tracking fragment group relations and convert
|
||||
storage of fragments to use a tree-like structure instead of string
|
||||
concatenation.
|
||||
|
||||
* Add support for tracking linker groups, e.g.
|
||||
|
||||
-Wl,--start-group -la -lb -lc -Wl,--end-group
|
||||
|
||||
as fragment groups.
|
||||
|
||||
* Properly contextualize the sysroot directory when processing package
|
||||
information, ensuring packages where ${pc_sysrootdir} does not match
|
||||
the default are properly processed.
|
||||
|
||||
Changes from 2.2.0 to 2.3.0:
|
||||
----------------------------
|
||||
|
||||
|
||||
99
README.md
99
README.md
@ -1,88 +1,75 @@
|
||||
# pkgconf [](https://github.com/pkgconf/pkgconf/actions/workflows/test.yml)
|
||||
|
||||
`pkgconf` is a program which helps to configure compiler and linker flags for
|
||||
development libraries. It is similar to pkg-config from freedesktop.org.
|
||||
development libraries. It is a superset of the functionality provided by
|
||||
pkg-config from freedesktop.org, but does not provide bug-compatibility with
|
||||
the original pkg-config.
|
||||
|
||||
`libpkgconf` is a library which provides access to most of `pkgconf`'s functionality,
|
||||
to allow other tooling such as compilers and IDEs to discover and use libraries
|
||||
configured by pkgconf.
|
||||
|
||||
## using `pkgconf` with autotools
|
||||
## release tarballs
|
||||
|
||||
Implementations of pkg-config, such as pkgconf, are typically used with the
|
||||
PKG_CHECK_MODULES autoconf macro. As far as we know, pkgconf is
|
||||
compatible with all known variations of this macro. pkgconf detects at
|
||||
runtime whether or not it was started as 'pkg-config', and if so, attempts
|
||||
to set program options such that its behaviour is similar.
|
||||
Release tarballs are available on [distfiles.ariadne.space][distfiles].
|
||||
|
||||
In terms of the autoconf macro, it is possible to specify the PKG_CONFIG
|
||||
environment variable, so that you can test pkgconf without overwriting your
|
||||
pkg-config binary. Some other build systems may also respect the PKG_CONFIG
|
||||
environment variable.
|
||||
[distfiles]: https://distfiles.ariadne.space/pkgconf/
|
||||
|
||||
To set the environment variable on the bourne shell and clones (i.e. bash), you
|
||||
can run:
|
||||
## build system setup
|
||||
|
||||
$ export PKG_CONFIG=/usr/bin/pkgconf
|
||||
If you would like to use the git sources directly, or a snapshot of the
|
||||
sources from GitHub, you will need to regenerate the autotools build
|
||||
system artifacts yourself, or use Meson instead. For example, on Alpine:
|
||||
|
||||
## comparison of `pkgconf` and `pkg-config` dependency resolvers
|
||||
$ apk add autoconf automake libtool build-base
|
||||
$ sh ./autogen.sh
|
||||
|
||||
pkgconf builds an acyclic directed dependency graph. This allows for the user
|
||||
to more conservatively link their binaries -- which may be helpful in some
|
||||
environments, such as when prelink(1) is being used. As a result of building
|
||||
a directed dependency graph designed for the specific problem domain provided
|
||||
by the user, more accurate dependencies can be determined.
|
||||
## pkgconf-lite
|
||||
|
||||
Current release versions of pkg-config, on the other hand, build a database of all
|
||||
known pkg-config files on the system before attempting to resolve dependencies, which
|
||||
is a considerably slower and less efficient design. Efforts have been made recently
|
||||
to improve this behaviour.
|
||||
If you only need the original pkg-config functionality, there is also pkgconf-lite,
|
||||
which builds the `pkgconf` frontend and relevant portions of `libpkgconf` functionality
|
||||
into a single binary:
|
||||
|
||||
As of the 1.1 series, pkgconf also fully implements support for `Provides` rules,
|
||||
while pkg-config does not. pkg-config only provides the `--print-provides` functionality
|
||||
as a stub. There are other intentional implementation differences in pkgconf's dependency
|
||||
resolver versus pkg-config's dependency resolver in terms of completeness and correctness,
|
||||
such as, for example, how `Conflicts` rules are processed.
|
||||
$ make -f Makefile.lite
|
||||
|
||||
## why `pkgconf` over original `pkg-config`?
|
||||
|
||||
pkgconf builds a flattened directed dependency graph, which allows for more insight
|
||||
into relationships between dependencies, allowing for some link-time dependency
|
||||
optimization, which allows for the user to more conservatively link their binaries,
|
||||
which may be helpful in some environments, such as when prelink(1) is being used.
|
||||
|
||||
The solver is also optimized to handle large dependency graphs with hundreds of
|
||||
thousands of edges, which can be seen in any project using the Abseil frameworks
|
||||
for example.
|
||||
|
||||
In addition, pkgconf has full support for virtual packages, while the original
|
||||
pkg-config does not, as well as fully supporting `Conflicts` at dependency
|
||||
resolution time, which is more efficient than checking for `Conflicts` while
|
||||
walking the dependency graph.
|
||||
|
||||
## linker flags optimization
|
||||
|
||||
As previously mentioned, pkgconf makes optimizations to the linker flags in both the
|
||||
case of static and shared linking in order to avoid overlinking binaries and also
|
||||
simplifies the `CFLAGS` and `LIBS` output of the pkgconf tool for improved readability.
|
||||
pkgconf, when used effectively, can make optimizations to avoid overlinking binaries.
|
||||
|
||||
This functionality depends on the pkg-config module properly declaring its dependency
|
||||
tree instead of using `Libs` and `Cflags` fields to directly link against other modules
|
||||
which have pkg-config metadata files installed.
|
||||
|
||||
Doing so is discouraged by the [freedesktop tutorial][fd-tut] anyway.
|
||||
The practice of using `Libs` and `Cflags` to describe unrelated dependencies is
|
||||
not recommended in [Dan Nicholson's pkg-config tutorial][fd-tut] for this reason.
|
||||
|
||||
[fd-tut]: http://people.freedesktop.org/~dbn/pkg-config-guide.html
|
||||
|
||||
## compatibility with pkg-config
|
||||
## bug compatibility with original pkg-config
|
||||
|
||||
I really hate that I have to have this section, I like being a nice person, but we
|
||||
unfortunately have to say this because otherwise we get passive-aggressive people who
|
||||
try to argue with us about what pkg-config compatibility means.
|
||||
|
||||
We do not provide bug-level compatibility with pkg-config.
|
||||
In general, we do not provide bug-level compatibility with pkg-config.
|
||||
|
||||
What that means is, if you feel that there is a legitimate regression versus pkg-config,
|
||||
do let us know, but also make sure that the .pc files are valid and follow the rules of
|
||||
the [pkg-config tutorial][fd-tut], as most likely fixing them to follow the specified
|
||||
rules will solve the problem.
|
||||
|
||||
Additionally, **we do not consider pkgconf doing what you tell it to do, in cases for
|
||||
which pkg-config fails to do so, to be a bug**.
|
||||
|
||||
If, for example, you use environment variables such as `PKG_CONFIG_SYSTEM_[INCLUDE|LIBRARY]_PATH`
|
||||
and then find yourself surprised that `pkgconf` is stripping `-I` and `-L` flags relating
|
||||
to those paths, it is not a `pkgconf` problem -- `pkgconf` is doing exactly what you told
|
||||
it to do.
|
||||
|
||||
We will reject bugs like this, and if someone insists on fixing such a non-bug, this
|
||||
constitutes a violation of our [Code of Conduct](CODE_OF_CONDUCT.md), which may be
|
||||
addressed by banning from this repository.
|
||||
|
||||
## debug output
|
||||
|
||||
Please use only the stable interfaces to query pkg-config. Do not screen-scrape the
|
||||
@ -114,7 +101,6 @@ flags like so:
|
||||
|
||||
## compiling `pkgconf` and `libpkgconf` with Meson (usually for Windows)
|
||||
|
||||
|
||||
pkgconf is compiled using [Meson](https://mesonbuild.com) on Windows. In theory, you could also use
|
||||
Meson to build on UNIX, but this is not recommended at this time as pkgconf is typically built
|
||||
much earlier than Meson.
|
||||
@ -123,8 +109,8 @@ much earlier than Meson.
|
||||
$ meson compile -C build
|
||||
$ meson install -C build
|
||||
|
||||
There are a few defines such as SYSTEM_LIBDIR, PKGCONFIGDIR and SYSTEM_INCLUDEDIR.
|
||||
However, on Windows, the default PKGCONFIGDIR value is usually overridden at runtime based
|
||||
There are a few defines such as `SYSTEM_LIBDIR`, `PKGCONFIGDIR` and `SYSTEM_INCLUDEDIR`.
|
||||
However, on Windows, the default `PKGCONFIGDIR` value is usually overridden at runtime based
|
||||
on path relocation.
|
||||
|
||||
## pkg-config symlink
|
||||
@ -135,11 +121,6 @@ to make this determination themselves.
|
||||
|
||||
$ ln -sf pkgconf /usr/bin/pkg-config
|
||||
|
||||
## release tarballs
|
||||
|
||||
Release tarballs are available at <https://distfiles.ariadne.space/pkgconf/>.
|
||||
Please only use the tarballs from distfiles.ariadne.space.
|
||||
|
||||
## contacts
|
||||
|
||||
You can report bugs at <https://github.com/pkgconf/pkgconf/issues>.
|
||||
|
||||
@ -80,8 +80,8 @@ parse_options "$@"
|
||||
|
||||
cd $TOP_DIR
|
||||
|
||||
run_or_die $LIBTOOLIZE --install
|
||||
run_or_die $ACLOCAL
|
||||
run_or_die $AUTOHEADER
|
||||
run_or_die $AUTOCONF
|
||||
run_or_die $LIBTOOLIZE --install
|
||||
run_or_die $AUTOMAKE --add-missing
|
||||
|
||||
@ -31,7 +31,15 @@ static pkgconf_client_t pkg_client;
|
||||
static uint64_t want_flags;
|
||||
static size_t maximum_package_count = 0;
|
||||
static int maximum_traverse_depth = 2000;
|
||||
FILE *error_msgout = NULL;
|
||||
static FILE *error_msgout = NULL;
|
||||
|
||||
static const char *
|
||||
environ_lookup_handler(const pkgconf_client_t *client, const char *key)
|
||||
{
|
||||
(void) client;
|
||||
|
||||
return getenv(key);
|
||||
}
|
||||
|
||||
static bool
|
||||
error_handler(const char *msg, const pkgconf_client_t *client, void *data)
|
||||
@ -136,6 +144,9 @@ write_sbom_package(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *unused)
|
||||
if (pkg->description != NULL)
|
||||
printf("PackageSummary: <text>%s</text>\n", pkg->description);
|
||||
|
||||
if (pkg->source != NULL)
|
||||
printf("PackageDownloadLocation: %s\n", pkg->source);
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
@ -282,7 +293,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
pkgconf_client_init(&pkg_client, error_handler, NULL, personality);
|
||||
pkgconf_client_init(&pkg_client, error_handler, NULL, personality, NULL, environ_lookup_handler);
|
||||
|
||||
/* we have determined what features we want most likely. in some cases, we override later. */
|
||||
pkgconf_client_set_flags(&pkg_client, want_client_flags);
|
||||
|
||||
1371
cli/core.c
Normal file
1371
cli/core.c
Normal file
File diff suppressed because it is too large
Load Diff
99
cli/core.h
Normal file
99
cli/core.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* core.h
|
||||
* core, printer functions
|
||||
*
|
||||
* Copyright (c) 2011-2025 pkgconf authors (see AUTHORS).
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* This software is provided 'as is' and without any warranty, express or
|
||||
* implied. In no event shall the authors be liable for any damages arising
|
||||
* from the use of this software.
|
||||
*/
|
||||
|
||||
#ifndef __CLI_CORE_H
|
||||
#define __CLI_CORE_H
|
||||
|
||||
#define PKG_CFLAGS_ONLY_I (((uint64_t) 1) << 2)
|
||||
#define PKG_CFLAGS_ONLY_OTHER (((uint64_t) 1) << 3)
|
||||
#define PKG_CFLAGS (PKG_CFLAGS_ONLY_I|PKG_CFLAGS_ONLY_OTHER)
|
||||
#define PKG_LIBS_ONLY_LDPATH (((uint64_t) 1) << 5)
|
||||
#define PKG_LIBS_ONLY_LIBNAME (((uint64_t) 1) << 6)
|
||||
#define PKG_LIBS_ONLY_OTHER (((uint64_t) 1) << 7)
|
||||
#define PKG_LIBS (PKG_LIBS_ONLY_LDPATH|PKG_LIBS_ONLY_LIBNAME|PKG_LIBS_ONLY_OTHER)
|
||||
#define PKG_MODVERSION (((uint64_t) 1) << 8)
|
||||
#define PKG_REQUIRES (((uint64_t) 1) << 9)
|
||||
#define PKG_REQUIRES_PRIVATE (((uint64_t) 1) << 10)
|
||||
#define PKG_VARIABLES (((uint64_t) 1) << 11)
|
||||
#define PKG_DIGRAPH (((uint64_t) 1) << 12)
|
||||
#define PKG_KEEP_SYSTEM_CFLAGS (((uint64_t) 1) << 13)
|
||||
#define PKG_KEEP_SYSTEM_LIBS (((uint64_t) 1) << 14)
|
||||
#define PKG_VERSION (((uint64_t) 1) << 15)
|
||||
#define PKG_ABOUT (((uint64_t) 1) << 16)
|
||||
#define PKG_ENV_ONLY (((uint64_t) 1) << 17)
|
||||
#define PKG_ERRORS_ON_STDOUT (((uint64_t) 1) << 18)
|
||||
#define PKG_SILENCE_ERRORS (((uint64_t) 1) << 19)
|
||||
#define PKG_IGNORE_CONFLICTS (((uint64_t) 1) << 20)
|
||||
#define PKG_STATIC (((uint64_t) 1) << 21)
|
||||
#define PKG_NO_UNINSTALLED (((uint64_t) 1) << 22)
|
||||
#define PKG_UNINSTALLED (((uint64_t) 1) << 23)
|
||||
#define PKG_LIST (((uint64_t) 1) << 24)
|
||||
#define PKG_HELP (((uint64_t) 1) << 25)
|
||||
#define PKG_PRINT_ERRORS (((uint64_t) 1) << 26)
|
||||
#define PKG_SIMULATE (((uint64_t) 1) << 27)
|
||||
#define PKG_NO_CACHE (((uint64_t) 1) << 28)
|
||||
#define PKG_PROVIDES (((uint64_t) 1) << 29)
|
||||
#define PKG_VALIDATE (((uint64_t) 1) << 30)
|
||||
#define PKG_LIST_PACKAGE_NAMES (((uint64_t) 1) << 31)
|
||||
#define PKG_NO_PROVIDES (((uint64_t) 1) << 32)
|
||||
#define PKG_PURE (((uint64_t) 1) << 33)
|
||||
#define PKG_PATH (((uint64_t) 1) << 34)
|
||||
#define PKG_DEFINE_PREFIX (((uint64_t) 1) << 35)
|
||||
#define PKG_DONT_DEFINE_PREFIX (((uint64_t) 1) << 36)
|
||||
#define PKG_DONT_RELOCATE_PATHS (((uint64_t) 1) << 37)
|
||||
#define PKG_DEBUG (((uint64_t) 1) << 38)
|
||||
#define PKG_SHORT_ERRORS (((uint64_t) 1) << 39)
|
||||
#define PKG_EXISTS (((uint64_t) 1) << 40)
|
||||
#define PKG_MSVC_SYNTAX (((uint64_t) 1) << 41)
|
||||
#define PKG_INTERNAL_CFLAGS (((uint64_t) 1) << 42)
|
||||
#define PKG_DUMP_PERSONALITY (((uint64_t) 1) << 43)
|
||||
#define PKG_SHARED (((uint64_t) 1) << 44)
|
||||
#define PKG_DUMP_LICENSE (((uint64_t) 1) << 45)
|
||||
#define PKG_SOLUTION (((uint64_t) 1) << 46)
|
||||
#define PKG_EXISTS_CFLAGS (((uint64_t) 1) << 47)
|
||||
#define PKG_FRAGMENT_TREE (((uint64_t) 1) << 48)
|
||||
#define PKG_DUMP_SOURCE (((uint64_t) 1) << 49)
|
||||
#define PKG_DUMP_LICENSE_FILE (((uint64_t) 1) << 50)
|
||||
#define PKG_NEWLINES (((uint64_t) 1) << 51)
|
||||
|
||||
typedef struct {
|
||||
pkgconf_client_t pkg_client;
|
||||
pkgconf_fragment_render_ops_t *want_render_ops;
|
||||
|
||||
uint64_t want_flags;
|
||||
int verbosity;
|
||||
int maximum_traverse_depth;
|
||||
size_t maximum_package_count;
|
||||
|
||||
const char *want_variable;
|
||||
const char *want_fragment_filter;
|
||||
const char *want_env_prefix;
|
||||
|
||||
char *required_pkgconfig_version;
|
||||
const char *required_exact_module_version;
|
||||
const char *required_max_module_version;
|
||||
const char *required_module_version;
|
||||
|
||||
FILE *error_msgout;
|
||||
FILE *logfile_out;
|
||||
|
||||
bool opened_error_msgout;
|
||||
} pkgconf_cli_state_t;
|
||||
|
||||
extern void path_list_to_buffer(const pkgconf_list_t *list, pkgconf_buffer_t *buffer, char delim);
|
||||
extern int pkgconf_cli_run(pkgconf_cli_state_t *state, int argc, char *argv[], int last_argc);
|
||||
extern void pkgconf_cli_state_reset(pkgconf_cli_state_t *state);
|
||||
|
||||
#endif
|
||||
1524
cli/main.c
1524
cli/main.c
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ fragment_should_quote(const pkgconf_fragment_t *frag)
|
||||
for (src = frag->data; *src; src++)
|
||||
{
|
||||
if (((*src < ' ') ||
|
||||
(*src >= (' ' + (frag->merged ? 1 : 0)) && *src < '$') ||
|
||||
(*src >= (' ' + (frag->children.head != NULL ? 1 : 0)) && *src < '$') ||
|
||||
(*src > '$' && *src < '(') ||
|
||||
(*src > ')' && *src < '+') ||
|
||||
(*src > ':' && *src < '=') ||
|
||||
@ -104,68 +104,50 @@ msvc_renderer_render_len(const pkgconf_list_t *list, bool escape)
|
||||
}
|
||||
|
||||
static void
|
||||
msvc_renderer_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape)
|
||||
msvc_renderer_render_buf(const pkgconf_list_t *list, pkgconf_buffer_t *buf, bool escape, char delim)
|
||||
{
|
||||
pkgconf_node_t *node;
|
||||
char *bptr = buf;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
const pkgconf_fragment_t *frag = node->data;
|
||||
size_t buf_remaining = buflen - (bptr - buf);
|
||||
size_t cnt;
|
||||
|
||||
if (!allowed_fragment(frag))
|
||||
continue;
|
||||
|
||||
if (fragment_len(frag) > buf_remaining)
|
||||
break;
|
||||
|
||||
switch(frag->type) {
|
||||
case 'D':
|
||||
case 'I':
|
||||
*bptr++ = '/';
|
||||
*bptr++ = frag->type;
|
||||
pkgconf_buffer_append_fmt(buf, "/%c", frag->type);
|
||||
break;
|
||||
case 'L':
|
||||
cnt = pkgconf_strlcpy(bptr, "/libpath:", buf_remaining);
|
||||
bptr += cnt;
|
||||
buf_remaining -= cnt;
|
||||
pkgconf_buffer_append(buf, "/libpath:");
|
||||
break;
|
||||
}
|
||||
|
||||
escape = fragment_should_quote(frag);
|
||||
|
||||
if (escape)
|
||||
*bptr++ = '"';
|
||||
pkgconf_buffer_push_byte(buf, '"');
|
||||
|
||||
cnt = pkgconf_strlcpy(bptr, frag->data, buf_remaining);
|
||||
bptr += cnt;
|
||||
buf_remaining -= cnt;
|
||||
pkgconf_buffer_append(buf, frag->data);
|
||||
|
||||
if (frag->type == 'l')
|
||||
{
|
||||
cnt = pkgconf_strlcpy(bptr, ".lib", buf_remaining);
|
||||
bptr += cnt;
|
||||
}
|
||||
pkgconf_buffer_append(buf, ".lib");
|
||||
|
||||
if (escape)
|
||||
*bptr++ = '"';
|
||||
pkgconf_buffer_push_byte(buf, '"');
|
||||
|
||||
*bptr++ = ' ';
|
||||
pkgconf_buffer_push_byte(buf, delim);
|
||||
}
|
||||
|
||||
*bptr = '\0';
|
||||
}
|
||||
|
||||
static const pkgconf_fragment_render_ops_t msvc_renderer_ops = {
|
||||
static pkgconf_fragment_render_ops_t msvc_renderer_ops = {
|
||||
.render_len = msvc_renderer_render_len,
|
||||
.render_buf = msvc_renderer_render_buf
|
||||
};
|
||||
|
||||
const pkgconf_fragment_render_ops_t *
|
||||
pkgconf_fragment_render_ops_t *
|
||||
msvc_renderer_get(void)
|
||||
{
|
||||
return &msvc_renderer_ops;
|
||||
|
||||
@ -18,6 +18,6 @@
|
||||
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
const pkgconf_fragment_render_ops_t *msvc_renderer_get(void);
|
||||
pkgconf_fragment_render_ops_t *msvc_renderer_get(void);
|
||||
|
||||
#endif
|
||||
|
||||
690
cli/spdxtool/core.c
Normal file
690
cli/spdxtool/core.c
Normal file
@ -0,0 +1,690 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "serialize.h"
|
||||
#include "core.h"
|
||||
#include "software.h"
|
||||
#include "simplelicensing.h"
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: spdxtool_core_agent_t *spdxtool_core_agent_new(pkgconf_client_t *client, char *creation_info_id, char *name)
|
||||
*
|
||||
* Create new /Core/Agent struct
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param char *creation_info_id: CreationInfo spdxId
|
||||
* :param char *name: Name of agent
|
||||
* :return: NULL if some problem occurs and Agent struct if not
|
||||
*/
|
||||
spdxtool_core_agent_t *
|
||||
spdxtool_core_agent_new(pkgconf_client_t *client, char *creation_info_id, char *name)
|
||||
{
|
||||
char spdx_id_name[1024];
|
||||
char *spdx_id = NULL;
|
||||
spdxtool_core_agent_t *agent_struct = NULL;
|
||||
|
||||
if(!client || !creation_info_id || !name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
agent_struct = calloc(1, sizeof(spdxtool_core_agent_t));
|
||||
|
||||
if(!agent_struct)
|
||||
{
|
||||
pkgconf_error(client, "Memory exhausted! Can't create agent struct.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
agent_struct->type = "Agent";
|
||||
memset(spdx_id_name, 0x00, 1024);
|
||||
strncpy(spdx_id_name, name, 1023);
|
||||
spdxtool_util_string_correction(spdx_id_name);
|
||||
spdx_id = spdxtool_util_get_spdx_id_string(client, agent_struct->type, spdx_id_name);
|
||||
|
||||
agent_struct->creation_info = creation_info_id;
|
||||
agent_struct->spdx_id = spdx_id;
|
||||
agent_struct->name = name;
|
||||
return agent_struct;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_agent_free(spdxtool_core_agent_t *agent_struct)
|
||||
*
|
||||
* Free /Core/Agent struct
|
||||
*
|
||||
* :param spdxtool_core_agent_t *agent_struct: Agent struct to be freed.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_agent_free(spdxtool_core_agent_t *agent_struct)
|
||||
{
|
||||
if(!agent_struct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(agent_struct->creation_info)
|
||||
{
|
||||
free(agent_struct->creation_info);
|
||||
agent_struct->creation_info = NULL;
|
||||
}
|
||||
|
||||
if(agent_struct->spdx_id)
|
||||
{
|
||||
free(agent_struct->spdx_id);
|
||||
agent_struct->spdx_id = NULL;
|
||||
}
|
||||
|
||||
if(agent_struct->name)
|
||||
{
|
||||
free(agent_struct->name);
|
||||
agent_struct->name = NULL;
|
||||
}
|
||||
|
||||
free(agent_struct);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_agent_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_agent_t *agent_struct, bool last)
|
||||
*
|
||||
* Serialize /Core/Agent struct to JSON
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param pkgconf_buffer_t *buffer: Buffer where struct is serialized
|
||||
* :param spdxtool_core_agent_t *agent_struct: Agent struct to be serialized
|
||||
* :param bool last: Is this last Agent struct or does it need comma at the end. True comma False not
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_agent_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_agent_t *agent_struct, bool last)
|
||||
{
|
||||
(void) client;
|
||||
spdxtool_serialize_obj_start(buffer, 2);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@type", agent_struct->type, 3, 1);
|
||||
spdxtool_serialize_parm_and_string(buffer, "creationInfo", agent_struct->creation_info, 3, 1);
|
||||
spdxtool_serialize_parm_and_string(buffer, "spdxId", agent_struct->spdx_id, 3, 1);
|
||||
spdxtool_serialize_parm_and_string(buffer, "name", agent_struct->name, 3, 0);
|
||||
spdxtool_serialize_obj_end(buffer, 2, last);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: spdxtool_core_creation_info_t *spdxtool_core_creation_info_new(pkgconf_client_t *client, char *agent_id, char *id)
|
||||
*
|
||||
* Create new /Core/CreationInfo struct
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param char *agent_id: Agent spdxId
|
||||
* :param char *id: Id for creation info
|
||||
* :param char *time: If NULL current time is used if not then
|
||||
* this time string is used. Time string should be
|
||||
* in ISO8601 format: YYYY-MM-DDTHH:MM:SSZ
|
||||
* :return: NULL if some problem occurs and CreationInfo struct if not
|
||||
*/
|
||||
spdxtool_core_creation_info_t *
|
||||
spdxtool_core_creation_info_new(pkgconf_client_t *client, char *agent_id, char *id, char *time)
|
||||
{
|
||||
spdxtool_core_creation_info_t *creation_struct = NULL;
|
||||
|
||||
if(!client || !agent_id || !id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
creation_struct = calloc(1, sizeof(spdxtool_core_creation_info_t));
|
||||
if(!creation_struct)
|
||||
{
|
||||
pkgconf_error(client, "Memory exhausted! Can't create agent struct.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
creation_struct->type = "CreationInfo";
|
||||
creation_struct->id = id;
|
||||
if(!time)
|
||||
{
|
||||
creation_struct->created = spdxtool_util_get_current_iso8601_time();
|
||||
}
|
||||
else
|
||||
{
|
||||
creation_struct->created = time;
|
||||
}
|
||||
creation_struct->created_by = agent_id;
|
||||
creation_struct->created_using="pkgconf spdxtool";
|
||||
creation_struct->spec_version = spdxtool_util_get_spdx_version(client);
|
||||
return creation_struct;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_creation_info_free(spdxtool_core_creation_info_t *creation_struct)
|
||||
*
|
||||
* Free /Core/CreationInfo struct
|
||||
*
|
||||
* :param spdxtool_core_creation_info_t *creation_struct: CreationInfo struct to be freed.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_creation_info_free(spdxtool_core_creation_info_t *creation_struct)
|
||||
{
|
||||
if(!creation_struct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(creation_struct->id)
|
||||
{
|
||||
free(creation_struct->id);
|
||||
creation_struct->id = NULL;
|
||||
}
|
||||
|
||||
if(creation_struct->created)
|
||||
{
|
||||
free(creation_struct->created);
|
||||
creation_struct->created = NULL;
|
||||
}
|
||||
|
||||
if(creation_struct->created_by)
|
||||
{
|
||||
free(creation_struct->created_by);
|
||||
creation_struct->created_by = NULL;
|
||||
}
|
||||
|
||||
|
||||
free(creation_struct);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_creation_info_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_creation_info_t *creation_struct, bool last)
|
||||
*
|
||||
* Serialize /Core/CreationInfo struct to JSON
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param pkgconf_buffer_t *buffer: Buffer where struct is serialized
|
||||
* :param spdxtool_core_creation_info_t *creation_struct: CreationInfo struct to be serialized
|
||||
* :param bool last: Is this last CreationInfo struct or does it need comma at the end. True comma False not
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_creation_info_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_creation_info_t *creation_struct, bool last)
|
||||
{
|
||||
(void) client;
|
||||
|
||||
spdxtool_serialize_obj_start(buffer, 2);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@type", creation_struct->type, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@id", creation_struct->id, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "created", creation_struct->created, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "createdBy", '[', 3, false);
|
||||
spdxtool_serialize_string(buffer, creation_struct->created_by, 4, false);
|
||||
spdxtool_serialize_array_end(buffer, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "specVersion", (char *)creation_struct->spec_version, 3, false);
|
||||
spdxtool_serialize_obj_end(buffer, 2, last);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: spdxtool_core_creation_info_t *spdxtool_core_creation_info_new(pkgconf_client_t *client, char *agent_id, char *id)
|
||||
*
|
||||
* Create new /Core/SpdxDocument struct
|
||||
* In SPDX Lite SBOM there can be only one SpdxDocument
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param char *spdx_id: Id of this SpdxDocument
|
||||
* :param char *creation_id: Id for creation info
|
||||
* :return: NULL if some problem occurs and SpdxDocument struct if not
|
||||
*/
|
||||
spdxtool_core_spdx_document_t *
|
||||
spdxtool_core_spdx_document_new(pkgconf_client_t *client, char *spdx_id, char *creation_id)
|
||||
{
|
||||
spdxtool_core_spdx_document_t *spdx_struct = NULL;
|
||||
|
||||
if(!client || !spdx_id || !creation_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(void)client;
|
||||
|
||||
spdx_struct = calloc(1, sizeof(spdxtool_core_spdx_document_t));
|
||||
|
||||
if(!spdx_struct)
|
||||
{
|
||||
pkgconf_error(client, "Memory exhausted! Can't create spdx_document struct.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spdx_struct->type = "SpdxDocument";
|
||||
spdx_struct->spdx_id = spdx_id;
|
||||
spdx_struct->creation_info = creation_id;
|
||||
return spdx_struct;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_spdx_document_free(spdxtool_core_spdx_document_t *spdx_struct)
|
||||
*
|
||||
* Free /Core/SpdxDocument struct
|
||||
*
|
||||
* :param spdxtool_core_spdx_document_t *spdx_struct: SpdxDocument struct to be freed.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_spdx_document_free(spdxtool_core_spdx_document_t *spdx_struct)
|
||||
{
|
||||
pkgconf_node_t *iter = NULL;
|
||||
pkgconf_node_t *iter_last = NULL;
|
||||
|
||||
if(!spdx_struct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(spdx_struct->spdx_id)
|
||||
{
|
||||
free(spdx_struct->spdx_id);
|
||||
spdx_struct->spdx_id = NULL;
|
||||
}
|
||||
|
||||
if(spdx_struct->creation_info)
|
||||
{
|
||||
free(spdx_struct->creation_info);
|
||||
spdx_struct->creation_info = NULL;
|
||||
}
|
||||
|
||||
if(spdx_struct->agent)
|
||||
{
|
||||
free(spdx_struct->agent);
|
||||
spdx_struct->agent = NULL;
|
||||
}
|
||||
|
||||
iter_last = NULL;
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->rootElement.head, iter)
|
||||
{
|
||||
if(iter_last)
|
||||
{
|
||||
free(iter_last);
|
||||
iter_last = NULL;
|
||||
}
|
||||
|
||||
spdxtool_software_sbom_t *sbom = iter->data;
|
||||
spdxtool_software_sbom_free(sbom);
|
||||
iter->data = NULL;
|
||||
iter_last = iter;
|
||||
}
|
||||
|
||||
if(iter_last)
|
||||
{
|
||||
free(iter_last);
|
||||
iter_last = NULL;
|
||||
}
|
||||
|
||||
|
||||
iter_last = NULL;
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->element.head, iter)
|
||||
{
|
||||
if(iter_last)
|
||||
{
|
||||
free(iter_last);
|
||||
iter_last = NULL;
|
||||
}
|
||||
|
||||
free(iter->data);
|
||||
iter_last = iter;
|
||||
}
|
||||
|
||||
if(iter_last)
|
||||
{
|
||||
free(iter_last);
|
||||
iter_last = NULL;
|
||||
}
|
||||
|
||||
|
||||
iter_last = NULL;
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->licenses.head, iter)
|
||||
{
|
||||
if(iter_last)
|
||||
{
|
||||
free(iter_last);
|
||||
iter_last = NULL;
|
||||
}
|
||||
spdxtool_simplelicensing_license_expression_t *expression = iter->data;
|
||||
spdxtool_simplelicensing_licenseExpression_free(expression);
|
||||
iter->data = NULL;
|
||||
iter_last = iter;
|
||||
}
|
||||
|
||||
if(iter_last)
|
||||
{
|
||||
free(iter_last);
|
||||
iter_last = NULL;
|
||||
}
|
||||
|
||||
free(spdx_struct);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool spdxtool_core_spdx_document_is_license(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *license)
|
||||
*
|
||||
* Find out if specific license is already there.
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param spdxtool_core_spdx_document_t *spdx_struct: SpdxDocument struct being used.
|
||||
* :param char *license: SPDX name of license
|
||||
* :return: true is license is there and false if not
|
||||
*/
|
||||
bool
|
||||
spdxtool_core_spdx_document_is_license(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *license)
|
||||
{
|
||||
pkgconf_node_t *iter = NULL;
|
||||
spdxtool_simplelicensing_license_expression_t *expression = NULL;
|
||||
|
||||
(void) client;
|
||||
|
||||
|
||||
if(!license)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->licenses.head, iter)
|
||||
{
|
||||
expression = iter->data;
|
||||
if (!strcmp(expression->license_expression, license))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_spdx_document_add_license(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *license)
|
||||
*
|
||||
* Add license to SpdxDocument and make sure that specific license is not already there.
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param spdxtool_core_spdx_document_t *spdx_struct: SpdxDocument struct being used.
|
||||
* :param char *license: SPDX name of license
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_spdx_document_add_license(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *license)
|
||||
{
|
||||
pkgconf_node_t *node = NULL;
|
||||
|
||||
|
||||
if(!license)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(spdxtool_core_spdx_document_is_license(client, spdx_struct, license))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
node = calloc(1, sizeof(pkgconf_node_t));
|
||||
if(!node)
|
||||
{
|
||||
pkgconf_error(client, "Memory exhausted! Cant't add license to spdx_document.");
|
||||
return;
|
||||
}
|
||||
spdxtool_simplelicensing_license_expression_t *expression = spdxtool_simplelicensing_licenseExpression_new(client, license);
|
||||
pkgconf_node_insert_tail(node, expression, &spdx_struct->licenses);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_spdx_document_add_element(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *element)
|
||||
*
|
||||
* Add element spdxId to SpdxDocument
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param spdxtool_core_spdx_document_t *spdx_struct: SpdxDocument struct being used.
|
||||
* :param char *element: spdxId of element
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_spdx_document_add_element(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *element)
|
||||
{
|
||||
pkgconf_node_t *node = NULL;
|
||||
|
||||
(void) client;
|
||||
|
||||
if(!element)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
node = calloc(1, sizeof(pkgconf_node_t));
|
||||
if(!node)
|
||||
{
|
||||
pkgconf_error(NULL, "Memory exhausted! Can't add spdx_id's to spdx_document.");
|
||||
return;
|
||||
}
|
||||
pkgconf_node_insert_tail(node, element, &spdx_struct->element);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_creation_info_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_creation_info_t *creation_struct, bool last)
|
||||
*
|
||||
* Serialize /Core/SpdxDocument struct to JSON
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param pkgconf_buffer_t *buffer: Buffer where struct is serialized
|
||||
* :param spdxtool_core_spdx_document_t *spdx_struct: SpdxDocument struct to be serialized
|
||||
* :param bool last: Is this last CreationInfo struct or does it need comma at the end. True comma False not
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_spdx_document_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_spdx_document_t *spdx_struct, bool last)
|
||||
{
|
||||
pkgconf_node_t *iter = NULL;
|
||||
bool is_next = false;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->rootElement.head, iter)
|
||||
{
|
||||
spdxtool_software_sbom_t *sbom = NULL;
|
||||
sbom = iter->data;
|
||||
spdxtool_software_sbom_serialize(client, buffer, sbom, true);
|
||||
}
|
||||
|
||||
spdxtool_serialize_obj_start(buffer, 2);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@type", spdx_struct->type, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "creationInfo", spdx_struct->creation_info, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "spdxId", spdx_struct->spdx_id, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "rootElement", '[', 3, false);
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->rootElement.head, iter)
|
||||
{
|
||||
spdxtool_software_sbom_t *sbom = NULL;
|
||||
sbom = iter->data;
|
||||
is_next = false;
|
||||
if(iter->next)
|
||||
{
|
||||
is_next = true;
|
||||
}
|
||||
spdxtool_serialize_string(buffer, sbom->spdx_id, 4, is_next);
|
||||
}
|
||||
spdxtool_serialize_array_end(buffer, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "element", '[', 3, false);
|
||||
spdxtool_serialize_string(buffer, spdx_struct->agent, 4, true);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->element.head, iter)
|
||||
{
|
||||
char *spdx_id = NULL;
|
||||
spdx_id = iter->data;
|
||||
spdxtool_serialize_string(buffer, spdx_id, 4, true);
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->rootElement.head, iter)
|
||||
{
|
||||
spdxtool_software_sbom_t *sbom = NULL;
|
||||
sbom = iter->data;
|
||||
is_next = false;
|
||||
if(iter->next)
|
||||
{
|
||||
is_next = true;
|
||||
}
|
||||
spdxtool_serialize_string(buffer, sbom->spdx_id, 4, true);
|
||||
spdxtool_serialize_string(buffer, pkgconf_tuple_find(client, &sbom->rootElement->vars, "spdxId"), 4, is_next);
|
||||
}
|
||||
|
||||
spdxtool_serialize_array_end(buffer, 3, false);
|
||||
spdxtool_serialize_obj_end(buffer, 2, last);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: spdxtool_core_relationship_t *spdxtool_core_relationship_new(pkgconf_client_t *client, char *creation_info_id, char *spdx_id, char *from, char *to, char *relationship_type)
|
||||
*
|
||||
* Create new /Core/Relationship struct
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param char *creation_id: Id for creation info
|
||||
* :param char *spdx_id: Id of this SpdxDocument
|
||||
* :param char *from: from spdxId
|
||||
* :param char *to: to spdxId
|
||||
* :param char *relationship_type: These can be found on SPDX documentation
|
||||
* :return: NULL if some problem occurs and SpdxDocument struct if not
|
||||
*/
|
||||
spdxtool_core_relationship_t *
|
||||
spdxtool_core_relationship_new(pkgconf_client_t *client, char *creation_info_id, char *spdx_id, char *from, char *to, char *relationship_type)
|
||||
{
|
||||
spdxtool_core_relationship_t *relationship = NULL;
|
||||
|
||||
if(!client || !creation_info_id || !spdx_id || !from || !to || !relationship_type)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(void) client;
|
||||
|
||||
relationship = calloc(1, sizeof(spdxtool_core_relationship_t));
|
||||
|
||||
if(!relationship)
|
||||
{
|
||||
pkgconf_error(client, "Memory exhausted! Can't create relationship struct.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
relationship->type = "Relationship";
|
||||
relationship->creation_info = creation_info_id;
|
||||
relationship->spdx_id = spdx_id;
|
||||
relationship->from = from;
|
||||
relationship->to = to;
|
||||
relationship->relationship_type = relationship_type;
|
||||
|
||||
return relationship;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_relationship_free(spdxtool_core_relationship_t *relationship_struct)
|
||||
*
|
||||
* Free /Core/Relationship struct
|
||||
*
|
||||
* :param spdxtool_core_relationship_t *relationship_struct: Relationship struct to be freed.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_relationship_free(spdxtool_core_relationship_t *relationship_struct)
|
||||
{
|
||||
if(!relationship_struct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(relationship_struct->spdx_id)
|
||||
{
|
||||
free(relationship_struct->spdx_id);
|
||||
relationship_struct->spdx_id = NULL;
|
||||
}
|
||||
|
||||
if(relationship_struct->creation_info)
|
||||
{
|
||||
free(relationship_struct->creation_info);
|
||||
relationship_struct->creation_info = NULL;
|
||||
}
|
||||
|
||||
if(relationship_struct->from)
|
||||
{
|
||||
free(relationship_struct->from);
|
||||
relationship_struct->from = NULL;
|
||||
}
|
||||
|
||||
if(relationship_struct->to)
|
||||
{
|
||||
free(relationship_struct->to);
|
||||
relationship_struct->to = NULL;
|
||||
}
|
||||
|
||||
if(relationship_struct->relationship_type)
|
||||
{
|
||||
free(relationship_struct->relationship_type);
|
||||
relationship_struct->relationship_type = NULL;
|
||||
}
|
||||
|
||||
free(relationship_struct);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_core_creation_info_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_creation_info_t *creation_struct, bool last)
|
||||
*
|
||||
* Serialize /Core/Relationship struct to JSON
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param pkgconf_buffer_t *buffer: Buffer where struct is serialized
|
||||
* :param spdxtool_core_relationship_t *relationship_struct: Relationship struct to be serialized
|
||||
* :param bool last: Is this last CreationInfo struct or does it need comma at the end. True comma False not
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_core_relationship_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_relationship_t *relationship_struct, bool last)
|
||||
{
|
||||
(void) client;
|
||||
|
||||
spdxtool_serialize_obj_start(buffer, 2);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@type", relationship_struct->type, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "creationInfo", relationship_struct->creation_info, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "spdxId", relationship_struct->spdx_id, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "from", relationship_struct->from, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "to", '[', 3, false);
|
||||
spdxtool_serialize_string(buffer, relationship_struct->to, 4, false);
|
||||
spdxtool_serialize_array_end(buffer, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "relationshipType", relationship_struct->relationship_type, 3, false);
|
||||
spdxtool_serialize_obj_end(buffer, 2, last);
|
||||
}
|
||||
73
cli/spdxtool/core.h
Normal file
73
cli/spdxtool/core.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#ifndef CLI__SPDXTOOL__CORE_H
|
||||
#define CLI__SPDXTOOL__CORE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
spdxtool_core_agent_t *
|
||||
spdxtool_core_agent_new(pkgconf_client_t *client, char *creation_id, char *name);
|
||||
|
||||
void
|
||||
spdxtool_core_agent_free(spdxtool_core_agent_t *agent_struct);
|
||||
|
||||
void
|
||||
spdxtool_core_agent_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_agent_t *agent_struct, bool last);
|
||||
|
||||
spdxtool_core_creation_info_t *
|
||||
spdxtool_core_creation_info_new(pkgconf_client_t *client, char *agent_id, char *id, char *time);
|
||||
|
||||
void
|
||||
spdxtool_core_creation_info_free(spdxtool_core_creation_info_t *creation_struct);
|
||||
|
||||
void
|
||||
spdxtool_core_creation_info_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_creation_info_t *creation_struct, bool last);
|
||||
|
||||
spdxtool_core_spdx_document_t *
|
||||
spdxtool_core_spdx_document_new(pkgconf_client_t *client, char *spdx_id, char *creation_id);
|
||||
|
||||
bool
|
||||
spdxtool_core_spdx_document_is_license(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *license);
|
||||
|
||||
|
||||
void
|
||||
spdxtool_core_spdx_document_add_license(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *license);
|
||||
|
||||
void
|
||||
spdxtool_core_spdx_document_add_element(pkgconf_client_t *client, spdxtool_core_spdx_document_t *spdx_struct, char *element);
|
||||
|
||||
|
||||
void
|
||||
spdxtool_core_spdx_document_free(spdxtool_core_spdx_document_t *spdx_struct);
|
||||
|
||||
void
|
||||
spdxtool_core_spdx_document_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_spdx_document_t *spdx_struct, bool last);
|
||||
|
||||
|
||||
spdxtool_core_relationship_t *
|
||||
spdxtool_core_relationship_new(pkgconf_client_t *client, char *creation_info_id, char *spdx_id, char *from, char *to, char *relationship_type);
|
||||
|
||||
void
|
||||
spdxtool_core_relationship_free(spdxtool_core_relationship_t *relationship_struct);
|
||||
|
||||
void
|
||||
spdxtool_core_relationship_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_relationship_t *relationship_struct, bool last);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
356
cli/spdxtool/main.c
Normal file
356
cli/spdxtool/main.c
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include "libpkgconf/config.h"
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
#include "getopt_long.h"
|
||||
#include "util.h"
|
||||
#include "core.h"
|
||||
#include "software.h"
|
||||
#include "serialize.h"
|
||||
#include "simplelicensing.h"
|
||||
|
||||
#define PKG_VERSION (((uint64_t) 1) << 1)
|
||||
#define PKG_ABOUT (((uint64_t) 1) << 2)
|
||||
#define PKG_HELP (((uint64_t) 1) << 3)
|
||||
|
||||
static const char *spdx_version = "3.0.1";
|
||||
static const char *bom_license = "CC0-1.0";
|
||||
static const char *xsd_any_uri_default_base = "https://github.com/pkgconf/pkgconf";
|
||||
static int maximum_traverse_depth = 2000;
|
||||
|
||||
static pkgconf_client_t pkg_client;
|
||||
static uint64_t want_flags;
|
||||
static size_t maximum_package_count = 0;
|
||||
// static int maximum_traverse_depth = 2000;
|
||||
static FILE *error_msgout = NULL;
|
||||
|
||||
static const char *
|
||||
environ_lookup_handler(const pkgconf_client_t *client, const char *key)
|
||||
{
|
||||
(void) client;
|
||||
|
||||
return getenv(key);
|
||||
}
|
||||
|
||||
static bool
|
||||
error_handler(const char *msg, const pkgconf_client_t *client, void *data)
|
||||
{
|
||||
(void) client;
|
||||
(void) data;
|
||||
fprintf(error_msgout, "%s", msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
write_jsonld_end(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_buffer_t *buffer)
|
||||
{
|
||||
(void) client;
|
||||
(void) world;
|
||||
|
||||
spdxtool_serialize_array_end(buffer, 1, false);
|
||||
spdxtool_serialize_obj_end(buffer, 0, false);
|
||||
}
|
||||
|
||||
static void
|
||||
write_jsonld_header(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_buffer_t *buffer)
|
||||
{
|
||||
(void) client;
|
||||
(void) world;
|
||||
|
||||
spdxtool_serialize_obj_start(buffer, 0);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@context", "https://spdx.org/rdf/3.0.1/spdx-context.jsonld", 1, true);
|
||||
|
||||
spdxtool_serialize_parm_and_char(buffer, "@graph", '[', 1, false);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
generate_spdx_package(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *ptr)
|
||||
{
|
||||
(void) client;
|
||||
pkgconf_node_t *node = NULL;
|
||||
spdxtool_core_spdx_document_t *document = (spdxtool_core_spdx_document_t *)ptr;
|
||||
char *package_spdx = NULL;
|
||||
char spdx_id_name[1024];
|
||||
|
||||
|
||||
if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
|
||||
return;
|
||||
|
||||
spdxtool_software_sbom_t *sbom = spdxtool_software_sbom_new(client, spdxtool_util_get_spdx_id_string(client, "software_Sbom", pkg->realname), strdup(document->creation_info), strdup("build"));
|
||||
sbom->spdx_document = document;
|
||||
sbom->rootElement = pkg;
|
||||
|
||||
package_spdx = spdxtool_util_get_spdx_id_string(client, "Package", pkg->realname);
|
||||
|
||||
pkgconf_tuple_add(client, &pkg->vars, "spdxId", package_spdx, false, 0);
|
||||
free(package_spdx);
|
||||
package_spdx = NULL;
|
||||
|
||||
pkgconf_tuple_add(client, &pkg->vars, "creationInfo", document->creation_info, false, 0);
|
||||
pkgconf_tuple_add(client, &pkg->vars, "agent", document->agent, false, 0);
|
||||
|
||||
if (pkg->license != NULL)
|
||||
{
|
||||
snprintf(spdx_id_name, 1024, "%s/hasDeclaredLicense", pkg->realname);
|
||||
package_spdx = spdxtool_util_get_spdx_id_string(client, "Relationship", spdx_id_name);
|
||||
pkgconf_tuple_add(client, &pkg->vars, "hasDeclaredLicense", package_spdx, false, 0);
|
||||
free(package_spdx);
|
||||
package_spdx = NULL;
|
||||
|
||||
snprintf(spdx_id_name, 1024, "%s/hasConcludedLicense", pkg->realname);
|
||||
package_spdx = spdxtool_util_get_spdx_id_string(client, "Relationship", spdx_id_name);
|
||||
pkgconf_tuple_add(client, &pkg->vars, "hasConcludedLicense", package_spdx, false, 0);
|
||||
free(package_spdx);
|
||||
package_spdx = NULL;
|
||||
|
||||
spdxtool_core_spdx_document_add_license(client, document, pkg->license);
|
||||
}
|
||||
|
||||
node = calloc(1, sizeof(pkgconf_node_t));
|
||||
|
||||
if(!node)
|
||||
{
|
||||
pkgconf_error(NULL, "Memory exhausted!");
|
||||
return;
|
||||
}
|
||||
pkgconf_node_insert_tail(node, sbom, &document->rootElement);
|
||||
}
|
||||
|
||||
static bool
|
||||
generate_spdx(pkgconf_client_t *client, pkgconf_pkg_t *world, char *creation_time, char *creation_id, char *agent_name)
|
||||
{
|
||||
int eflag;
|
||||
pkgconf_buffer_t buffer = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
char *agent_name_string = "Default";
|
||||
char *creation_id_string = "_:creationinfo_1";
|
||||
char *creation_time_string = NULL;
|
||||
|
||||
|
||||
if(agent_name)
|
||||
{
|
||||
agent_name_string = agent_name;
|
||||
}
|
||||
|
||||
if(creation_time)
|
||||
{
|
||||
creation_time_string = strdup(creation_time);
|
||||
}
|
||||
|
||||
if(creation_id)
|
||||
{
|
||||
creation_id_string = creation_id;
|
||||
}
|
||||
|
||||
spdxtool_core_agent_t *agent = spdxtool_core_agent_new(client, strdup(creation_id_string), strdup(agent_name_string));
|
||||
spdxtool_core_creation_info_t *creation = spdxtool_core_creation_info_new(&pkg_client, strdup(agent->spdx_id), strdup(creation_id_string), creation_time_string);
|
||||
spdxtool_core_spdx_document_t *document = spdxtool_core_spdx_document_new(&pkg_client, spdxtool_util_get_spdx_id_int(&pkg_client, "spdxDocument"), strdup(creation_id_string));
|
||||
|
||||
document->agent = strdup(agent->spdx_id);
|
||||
|
||||
eflag = pkgconf_pkg_traverse(client, world, generate_spdx_package, document, maximum_traverse_depth, 0);
|
||||
if (eflag != PKGCONF_PKG_ERRF_OK)
|
||||
return false;
|
||||
|
||||
write_jsonld_header(client, world, &buffer);
|
||||
|
||||
spdxtool_core_agent_serialize(client, &buffer, agent, true);
|
||||
spdxtool_core_creation_info_serialize(client, &buffer, creation, true);
|
||||
|
||||
spdxtool_simplelicensing_licenseExpression_serialize(client, &buffer, document, true);
|
||||
|
||||
spdxtool_core_spdx_document_serialize(client, &buffer, document, false);
|
||||
|
||||
write_jsonld_end(client, world, &buffer);
|
||||
|
||||
spdxtool_core_spdx_document_free(document);
|
||||
spdxtool_core_agent_free(agent);
|
||||
spdxtool_core_creation_info_free(creation);
|
||||
|
||||
printf("%s\n", pkgconf_buffer_str(&buffer));
|
||||
|
||||
pkgconf_buffer_finalize(&buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
version(void)
|
||||
{
|
||||
printf("spdxtool %s\n", PACKAGE_VERSION);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
about(void)
|
||||
{
|
||||
printf("spdxtool (%s %s)\n\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
printf("SPDX-License-Identifier: BSD-2-Clause\n\n");
|
||||
printf("Copyright (c) 2025 The FreeBSD Foundation\n\n");
|
||||
printf("Portions of this software were developed by\n");
|
||||
printf("Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from\n");
|
||||
printf("the FreeBSD Foundation\n\n");
|
||||
printf("Report bugs at <%s>.\n", PACKAGE_BUGREPORT);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: spdxtool [modules]\n");
|
||||
|
||||
printf("\nOptions:\n");
|
||||
|
||||
printf(" --agent-name Set agent name [default: 'Default']\n");
|
||||
printf(" --creation-time Use string as creation time (Should be in ISO8601 format) [default: current time]\n");
|
||||
printf(" --creation-id Use string as creation id [default: '_:creationinfo_1']\n");
|
||||
printf(" --help this message\n");
|
||||
printf(" --about print bomtool version and license to stdout\n");
|
||||
printf(" --version print bomtool version to stdout\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ret = EXIT_SUCCESS;
|
||||
pkgconf_list_t pkgq = PKGCONF_LIST_INITIALIZER;
|
||||
unsigned int want_client_flags = PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
|
||||
pkgconf_cross_personality_t *personality = pkgconf_cross_personality_default();
|
||||
char *creation_time = NULL;
|
||||
char *creation_id = NULL;
|
||||
char *agent_name = NULL;
|
||||
pkgconf_pkg_t world =
|
||||
{
|
||||
.id = "virtual:world",
|
||||
.realname = "virtual world package",
|
||||
.flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
|
||||
};
|
||||
|
||||
error_msgout = stderr;
|
||||
|
||||
struct pkg_option options[] =
|
||||
{
|
||||
{ "agent-name", required_argument, NULL, 100, },
|
||||
{ "creation-time", required_argument, NULL, 101, },
|
||||
{ "creation-id", required_argument, NULL, 102, },
|
||||
{ "version", no_argument, &want_flags, PKG_VERSION, },
|
||||
{ "about", no_argument, &want_flags, PKG_ABOUT, },
|
||||
{ "help", no_argument, &want_flags, PKG_HELP, },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
while ((ret = pkg_getopt_long_only(argc, argv, "", options, NULL)) != -1)
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case 100:
|
||||
agent_name = pkg_optarg;
|
||||
break;
|
||||
case 101:
|
||||
creation_time = pkg_optarg;
|
||||
break;
|
||||
case 102:
|
||||
creation_id = pkg_optarg;
|
||||
break;
|
||||
case '?':
|
||||
case ':':
|
||||
return EXIT_FAILURE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pkgconf_client_init(&pkg_client, error_handler, NULL, personality, NULL, environ_lookup_handler);
|
||||
|
||||
/* we have determined what features we want most likely. in some cases, we override later. */
|
||||
pkgconf_client_set_flags(&pkg_client, want_client_flags);
|
||||
|
||||
/* at this point, want_client_flags should be set, so build the dir list */
|
||||
pkgconf_client_dir_list_build(&pkg_client, personality);
|
||||
|
||||
|
||||
if ((want_flags & PKG_ABOUT) == PKG_ABOUT)
|
||||
return about();
|
||||
|
||||
if ((want_flags & PKG_VERSION) == PKG_VERSION)
|
||||
return version();
|
||||
|
||||
if ((want_flags & PKG_HELP) == PKG_HELP)
|
||||
return usage();
|
||||
|
||||
while (1)
|
||||
{
|
||||
const char *package = argv[pkg_optind];
|
||||
|
||||
if (package == NULL)
|
||||
break;
|
||||
|
||||
/* check if there is a limit to the number of packages allowed to be included, if so and we have hit
|
||||
* the limit, stop adding packages to the queue.
|
||||
*/
|
||||
if (maximum_package_count > 0 && pkgq.length > maximum_package_count)
|
||||
break;
|
||||
|
||||
while (isspace((unsigned char)package[0]))
|
||||
package++;
|
||||
|
||||
/* skip empty packages */
|
||||
if (package[0] == '\0')
|
||||
{
|
||||
pkg_optind++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[pkg_optind + 1] == NULL || !PKGCONF_IS_OPERATOR_CHAR(*(argv[pkg_optind + 1])))
|
||||
{
|
||||
pkgconf_queue_push(&pkgq, package);
|
||||
pkg_optind++;
|
||||
}
|
||||
else
|
||||
{
|
||||
char packagebuf[PKGCONF_BUFSIZE];
|
||||
|
||||
snprintf(packagebuf, sizeof packagebuf, "%s %s %s", package, argv[pkg_optind + 1], argv[pkg_optind + 2]);
|
||||
pkg_optind += 3;
|
||||
|
||||
pkgconf_queue_push(&pkgq, packagebuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pkgconf_queue_solve(&pkg_client, &pkgq, &world, maximum_traverse_depth))
|
||||
{
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spdxtool_util_set_uri_root(&pkg_client, xsd_any_uri_default_base);
|
||||
spdxtool_util_set_spdx_license(&pkg_client, bom_license);
|
||||
spdxtool_util_set_spdx_version(&pkg_client, spdx_version);
|
||||
|
||||
if (!generate_spdx(&pkg_client, &world, creation_time, creation_id, agent_name))
|
||||
{
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
|
||||
out:
|
||||
pkgconf_solution_free(&pkg_client, &world);
|
||||
pkgconf_queue_free(&pkgq);
|
||||
pkgconf_cross_personality_deinit(personality);
|
||||
pkgconf_client_deinit(&pkg_client);
|
||||
|
||||
return ret;
|
||||
}
|
||||
206
cli/spdxtool/serialize.c
Normal file
206
cli/spdxtool/serialize.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "core.h"
|
||||
|
||||
static inline void
|
||||
serialize_add_indent(pkgconf_buffer_t *buffer, unsigned int level)
|
||||
{
|
||||
for (; level; level--)
|
||||
pkgconf_buffer_append(buffer, " ");
|
||||
}
|
||||
|
||||
static inline void
|
||||
serialize_next_line(pkgconf_buffer_t *buffer, bool more)
|
||||
{
|
||||
if (more)
|
||||
pkgconf_buffer_push_byte(buffer, ',');
|
||||
|
||||
pkgconf_buffer_push_byte(buffer, '\n');
|
||||
}
|
||||
|
||||
static inline void
|
||||
serialize_begin_object(pkgconf_buffer_t *buffer, char ch, unsigned int level)
|
||||
{
|
||||
serialize_add_indent(buffer, level);
|
||||
pkgconf_buffer_push_byte(buffer, ch);
|
||||
serialize_next_line(buffer, false);
|
||||
}
|
||||
|
||||
static inline void
|
||||
serialize_end_object(pkgconf_buffer_t *buffer, char ch, unsigned int level, bool more)
|
||||
{
|
||||
serialize_add_indent(buffer, level);
|
||||
pkgconf_buffer_push_byte(buffer, ch);
|
||||
serialize_next_line(buffer, more);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_parm_and_string(pkgconf_buffer_t *buffer, char *parm, char *string, unsigned int level, bool more)
|
||||
*
|
||||
* Add paramter, string and optional comma to buffer
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param char *param: Parameter name
|
||||
* :param char *string: String to add
|
||||
* :param unsigned int level: Indent level
|
||||
* :param bool more: true if more fields are expected, else false
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_parm_and_string(pkgconf_buffer_t *buffer, char *parm, char *string, unsigned int level, bool more)
|
||||
{
|
||||
serialize_add_indent(buffer, level);
|
||||
pkgconf_buffer_append_fmt(buffer, "\"%s\": \"%s\"", parm, string);
|
||||
serialize_next_line(buffer, more);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_parm_and_char(pkgconf_buffer_t *buffer, char *parm, char ch, unsigned int level, bool more)
|
||||
*
|
||||
* Add paramter, char and optional comma to buffer
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param char *param: Parameter name
|
||||
* :param char ch: Char to add
|
||||
* :param unsigned int level: Indent level
|
||||
* :param bool more: true if more fields are expected, else false
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_parm_and_char(pkgconf_buffer_t *buffer, char *parm, char ch, unsigned int level, bool more)
|
||||
{
|
||||
serialize_add_indent(buffer, level);
|
||||
pkgconf_buffer_append_fmt(buffer, "\"%s\": %c", parm, ch);
|
||||
serialize_next_line(buffer, more);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_parm_and_int(pkgconf_buffer_t *buffer, char *parm, int integer, unsigned int level, bool more)
|
||||
*
|
||||
* Add paramter, integer and optional comma to buffer
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param char *param: Parameter name
|
||||
* :param int integer: Int to add
|
||||
* :param unsigned int level: Indent level
|
||||
* :param bool more: true if more fields are expected, else false
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_parm_and_int(pkgconf_buffer_t *buffer, char *parm, int integer, unsigned int level, bool more)
|
||||
{
|
||||
serialize_add_indent(buffer, level);
|
||||
pkgconf_buffer_append_fmt(buffer, "\"%s\": %d", parm, integer);
|
||||
serialize_next_line(buffer, more);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_string(pkgconf_buffer_t *buffer, char *string, unsigned int level, bool more)
|
||||
*
|
||||
* Add just string.
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param char *param: Parameter name
|
||||
* :param char *ch: String to add
|
||||
* :param unsigned int: level Indent level
|
||||
* :param bool more: true if more fields are expected, else false
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_string(pkgconf_buffer_t *buffer, char *string, unsigned int level, bool more)
|
||||
{
|
||||
serialize_add_indent(buffer, level);
|
||||
pkgconf_buffer_push_byte(buffer, '"');
|
||||
pkgconf_buffer_append(buffer, string);
|
||||
pkgconf_buffer_push_byte(buffer, '"');
|
||||
serialize_next_line(buffer, more);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_obj_start(pkgconf_buffer_t *buffer, unsigned int level)
|
||||
*
|
||||
* Start JSON object to buffer
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param unsigned int level: Indent level
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_obj_start(pkgconf_buffer_t *buffer, unsigned int level)
|
||||
{
|
||||
serialize_begin_object(buffer, '{', level);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_obj_end(pkgconf_buffer_t *buffer, unsigned int level, bool more)
|
||||
*
|
||||
* End JSON object to buffer
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param unsigned int level: Level which is added
|
||||
* :param bool more: true if more fields are expected, else false
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_obj_end(pkgconf_buffer_t *buffer, unsigned int level, bool more)
|
||||
{
|
||||
serialize_end_object(buffer, '}', level, more);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_obj_start(pkgconf_buffer_t *buffer, unsigned int level)
|
||||
*
|
||||
* Start JSON array to buffer
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param unsigned int level: Level which is added
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_array_start(pkgconf_buffer_t *buffer, unsigned int level)
|
||||
{
|
||||
serialize_begin_object(buffer, '[', level);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_serialize_array_end(pkgconf_buffer_t *buffer, unsigned int level, bool more)
|
||||
*
|
||||
* End JSON array to buffer
|
||||
*
|
||||
* :param pkgconf_buffer_t *buffer: Buffer to add.
|
||||
* :param unsigned int level: Level which is added
|
||||
* :param bool more: true if more fields are expected, else false
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_serialize_array_end(pkgconf_buffer_t *buffer, unsigned int level, bool more)
|
||||
{
|
||||
serialize_end_object(buffer, ']', level, more);
|
||||
}
|
||||
50
cli/spdxtool/serialize.h
Normal file
50
cli/spdxtool/serialize.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifndef CLI__SPDXTOOL__SERIALIZE_H
|
||||
#define CLI__SPDXTOOL__SERIALIZE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
spdxtool_serialize_parm_and_string(pkgconf_buffer_t *buffer, char *parm, char *string, unsigned int level, bool comma);
|
||||
|
||||
void
|
||||
spdxtool_serialize_parm_and_char(pkgconf_buffer_t *buffer, char *parm, char ch, unsigned int level, bool comma);
|
||||
|
||||
void
|
||||
spdxtool_serialize_parm_and_int(pkgconf_buffer_t *buffer, char *parm, int integer, unsigned int level, bool comma);
|
||||
|
||||
void
|
||||
spdxtool_serialize_string(pkgconf_buffer_t *buffer, char *string, unsigned int level, bool comma);
|
||||
|
||||
void
|
||||
spdxtool_serialize_obj_start(pkgconf_buffer_t *buffer, unsigned int level);
|
||||
|
||||
void
|
||||
spdxtool_serialize_obj_end(pkgconf_buffer_t *buffer, unsigned int level, bool comma);
|
||||
|
||||
void
|
||||
spdxtool_serialize_array_start(pkgconf_buffer_t *buffer, unsigned int level);
|
||||
|
||||
void
|
||||
spdxtool_serialize_array_end(pkgconf_buffer_t *buffer, unsigned int level, bool comma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
120
cli/spdxtool/simplelicensing.c
Normal file
120
cli/spdxtool/simplelicensing.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "serialize.h"
|
||||
#include "software.h"
|
||||
#include "core.h"
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: spdxtool_simplelicensing_license_expression_t *spdxtool_simplelicensing_licenseExpression_new(pkgconf_client_t *client, char *license)
|
||||
*
|
||||
* Create new /SimpleLicensing/SimpleLicensingText struct
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param char *license: SPDX name of license
|
||||
* :return: NULL if some problem occurs and SimpleLicensingText struct if not
|
||||
*/
|
||||
spdxtool_simplelicensing_license_expression_t *
|
||||
spdxtool_simplelicensing_licenseExpression_new(pkgconf_client_t *client, char *license)
|
||||
{
|
||||
spdxtool_simplelicensing_license_expression_t *expression = NULL;
|
||||
|
||||
if(!client || !license)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expression = calloc(1, sizeof(spdxtool_simplelicensing_license_expression_t));
|
||||
|
||||
if(!expression)
|
||||
{
|
||||
pkgconf_error(client, "Memory exhausted! Can't create simplelicense_expression struct!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expression->type = "simplelicensing_LicenseExpression";
|
||||
expression->license_expression = strdup(license);
|
||||
expression->spdx_id = spdxtool_util_get_spdx_id_string(client, expression->type, license);
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_simplelicensing_licenseExpression_free(spdxtool_simplelicensing_license_expression_t *expression_struct)
|
||||
*
|
||||
* Free /SimpleLicensing/SimpleLicensingText struct
|
||||
*
|
||||
* :param spdxtool_simplelicensing_license_expression_t *expression_struct: SimpleLicensingText struct to be freed.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_simplelicensing_licenseExpression_free(spdxtool_simplelicensing_license_expression_t *expression_struct)
|
||||
{
|
||||
if(!expression_struct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(expression_struct->spdx_id)
|
||||
{
|
||||
free(expression_struct->spdx_id);
|
||||
expression_struct->spdx_id = NULL;
|
||||
}
|
||||
|
||||
if(expression_struct->license_expression)
|
||||
{
|
||||
free(expression_struct->license_expression);
|
||||
expression_struct->license_expression = NULL;
|
||||
}
|
||||
|
||||
free(expression_struct);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_simplelicensing_licenseExpression_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_spdx_document_t *spdx_struct, bool last)
|
||||
*
|
||||
* Serialize /SimpleLicensing/SimpleLicensingText struct to JSON
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param pkgconf_buffer_t *buffer: Buffer where struct is serialized
|
||||
* :param spdxtool_core_spdx_document_t *spdx_struct: SimpleLicensingText struct to be serialized
|
||||
* :param bool last: Is this last CreationInfo struct or does it need comma at the end. True comma False not
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_simplelicensing_licenseExpression_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_spdx_document_t *spdx_struct, bool last)
|
||||
{
|
||||
pkgconf_node_t *iter = NULL;
|
||||
|
||||
(void) last;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(spdx_struct->licenses.head, iter)
|
||||
{
|
||||
spdxtool_simplelicensing_license_expression_t *expression = iter->data;
|
||||
|
||||
spdxtool_serialize_obj_start(buffer, 2);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@type", "simplelicensing_LicenseExpression", 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "creationInfo", spdx_struct->creation_info, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "spdxId",expression->spdx_id, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "simplelicensing_licenseExpression", expression->license_expression, 3, false);
|
||||
spdxtool_serialize_obj_end(buffer, 2, true);
|
||||
|
||||
spdxtool_core_spdx_document_add_element(client, spdx_struct, strdup(expression->spdx_id));
|
||||
}
|
||||
}
|
||||
38
cli/spdxtool/simplelicensing.h
Normal file
38
cli/spdxtool/simplelicensing.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifndef CLI__SPDXTOOL__SIMPLELICENSING_H
|
||||
#define CLI__SPDXTOOL__SIMPLELICENSING_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
spdxtool_simplelicensing_license_expression_t *
|
||||
spdxtool_simplelicensing_licenseExpression_new(pkgconf_client_t *client, char *license);
|
||||
|
||||
void
|
||||
spdxtool_simplelicensing_licenseExpression_free(spdxtool_simplelicensing_license_expression_t *expression_struct);
|
||||
|
||||
|
||||
void
|
||||
spdxtool_simplelicensing_licenseExpression_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_core_spdx_document_t *spdx_struct, bool last);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
241
cli/spdxtool/software.c
Normal file
241
cli/spdxtool/software.c
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "serialize.h"
|
||||
#include "software.h"
|
||||
#include "core.h"
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: spdxtool_software_sbom_t *spdxtool_software_sbom_new(pkgconf_client_t *client, char *spdx_id, char *creation_id, char *sbom_type)
|
||||
*
|
||||
* Create new /Software/Sbom struct
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param char *spdx_id: spdxId for this SBOM element
|
||||
* :param char *creation_id: id for CreationInfo
|
||||
* :param char *sbom_type: Sbom types can be found SPDX documention
|
||||
* :return: NULL if some problem occurs and Sbom struct if not
|
||||
*/
|
||||
spdxtool_software_sbom_t *
|
||||
spdxtool_software_sbom_new(pkgconf_client_t *client, char *spdx_id, char *creation_id, char *sbom_type)
|
||||
{
|
||||
spdxtool_software_sbom_t *sbom_struct = NULL;
|
||||
|
||||
if(!client || !spdx_id || !creation_id || !sbom_type)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(void)client;
|
||||
|
||||
sbom_struct = calloc(1, sizeof(spdxtool_software_sbom_t));
|
||||
|
||||
if(!sbom_struct)
|
||||
{
|
||||
pkgconf_error(client, "Memory exhausted! Can't create sbom struct.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sbom_struct->type="software_Sbom";
|
||||
sbom_struct->spdx_id = spdx_id;
|
||||
sbom_struct->creation_info = creation_id;
|
||||
sbom_struct->sbom_type = sbom_type;
|
||||
return sbom_struct;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_software_sbom_free(spdxtool_software_sbom_t *sbom_struct)
|
||||
*
|
||||
* Free /Software/Sbom struct
|
||||
*
|
||||
* :param spdxtool_software_sbom_t *sbom_struct: Sbom struct to be freed.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_software_sbom_free(spdxtool_software_sbom_t *sbom_struct)
|
||||
{
|
||||
|
||||
if(!sbom_struct)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(sbom_struct->spdx_id)
|
||||
{
|
||||
free(sbom_struct->spdx_id);
|
||||
sbom_struct->spdx_id = NULL;
|
||||
}
|
||||
|
||||
if(sbom_struct->creation_info)
|
||||
{
|
||||
free(sbom_struct->creation_info);
|
||||
sbom_struct->creation_info = NULL;
|
||||
}
|
||||
|
||||
if(sbom_struct->sbom_type)
|
||||
{
|
||||
free(sbom_struct->sbom_type);
|
||||
sbom_struct->sbom_type = NULL;
|
||||
}
|
||||
|
||||
free(sbom_struct);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_software_sbom_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_software_sbom_t *sbom_struct, bool last)
|
||||
*
|
||||
* Serialize /Software/Sbom struct to JSON
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param pkgconf_buffer_t *buffer: Buffer where struct is serialized
|
||||
* :param spdxtool_software_sbom_t *sbom_struct: SimpleLicensingText struct to be serialized
|
||||
* :param bool last: Is this last CreationInfo struct or does it need comma at the end. True comma False not
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_software_sbom_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_software_sbom_t *sbom_struct, bool last)
|
||||
{
|
||||
pkgconf_node_t *node = NULL;
|
||||
char *value;
|
||||
|
||||
spdxtool_serialize_obj_start(buffer, 2);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@type", sbom_struct->type, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "creationInfo", sbom_struct->creation_info, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "spdxId", sbom_struct->spdx_id, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "software_sbomType", '[', 3, false);
|
||||
spdxtool_serialize_string(buffer, sbom_struct->sbom_type, 4, false);
|
||||
spdxtool_serialize_array_end(buffer, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "rootElement", '[', 3, false);
|
||||
spdxtool_serialize_string(buffer, pkgconf_tuple_find(client, &sbom_struct->rootElement->vars, "spdxId"), 4, false);
|
||||
spdxtool_serialize_array_end(buffer, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "element", '[', 3, false);
|
||||
PKGCONF_FOREACH_LIST_ENTRY(sbom_struct->rootElement->required.head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_pkg_t *match = dep->match;
|
||||
char *spdx_id_relation = NULL;
|
||||
char tmp_str[1024];
|
||||
|
||||
// New relation spdxId
|
||||
snprintf(tmp_str, 1024, "%s/dependsOn/%s", sbom_struct->rootElement->realname, match->realname);
|
||||
|
||||
spdx_id_relation = spdxtool_util_get_spdx_id_string(client, "Releationship", tmp_str);
|
||||
|
||||
spdxtool_serialize_string(buffer, spdx_id_relation, 4, true);
|
||||
|
||||
spdxtool_core_spdx_document_add_element(client, sbom_struct->spdx_document, strdup(spdx_id_relation));
|
||||
|
||||
free(spdx_id_relation);
|
||||
}
|
||||
|
||||
value = pkgconf_tuple_find(client, &sbom_struct->rootElement->vars, "hasDeclaredLicense");
|
||||
if (value != NULL)
|
||||
{
|
||||
spdxtool_serialize_string(buffer, value, 4, true);
|
||||
spdxtool_core_spdx_document_add_element(client, sbom_struct->spdx_document, strdup(value));
|
||||
}
|
||||
|
||||
value = pkgconf_tuple_find(client, &sbom_struct->rootElement->vars, "hasConcludedLicense");
|
||||
if (value != NULL)
|
||||
{
|
||||
spdxtool_serialize_string(buffer, value, 4, false);
|
||||
spdxtool_core_spdx_document_add_element(client, sbom_struct->spdx_document, strdup(value));
|
||||
}
|
||||
|
||||
spdxtool_serialize_array_end(buffer, 3, false);
|
||||
spdxtool_serialize_obj_end(buffer, 2, last);
|
||||
|
||||
spdxtool_software_package_serialize(client, buffer, sbom_struct->rootElement, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_software_sbom_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_software_sbom_t *sbom_struct, bool last)
|
||||
*
|
||||
* Serialize /Software/Package struct to JSON
|
||||
* This is bit special case as it takes pkgconf pkg struct and serializes that one
|
||||
* There is not new or free for this stype
|
||||
*
|
||||
* :param pkgconf_client_t *client: The pkgconf client being accessed.
|
||||
* :param pkgconf_buffer_t *buffer: Buffer where struct is serialized
|
||||
* :param pkgconf_pkg_t *pkg: Pkgconf package
|
||||
* :param bool last: Is this last CreationInfo struct or does it need comma at the end. True comma False not
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_software_package_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, pkgconf_pkg_t *pkg, bool last)
|
||||
{
|
||||
spdxtool_core_relationship_t *relationship_struct = NULL;
|
||||
char *spdx_id_license = NULL, *tuple_license;
|
||||
pkgconf_node_t *node = NULL;
|
||||
|
||||
(void) last;
|
||||
|
||||
spdxtool_serialize_obj_start(buffer, 2);
|
||||
spdxtool_serialize_parm_and_string(buffer, "@type", "software_Package", 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "creationInfo", pkgconf_tuple_find(client, &pkg->vars, "creationInfo"), 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "spdxId", pkgconf_tuple_find(client, &pkg->vars, "spdxId"), 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "name", pkg->realname, 3, true);
|
||||
spdxtool_serialize_parm_and_char(buffer, "originatedBy", '[', 3, false);
|
||||
spdxtool_serialize_string(buffer, pkgconf_tuple_find(client, &pkg->vars, "agent"), 4, false);
|
||||
spdxtool_serialize_array_end(buffer, 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "software_copyrightText", "NOASSERTION", 3, true);
|
||||
spdxtool_serialize_parm_and_string(buffer, "software_packageVersion", pkg->version, 3, false);
|
||||
spdxtool_serialize_obj_end(buffer, 2, true);
|
||||
|
||||
/* These are must so add them right a way */
|
||||
spdx_id_license = spdxtool_util_get_spdx_id_string(client, "simplelicensing_LicenseExpression", pkg->license);
|
||||
|
||||
tuple_license = pkgconf_tuple_find(client, &pkg->vars, "hasDeclaredLicense");
|
||||
if (tuple_license != NULL)
|
||||
{
|
||||
relationship_struct = spdxtool_core_relationship_new(client, strdup(pkgconf_tuple_find(client, &pkg->vars, "creationInfo")), strdup(tuple_license), strdup(pkgconf_tuple_find(client, &pkg->vars, "spdxId")), strdup(spdx_id_license), strdup("hasDeclaredLicense"));
|
||||
spdxtool_core_relationship_serialize(client, buffer, relationship_struct, true);
|
||||
spdxtool_core_relationship_free(relationship_struct);
|
||||
}
|
||||
|
||||
tuple_license = pkgconf_tuple_find(client, &pkg->vars, "hasConcludedLicense");
|
||||
if (tuple_license != NULL)
|
||||
{
|
||||
relationship_struct = spdxtool_core_relationship_new(client, strdup(pkgconf_tuple_find(client, &pkg->vars, "creationInfo")), strdup(tuple_license), strdup(pkgconf_tuple_find(client, &pkg->vars, "spdxId")), spdx_id_license, strdup("hasConcludedLicense"));
|
||||
spdxtool_core_relationship_serialize(client, buffer, relationship_struct, true);
|
||||
spdxtool_core_relationship_free(relationship_struct);
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(pkg->required.head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_pkg_t *match = dep->match;
|
||||
char *spdx_id_relation = NULL;
|
||||
char *spdx_id_package = NULL;
|
||||
char tmp_str[1024];
|
||||
|
||||
// New relation spdxId
|
||||
snprintf(tmp_str, 1024, "%s/dependsOn/%s", pkg->realname, match->realname);
|
||||
spdx_id_relation = spdxtool_util_get_spdx_id_string(client, "Releationship", tmp_str);
|
||||
|
||||
// new package spdxId which will be hopefully come later on
|
||||
spdx_id_package = spdxtool_util_get_spdx_id_string(client, "Package", match->realname);
|
||||
|
||||
relationship_struct = spdxtool_core_relationship_new(client, strdup(pkgconf_tuple_find(client, &pkg->vars, "creationInfo")), spdx_id_relation, strdup(pkgconf_tuple_find(client, &pkg->vars, "spdxId")), spdx_id_package, strdup("dependsOn"));
|
||||
spdxtool_core_relationship_serialize(client, buffer, relationship_struct, true);
|
||||
spdxtool_core_relationship_free(relationship_struct);
|
||||
}
|
||||
}
|
||||
37
cli/spdxtool/software.h
Normal file
37
cli/spdxtool/software.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#ifndef CLI__SPDXTOOL_SOFTWARE_H
|
||||
#define CLI__SPDXTOOL_SOFTWARE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
spdxtool_software_sbom_t *
|
||||
spdxtool_software_sbom_new(pkgconf_client_t *client, char *spdx_id, char *creation_id, char *sbom_type);
|
||||
|
||||
void
|
||||
spdxtool_software_sbom_free(spdxtool_software_sbom_t *sbom_struct);
|
||||
|
||||
void
|
||||
spdxtool_software_sbom_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, spdxtool_software_sbom_t *sbom_struct, bool last);
|
||||
|
||||
void
|
||||
spdxtool_software_package_serialize(pkgconf_client_t *client, pkgconf_buffer_t *buffer, pkgconf_pkg_t *pkg, bool last);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
255
cli/spdxtool/util.c
Normal file
255
cli/spdxtool/util.c
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_util_set_key(pkgconf_client_t *client, const char *key, const char *key_value, const char *key_default)
|
||||
*
|
||||
* Set key wit default value. Default value is used if key is NULL
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param const char *key: Key to be preserved
|
||||
* :param const char *key_value: Value for key
|
||||
* :param const char *key_default: Default value if key_value is NULL
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_util_set_key(pkgconf_client_t *client, const char *key, const char *key_value, const char *key_default)
|
||||
{
|
||||
PKGCONF_TRACE(client, "set uri_root to: %s", key_value != NULL ? key_value : key_default);
|
||||
pkgconf_tuple_add_global(client, key, key_value != NULL ? key_value : key_default);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_util_set_uri_root(pkgconf_client_t *client, const char *uri_root)
|
||||
*
|
||||
* Set URI/URL root for spdxId. Type for this is 'xsd:anyURI' which means
|
||||
* it can they may be absolute or relative.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param const char *uri_root: URI root.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_util_set_uri_root(pkgconf_client_t *client, const char *uri_root)
|
||||
{
|
||||
spdxtool_util_set_key(client, "spdx_uri_root", uri_root, "https://github.com/pkgconf/pkgconf");
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const char *spdxtool_util_get_uri_root(pkgconf_client_t *client)
|
||||
*
|
||||
* Get current URI
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :return: URI or NULL
|
||||
*/
|
||||
const char *
|
||||
spdxtool_util_get_uri_root(pkgconf_client_t *client)
|
||||
{
|
||||
return pkgconf_tuple_find_global(client, "spdx_uri_root");
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_util_set_spdx_version(pkgconf_client_t *client, const char *spdx_version)
|
||||
*
|
||||
* Set current SPDX SBOM Spec version. If not set it's 3.0.1
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param char* spdx_version: SPDX specification version.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_util_set_spdx_version(pkgconf_client_t *client, const char *spdx_version)
|
||||
{
|
||||
spdxtool_util_set_key(client, "spdx_version", spdx_version, "3.0.1");
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const char *spdxtool_util_get_spdx_version(pkgconf_client_t *client)
|
||||
*
|
||||
* Get SPDX SBOM specification version in use
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :return: Spec version
|
||||
*/
|
||||
const char *
|
||||
spdxtool_util_get_spdx_version(pkgconf_client_t *client)
|
||||
{
|
||||
return pkgconf_tuple_find_global(client, "spdx_version");
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void spdxtool_util_set_spdx_license(pkgconf_client_t *client, const char *spdx_license)
|
||||
*
|
||||
* Under which license SBOM is released. License string should be in
|
||||
* SPDX style. Something like: FreeBSD-DOC, CC0-1.0 or MIT
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param const char *spdx_license: SPDX compatible license
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
spdxtool_util_set_spdx_license(pkgconf_client_t *client, const char *spdx_license)
|
||||
{
|
||||
spdxtool_util_set_key(client, "spdx_license", spdx_license, "CC0-1.0");
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const char *spdxtool_util_get_spdx_license(pkgconf_client_t *client)
|
||||
*
|
||||
* Get license which SBOM is release in
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :return: SPDX license
|
||||
*/
|
||||
const char *
|
||||
spdxtool_util_get_spdx_license(pkgconf_client_t *client)
|
||||
{
|
||||
return pkgconf_tuple_find_global(client, "spdx_license");
|
||||
}
|
||||
|
||||
static size_t last_id = 0;
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *spdxtool_util_get_spdx_id_int(pkgconf_client_t *client, char *part)
|
||||
*
|
||||
* Get spdxId with current URI.
|
||||
* URI is lookg like https://test/part/1
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param char *part: Addition subdir part before number
|
||||
* :return: URI
|
||||
*/
|
||||
char *
|
||||
spdxtool_util_get_spdx_id_int(pkgconf_client_t *client, char *part)
|
||||
{
|
||||
const char *global_xsd_any_uri = spdxtool_util_get_uri_root(client);
|
||||
pkgconf_buffer_t current_uri = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
pkgconf_buffer_join(¤t_uri, '/', global_xsd_any_uri, part, NULL);
|
||||
pkgconf_buffer_append_fmt(¤t_uri, "/" SIZE_FMT_SPECIFIER, ++last_id);
|
||||
|
||||
return pkgconf_buffer_freeze(¤t_uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *spdxtool_util_get_spdx_id_string(pkgconf_client_t *client, char *part, char *string_id)
|
||||
*
|
||||
* Get string id URI
|
||||
* looks something like: https://test/part/string_id
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client being accessed.
|
||||
* :param char* part: subdir part of URI.
|
||||
* :param char* string_id: String ID.
|
||||
* :return: URI
|
||||
*/
|
||||
char *
|
||||
spdxtool_util_get_spdx_id_string(pkgconf_client_t *client, char *part, char *string_id)
|
||||
{
|
||||
const char *global_xsd_any_uri = spdxtool_util_get_uri_root(client);
|
||||
pkgconf_buffer_t current_uri = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
pkgconf_buffer_join(¤t_uri, '/', global_xsd_any_uri, part, string_id, NULL);
|
||||
|
||||
return pkgconf_buffer_freeze(¤t_uri);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *spdxtool_util_get_iso8601_time(time_t *wanted_time)
|
||||
*
|
||||
* Get ISO8601 time string
|
||||
*
|
||||
* :param time_t *wanted_time: Time to be converted
|
||||
* :return: Time string in ISO8601 format
|
||||
*/
|
||||
char *
|
||||
spdxtool_util_get_iso8601_time(time_t *wanted_time)
|
||||
{
|
||||
char buf[PKGCONF_ITEM_SIZE];
|
||||
struct tm *tm_info = gmtime(wanted_time);
|
||||
|
||||
if(!wanted_time)
|
||||
return NULL;
|
||||
|
||||
/* ISO8601 time with Z at the end */
|
||||
strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%SZ", tm_info);
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *spdxtool_util_get_current_iso8601_time()
|
||||
*
|
||||
* Get ISO8601 current timestamp
|
||||
*
|
||||
* :return: Time string in ISO8601 format
|
||||
*/
|
||||
char *
|
||||
spdxtool_util_get_current_iso8601_time()
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
return spdxtool_util_get_iso8601_time(&now);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *spdxtool_util_string_correction(char *str)
|
||||
*
|
||||
* Lowercase string and change spaces to '_'
|
||||
*
|
||||
* :param char *str: String to be converted
|
||||
* :return: Converted string
|
||||
*/
|
||||
char *
|
||||
spdxtool_util_string_correction(char *str)
|
||||
{
|
||||
char *ptr = str;
|
||||
/* Lowecase string and make spaces '_' */
|
||||
for ( ; *ptr; ++ptr)
|
||||
{
|
||||
*ptr = tolower(*ptr);
|
||||
if(isspace((unsigned char) *ptr))
|
||||
{
|
||||
*ptr = '_';
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
123
cli/spdxtool/util.h
Normal file
123
cli/spdxtool/util.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 The FreeBSD Foundation
|
||||
*
|
||||
* Portions of this software were developed by
|
||||
* Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from
|
||||
* the FreeBSD Foundation
|
||||
*/
|
||||
|
||||
#ifndef CLI__SPDXTOOL__UTIL_H
|
||||
#define CLI__SPDXTOOL__UTIL_H
|
||||
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct spdxtool_core_agent_
|
||||
{
|
||||
int refcount;
|
||||
char *spdx_id;
|
||||
char *type;
|
||||
char *creation_info;
|
||||
char *name;
|
||||
} spdxtool_core_agent_t;
|
||||
|
||||
typedef struct spdxtool_core_creation_info_
|
||||
{
|
||||
int refcount;
|
||||
char *id;
|
||||
char *type;
|
||||
char *created;
|
||||
char *created_by;
|
||||
char *created_using;
|
||||
const char *spec_version;
|
||||
} spdxtool_core_creation_info_t;
|
||||
|
||||
typedef struct spdxtool_core_spdx_document
|
||||
{
|
||||
int refcount;
|
||||
char *type;
|
||||
char *spdx_id;
|
||||
char *creation_info;
|
||||
char *agent;
|
||||
pkgconf_list_t licenses;
|
||||
pkgconf_list_t element;
|
||||
pkgconf_list_t rootElement;
|
||||
} spdxtool_core_spdx_document_t;
|
||||
|
||||
typedef struct spdxtool_software_sbom_
|
||||
{
|
||||
int refcount;
|
||||
char *spdx_id;
|
||||
char *type;
|
||||
char *creation_info;
|
||||
char *sbom_type;
|
||||
spdxtool_core_spdx_document_t *spdx_document;
|
||||
pkgconf_pkg_t *rootElement;
|
||||
} spdxtool_software_sbom_t;
|
||||
|
||||
typedef struct spdxtool_simplelicensing_license_expression_
|
||||
{
|
||||
int refcount;
|
||||
char *type;
|
||||
char *spdx_id;
|
||||
char *license_expression;
|
||||
} spdxtool_simplelicensing_license_expression_t;
|
||||
|
||||
typedef struct spdxtool_core_relationship_
|
||||
{
|
||||
int refcount;
|
||||
char *type;
|
||||
char *spdx_id;
|
||||
char *creation_info;
|
||||
char *from;
|
||||
char *to;
|
||||
char *relationship_type;
|
||||
} spdxtool_core_relationship_t;
|
||||
|
||||
void
|
||||
spdxtool_util_set_key(pkgconf_client_t *client, const char *key, const char *key_value, const char *key_default);
|
||||
|
||||
void
|
||||
spdxtool_util_set_uri_root(pkgconf_client_t *client, const char *uri_root);
|
||||
|
||||
const char *
|
||||
spdxtool_util_get_uri_root(pkgconf_client_t *client);
|
||||
|
||||
void
|
||||
spdxtool_util_set_spdx_version(pkgconf_client_t *client, const char *spdx_version);
|
||||
|
||||
const char *
|
||||
spdxtool_util_get_spdx_version(pkgconf_client_t *client);
|
||||
|
||||
void
|
||||
spdxtool_util_set_spdx_license(pkgconf_client_t *client, const char *spdx_license);
|
||||
|
||||
const char *
|
||||
spdxtool_util_get_spdx_license(pkgconf_client_t *client);
|
||||
|
||||
char *
|
||||
spdxtool_util_get_spdx_id_int(pkgconf_client_t *client, char *part);
|
||||
|
||||
char *
|
||||
spdxtool_util_get_spdx_id_string(pkgconf_client_t *client, char *part, char *string_id);
|
||||
|
||||
char *
|
||||
spdxtool_util_get_iso8601_time(time_t *wanted_time);
|
||||
|
||||
char *
|
||||
spdxtool_util_get_current_iso8601_time();
|
||||
|
||||
char *
|
||||
spdxtool_util_string_correction(char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
29
configure.ac
29
configure.ac
@ -12,7 +12,7 @@ dnl implied. In no event shall the authors be liable for any damages arising
|
||||
dnl from the use of this software.
|
||||
|
||||
AC_PREREQ([2.71])
|
||||
AC_INIT([pkgconf],[2.3.0],[https://github.com/pkgconf/pkgconf/issues/new])
|
||||
AC_INIT([pkgconf],[2.5.1],[https://github.com/pkgconf/pkgconf/issues/new])
|
||||
AC_CONFIG_SRCDIR([cli/main.c])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"])
|
||||
@ -23,7 +23,9 @@ AX_CHECK_COMPILE_FLAG([-std=gnu99], [CFLAGS="$CFLAGS -std=gnu99"], [
|
||||
])
|
||||
AC_CONFIG_HEADERS([libpkgconf/config.h])
|
||||
AC_CHECK_DECLS([strlcpy, strlcat, strndup], [], [], [[#include <string.h>]])
|
||||
AC_CHECK_DECLS([reallocarray])
|
||||
AC_CHECK_DECLS([pledge, unveil], [], [], [[#include <unistd.h>]])
|
||||
AC_CHECK_DECLS([readlinkat], [], [], [[#include <unistd.h>]])
|
||||
AC_CHECK_DECLS([reallocarray], [], [], [[#include <stdlib.h>]])
|
||||
AC_CHECK_HEADERS([sys/stat.h])
|
||||
AM_INIT_AUTOMAKE([foreign dist-xz subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
@ -46,13 +48,21 @@ AC_SUBST([PKG_DEFAULT_PATH])
|
||||
|
||||
AC_ARG_WITH([system-libdir],[AS_HELP_STRING([--with-system-libdir],[specify the
|
||||
system library directory (default LIBDIR)])],
|
||||
SYSTEM_LIBDIR="$withval", SYSTEM_LIBDIR="${libdir}")
|
||||
[SYSTEM_LIBDIR="$withval"], [
|
||||
AC_MSG_WARN([--with-system-libdir is not set, assuming ${libdir}])
|
||||
AC_MSG_WARN([It is important that this value be properly set for correct behavior!])
|
||||
SYSTEM_LIBDIR="${libdir}"
|
||||
])
|
||||
|
||||
AC_SUBST([SYSTEM_LIBDIR])
|
||||
|
||||
AC_ARG_WITH([system-includedir],[AS_HELP_STRING([--with-system-includedir],[specify the
|
||||
system include directory (default INCLUDEDIR)])],
|
||||
SYSTEM_INCLUDEDIR="$withval", SYSTEM_INCLUDEDIR="${includedir}")
|
||||
[SYSTEM_INCLUDEDIR="$withval"], [
|
||||
AC_MSG_WARN([--with-system-includedir is not set, assuming ${includedir}])
|
||||
AC_MSG_WARN([It is important that this value be properly set for correct behavior!])
|
||||
SYSTEM_INCLUDEDIR="${includedir}"
|
||||
])
|
||||
|
||||
AC_SUBST([SYSTEM_INCLUDEDIR])
|
||||
|
||||
@ -63,3 +73,14 @@ AC_PROG_LN_S
|
||||
|
||||
AC_CONFIG_FILES([Makefile Kyuafile libpkgconf.pc tests/Kyuafile tests/test_env.sh])
|
||||
AC_OUTPUT
|
||||
|
||||
cat << EOF
|
||||
Build configuration:
|
||||
|
||||
Default personality search paths: ${PERSONALITY_PATH}
|
||||
Default package search paths: ${PKG_DEFAULT_PATH}
|
||||
Default include search paths: ${SYSTEM_INCLUDEDIR}
|
||||
Default library search paths: ${SYSTEM_LIBDIR}
|
||||
|
||||
Incorrect paths may result in unexpected behavior from pkgconf.
|
||||
EOF
|
||||
|
||||
@ -7,6 +7,8 @@ Name: libpkgconf
|
||||
Description: a library for accessing and manipulating development framework configuration
|
||||
URL: https://gitea.treehouse.systems/ariadne/pkgconf
|
||||
License: ISC
|
||||
License.file: https://raw.githubusercontent.com/pkgconf/pkgconf/refs/heads/master/COPYING
|
||||
Source: https://github.com/pkgconf/pkgconf
|
||||
Version: @PACKAGE_VERSION@
|
||||
CFlags: -I${includedir}/pkgconf
|
||||
Libs: -L${libdir} -lpkgconf
|
||||
|
||||
@ -59,7 +59,10 @@ pkgconf_argv_free(char **argv)
|
||||
int
|
||||
pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||
{
|
||||
char *buf = malloc(strlen(src) + 1);
|
||||
char *buf = calloc(1, strlen(src) + 1);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
const char *src_iter;
|
||||
char *dst_iter;
|
||||
int argc_count = 0;
|
||||
@ -70,9 +73,13 @@ pkgconf_argv_split(const char *src, int *argc, char ***argv)
|
||||
src_iter = src;
|
||||
dst_iter = buf;
|
||||
|
||||
memset(buf, 0, strlen(src) + 1);
|
||||
|
||||
*argv = calloc(argv_size, sizeof (void *));
|
||||
if (*argv == NULL)
|
||||
{
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*argv)[argc_count] = dst_iter;
|
||||
|
||||
while (*src_iter)
|
||||
|
||||
@ -17,11 +17,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/bsdstubs.h>
|
||||
#include <libpkgconf/config.h>
|
||||
|
||||
@ -121,6 +117,28 @@ strndup(const char *src, size_t len)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_PLEDGE
|
||||
static inline int
|
||||
pledge(const char *promises, const char *execpromises)
|
||||
{
|
||||
(void) promises;
|
||||
(void) execpromises;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_UNVEIL
|
||||
static inline int
|
||||
unveil(const char *path, const char *permissions)
|
||||
{
|
||||
(void) path;
|
||||
(void) permissions;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t
|
||||
pkgconf_strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
@ -158,3 +176,15 @@ pkgconf_reallocarray(void *ptr, size_t m, size_t n)
|
||||
{
|
||||
return reallocarray(ptr, m, n);
|
||||
}
|
||||
|
||||
int
|
||||
pkgconf_pledge(const char *promises, const char *execpromises)
|
||||
{
|
||||
return pledge(promises, execpromises);
|
||||
}
|
||||
|
||||
int
|
||||
pkgconf_unveil(const char *path, const char *permissions)
|
||||
{
|
||||
return unveil(path, permissions);
|
||||
}
|
||||
|
||||
@ -26,6 +26,8 @@ PKGCONF_API extern size_t pkgconf_strlcpy(char *dst, const char *src, size_t siz
|
||||
PKGCONF_API extern size_t pkgconf_strlcat(char *dst, const char *src, size_t siz);
|
||||
PKGCONF_API extern char *pkgconf_strndup(const char *src, size_t len);
|
||||
PKGCONF_API extern void *pkgconf_reallocarray(void *ptr, size_t m, size_t n);
|
||||
PKGCONF_API extern int pkgconf_pledge(const char *promises, const char *execpromises);
|
||||
PKGCONF_API extern int pkgconf_unveil(const char *path, const char *permissions);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
246
libpkgconf/buffer.c
Normal file
246
libpkgconf/buffer.c
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* buffer.c
|
||||
* dynamically-managed buffers
|
||||
*
|
||||
* Copyright (c) 2024 pkgconf authors (see AUTHORS).
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* This software is provided 'as is' and without any warranty, express or
|
||||
* implied. In no event shall the authors be liable for any damages arising
|
||||
* from the use of this software.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* libpkgconf `buffer` module
|
||||
* ==========================
|
||||
*
|
||||
* The libpkgconf `buffer` module contains the functions related to managing
|
||||
* dynamically-allocated buffers.
|
||||
*/
|
||||
|
||||
static inline size_t
|
||||
target_allocation_size(size_t target_size)
|
||||
{
|
||||
return 4096 + (4096 * (target_size / 4096));
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
buffer_debug(pkgconf_buffer_t *buffer)
|
||||
{
|
||||
for (char *c = buffer->base; c <= buffer->end; c++) {
|
||||
fprintf(stderr, "%02x ", (unsigned char) *c);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
pkgconf_buffer_append(pkgconf_buffer_t *buffer, const char *text)
|
||||
{
|
||||
size_t needed = strlen(text) + 1;
|
||||
size_t newsize = pkgconf_buffer_len(buffer) + needed;
|
||||
|
||||
char *newbase = realloc(buffer->base, target_allocation_size(newsize));
|
||||
|
||||
/* XXX: silently failing here is antisocial */
|
||||
if (newbase == NULL)
|
||||
return;
|
||||
|
||||
char *newend = newbase + pkgconf_buffer_len(buffer);
|
||||
pkgconf_strlcpy(newend, text, needed);
|
||||
|
||||
buffer->base = newbase;
|
||||
buffer->end = newend + (needed - 1);
|
||||
|
||||
*buffer->end = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_append_vfmt(pkgconf_buffer_t *buffer, const char *fmt, va_list src_va)
|
||||
{
|
||||
va_list va;
|
||||
char *buf;
|
||||
size_t needed;
|
||||
|
||||
va_copy(va, src_va);
|
||||
needed = vsnprintf(NULL, 0, fmt, va) + 1;
|
||||
va_end(va);
|
||||
|
||||
buf = malloc(needed);
|
||||
|
||||
va_copy(va, src_va);
|
||||
vsnprintf(buf, needed, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
pkgconf_buffer_append(buffer, buf);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_append_fmt(pkgconf_buffer_t *buffer, const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
pkgconf_buffer_append_vfmt(buffer, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_push_byte(pkgconf_buffer_t *buffer, char byte)
|
||||
{
|
||||
size_t newsize = pkgconf_buffer_len(buffer) + 1;
|
||||
char *newbase = realloc(buffer->base, target_allocation_size(newsize));
|
||||
|
||||
/* XXX: silently failing here remains antisocial */
|
||||
if (newbase == NULL)
|
||||
return;
|
||||
|
||||
char *newend = newbase + newsize;
|
||||
*(newend - 1) = byte;
|
||||
*newend = '\0';
|
||||
|
||||
buffer->base = newbase;
|
||||
buffer->end = newend;
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_trim_byte(pkgconf_buffer_t *buffer)
|
||||
{
|
||||
size_t newsize = pkgconf_buffer_len(buffer) - 1;
|
||||
char *newbase = realloc(buffer->base, target_allocation_size(newsize));
|
||||
|
||||
buffer->base = newbase;
|
||||
buffer->end = newbase + newsize;
|
||||
*(buffer->end) = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_finalize(pkgconf_buffer_t *buffer)
|
||||
{
|
||||
free(buffer->base);
|
||||
buffer->base = buffer->end = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_fputs(pkgconf_buffer_t *buffer, FILE *out)
|
||||
{
|
||||
if (pkgconf_buffer_len(buffer) != 0)
|
||||
fputs(pkgconf_buffer_str(buffer), out);
|
||||
|
||||
fputc('\n', out);
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_vjoin(pkgconf_buffer_t *buffer, char delim, va_list src_va)
|
||||
{
|
||||
va_list va;
|
||||
const char *arg;
|
||||
|
||||
va_copy(va, src_va);
|
||||
|
||||
while ((arg = va_arg(va, const char *)) != NULL)
|
||||
{
|
||||
if (pkgconf_buffer_str(buffer) != NULL)
|
||||
pkgconf_buffer_push_byte(buffer, delim);
|
||||
|
||||
pkgconf_buffer_append(buffer, arg);
|
||||
}
|
||||
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
// NOTE: due to C's rules regarding promotion in variable args and permissible variables, delim must
|
||||
// be an int here.
|
||||
void
|
||||
pkgconf_buffer_join(pkgconf_buffer_t *buffer, int delim, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, delim);
|
||||
pkgconf_buffer_vjoin(buffer, (char)delim, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
bool
|
||||
pkgconf_buffer_contains(const pkgconf_buffer_t *haystack, const pkgconf_buffer_t *needle)
|
||||
{
|
||||
const char *haystack_str = pkgconf_buffer_str_or_empty(haystack);
|
||||
const char *needle_str = pkgconf_buffer_str_or_empty(needle);
|
||||
|
||||
return strstr(haystack_str, needle_str) != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
pkgconf_buffer_contains_byte(const pkgconf_buffer_t *haystack, char needle)
|
||||
{
|
||||
const char *haystack_str = pkgconf_buffer_str_or_empty(haystack);
|
||||
return strchr(haystack_str, needle) != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
pkgconf_buffer_match(const pkgconf_buffer_t *haystack, const pkgconf_buffer_t *needle)
|
||||
{
|
||||
const char *haystack_str = pkgconf_buffer_str_or_empty(haystack);
|
||||
const char *needle_str = pkgconf_buffer_str_or_empty(needle);
|
||||
|
||||
if (pkgconf_buffer_len(haystack) != pkgconf_buffer_len(needle))
|
||||
return false;
|
||||
|
||||
return memcmp(haystack_str, needle_str, pkgconf_buffer_len(haystack)) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_subst(pkgconf_buffer_t *dest, const pkgconf_buffer_t *src, const char *pattern, const char *value)
|
||||
{
|
||||
const char *iter = src->base;
|
||||
size_t pattern_len = strlen(pattern);
|
||||
|
||||
if (!pkgconf_buffer_len(src))
|
||||
return;
|
||||
|
||||
if (!pattern_len)
|
||||
{
|
||||
pkgconf_buffer_append(dest, pkgconf_buffer_str(src));
|
||||
return;
|
||||
}
|
||||
|
||||
while (iter < src->end)
|
||||
{
|
||||
if ((size_t)(src->end - iter) >= pattern_len && !memcmp(iter, pattern, pattern_len))
|
||||
{
|
||||
pkgconf_buffer_append(dest, value);
|
||||
iter += pattern_len;
|
||||
}
|
||||
else
|
||||
pkgconf_buffer_push_byte(dest, *iter++);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_buffer_escape(pkgconf_buffer_t *dest, const pkgconf_buffer_t *src, const pkgconf_span_t *spans, size_t nspans)
|
||||
{
|
||||
const char *p = pkgconf_buffer_str(src);
|
||||
|
||||
if (!pkgconf_buffer_len(src))
|
||||
return;
|
||||
|
||||
for (; *p; p++)
|
||||
{
|
||||
if (pkgconf_span_contains((unsigned char) *p, spans, nspans))
|
||||
pkgconf_buffer_push_byte(dest, '\\');
|
||||
|
||||
pkgconf_buffer_push_byte(dest, *p);
|
||||
}
|
||||
}
|
||||
@ -60,17 +60,22 @@ trace_path_list(const pkgconf_client_t *client, const char *desc, pkgconf_list_t
|
||||
void
|
||||
pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality)
|
||||
{
|
||||
pkgconf_path_build_from_environ("PKG_CONFIG_PATH", NULL, &client->dir_list, true);
|
||||
pkgconf_path_build_from_environ(client, "PKG_CONFIG_PATH", NULL, &client->dir_list, true);
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_ENV_ONLY))
|
||||
{
|
||||
pkgconf_list_t dir_list = PKGCONF_LIST_INITIALIZER;
|
||||
const pkgconf_list_t *prepend_list = &personality->dir_list;
|
||||
|
||||
if (getenv("PKG_CONFIG_LIBDIR") != NULL)
|
||||
#ifdef _WIN32
|
||||
(void) pkgconf_path_build_from_registry(HKEY_CURRENT_USER, &client->dir_list, true);
|
||||
(void) pkgconf_path_build_from_registry(HKEY_LOCAL_MACHINE, &client->dir_list, true);
|
||||
#endif
|
||||
|
||||
if (pkgconf_client_getenv(client, "PKG_CONFIG_LIBDIR") != NULL)
|
||||
{
|
||||
/* PKG_CONFIG_LIBDIR= should empty the search path entirely. */
|
||||
(void) pkgconf_path_build_from_environ("PKG_CONFIG_LIBDIR", NULL, &dir_list, true);
|
||||
(void) pkgconf_path_build_from_environ(client, "PKG_CONFIG_LIBDIR", NULL, &dir_list, true);
|
||||
prepend_list = &dir_list;
|
||||
}
|
||||
|
||||
@ -82,7 +87,7 @@ pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_pers
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
* .. c:function:: void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler)
|
||||
*
|
||||
* Initialise a pkgconf client object.
|
||||
*
|
||||
@ -90,11 +95,16 @@ pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_pers
|
||||
* :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
|
||||
* :param void* error_handler_data: user data passed to optional error handler
|
||||
* :param pkgconf_cross_personality_t* personality: the cross-compile personality to use for defaults
|
||||
* :param void* client_data: user data associated with the client
|
||||
* :param pkgconf_environ_lookup_handler_func_t environ_lookup_handler: the lookup handler to use for environment variables
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler)
|
||||
{
|
||||
client->personality = personality;
|
||||
client->client_data = client_data;
|
||||
client->environ_lookup_handler = environ_lookup_handler;
|
||||
client->error_handler_data = error_handler_data;
|
||||
client->error_handler = error_handler;
|
||||
client->auditf = NULL;
|
||||
@ -106,6 +116,9 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
|
||||
pkgconf_client_set_trace_handler(client, NULL, NULL);
|
||||
#endif
|
||||
|
||||
if (client->unveil_handler == NULL)
|
||||
pkgconf_client_set_unveil_handler(client, NULL);
|
||||
|
||||
pkgconf_client_set_error_handler(client, error_handler, error_handler_data);
|
||||
pkgconf_client_set_warn_handler(client, NULL, NULL);
|
||||
|
||||
@ -113,36 +126,38 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
|
||||
pkgconf_client_set_buildroot_dir(client, NULL);
|
||||
pkgconf_client_set_prefix_varname(client, NULL);
|
||||
|
||||
if(getenv("PKG_CONFIG_SYSTEM_LIBRARY_PATH") == NULL)
|
||||
if(pkgconf_client_getenv(client, "PKG_CONFIG_SYSTEM_LIBRARY_PATH") == NULL)
|
||||
pkgconf_path_copy_list(&client->filter_libdirs, &personality->filter_libdirs);
|
||||
else
|
||||
pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_LIBRARY_PATH", NULL, &client->filter_libdirs, false);
|
||||
pkgconf_path_build_from_environ(client, "PKG_CONFIG_SYSTEM_LIBRARY_PATH", NULL, &client->filter_libdirs, false);
|
||||
|
||||
if(getenv("PKG_CONFIG_SYSTEM_INCLUDE_PATH") == NULL)
|
||||
if(pkgconf_client_getenv(client, "PKG_CONFIG_SYSTEM_INCLUDE_PATH") == NULL)
|
||||
pkgconf_path_copy_list(&client->filter_includedirs, &personality->filter_includedirs);
|
||||
else
|
||||
pkgconf_path_build_from_environ("PKG_CONFIG_SYSTEM_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ(client, "PKG_CONFIG_SYSTEM_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
|
||||
/* GCC uses these environment variables to define system include paths, so we should check them. */
|
||||
#ifdef __HAIKU__
|
||||
pkgconf_path_build_from_environ("BELIBRARIES", NULL, &client->filter_libdirs, false);
|
||||
pkgconf_path_build_from_environ(client, "BELIBRARIES", NULL, &client->filter_libdirs, false);
|
||||
#else
|
||||
pkgconf_path_build_from_environ("LIBRARY_PATH", NULL, &client->filter_libdirs, false);
|
||||
pkgconf_path_build_from_environ(client, "LIBRARY_PATH", NULL, &client->filter_libdirs, false);
|
||||
#endif
|
||||
pkgconf_path_build_from_environ("CPATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ("C_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ("CPLUS_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ("OBJC_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ(client, "CPATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ(client, "C_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ(client, "CPLUS_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ(client, "OBJC_INCLUDE_PATH", NULL, &client->filter_includedirs, false);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* also use the path lists that MSVC uses on windows */
|
||||
pkgconf_path_build_from_environ("INCLUDE", NULL, &client->filter_includedirs, false);
|
||||
pkgconf_path_build_from_environ(client, "INCLUDE", NULL, &client->filter_includedirs, false);
|
||||
#endif
|
||||
|
||||
PKGCONF_TRACE(client, "initialized client @%p", client);
|
||||
|
||||
trace_path_list(client, "filtered library paths", &client->filter_libdirs);
|
||||
trace_path_list(client, "filtered include paths", &client->filter_includedirs);
|
||||
|
||||
client->output = pkgconf_output_default();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -155,17 +170,34 @@ pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error
|
||||
* :param pkgconf_error_handler_func_t error_handler: An optional error handler to use for logging errors.
|
||||
* :param void* error_handler_data: user data passed to optional error handler
|
||||
* :param pkgconf_cross_personality_t* personality: cross-compile personality to use
|
||||
* :param void* client_data: user data associated with the client
|
||||
* :param pkgconf_environ_lookup_handler_func_t environ_lookup_handler: the lookup handler to use for environment variables
|
||||
* :return: A pkgconf client object.
|
||||
* :rtype: pkgconf_client_t*
|
||||
*/
|
||||
pkgconf_client_t *
|
||||
pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality)
|
||||
pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler)
|
||||
{
|
||||
pkgconf_client_t *out = calloc(1, sizeof(pkgconf_client_t));
|
||||
pkgconf_client_init(out, error_handler, error_handler_data, personality);
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
pkgconf_client_init(out, error_handler, error_handler_data, personality, client_data, environ_lookup_handler);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void
|
||||
unref_preload_list(pkgconf_client_t *client)
|
||||
{
|
||||
pkgconf_node_t *n, *tn;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY_SAFE(client->preloaded_pkgs.head, tn, n)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = n->data;
|
||||
pkgconf_pkg_unref(client, pkg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
@ -181,6 +213,8 @@ pkgconf_client_deinit(pkgconf_client_t *client)
|
||||
{
|
||||
PKGCONF_TRACE(client, "deinit @%p", client);
|
||||
|
||||
unref_preload_list(client);
|
||||
|
||||
if (client->prefix_varname != NULL)
|
||||
free(client->prefix_varname);
|
||||
|
||||
@ -196,6 +230,8 @@ pkgconf_client_deinit(pkgconf_client_t *client)
|
||||
pkgconf_tuple_free_global(client);
|
||||
pkgconf_path_free(&client->dir_list);
|
||||
pkgconf_cache_free(client);
|
||||
|
||||
memset(client, '\0', sizeof(*client));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -256,7 +292,7 @@ pkgconf_client_set_sysroot_dir(pkgconf_client_t *client, const char *sysroot_dir
|
||||
|
||||
PKGCONF_TRACE(client, "set sysroot_dir to: %s", client->sysroot_dir != NULL ? client->sysroot_dir : "<default>");
|
||||
|
||||
pkgconf_tuple_add_global(client, "pc_sysrootdir", client->sysroot_dir != NULL ? client->sysroot_dir : "/");
|
||||
pkgconf_tuple_add_global(client, "pc_sysrootdir", client->sysroot_dir != NULL ? client->sysroot_dir : "");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -318,14 +354,32 @@ pkgconf_client_set_buildroot_dir(pkgconf_client_t *client, const char *buildroot
|
||||
bool
|
||||
pkgconf_error(const pkgconf_client_t *client, const char *format, ...)
|
||||
{
|
||||
char errbuf[PKGCONF_BUFSIZE];
|
||||
char *errbuf;
|
||||
ssize_t msgsize = 0;
|
||||
bool ret;
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, sizeof errbuf, format, va);
|
||||
msgsize = vsnprintf(NULL, 0, format, va);
|
||||
va_end(va);
|
||||
|
||||
return client->error_handler(errbuf, client, client->error_handler_data);
|
||||
if (msgsize < 0)
|
||||
return false;
|
||||
|
||||
msgsize++;
|
||||
|
||||
errbuf = calloc(1, msgsize);
|
||||
if (errbuf == NULL)
|
||||
return false;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, msgsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
ret = client->error_handler(errbuf, client, client->error_handler_data);
|
||||
free(errbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -343,14 +397,32 @@ pkgconf_error(const pkgconf_client_t *client, const char *format, ...)
|
||||
bool
|
||||
pkgconf_warn(const pkgconf_client_t *client, const char *format, ...)
|
||||
{
|
||||
char errbuf[PKGCONF_BUFSIZE];
|
||||
char *errbuf;
|
||||
ssize_t msgsize = 0;
|
||||
bool ret;
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, sizeof errbuf, format, va);
|
||||
msgsize = vsnprintf(NULL, 0, format, va);
|
||||
va_end(va);
|
||||
|
||||
return client->warn_handler(errbuf, client, client->warn_handler_data);
|
||||
if (msgsize < 0)
|
||||
return false;
|
||||
|
||||
msgsize++;
|
||||
|
||||
errbuf = calloc(1, msgsize);
|
||||
if (errbuf == NULL)
|
||||
return false;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, msgsize, format, va);
|
||||
va_end(va);
|
||||
|
||||
ret = client->warn_handler(errbuf, client, client->warn_handler_data);
|
||||
free(errbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -371,22 +443,56 @@ pkgconf_warn(const pkgconf_client_t *client, const char *format, ...)
|
||||
bool
|
||||
pkgconf_trace(const pkgconf_client_t *client, const char *filename, size_t lineno, const char *funcname, const char *format, ...)
|
||||
{
|
||||
char errbuf[PKGCONF_BUFSIZE];
|
||||
size_t len;
|
||||
char prefix[PKGCONF_ITEM_SIZE];
|
||||
char *errbuf = NULL;
|
||||
ssize_t errlen;
|
||||
char *finalbuf = NULL;
|
||||
ssize_t finallen;
|
||||
bool ret;
|
||||
va_list va;
|
||||
|
||||
if (client == NULL || client->trace_handler == NULL)
|
||||
return false;
|
||||
|
||||
len = snprintf(errbuf, sizeof errbuf, "%s:" SIZE_FMT_SPECIFIER " [%s]: ", filename, lineno, funcname);
|
||||
snprintf(prefix, sizeof prefix, "%s:" SIZE_FMT_SPECIFIER " [%s]:", filename, lineno, funcname);
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf + len, sizeof(errbuf) - len, format, va);
|
||||
errlen = vsnprintf(NULL, 0, format, va);
|
||||
va_end(va);
|
||||
|
||||
pkgconf_strlcat(errbuf, "\n", sizeof errbuf);
|
||||
if (errlen < 0)
|
||||
return false;
|
||||
|
||||
return client->trace_handler(errbuf, client, client->trace_handler_data);
|
||||
errlen++;
|
||||
errbuf = calloc(1, errlen);
|
||||
if (errbuf == NULL)
|
||||
return false;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(errbuf, errlen, format, va);
|
||||
va_end(va);
|
||||
|
||||
finallen = snprintf(NULL, 0, "%s %s\n", prefix, errbuf);
|
||||
if (finallen < 0)
|
||||
{
|
||||
free(errbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
finallen++;
|
||||
finalbuf = calloc(1, finallen);
|
||||
if (finalbuf == NULL)
|
||||
{
|
||||
free(errbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(finalbuf, finallen, "%s %s\n", prefix, errbuf);
|
||||
ret = client->trace_handler(finalbuf, client, client->trace_handler_data);
|
||||
free(errbuf);
|
||||
free(finalbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -412,6 +518,14 @@ pkgconf_default_error_handler(const char *msg, const pkgconf_client_t *client, v
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
default_unveil_handler(const pkgconf_client_t *client, const char *path, const char *permissions)
|
||||
{
|
||||
(void) client;
|
||||
(void) path;
|
||||
(void) permissions;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
@ -571,6 +685,45 @@ pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_get_unveil_handler(const pkgconf_client_t *client)
|
||||
*
|
||||
* Returns the unveil handler if one is set, else ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to get the unveil handler from.
|
||||
* :return: a function pointer to the error handler or ``NULL``
|
||||
*/
|
||||
pkgconf_unveil_handler_func_t
|
||||
pkgconf_client_get_unveil_handler(const pkgconf_client_t *client)
|
||||
{
|
||||
return client->unveil_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler)
|
||||
*
|
||||
* Sets an unveil handler on a client object or uninstalls one if set to ``NULL``.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the error handler on.
|
||||
* :param pkgconf_unveil_handler_func_t unveil_handler: The unveil handler to set.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler)
|
||||
{
|
||||
client->unveil_handler = unveil_handler;
|
||||
|
||||
if (client->unveil_handler == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "installing default unveil handler");
|
||||
client->unveil_handler = default_unveil_handler;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PKGCONF_LITE
|
||||
/*
|
||||
* !doc
|
||||
@ -613,3 +766,131 @@ pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_client_preload_one(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
*
|
||||
* Adds a package to the preloaded packages set.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object for preloading.
|
||||
* :param pkgconf_pkg_t* pkg: The package to preload.
|
||||
* :return: true on success, false on error
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_client_preload_one(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
{
|
||||
PKGCONF_TRACE(client, "preloading pkg %s@%p", pkg->id, pkg);
|
||||
|
||||
pkg->flags |= PKGCONF_PKG_PROPF_PRELOADED;
|
||||
|
||||
pkgconf_pkg_ref(client, pkg);
|
||||
pkgconf_node_insert_tail(&pkg->preload_node, pkg, &client->preloaded_pkgs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_client_preload_path(pkgconf_client_t *client, const char *path)
|
||||
*
|
||||
* Loads a pkg-config file into the preloaded packages set.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object for preloading.
|
||||
* :param char* path: The path to the pkg-config file to preload.
|
||||
* :return: true on success, false on error
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_client_preload_path(pkgconf_client_t *client, const char *path)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = pkgconf_pkg_new_from_path(client, path, PKGCONF_PKG_PROPF_PRELOADED);
|
||||
if (pkg == NULL)
|
||||
return false;
|
||||
|
||||
return pkgconf_client_preload_one(client, pkg);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: bool pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env)
|
||||
*
|
||||
* Loads zero or more pkg-config files specified in the given environmental
|
||||
* variable.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object for preloading.
|
||||
* :param char* environ: The environment variable to use for preloading.
|
||||
* :return: true on success, false on error
|
||||
* :rtype: bool
|
||||
*/
|
||||
bool
|
||||
pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env)
|
||||
{
|
||||
const char *data;
|
||||
pkgconf_list_t pathlist = PKGCONF_LIST_INITIALIZER;
|
||||
pkgconf_node_t *n;
|
||||
bool ret = true;
|
||||
|
||||
data = getenv(env);
|
||||
if (data == NULL)
|
||||
return true;
|
||||
|
||||
pkgconf_path_split(data, &pathlist, true);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(pathlist.head, n)
|
||||
{
|
||||
pkgconf_path_t *pn = n->data;
|
||||
|
||||
ret = pkgconf_client_preload_path(client, pn->path);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
|
||||
pkgconf_path_free(&pathlist);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_client_set_output(pkgconf_client_t *client, pkgconf_output_t *output)
|
||||
*
|
||||
* Sets the client's output object. This is mainly a convenience function for clients
|
||||
* to use.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client object to set the output object for.
|
||||
* :param pkgconf_output_t* output: The output object to use.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_client_set_output(pkgconf_client_t *client, pkgconf_output_t *output)
|
||||
{
|
||||
client->output = output;
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: const char *pkgconf_client_getenv(const pkgconf_client_t *client, const char *key)
|
||||
*
|
||||
* Looks up an environmental variable which may be mocked, otherwise fetches
|
||||
* from the main environment.
|
||||
*
|
||||
* :param pkgconf_client_t* client: yhe client object to use for looking up environmental variables.
|
||||
* :param char* key: the environmental variable to look up.
|
||||
* :return: the environmental variable contents else NULL
|
||||
* :rtype: const char*
|
||||
*/
|
||||
const char *
|
||||
pkgconf_client_getenv(const pkgconf_client_t *client, const char *key)
|
||||
{
|
||||
if (client != NULL && client->environ_lookup_handler != NULL)
|
||||
return client->environ_lookup_handler(client, key);
|
||||
|
||||
return getenv(key);
|
||||
}
|
||||
|
||||
@ -24,6 +24,12 @@
|
||||
/* Define to 1 if you have the `reallocarray' function. */
|
||||
#mesondefine HAVE_DECL_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the `pledge' function. */
|
||||
#mesondefine HAVE_DECL_PLEDGE
|
||||
|
||||
/* Define to 1 if you have the `unveil' function. */
|
||||
#mesondefine HAVE_DECL_UNVEIL
|
||||
|
||||
/* Name of package */
|
||||
#mesondefine PACKAGE
|
||||
|
||||
|
||||
@ -131,6 +131,9 @@ pkgconf_dependency_addraw(pkgconf_client_t *client, pkgconf_list_t *list, const
|
||||
pkgconf_dependency_t *dep;
|
||||
|
||||
dep = calloc(1, sizeof(pkgconf_dependency_t));
|
||||
if (dep == NULL)
|
||||
return NULL;
|
||||
|
||||
dep->package = pkgconf_strndup(package, package_sz);
|
||||
|
||||
if (version_sz != 0)
|
||||
@ -208,6 +211,9 @@ pkgconf_dependency_free_one(pkgconf_dependency_t *dep)
|
||||
if (dep->version != NULL)
|
||||
free(dep->version);
|
||||
|
||||
if (dep->why != NULL)
|
||||
free(dep->why);
|
||||
|
||||
free(dep);
|
||||
}
|
||||
|
||||
@ -304,19 +310,29 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
|
||||
parse_state_t state = OUTSIDE_MODULE;
|
||||
pkgconf_pkg_comparator_t compare = PKGCONF_CMP_ANY;
|
||||
char cmpname[PKGCONF_ITEM_SIZE];
|
||||
char buf[PKGCONF_BUFSIZE];
|
||||
size_t package_sz = 0, version_sz = 0;
|
||||
char *start = buf;
|
||||
char *ptr = buf;
|
||||
size_t package_sz = 0, version_sz = 0, buf_sz = 0;
|
||||
char *buf;
|
||||
char *start = NULL;
|
||||
char *ptr = NULL;
|
||||
char *vstart = NULL;
|
||||
char *package = NULL, *version = NULL;
|
||||
char *cnameptr = cmpname;
|
||||
char *cnameend = cmpname + PKGCONF_ITEM_SIZE - 1;
|
||||
|
||||
if (!*depends)
|
||||
return;
|
||||
|
||||
memset(cmpname, '\0', sizeof cmpname);
|
||||
|
||||
pkgconf_strlcpy(buf, depends, sizeof buf);
|
||||
pkgconf_strlcat(buf, " ", sizeof buf);
|
||||
buf_sz = (strlen(depends) * 2) + 1;
|
||||
buf = calloc(1, buf_sz);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
|
||||
pkgconf_strlcpy(buf, depends, buf_sz);
|
||||
pkgconf_strlcat(buf, " ", buf_sz);
|
||||
|
||||
start = ptr = buf;
|
||||
|
||||
while (*ptr)
|
||||
{
|
||||
@ -427,6 +443,8 @@ pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_h
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -471,6 +489,9 @@ pkgconf_dependency_copy(pkgconf_client_t *client, const pkgconf_dependency_t *de
|
||||
pkgconf_dependency_t *new_dep;
|
||||
|
||||
new_dep = calloc(1, sizeof(pkgconf_dependency_t));
|
||||
if (new_dep == NULL)
|
||||
return NULL;
|
||||
|
||||
new_dep->package = strdup(dep->package);
|
||||
|
||||
if (dep->version != NULL)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* fileio.c
|
||||
* File reading utilities
|
||||
*
|
||||
* Copyright (c) 2012 pkgconf authors (see AUTHORS).
|
||||
* Copyright (c) 2012, 2025 pkgconf authors (see AUTHORS).
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -16,18 +16,13 @@
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
char *
|
||||
pkgconf_fgetline(char *line, size_t size, FILE *stream)
|
||||
bool
|
||||
pkgconf_fgetline(pkgconf_buffer_t *buffer, FILE *stream)
|
||||
{
|
||||
char *s = line;
|
||||
char *end = line + size - 2;
|
||||
bool quoted = false;
|
||||
int c = '\0', c2;
|
||||
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
while (s < end && (c = getc(stream)) != EOF)
|
||||
while ((c = getc(stream)) != EOF)
|
||||
{
|
||||
if (c == '\\' && !quoted)
|
||||
{
|
||||
@ -41,11 +36,11 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
|
||||
do {
|
||||
c = getc(stream);
|
||||
} while (c != '\n' && c != EOF);
|
||||
*s++ = c;
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
break;
|
||||
}
|
||||
else
|
||||
*s++ = c;
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
|
||||
quoted = false;
|
||||
continue;
|
||||
@ -66,14 +61,14 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
|
||||
}
|
||||
else
|
||||
{
|
||||
*s++ = c;
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (c == '\r')
|
||||
{
|
||||
*s++ = '\n';
|
||||
pkgconf_buffer_push_byte(buffer, '\n');
|
||||
|
||||
if ((c2 = getc(stream)) == '\n')
|
||||
{
|
||||
@ -99,26 +94,20 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
|
||||
else
|
||||
{
|
||||
if (quoted) {
|
||||
*s++ = '\\';
|
||||
pkgconf_buffer_push_byte(buffer, '\\');
|
||||
quoted = false;
|
||||
}
|
||||
*s++ = c;
|
||||
pkgconf_buffer_push_byte(buffer, c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (c == EOF && (s == line || ferror(stream)))
|
||||
return NULL;
|
||||
|
||||
*s = '\0';
|
||||
|
||||
/* Remove newline character. */
|
||||
if (s > line && *(--s) == '\n') {
|
||||
*s = '\0';
|
||||
if (pkgconf_buffer_lastc(buffer) == '\n')
|
||||
pkgconf_buffer_trim_byte(buffer);
|
||||
|
||||
if (s > line && *(--s) == '\r')
|
||||
*s = '\0';
|
||||
}
|
||||
if (pkgconf_buffer_lastc(buffer) == '\r')
|
||||
pkgconf_buffer_trim_byte(buffer);
|
||||
|
||||
return line;
|
||||
return !(c == EOF || ferror(stream));
|
||||
}
|
||||
|
||||
@ -32,6 +32,31 @@ struct pkgconf_fragment_check {
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_greedy(const char *string)
|
||||
{
|
||||
static const struct pkgconf_fragment_check check_fragments[] = {
|
||||
{"-F", 2},
|
||||
{"-I", 2},
|
||||
{"-L", 2},
|
||||
{"-D", 2},
|
||||
{"-l", 2},
|
||||
};
|
||||
|
||||
if (*string != '-')
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < PKGCONF_ARRAY_SIZE(check_fragments); i++)
|
||||
if (!strncmp(string, check_fragments[i].token, check_fragments[i].len))
|
||||
{
|
||||
/* if it is the bare flag, then we want the next token to be the data */
|
||||
if (!*(string + check_fragments[i].len))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_unmergeable(const char *string)
|
||||
{
|
||||
@ -52,6 +77,7 @@ pkgconf_fragment_is_unmergeable(const char *string)
|
||||
{"-nostdinc", 9},
|
||||
{"-nostdlibinc", 12},
|
||||
{"-nobuiltininc", 13},
|
||||
{"-nodefaultlibs", 14},
|
||||
};
|
||||
|
||||
if (*string != '-')
|
||||
@ -80,6 +106,38 @@ pkgconf_fragment_should_munge(const char *string, const char *sysroot_dir)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_groupable(const char *string)
|
||||
{
|
||||
static const struct pkgconf_fragment_check check_fragments[] = {
|
||||
{"-Wl,--start-group", 17},
|
||||
{"-framework", 10},
|
||||
{"-isystem", 8},
|
||||
{"-idirafter", 10},
|
||||
{"-include", 8},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < PKGCONF_ARRAY_SIZE(check_fragments); i++)
|
||||
if (!strncmp(string, check_fragments[i].token, check_fragments[i].len))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_terminus(const char *string)
|
||||
{
|
||||
static const struct pkgconf_fragment_check check_fragments[] = {
|
||||
{"-Wl,--end-group", 15},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < PKGCONF_ARRAY_SIZE(check_fragments); i++)
|
||||
if (!strncmp(string, check_fragments[i].token, check_fragments[i].len))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pkgconf_fragment_is_special(const char *string)
|
||||
{
|
||||
@ -168,15 +226,41 @@ pkgconf_fragment_insert(const pkgconf_client_t *client, pkgconf_list_t *list, ch
|
||||
void
|
||||
pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *string, unsigned int flags)
|
||||
{
|
||||
pkgconf_list_t *target = list;
|
||||
pkgconf_fragment_t *frag;
|
||||
|
||||
if (*string == '\0')
|
||||
return;
|
||||
|
||||
if (list->tail != NULL && list->tail->data != NULL &&
|
||||
!(client->flags & PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS))
|
||||
{
|
||||
pkgconf_fragment_t *parent = list->tail->data;
|
||||
|
||||
/* only attempt to merge 'special' fragments together */
|
||||
if (!parent->type && parent->data != NULL &&
|
||||
pkgconf_fragment_is_unmergeable(parent->data) &&
|
||||
!(parent->flags & PKGCONF_PKG_FRAGF_TERMINATED))
|
||||
{
|
||||
if (pkgconf_fragment_is_groupable(parent->data))
|
||||
target = &parent->children;
|
||||
|
||||
if (pkgconf_fragment_is_terminus(string))
|
||||
parent->flags |= PKGCONF_PKG_FRAGF_TERMINATED;
|
||||
|
||||
PKGCONF_TRACE(client, "adding fragment as child to list @%p", target);
|
||||
}
|
||||
}
|
||||
|
||||
frag = calloc(1, sizeof(pkgconf_fragment_t));
|
||||
if (frag == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "failed to add new fragment due to allocation failure to list @%p", target);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(string) > 1 && !pkgconf_fragment_is_special(string))
|
||||
{
|
||||
frag = calloc(1, sizeof(pkgconf_fragment_t));
|
||||
|
||||
frag->type = *(string + 1);
|
||||
frag->data = pkgconf_fragment_copy_munged(client, string + 2, flags);
|
||||
|
||||
@ -184,55 +268,13 @@ pkgconf_fragment_add(const pkgconf_client_t *client, pkgconf_list_t *list, const
|
||||
}
|
||||
else
|
||||
{
|
||||
char mungebuf[PKGCONF_ITEM_SIZE];
|
||||
|
||||
if (list->tail != NULL && list->tail->data != NULL &&
|
||||
!(client->flags & PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS))
|
||||
{
|
||||
pkgconf_fragment_t *parent = list->tail->data;
|
||||
|
||||
/* only attempt to merge 'special' fragments together */
|
||||
if (!parent->type && parent->data != NULL && pkgconf_fragment_is_unmergeable(parent->data))
|
||||
{
|
||||
size_t len;
|
||||
char *newdata;
|
||||
|
||||
pkgconf_fragment_munge(client, mungebuf, sizeof mungebuf, string, NULL, flags);
|
||||
|
||||
len = strlen(parent->data) + strlen(mungebuf) + 2;
|
||||
newdata = malloc(len);
|
||||
|
||||
pkgconf_strlcpy(newdata, parent->data, len);
|
||||
pkgconf_strlcat(newdata, " ", len);
|
||||
pkgconf_strlcat(newdata, mungebuf, len);
|
||||
|
||||
PKGCONF_TRACE(client, "merging '%s' to '%s' to form fragment {'%s'} in list @%p", mungebuf, parent->data, newdata, list);
|
||||
|
||||
free(parent->data);
|
||||
parent->data = newdata;
|
||||
parent->merged = true;
|
||||
|
||||
/* use a copy operation to force a dedup */
|
||||
pkgconf_node_delete(&parent->iter, list);
|
||||
pkgconf_fragment_copy(client, list, parent, false);
|
||||
|
||||
/* the fragment list now (maybe) has the copied node, so free the original */
|
||||
free(parent->data);
|
||||
free(parent);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
frag = calloc(1, sizeof(pkgconf_fragment_t));
|
||||
|
||||
frag->type = 0;
|
||||
frag->data = strdup(string);
|
||||
frag->data = pkgconf_fragment_copy_munged(client, string, flags);
|
||||
|
||||
PKGCONF_TRACE(client, "created special fragment {'%s'} in list @%p", frag->data, list);
|
||||
PKGCONF_TRACE(client, "created special fragment {'%s'} in list @%p", frag->data, target);
|
||||
}
|
||||
|
||||
pkgconf_node_insert_tail(&frag->iter, frag, list);
|
||||
pkgconf_node_insert_tail(&frag->iter, frag, target);
|
||||
}
|
||||
|
||||
static inline pkgconf_fragment_t *
|
||||
@ -285,6 +327,9 @@ pkgconf_fragment_can_merge(const pkgconf_fragment_t *base, unsigned int flags, b
|
||||
if (is_private)
|
||||
return false;
|
||||
|
||||
if (base->children.head != NULL)
|
||||
return false;
|
||||
|
||||
return pkgconf_fragment_is_unmergeable(base->data);
|
||||
}
|
||||
|
||||
@ -388,7 +433,7 @@ pkgconf_fragment_copy(const pkgconf_client_t *client, pkgconf_list_t *list, cons
|
||||
frag = calloc(1, sizeof(pkgconf_fragment_t));
|
||||
|
||||
frag->type = base->type;
|
||||
frag->merged = base->merged;
|
||||
pkgconf_fragment_copy_list(client, &frag->children, &base->children);
|
||||
if (base->data != NULL)
|
||||
frag->data = strdup(base->data);
|
||||
|
||||
@ -449,49 +494,27 @@ pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pk
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *
|
||||
fragment_quote(const pkgconf_fragment_t *frag)
|
||||
static void
|
||||
fragment_quote(pkgconf_buffer_t *out, const pkgconf_fragment_t *frag)
|
||||
{
|
||||
const char *src = frag->data;
|
||||
ssize_t outlen = strlen(src) + 10;
|
||||
char *out, *dst;
|
||||
|
||||
if (frag->data == NULL)
|
||||
return NULL;
|
||||
return;
|
||||
|
||||
out = dst = calloc(1, outlen);
|
||||
const pkgconf_buffer_t *src = PKGCONF_BUFFER_FROM_STR(frag->data);
|
||||
const pkgconf_span_t quote_spans[] = {
|
||||
{ 0x00, 0x1f },
|
||||
{ (unsigned char)' ', (unsigned char)'#' },
|
||||
{ (unsigned char)'%', (unsigned char)'\'' },
|
||||
{ (unsigned char)'*', (unsigned char)'*' },
|
||||
{ (unsigned char)';', (unsigned char)'<' },
|
||||
{ (unsigned char)'>', (unsigned char)'?' },
|
||||
{ (unsigned char)'[', (unsigned char)']' },
|
||||
{ (unsigned char)'`', (unsigned char)'`' },
|
||||
{ (unsigned char)'{', (unsigned char)'}' },
|
||||
{ 0x7f, 0xff },
|
||||
};
|
||||
|
||||
for (; *src; src++)
|
||||
{
|
||||
if (((*src < ' ') ||
|
||||
(*src >= (' ' + (frag->merged ? 1 : 0)) && *src < '$') ||
|
||||
(*src > '$' && *src < '(') ||
|
||||
(*src > ')' && *src < '+') ||
|
||||
(*src > ':' && *src < '=') ||
|
||||
(*src > '=' && *src < '@') ||
|
||||
(*src > 'Z' && *src < '\\') ||
|
||||
#ifndef _WIN32
|
||||
(*src == '\\') ||
|
||||
#endif
|
||||
(*src > '\\' && *src < '^') ||
|
||||
(*src == '`') ||
|
||||
(*src > 'z' && *src < '~') ||
|
||||
(*src > '~')))
|
||||
*dst++ = '\\';
|
||||
|
||||
*dst++ = *src;
|
||||
|
||||
if ((ptrdiff_t)(dst - out) + 2 > outlen)
|
||||
{
|
||||
ptrdiff_t offset = dst - out;
|
||||
outlen *= 2;
|
||||
out = realloc(out, outlen);
|
||||
dst = out + offset;
|
||||
}
|
||||
}
|
||||
|
||||
*dst = 0;
|
||||
return out;
|
||||
pkgconf_buffer_escape(out, src, quote_spans, PKGCONF_ARRAY_SIZE(quote_spans));
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
@ -504,9 +527,18 @@ pkgconf_fragment_len(const pkgconf_fragment_t *frag)
|
||||
|
||||
if (frag->data != NULL)
|
||||
{
|
||||
char *quoted = fragment_quote(frag);
|
||||
len += strlen(quoted);
|
||||
free(quoted);
|
||||
pkgconf_node_t *iter;
|
||||
|
||||
pkgconf_buffer_t quoted = PKGCONF_BUFFER_INITIALIZER;
|
||||
fragment_quote("ed, frag);
|
||||
len += pkgconf_buffer_len("ed);
|
||||
pkgconf_buffer_finalize("ed);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(frag->children.head, iter)
|
||||
{
|
||||
const pkgconf_fragment_t *child_frag = iter->data;
|
||||
len += pkgconf_fragment_len(child_frag) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
@ -529,45 +561,46 @@ fragment_render_len(const pkgconf_list_t *list, bool escape)
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
fragment_render_item(const pkgconf_fragment_t *frag, pkgconf_buffer_t *buf, char delim)
|
||||
{
|
||||
const pkgconf_node_t *iter;
|
||||
pkgconf_buffer_t quoted = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
fragment_quote("ed, frag);
|
||||
|
||||
if (frag->type)
|
||||
pkgconf_buffer_append_fmt(buf, "-%c", frag->type);
|
||||
|
||||
pkgconf_buffer_append(buf, pkgconf_buffer_str_or_empty("ed));
|
||||
pkgconf_buffer_finalize("ed);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(frag->children.head, iter)
|
||||
{
|
||||
const pkgconf_fragment_t *child_frag = iter->data;
|
||||
|
||||
pkgconf_buffer_push_byte(buf, delim);
|
||||
fragment_render_item(child_frag, buf, delim);
|
||||
}
|
||||
|
||||
return pkgconf_buffer_len(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape)
|
||||
fragment_render_buf(const pkgconf_list_t *list, pkgconf_buffer_t *buf, bool escape, char delim)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
pkgconf_node_t *node;
|
||||
char *bptr = buf;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
|
||||
{
|
||||
const pkgconf_fragment_t *frag = node->data;
|
||||
size_t buf_remaining = buflen - (bptr - buf);
|
||||
char *quoted = fragment_quote(frag);
|
||||
|
||||
if (strlen(quoted) > buf_remaining)
|
||||
{
|
||||
free(quoted);
|
||||
break;
|
||||
}
|
||||
|
||||
if (frag->type)
|
||||
{
|
||||
*bptr++ = '-';
|
||||
*bptr++ = frag->type;
|
||||
}
|
||||
|
||||
if (quoted != NULL)
|
||||
{
|
||||
bptr += pkgconf_strlcpy(bptr, quoted, buf_remaining);
|
||||
free(quoted);
|
||||
}
|
||||
fragment_render_item(frag, buf, delim);
|
||||
|
||||
if (node->next != NULL)
|
||||
*bptr++ = ' ';
|
||||
pkgconf_buffer_push_byte(buf, delim);
|
||||
}
|
||||
|
||||
*bptr = '\0';
|
||||
}
|
||||
|
||||
static const pkgconf_fragment_render_ops_t default_render_ops = {
|
||||
@ -600,7 +633,7 @@ pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgco
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
* .. c:function:: void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops, char delim)
|
||||
*
|
||||
* Renders a `fragment list` into a buffer.
|
||||
*
|
||||
@ -609,41 +642,16 @@ pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgco
|
||||
* :param size_t buflen: The length of the buffer.
|
||||
* :param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
* :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
* :param char delim: The delimiter to use between fragments.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t buflen, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
pkgconf_fragment_render_buf(const pkgconf_list_t *list, pkgconf_buffer_t *buf, bool escape, const pkgconf_fragment_render_ops_t *ops, char delim)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
ops = ops != NULL ? ops : &default_render_ops;
|
||||
ops->render_buf(list, buf, buflen, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: char *pkgconf_fragment_render(const pkgconf_list_t *list)
|
||||
*
|
||||
* Allocate memory and render a `fragment list` into it.
|
||||
*
|
||||
* :param pkgconf_list_t* list: The `fragment list` being rendered.
|
||||
* :param bool escape: Whether or not to escape special shell characters (deprecated).
|
||||
* :param pkgconf_fragment_render_ops_t* ops: An optional ops structure to use for custom renderers, else ``NULL``.
|
||||
* :return: An allocated string containing the rendered `fragment list`.
|
||||
* :rtype: char *
|
||||
*/
|
||||
char *
|
||||
pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops)
|
||||
{
|
||||
(void) escape;
|
||||
|
||||
size_t buflen = pkgconf_fragment_render_len(list, true, ops);
|
||||
char *buf = calloc(1, buflen);
|
||||
|
||||
pkgconf_fragment_render_buf(list, buf, buflen, true, ops);
|
||||
|
||||
return buf;
|
||||
ops->render_buf(list, buf, true, delim);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -685,6 +693,7 @@ pkgconf_fragment_free(pkgconf_list_t *list)
|
||||
{
|
||||
pkgconf_fragment_t *frag = node->data;
|
||||
|
||||
pkgconf_fragment_free(&frag->children);
|
||||
free(frag->data);
|
||||
free(frag);
|
||||
}
|
||||
@ -723,8 +732,6 @@ pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkg
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
PKGCONF_TRACE(client, "processing %s", argv[i]);
|
||||
|
||||
if (argv[i] == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "parsed fragment string is inconsistent: argc = %d while argv[%d] == NULL", argc, i);
|
||||
@ -733,7 +740,24 @@ pkgconf_fragment_parse(const pkgconf_client_t *client, pkgconf_list_t *list, pkg
|
||||
return false;
|
||||
}
|
||||
|
||||
pkgconf_fragment_add(client, list, argv[i], flags);
|
||||
bool greedy = pkgconf_fragment_is_greedy(argv[i]);
|
||||
|
||||
PKGCONF_TRACE(client, "processing [%s] greedy=%d", argv[i], greedy);
|
||||
|
||||
if (greedy && i + 1 < argc)
|
||||
{
|
||||
pkgconf_buffer_t greedybuf = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
pkgconf_buffer_append(&greedybuf, argv[i]);
|
||||
pkgconf_buffer_append(&greedybuf, argv[i + 1]);
|
||||
pkgconf_fragment_add(client, list, pkgconf_buffer_str(&greedybuf), flags);
|
||||
pkgconf_buffer_finalize(&greedybuf);
|
||||
|
||||
/* skip over next arg as we combined them */
|
||||
i++;
|
||||
}
|
||||
else
|
||||
pkgconf_fragment_add(client, list, argv[i], flags);
|
||||
}
|
||||
|
||||
pkgconf_argv_free(argv);
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <libpkgconf/libpkgconf-api.h>
|
||||
#include <libpkgconf/iter.h>
|
||||
#include <libpkgconf/bsdstubs.h>
|
||||
@ -30,23 +31,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* pkg-config uses ';' on win32 as ':' is part of path */
|
||||
#ifdef _WIN32
|
||||
#define PKG_CONFIG_PATH_SEP_S ";"
|
||||
#else
|
||||
#define PKG_CONFIG_PATH_SEP_S ":"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PKG_DIR_SEP_S '\\'
|
||||
#else
|
||||
#define PKG_DIR_SEP_S '/'
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
|
||||
#endif
|
||||
|
||||
#define PKGCONF_BUFSIZE (65535)
|
||||
|
||||
typedef enum {
|
||||
@ -64,11 +48,14 @@ typedef enum {
|
||||
typedef struct pkgconf_pkg_ pkgconf_pkg_t;
|
||||
typedef struct pkgconf_dependency_ pkgconf_dependency_t;
|
||||
typedef struct pkgconf_tuple_ pkgconf_tuple_t;
|
||||
typedef struct pkgconf_buffer_ pkgconf_buffer_t;
|
||||
typedef struct pkgconf_span_ pkgconf_span_t;
|
||||
typedef struct pkgconf_fragment_ pkgconf_fragment_t;
|
||||
typedef struct pkgconf_path_ pkgconf_path_t;
|
||||
typedef struct pkgconf_client_ pkgconf_client_t;
|
||||
typedef struct pkgconf_cross_personality_ pkgconf_cross_personality_t;
|
||||
typedef struct pkgconf_queue_ pkgconf_queue_t;
|
||||
typedef struct pkgconf_output_ pkgconf_output_t;
|
||||
|
||||
#define PKGCONF_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
|
||||
@ -81,12 +68,14 @@ typedef struct pkgconf_queue_ pkgconf_queue_t;
|
||||
#define PKGCONF_FOREACH_LIST_ENTRY_REVERSE(tail, value) \
|
||||
for ((value) = (tail); (value) != NULL; (value) = (value)->prev)
|
||||
|
||||
#define LIBPKGCONF_VERSION 20300
|
||||
#define LIBPKGCONF_VERSION_STR "2.3.0"
|
||||
#define LIBPKGCONF_VERSION 20501
|
||||
#define LIBPKGCONF_VERSION_STR "2.5.1"
|
||||
|
||||
struct pkgconf_queue_ {
|
||||
pkgconf_node_t iter;
|
||||
char *package;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct pkgconf_fragment_ {
|
||||
@ -95,9 +84,12 @@ struct pkgconf_fragment_ {
|
||||
char type;
|
||||
char *data;
|
||||
|
||||
bool merged;
|
||||
pkgconf_list_t children;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define PKGCONF_PKG_FRAGF_TERMINATED 0x1
|
||||
|
||||
struct pkgconf_dependency_ {
|
||||
pkgconf_node_t iter;
|
||||
|
||||
@ -111,6 +103,8 @@ struct pkgconf_dependency_ {
|
||||
|
||||
int refcount;
|
||||
pkgconf_client_t *owner;
|
||||
|
||||
char *why;
|
||||
};
|
||||
|
||||
struct pkgconf_tuple_ {
|
||||
@ -122,6 +116,11 @@ struct pkgconf_tuple_ {
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct pkgconf_buffer_ {
|
||||
char *base;
|
||||
char *end;
|
||||
};
|
||||
|
||||
#define PKGCONF_PKG_TUPLEF_OVERRIDE 0x1
|
||||
|
||||
struct pkgconf_path_ {
|
||||
@ -130,6 +129,8 @@ struct pkgconf_path_ {
|
||||
char *path;
|
||||
void *handle_path;
|
||||
void *handle_device;
|
||||
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define PKGCONF_PKG_PROPF_NONE 0x00
|
||||
@ -139,6 +140,7 @@ struct pkgconf_path_ {
|
||||
#define PKGCONF_PKG_PROPF_VIRTUAL 0x10
|
||||
#define PKGCONF_PKG_PROPF_ANCESTOR 0x20
|
||||
#define PKGCONF_PKG_PROPF_VISITED_PRIVATE 0x40
|
||||
#define PKGCONF_PKG_PROPF_PRELOADED 0x80
|
||||
|
||||
struct pkgconf_pkg_ {
|
||||
int refcount;
|
||||
@ -152,6 +154,8 @@ struct pkgconf_pkg_ {
|
||||
char *license;
|
||||
char *maintainer;
|
||||
char *copyright;
|
||||
char *source;
|
||||
char *license_file;
|
||||
char *why;
|
||||
|
||||
pkgconf_list_t libs;
|
||||
@ -178,12 +182,16 @@ struct pkgconf_pkg_ {
|
||||
|
||||
uint64_t serial;
|
||||
uint64_t identifier;
|
||||
|
||||
pkgconf_node_t preload_node;
|
||||
};
|
||||
|
||||
typedef bool (*pkgconf_pkg_iteration_func_t)(const pkgconf_pkg_t *pkg, void *data);
|
||||
typedef void (*pkgconf_pkg_traverse_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data);
|
||||
typedef bool (*pkgconf_queue_apply_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *world, void *data, int maxdepth);
|
||||
typedef bool (*pkgconf_error_handler_func_t)(const char *msg, const pkgconf_client_t *client, void *data);
|
||||
typedef void (*pkgconf_unveil_handler_func_t)(const pkgconf_client_t *client, const char *path, const char *permissions);
|
||||
typedef const char *(*pkgconf_environ_lookup_handler_func_t)(const pkgconf_client_t *client, const char *variable);
|
||||
|
||||
struct pkgconf_client_ {
|
||||
pkgconf_list_t dir_list;
|
||||
@ -193,6 +201,7 @@ struct pkgconf_client_ {
|
||||
|
||||
pkgconf_list_t global_vars;
|
||||
|
||||
void *client_data;
|
||||
void *error_handler_data;
|
||||
void *warn_handler_data;
|
||||
void *trace_handler_data;
|
||||
@ -201,6 +210,8 @@ struct pkgconf_client_ {
|
||||
pkgconf_error_handler_func_t warn_handler;
|
||||
pkgconf_error_handler_func_t trace_handler;
|
||||
|
||||
pkgconf_environ_lookup_handler_func_t environ_lookup_handler;
|
||||
|
||||
FILE *auditf;
|
||||
|
||||
char *sysroot_dir;
|
||||
@ -217,10 +228,18 @@ struct pkgconf_client_ {
|
||||
|
||||
pkgconf_pkg_t **cache_table;
|
||||
size_t cache_count;
|
||||
|
||||
pkgconf_unveil_handler_func_t unveil_handler;
|
||||
|
||||
pkgconf_list_t preloaded_pkgs;
|
||||
|
||||
pkgconf_output_t *output;
|
||||
|
||||
const pkgconf_cross_personality_t *personality;
|
||||
};
|
||||
|
||||
struct pkgconf_cross_personality_ {
|
||||
const char *name;
|
||||
char *name;
|
||||
|
||||
pkgconf_list_t dir_list;
|
||||
|
||||
@ -234,8 +253,8 @@ struct pkgconf_cross_personality_ {
|
||||
};
|
||||
|
||||
/* client.c */
|
||||
PKGCONF_API void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality);
|
||||
PKGCONF_API pkgconf_client_t * pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality);
|
||||
PKGCONF_API void pkgconf_client_init(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler);
|
||||
PKGCONF_API pkgconf_client_t * pkgconf_client_new(pkgconf_error_handler_func_t error_handler, void *error_handler_data, const pkgconf_cross_personality_t *personality, void *client_data, pkgconf_environ_lookup_handler_func_t environ_lookup_handler);
|
||||
PKGCONF_API void pkgconf_client_deinit(pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_free(pkgconf_client_t *client);
|
||||
PKGCONF_API const char *pkgconf_client_get_sysroot_dir(const pkgconf_client_t *client);
|
||||
@ -252,7 +271,14 @@ PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_error_handler(const
|
||||
PKGCONF_API void pkgconf_client_set_error_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t error_handler, void *error_handler_data);
|
||||
PKGCONF_API pkgconf_error_handler_func_t pkgconf_client_get_trace_handler(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_trace_handler(pkgconf_client_t *client, pkgconf_error_handler_func_t trace_handler, void *trace_handler_data);
|
||||
PKGCONF_API pkgconf_unveil_handler_func_t pkgconf_client_get_unveil_handler(const pkgconf_client_t *client);
|
||||
PKGCONF_API void pkgconf_client_set_unveil_handler(pkgconf_client_t *client, pkgconf_unveil_handler_func_t unveil_handler);
|
||||
PKGCONF_API void pkgconf_client_dir_list_build(pkgconf_client_t *client, const pkgconf_cross_personality_t *personality);
|
||||
PKGCONF_API bool pkgconf_client_preload_one(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
|
||||
PKGCONF_API bool pkgconf_client_preload_path(pkgconf_client_t *client, const char *path);
|
||||
PKGCONF_API bool pkgconf_client_preload_from_environ(pkgconf_client_t *client, const char *env);
|
||||
PKGCONF_API void pkgconf_client_set_output(pkgconf_client_t *client, pkgconf_output_t *output);
|
||||
PKGCONF_API const char *pkgconf_client_getenv(const pkgconf_client_t *client, const char *key);
|
||||
|
||||
/* personality.c */
|
||||
PKGCONF_API pkgconf_cross_personality_t *pkgconf_cross_personality_default(void);
|
||||
@ -280,6 +306,7 @@ PKGCONF_API void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *p
|
||||
#define PKGCONF_PKG_PKGF_DONT_MERGE_SPECIAL_FRAGMENTS 0x4000
|
||||
#define PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES 0x8000
|
||||
#define PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES 0x10000
|
||||
#define PKGCONF_PKG_PKGF_REQUIRE_INTERNAL 0x20000
|
||||
|
||||
#define PKGCONF_PKG_DEPF_INTERNAL 0x1
|
||||
#define PKGCONF_PKG_DEPF_PRIVATE 0x2
|
||||
@ -291,21 +318,23 @@ PKGCONF_API void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *p
|
||||
#define PKGCONF_PKG_ERRF_PACKAGE_CONFLICT 0x4
|
||||
#define PKGCONF_PKG_ERRF_DEPGRAPH_BREAK 0x8
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
#define PRINTFLIKE(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#define DEPRECATED \
|
||||
__attribute__((deprecated))
|
||||
#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
|
||||
# define PRINTFLIKE(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (gnu_printf, fmtarg, firstvararg)))
|
||||
#elif defined(__clang__) || defined(__INTEL_COMPILER) || __GNUC__ > 2 || (_GNUC__ == 2 && __GNUC_MINOR__ >= 5)
|
||||
# define PRINTFLIKE(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#else
|
||||
#define PRINTFLIKE(fmtarg, firstvararg)
|
||||
#define DEPRECATED
|
||||
#endif /* defined(__INTEL_COMPILER) || defined(__GNUC__) */
|
||||
# define PRINTFLIKE(fmtarg, firstvararg)
|
||||
#endif
|
||||
|
||||
/* parser.c */
|
||||
typedef void (*pkgconf_parser_operand_func_t)(void *data, const size_t lineno, const char *key, const char *value);
|
||||
typedef void (*pkgconf_parser_warn_func_t)(void *data, const char *fmt, ...);
|
||||
|
||||
PKGCONF_API void pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, const char *filename);
|
||||
#if defined(__clang__) || defined(__INTEL_COMPILER) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
# define DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
# define DEPRECATED
|
||||
#endif
|
||||
|
||||
/* pkg.c */
|
||||
PKGCONF_API bool pkgconf_error(const pkgconf_client_t *client, const char *format, ...) PRINTFLIKE(2, 3);
|
||||
@ -332,19 +361,19 @@ PKGCONF_API void pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
PKGCONF_API void pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_find(pkgconf_client_t *client, const char *name);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_traverse(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_pkg_traverse_func_t func, void *data, int maxdepth, unsigned int skip_flags);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_walk_conflicts_list(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *deplist);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_verify_graph(pkgconf_client_t *client, pkgconf_pkg_t *root, int depth);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pkgdep, unsigned int *eflags);
|
||||
PKGCONF_API const char *pkgconf_pkg_get_comparator(const pkgconf_dependency_t *pkgdep);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_cflags(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth);
|
||||
PKGCONF_API unsigned int pkgconf_pkg_libs(pkgconf_client_t *client, pkgconf_pkg_t *root, pkgconf_list_t *list, int maxdepth);
|
||||
PKGCONF_API pkgconf_pkg_comparator_t pkgconf_pkg_comparator_lookup_by_name(const char *name);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_builtin_pkg_get(const char *name);
|
||||
|
||||
PKGCONF_API int pkgconf_compare_version(const char *a, const char *b);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_scan_all(pkgconf_client_t *client, void *ptr, pkgconf_pkg_iteration_func_t func);
|
||||
|
||||
/* parse.c */
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *path, FILE *f, unsigned int flags);
|
||||
PKGCONF_API pkgconf_pkg_t *pkgconf_pkg_new_from_path(pkgconf_client_t *client, const char *path, unsigned int flags);
|
||||
PKGCONF_API void pkgconf_dependency_parse_str(pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags);
|
||||
PKGCONF_API void pkgconf_dependency_parse(pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags);
|
||||
PKGCONF_API void pkgconf_dependency_append(pkgconf_list_t *list, pkgconf_dependency_t *tail);
|
||||
@ -362,7 +391,7 @@ PKGCONF_API void pkgconf_argv_free(char **argv);
|
||||
/* fragment.c */
|
||||
typedef struct pkgconf_fragment_render_ops_ {
|
||||
size_t (*render_len)(const pkgconf_list_t *list, bool escape);
|
||||
void (*render_buf)(const pkgconf_list_t *list, char *buf, size_t len, bool escape);
|
||||
void (*render_buf)(const pkgconf_list_t *list, pkgconf_buffer_t *buf, bool escape, char delim);
|
||||
} pkgconf_fragment_render_ops_t;
|
||||
|
||||
typedef bool (*pkgconf_fragment_filter_func_t)(const pkgconf_client_t *client, const pkgconf_fragment_t *frag, void *data);
|
||||
@ -375,13 +404,9 @@ PKGCONF_API void pkgconf_fragment_delete(pkgconf_list_t *list, pkgconf_fragment_
|
||||
PKGCONF_API void pkgconf_fragment_free(pkgconf_list_t *list);
|
||||
PKGCONF_API void pkgconf_fragment_filter(const pkgconf_client_t *client, pkgconf_list_t *dest, pkgconf_list_t *src, pkgconf_fragment_filter_func_t filter_func, void *data);
|
||||
PKGCONF_API size_t pkgconf_fragment_render_len(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops);
|
||||
PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *buf, size_t len, bool escape, const pkgconf_fragment_render_ops_t *ops);
|
||||
PKGCONF_API char *pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops);
|
||||
PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, pkgconf_buffer_t *buf, bool escape, const pkgconf_fragment_render_ops_t *ops, char delim);
|
||||
PKGCONF_API bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag);
|
||||
|
||||
/* fileio.c */
|
||||
PKGCONF_API char *pkgconf_fgetline(char *line, size_t size, FILE *stream);
|
||||
|
||||
/* tuple.c */
|
||||
PKGCONF_API pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *parent, const char *key, const char *value, bool parse, unsigned int flags);
|
||||
PKGCONF_API char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key);
|
||||
@ -395,6 +420,7 @@ PKGCONF_API void pkgconf_tuple_define_global(pkgconf_client_t *client, const cha
|
||||
|
||||
/* queue.c */
|
||||
PKGCONF_API void pkgconf_queue_push(pkgconf_list_t *list, const char *package);
|
||||
PKGCONF_API void pkgconf_queue_push_dependency(pkgconf_list_t *list, const pkgconf_dependency_t *dep);
|
||||
PKGCONF_API bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list);
|
||||
PKGCONF_API bool pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_t *world, int maxdepth);
|
||||
PKGCONF_API void pkgconf_queue_free(pkgconf_list_t *list);
|
||||
@ -417,11 +443,113 @@ PKGCONF_API void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pk
|
||||
PKGCONF_API void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter);
|
||||
PKGCONF_API void pkgconf_path_prepend(const char *text, pkgconf_list_t *dirlist, bool filter);
|
||||
PKGCONF_API size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter);
|
||||
PKGCONF_API size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter);
|
||||
PKGCONF_API size_t pkgconf_path_build_from_environ(const pkgconf_client_t *client, const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter);
|
||||
#ifdef _WIN32
|
||||
PKGCONF_API size_t pkgconf_path_build_from_registry(/* HKEY -> HANDLE -> PVOID */ void *hKey, pkgconf_list_t *dirlist, bool filter);
|
||||
#endif
|
||||
PKGCONF_API bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist);
|
||||
PKGCONF_API void pkgconf_path_free(pkgconf_list_t *dirlist);
|
||||
PKGCONF_API bool pkgconf_path_relocate(char *buf, size_t buflen);
|
||||
PKGCONF_API void pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src);
|
||||
PKGCONF_API void pkgconf_path_prepend_list(pkgconf_list_t *dst, const pkgconf_list_t *src);
|
||||
|
||||
/* buffer.c */
|
||||
struct pkgconf_span_ {
|
||||
unsigned char lo;
|
||||
unsigned char hi; /* inclusive */
|
||||
};
|
||||
|
||||
static inline bool pkgconf_span_contains(unsigned char c, const pkgconf_span_t *spans, size_t nspans) {
|
||||
for (size_t i = 0; i < nspans; i++)
|
||||
if (c >= spans[i].lo && c <= spans[i].hi)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PKGCONF_API void pkgconf_buffer_append(pkgconf_buffer_t *buffer, const char *text);
|
||||
PKGCONF_API void pkgconf_buffer_append_fmt(pkgconf_buffer_t *buffer, const char *fmt, ...) PRINTFLIKE(2, 3);
|
||||
PKGCONF_API void pkgconf_buffer_append_vfmt(pkgconf_buffer_t *buffer, const char *fmt, va_list va);
|
||||
PKGCONF_API void pkgconf_buffer_push_byte(pkgconf_buffer_t *buffer, char byte);
|
||||
PKGCONF_API void pkgconf_buffer_trim_byte(pkgconf_buffer_t *buffer);
|
||||
PKGCONF_API void pkgconf_buffer_finalize(pkgconf_buffer_t *buffer);
|
||||
PKGCONF_API void pkgconf_buffer_fputs(pkgconf_buffer_t *buffer, FILE *out);
|
||||
PKGCONF_API void pkgconf_buffer_vjoin(pkgconf_buffer_t *buffer, char delim, va_list va);
|
||||
PKGCONF_API void pkgconf_buffer_join(pkgconf_buffer_t *buffer, int delim, ...);
|
||||
PKGCONF_API bool pkgconf_buffer_contains(const pkgconf_buffer_t *haystack, const pkgconf_buffer_t *needle);
|
||||
PKGCONF_API bool pkgconf_buffer_contains_byte(const pkgconf_buffer_t *haystack, char needle);
|
||||
PKGCONF_API bool pkgconf_buffer_match(const pkgconf_buffer_t *haystack, const pkgconf_buffer_t *needle);
|
||||
PKGCONF_API void pkgconf_buffer_subst(pkgconf_buffer_t *dest, const pkgconf_buffer_t *src, const char *pattern, const char *value);
|
||||
PKGCONF_API void pkgconf_buffer_escape(pkgconf_buffer_t *dest, const pkgconf_buffer_t *src, const pkgconf_span_t *spans, size_t nspans);
|
||||
static inline const char *pkgconf_buffer_str(const pkgconf_buffer_t *buffer) {
|
||||
return buffer->base;
|
||||
}
|
||||
|
||||
static inline const char *pkgconf_buffer_str_or_empty(const pkgconf_buffer_t *buffer) {
|
||||
return buffer->base != NULL ? buffer->base : "";
|
||||
}
|
||||
|
||||
static inline size_t pkgconf_buffer_len(const pkgconf_buffer_t *buffer) {
|
||||
return (size_t)(ptrdiff_t)(buffer->end - buffer->base);
|
||||
}
|
||||
|
||||
static inline char pkgconf_buffer_lastc(const pkgconf_buffer_t *buffer) {
|
||||
if (buffer->base == buffer->end)
|
||||
return '\0';
|
||||
|
||||
return *(buffer->end - 1);
|
||||
}
|
||||
|
||||
#define PKGCONF_BUFFER_INITIALIZER { NULL, NULL }
|
||||
#define PKGCONF_BUFFER_FROM_STR(str) &(const pkgconf_buffer_t){ .base = str, .end = str + strlen(str) }
|
||||
|
||||
static inline void pkgconf_buffer_reset(pkgconf_buffer_t *buffer) {
|
||||
pkgconf_buffer_finalize(buffer);
|
||||
buffer->base = buffer->end = NULL;
|
||||
}
|
||||
|
||||
static inline char *pkgconf_buffer_freeze(pkgconf_buffer_t *buffer) {
|
||||
if (buffer->base == NULL)
|
||||
return NULL;
|
||||
|
||||
char *out = strdup(pkgconf_buffer_str(buffer));
|
||||
pkgconf_buffer_reset(buffer);
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline void pkgconf_buffer_copy(pkgconf_buffer_t *buffer, pkgconf_buffer_t *newptr)
|
||||
{
|
||||
pkgconf_buffer_reset(newptr);
|
||||
pkgconf_buffer_append(newptr, pkgconf_buffer_str(buffer));
|
||||
}
|
||||
|
||||
/* fileio.c */
|
||||
PKGCONF_API bool pkgconf_fgetline(pkgconf_buffer_t *buffer, FILE *stream);
|
||||
|
||||
/* parser.c */
|
||||
typedef void (*pkgconf_parser_operand_func_t)(void *data, const char *warnprefix, const char *key, const char *value);
|
||||
typedef void (*pkgconf_parser_warn_func_t)(void *data, const char *fmt, ...);
|
||||
|
||||
PKGCONF_API void pkgconf_parser_parse_buffer(void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, pkgconf_buffer_t *buffer, const char *warnprefix);
|
||||
PKGCONF_API void pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, const char *filename);
|
||||
|
||||
/* output.c */
|
||||
typedef enum {
|
||||
PKGCONF_OUTPUT_STDOUT,
|
||||
PKGCONF_OUTPUT_STDERR,
|
||||
} pkgconf_output_stream_t;
|
||||
|
||||
struct pkgconf_output_ {
|
||||
void *privdata;
|
||||
|
||||
bool (*write)(pkgconf_output_t *output, pkgconf_output_stream_t stream, const pkgconf_buffer_t *buffer);
|
||||
};
|
||||
|
||||
PKGCONF_API bool pkgconf_output_putbuf(pkgconf_output_t *output, pkgconf_output_stream_t stream, const pkgconf_buffer_t *buffer, bool newline);
|
||||
PKGCONF_API bool pkgconf_output_puts(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *str);
|
||||
PKGCONF_API bool pkgconf_output_fmt(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *fmt, ...);
|
||||
PKGCONF_API bool pkgconf_output_vfmt(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *fmt, va_list va);
|
||||
PKGCONF_API pkgconf_output_t *pkgconf_output_default(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
110
libpkgconf/output.c
Normal file
110
libpkgconf/output.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* output.c
|
||||
* I/O abstraction layer
|
||||
*
|
||||
* Copyright (c) 2025 pkgconf authors (see AUTHORS).
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* This software is provided 'as is' and without any warranty, express or
|
||||
* implied. In no event shall the authors be liable for any damages arising
|
||||
* from the use of this software.
|
||||
*/
|
||||
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
bool
|
||||
pkgconf_output_putbuf(pkgconf_output_t *output, pkgconf_output_stream_t stream, const pkgconf_buffer_t *buffer, bool newline)
|
||||
{
|
||||
bool ret;
|
||||
pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
if (pkgconf_buffer_len(buffer) != 0)
|
||||
pkgconf_buffer_append(&buf, pkgconf_buffer_str(buffer));
|
||||
|
||||
if (newline)
|
||||
pkgconf_buffer_push_byte(&buf, '\n');
|
||||
|
||||
ret = output->write(output, stream, &buf);
|
||||
pkgconf_buffer_finalize(&buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
pkgconf_output_puts(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *str)
|
||||
{
|
||||
bool ret;
|
||||
pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
pkgconf_buffer_append(&buf, str);
|
||||
pkgconf_buffer_push_byte(&buf, '\n');
|
||||
ret = output->write(output, stream, &buf);
|
||||
pkgconf_buffer_finalize(&buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
pkgconf_output_fmt(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *fmt, ...)
|
||||
{
|
||||
bool ret;
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
ret = pkgconf_output_vfmt(output, stream, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
pkgconf_output_vfmt(pkgconf_output_t *output, pkgconf_output_stream_t stream, const char *fmt, va_list src_va)
|
||||
{
|
||||
va_list va;
|
||||
bool ret;
|
||||
pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER;
|
||||
|
||||
va_copy(va, src_va);
|
||||
pkgconf_buffer_append_vfmt(&buf, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
ret = output->write(output, stream, &buf);
|
||||
pkgconf_buffer_finalize(&buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
pkgconf_output_stdio_write(pkgconf_output_t *output, pkgconf_output_stream_t stream, const pkgconf_buffer_t *buffer)
|
||||
{
|
||||
(void) output;
|
||||
|
||||
FILE *target = stream == PKGCONF_OUTPUT_STDERR ? stderr : stdout;
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
const char *str = pkgconf_buffer_str(buffer);
|
||||
size_t size = pkgconf_buffer_len(buffer);
|
||||
|
||||
if (size > 0 && !fwrite(str, size, 1, target))
|
||||
return false;
|
||||
}
|
||||
|
||||
fflush(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
static pkgconf_output_t pkgconf_default_output = {
|
||||
.privdata = NULL,
|
||||
.write = pkgconf_output_stdio_write,
|
||||
};
|
||||
|
||||
pkgconf_output_t *
|
||||
pkgconf_output_default(void)
|
||||
{
|
||||
return &pkgconf_default_output;
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
* parser.c
|
||||
* rfc822 message parser
|
||||
*
|
||||
* Copyright (c) 2018 pkgconf authors (see AUTHORS).
|
||||
* Copyright (c) 2018, 2025 pkgconf authors (see AUTHORS).
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -17,90 +17,84 @@
|
||||
#include <libpkgconf/stdinc.h>
|
||||
#include <libpkgconf/libpkgconf.h>
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_pkg_t *pkgconf_pkg_new_from_file(const pkgconf_client_t *client, const char *filename, FILE *f)
|
||||
*
|
||||
* Parse a .pc file into a pkgconf_pkg_t object structure.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
|
||||
* :param char* filename: The filename of the package file (including full path).
|
||||
* :param FILE* f: The file object to read from.
|
||||
* :returns: A ``pkgconf_pkg_t`` object which contains the package data.
|
||||
* :rtype: pkgconf_pkg_t *
|
||||
*/
|
||||
void
|
||||
pkgconf_parser_parse_buffer(void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, pkgconf_buffer_t *buffer, const char *warnprefix)
|
||||
{
|
||||
char op, *p, *key, *value;
|
||||
|
||||
p = buffer->base;
|
||||
if (p == NULL)
|
||||
return;
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (*p && p != buffer->base)
|
||||
{
|
||||
warnfunc(data, "%s: warning: whitespace encountered while parsing key section\n",
|
||||
warnprefix);
|
||||
}
|
||||
key = p;
|
||||
while (*p && (isalpha((unsigned char)*p) || isdigit((unsigned char)*p) || *p == '_' || *p == '.'))
|
||||
p++;
|
||||
|
||||
if (!isalpha((unsigned char)*key) &&
|
||||
!isdigit((unsigned char)*p))
|
||||
return;
|
||||
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
{
|
||||
warnfunc(data, "%s: warning: whitespace encountered while parsing key section\n",
|
||||
warnprefix);
|
||||
|
||||
/* set to null to avoid trailing spaces in key */
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
op = *p;
|
||||
if (*p != '\0')
|
||||
{
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
p++;
|
||||
|
||||
value = p;
|
||||
p = value + (strlen(value) - 1);
|
||||
while (*p && isspace((unsigned char) *p) && p > value)
|
||||
{
|
||||
if (op == '=')
|
||||
{
|
||||
warnfunc(data, "%s: warning: trailing whitespace encountered while parsing value section\n",
|
||||
warnprefix);
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
p--;
|
||||
}
|
||||
if (ops[(unsigned char) op])
|
||||
ops[(unsigned char) op](data, warnprefix, key, value);
|
||||
}
|
||||
|
||||
void
|
||||
pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, const char *filename)
|
||||
{
|
||||
char readbuf[PKGCONF_BUFSIZE];
|
||||
pkgconf_buffer_t readbuf = PKGCONF_BUFFER_INITIALIZER;
|
||||
size_t lineno = 0;
|
||||
bool continue_reading = true;
|
||||
|
||||
while (pkgconf_fgetline(readbuf, PKGCONF_BUFSIZE, f) != NULL)
|
||||
while (continue_reading)
|
||||
{
|
||||
char op, *p, *key, *value;
|
||||
bool warned_key_whitespace = false, warned_value_whitespace = false;
|
||||
char warnprefix[PKGCONF_ITEM_SIZE];
|
||||
|
||||
continue_reading = pkgconf_fgetline(&readbuf, f);
|
||||
lineno++;
|
||||
|
||||
p = readbuf;
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (*p && p != readbuf)
|
||||
{
|
||||
warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: whitespace encountered while parsing key section\n",
|
||||
filename, lineno);
|
||||
warned_key_whitespace = true;
|
||||
}
|
||||
key = p;
|
||||
while (*p && (isalpha((unsigned char)*p) || isdigit((unsigned char)*p) || *p == '_' || *p == '.'))
|
||||
p++;
|
||||
|
||||
if (!isalpha((unsigned char)*key) &&
|
||||
!isdigit((unsigned char)*p))
|
||||
continue;
|
||||
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
{
|
||||
if (!warned_key_whitespace)
|
||||
{
|
||||
warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: whitespace encountered while parsing key section\n",
|
||||
filename, lineno);
|
||||
warned_key_whitespace = true;
|
||||
}
|
||||
|
||||
/* set to null to avoid trailing spaces in key */
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
op = *p;
|
||||
if (*p != '\0')
|
||||
{
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
|
||||
while (*p && isspace((unsigned char)*p))
|
||||
p++;
|
||||
|
||||
value = p;
|
||||
p = value + (strlen(value) - 1);
|
||||
while (*p && isspace((unsigned char) *p) && p > value)
|
||||
{
|
||||
if (!warned_value_whitespace && op == '=')
|
||||
{
|
||||
warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: trailing whitespace encountered while parsing value section\n",
|
||||
filename, lineno);
|
||||
warned_value_whitespace = true;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
p--;
|
||||
}
|
||||
if (ops[(unsigned char) op])
|
||||
ops[(unsigned char) op](data, lineno, key, value);
|
||||
snprintf(warnprefix, sizeof warnprefix, "%s:" SIZE_FMT_SPECIFIER, filename, lineno);
|
||||
pkgconf_parser_parse_buffer(data, ops, warnfunc, &readbuf, warnprefix);
|
||||
pkgconf_buffer_reset(&readbuf);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
pkgconf_buffer_finalize(&readbuf);
|
||||
}
|
||||
|
||||
@ -91,6 +91,9 @@ prepare_path_node(const char *text, pkgconf_list_t *dirlist, bool filter)
|
||||
#endif
|
||||
|
||||
node = calloc(1, sizeof(pkgconf_path_t));
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
node->path = strdup(path);
|
||||
|
||||
#ifdef PKGCONF_CACHE_INODES
|
||||
@ -189,6 +192,7 @@ pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter)
|
||||
* Adds the paths specified in an environment variable to a path list. If the environment variable is not set,
|
||||
* an optional default set of paths is added.
|
||||
*
|
||||
* :param pkgconf_client_t* client: The client to use for environmental variable lookup (can be NULL).
|
||||
* :param char* envvarname: The environment variable to look up.
|
||||
* :param char* fallback: The fallback paths to use if the environment variable is not set.
|
||||
* :param pkgconf_list_t* dirlist: The path list to add the path nodes to.
|
||||
@ -197,11 +201,11 @@ pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter)
|
||||
* :rtype: size_t
|
||||
*/
|
||||
size_t
|
||||
pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter)
|
||||
pkgconf_path_build_from_environ(const pkgconf_client_t *client, const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter)
|
||||
{
|
||||
const char *data;
|
||||
|
||||
data = getenv(envvarname);
|
||||
data = pkgconf_client_getenv(client, envvarname);
|
||||
if (data != NULL)
|
||||
return pkgconf_path_split(data, dirlist, filter);
|
||||
|
||||
@ -267,6 +271,9 @@ pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
pkgconf_path_t *srcpath = n->data, *path;
|
||||
|
||||
path = calloc(1, sizeof(pkgconf_path_t));
|
||||
if (path == NULL)
|
||||
continue;
|
||||
|
||||
path->path = strdup(srcpath->path);
|
||||
|
||||
#ifdef PKGCONF_CACHE_INODES
|
||||
@ -278,6 +285,41 @@ pkgconf_path_copy_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_path_prepend_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
*
|
||||
* Copies a path list to another path list.
|
||||
*
|
||||
* :param pkgconf_list_t* dst: The path list to copy to.
|
||||
* :param pkgconf_list_t* src: The path list to copy from.
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_path_prepend_list(pkgconf_list_t *dst, const pkgconf_list_t *src)
|
||||
{
|
||||
pkgconf_node_t *n;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(src->head, n)
|
||||
{
|
||||
pkgconf_path_t *srcpath = n->data, *path;
|
||||
|
||||
path = calloc(1, sizeof(pkgconf_path_t));
|
||||
if (path == NULL)
|
||||
continue;
|
||||
|
||||
path->path = strdup(srcpath->path);
|
||||
|
||||
#ifdef PKGCONF_CACHE_INODES
|
||||
path->handle_path = srcpath->handle_path;
|
||||
path->handle_device = srcpath->handle_device;
|
||||
#endif
|
||||
|
||||
pkgconf_node_insert(&path->lnode, path, dst);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
@ -346,10 +388,6 @@ normpath(const char *path)
|
||||
bool
|
||||
pkgconf_path_relocate(char *buf, size_t buflen)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char *ti;
|
||||
#endif
|
||||
|
||||
char *tmpbuf;
|
||||
|
||||
if ((tmpbuf = normpath(buf)) != NULL)
|
||||
@ -367,3 +405,53 @@ pkgconf_path_relocate(char *buf, size_t buflen)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PKG_CONFIG_REG_KEY "Software\\pkgconfig\\PKG_CONFIG_PATH"
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_path_build_from_registry(HKEY hKey, pkgconf_list_t *dir_list, bool filter)
|
||||
*
|
||||
* Adds paths to a directory list discovered from a given registry key.
|
||||
*
|
||||
* :param HKEY hKey: The registry key to enumerate.
|
||||
* :param pkgconf_list_t* dir_list: The directory list to append enumerated paths to.
|
||||
* :param bool filter: Whether duplicate paths should be filtered.
|
||||
* :return: number of path nodes added to the list
|
||||
* :rtype: size_t
|
||||
*/
|
||||
size_t
|
||||
pkgconf_path_build_from_registry(void *hKey, pkgconf_list_t *dir_list, bool filter)
|
||||
{
|
||||
HKEY key;
|
||||
int i = 0;
|
||||
size_t added = 0;
|
||||
|
||||
char buf[16384]; /* per registry limits */
|
||||
DWORD bufsize = sizeof buf;
|
||||
if (RegOpenKeyEx(hKey, PKG_CONFIG_REG_KEY,
|
||||
0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
return 0;
|
||||
|
||||
while (RegEnumValue(key, i++, buf, &bufsize, NULL, NULL, NULL, NULL)
|
||||
== ERROR_SUCCESS)
|
||||
{
|
||||
char pathbuf[PKGCONF_ITEM_SIZE];
|
||||
DWORD type;
|
||||
DWORD pathbuflen = sizeof pathbuf;
|
||||
|
||||
if (RegQueryValueEx(key, buf, NULL, &type, (LPBYTE) pathbuf, &pathbuflen)
|
||||
== ERROR_SUCCESS && type == REG_SZ)
|
||||
{
|
||||
pkgconf_path_add(pathbuf, dir_list, filter);
|
||||
added++;
|
||||
}
|
||||
|
||||
bufsize = sizeof buf;
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
return added;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -24,10 +24,6 @@
|
||||
* =========================
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Increment each time the default personality is inited, decrement each time
|
||||
* it's deinited. Whenever it is 0, then the deinit frees the personality. In
|
||||
@ -37,10 +33,6 @@ static unsigned default_personality_init = 0;
|
||||
|
||||
static pkgconf_cross_personality_t default_personality = {
|
||||
.name = "default",
|
||||
#ifdef _WIN32
|
||||
.want_default_static = true,
|
||||
.want_default_pure = true,
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void
|
||||
@ -87,7 +79,7 @@ build_default_search_path(pkgconf_list_t* dirlist)
|
||||
paths = NULL;
|
||||
}
|
||||
#else
|
||||
pkgconf_path_split(PKG_DEFAULT_PATH, dirlist, true);
|
||||
pkgconf_path_split(PKG_DEFAULT_PATH, dirlist, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -125,7 +117,8 @@ pkgconf_cross_personality_default(void)
|
||||
*
|
||||
* .. c:function:: void pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *)
|
||||
*
|
||||
* Decrements the count of default cross personality instances.
|
||||
* Destroys a cross personality object and/or decreases the reference count on the
|
||||
* default cross personality object.
|
||||
*
|
||||
* Not thread safe.
|
||||
*
|
||||
@ -134,11 +127,28 @@ pkgconf_cross_personality_default(void)
|
||||
void
|
||||
pkgconf_cross_personality_deinit(pkgconf_cross_personality_t *personality)
|
||||
{
|
||||
if (--default_personality_init == 0) {
|
||||
pkgconf_path_free(&personality->dir_list);
|
||||
pkgconf_path_free(&personality->filter_libdirs);
|
||||
pkgconf_path_free(&personality->filter_includedirs);
|
||||
}
|
||||
/* allow NULL parameter for API backwards compatibility */
|
||||
if (personality == NULL)
|
||||
return;
|
||||
|
||||
/* XXX: this hack is rather ugly, but it works for now... */
|
||||
if (personality == &default_personality && --default_personality_init > 0)
|
||||
return;
|
||||
|
||||
pkgconf_path_free(&personality->dir_list);
|
||||
pkgconf_path_free(&personality->filter_libdirs);
|
||||
pkgconf_path_free(&personality->filter_includedirs);
|
||||
|
||||
if (personality->sysroot_dir != NULL)
|
||||
free(personality->sysroot_dir);
|
||||
|
||||
if (personality == &default_personality)
|
||||
return;
|
||||
|
||||
if (personality->name != NULL)
|
||||
free(personality->name);
|
||||
|
||||
free(personality);
|
||||
}
|
||||
|
||||
#ifndef PKGCONF_LITE
|
||||
@ -154,7 +164,7 @@ valid_triplet(const char *triplet)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef void (*personality_keyword_func_t)(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value);
|
||||
typedef void (*personality_keyword_func_t)(pkgconf_cross_personality_t *p, const char *keyword, const char *warnprefix, const ptrdiff_t offset, char *value);
|
||||
typedef struct {
|
||||
const char *keyword;
|
||||
const personality_keyword_func_t func;
|
||||
@ -162,30 +172,30 @@ typedef struct {
|
||||
} personality_keyword_pair_t;
|
||||
|
||||
static void
|
||||
personality_bool_func(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value)
|
||||
personality_bool_func(pkgconf_cross_personality_t *p, const char *keyword, const char *warnprefix, const ptrdiff_t offset, char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
(void) warnprefix;
|
||||
|
||||
bool *dest = (bool *)((char *) p + offset);
|
||||
*dest = strcasecmp(value, "true") || strcasecmp(value, "yes") || *value == '1';
|
||||
}
|
||||
|
||||
static void
|
||||
personality_copy_func(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value)
|
||||
personality_copy_func(pkgconf_cross_personality_t *p, const char *keyword, const char *warnprefix, const ptrdiff_t offset, char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
(void) warnprefix;
|
||||
|
||||
char **dest = (char **)((char *) p + offset);
|
||||
*dest = strdup(value);
|
||||
}
|
||||
|
||||
static void
|
||||
personality_fragment_func(pkgconf_cross_personality_t *p, const char *keyword, const size_t lineno, const ptrdiff_t offset, char *value)
|
||||
personality_fragment_func(pkgconf_cross_personality_t *p, const char *keyword, const char *warnprefix, const ptrdiff_t offset, char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
(void) warnprefix;
|
||||
|
||||
pkgconf_list_t *dest = (pkgconf_list_t *)((char *) p + offset);
|
||||
pkgconf_path_split(value, dest, false);
|
||||
@ -210,7 +220,7 @@ personality_keyword_pair_cmp(const void *key, const void *ptr)
|
||||
}
|
||||
|
||||
static void
|
||||
personality_keyword_set(pkgconf_cross_personality_t *p, const size_t lineno, const char *keyword, char *value)
|
||||
personality_keyword_set(pkgconf_cross_personality_t *p, const char *warnprefix, const char *keyword, char *value)
|
||||
{
|
||||
const personality_keyword_pair_t *pair = bsearch(keyword,
|
||||
personality_keyword_pairs, PKGCONF_ARRAY_SIZE(personality_keyword_pairs),
|
||||
@ -219,7 +229,7 @@ personality_keyword_set(pkgconf_cross_personality_t *p, const size_t lineno, con
|
||||
if (pair == NULL || pair->func == NULL)
|
||||
return;
|
||||
|
||||
pair->func(p, keyword, lineno, pair->offset, value);
|
||||
pair->func(p, keyword, warnprefix, pair->offset, value);
|
||||
}
|
||||
|
||||
static const pkgconf_parser_operand_func_t personality_parser_ops[256] = {
|
||||
@ -255,13 +265,19 @@ load_personality_with_path(const char *path, const char *triplet, bool datadir)
|
||||
else
|
||||
snprintf(pathbuf, sizeof pathbuf, "%s/%s.personality", path, triplet);
|
||||
|
||||
f = fopen(pathbuf, "r");
|
||||
if (f == NULL)
|
||||
p = calloc(1, sizeof(pkgconf_cross_personality_t));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
p = calloc(1, sizeof(pkgconf_cross_personality_t));
|
||||
if (triplet != NULL)
|
||||
p->name = strdup(triplet);
|
||||
|
||||
f = fopen(pathbuf, "r");
|
||||
if (f == NULL) {
|
||||
pkgconf_cross_personality_deinit(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkgconf_parser_parse(f, p, personality_parser_ops, personality_warn_func, pathbuf);
|
||||
|
||||
return p;
|
||||
@ -308,7 +324,7 @@ pkgconf_cross_personality_find(const char *triplet)
|
||||
}
|
||||
}
|
||||
|
||||
pkgconf_path_build_from_environ("XDG_DATA_DIRS", "/usr/local/share" PKG_CONFIG_PATH_SEP_S "/usr/share", &plist, true);
|
||||
pkgconf_path_build_from_environ(NULL, "XDG_DATA_DIRS", "/usr/local/share" PKG_CONFIG_PATH_SEP_S "/usr/share", &plist, true);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(plist.head, n)
|
||||
{
|
||||
|
||||
613
libpkgconf/pkg.c
613
libpkgconf/pkg.c
@ -27,14 +27,6 @@
|
||||
* routines.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# define PKG_CONFIG_REG_KEY "Software\\pkgconfig\\PKG_CONFIG_PATH"
|
||||
# undef PKG_DEFAULT_PATH
|
||||
# define PKG_DEFAULT_PATH "../lib/pkgconfig;../share/pkgconfig"
|
||||
# define strncasecmp _strnicmp
|
||||
# define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
#define PKG_CONFIG_EXT ".pc"
|
||||
|
||||
static unsigned int
|
||||
@ -63,6 +55,70 @@ pkg_get_parent_dir(pkgconf_pkg_t *pkg)
|
||||
char buf[PKGCONF_ITEM_SIZE], *pathbuf;
|
||||
|
||||
pkgconf_strlcpy(buf, pkg->filename, sizeof buf);
|
||||
#ifndef _WIN32
|
||||
/*
|
||||
* We want to resolve symlinks, since ${pcfiledir} should point to the
|
||||
* parent of the file symlinked to.
|
||||
*/
|
||||
struct stat path_stat;
|
||||
while (!lstat(buf, &path_stat) && S_ISLNK(path_stat.st_mode))
|
||||
{
|
||||
char sourcebuf[PKGCONF_ITEM_SIZE];
|
||||
|
||||
/*
|
||||
* Have to split the path into the dir + file components,
|
||||
* in order to extract the directory file descriptor.
|
||||
*
|
||||
* The nomenclature here uses the
|
||||
*
|
||||
* ln <source> <target>
|
||||
*
|
||||
* model.
|
||||
*/
|
||||
char basenamebuf[PKGCONF_ITEM_SIZE];
|
||||
pkgconf_strlcpy(basenamebuf, buf, sizeof(basenamebuf));
|
||||
|
||||
char dirnamebuf[PKGCONF_ITEM_SIZE];
|
||||
pkgconf_strlcpy(dirnamebuf, buf, sizeof(dirnamebuf));
|
||||
const char* targetdir = dirname(dirnamebuf);
|
||||
|
||||
#ifdef HAVE_DECL_READLINKAT
|
||||
const char* targetfilename = basename(basenamebuf);
|
||||
const int dirfd = open(targetdir, O_DIRECTORY);
|
||||
if (dirfd == -1)
|
||||
break;
|
||||
|
||||
ssize_t len = readlinkat(dirfd, targetfilename, sourcebuf, sizeof(sourcebuf) - 1);
|
||||
close(dirfd);
|
||||
#else
|
||||
ssize_t len = readlink(buf, sourcebuf, sizeof(sourcebuf) - 1);
|
||||
#endif
|
||||
|
||||
if (len == -1)
|
||||
break;
|
||||
sourcebuf[len] = '\0';
|
||||
|
||||
memset(buf, '\0', sizeof buf);
|
||||
/*
|
||||
* The logic here can be a bit tricky, so here's a table:
|
||||
*
|
||||
* <source> | <target> | result
|
||||
* -----------------------------------------------------------------------
|
||||
* /bar (absolute) | foo/link (relative) | /bar (absolute)
|
||||
* ../bar (relative) | foo/link (relative) | foo/../bar (relative)
|
||||
* /bar (absolute) | /foo/link (absolute) | /bar (absolute)
|
||||
* ../bar (relative) | /foo/link (absolute) | /foo/../bar (relative)
|
||||
*/
|
||||
if ((sourcebuf[0] != '/') /* absolute path in <source> wins */
|
||||
&& (strcmp(targetdir, "."))) /* do not prepend "." */
|
||||
{
|
||||
pkgconf_strlcat(buf, targetdir, sizeof buf);
|
||||
pkgconf_strlcat(buf, "/", sizeof buf);
|
||||
}
|
||||
pkgconf_strlcat(buf, sourcebuf, sizeof buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
pathbuf = strrchr(buf, PKG_DIR_SEP_S);
|
||||
if (pathbuf == NULL)
|
||||
pathbuf = strrchr(buf, '/');
|
||||
@ -72,7 +128,7 @@ pkg_get_parent_dir(pkgconf_pkg_t *pkg)
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
typedef void (*pkgconf_pkg_parser_keyword_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value);
|
||||
typedef void (*pkgconf_pkg_parser_keyword_func_t)(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const char *warnprefix, const ptrdiff_t offset, const char *value);
|
||||
typedef struct {
|
||||
const char *keyword;
|
||||
const pkgconf_pkg_parser_keyword_func_t func;
|
||||
@ -86,20 +142,19 @@ static int pkgconf_pkg_parser_keyword_pair_cmp(const void *key, const void *ptr)
|
||||
}
|
||||
|
||||
static void
|
||||
pkgconf_pkg_parser_tuple_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
|
||||
pkgconf_pkg_parser_tuple_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const char *warnprefix, const ptrdiff_t offset, const char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
(void) warnprefix;
|
||||
|
||||
char **dest = (char **)((char *) pkg + offset);
|
||||
*dest = pkgconf_tuple_parse(client, &pkg->vars, value, pkg->flags);
|
||||
}
|
||||
|
||||
static void
|
||||
pkgconf_pkg_parser_version_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
|
||||
pkgconf_pkg_parser_version_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const char *warnprefix, const ptrdiff_t offset, const char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
char *p, *i;
|
||||
size_t len;
|
||||
char **dest = (char **)((char *) pkg + offset);
|
||||
@ -113,55 +168,75 @@ pkgconf_pkg_parser_version_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, co
|
||||
i = p + (ptrdiff_t) len;
|
||||
*i = '\0';
|
||||
|
||||
pkgconf_warn(client, "%s:" SIZE_FMT_SPECIFIER ": warning: malformed version field with whitespace, trimming to [%s]\n", pkg->filename,
|
||||
lineno, p);
|
||||
pkgconf_warn(client, "%s: warning: malformed version field with whitespace, trimming to [%s]\n",
|
||||
warnprefix, p);
|
||||
}
|
||||
|
||||
*dest = p;
|
||||
}
|
||||
|
||||
static void
|
||||
pkgconf_pkg_parser_fragment_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
|
||||
pkgconf_pkg_parser_fragment_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const char *warnprefix, const ptrdiff_t offset, const char *value)
|
||||
{
|
||||
pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset);
|
||||
|
||||
/* we patch client-wide sysroot dir and then patch it back when it is overridden */
|
||||
char *sysroot_dir = client->sysroot_dir;
|
||||
char *pkg_sysroot_dir = pkgconf_tuple_find(client, &pkg->vars, "pc_sysrootdir");
|
||||
if (pkg_sysroot_dir != NULL)
|
||||
client->sysroot_dir = pkg_sysroot_dir;
|
||||
|
||||
bool ret = pkgconf_fragment_parse(client, dest, &pkg->vars, value, pkg->flags);
|
||||
client->sysroot_dir = sysroot_dir;
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
pkgconf_warn(client, "%s:" SIZE_FMT_SPECIFIER ": warning: unable to parse field '%s' into an argument vector, value [%s]\n", pkg->filename,
|
||||
lineno, keyword, value);
|
||||
pkgconf_warn(client, "%s: warning: unable to parse field '%s' into an argument vector, value [%s]\n",
|
||||
warnprefix, keyword, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pkgconf_pkg_parser_dependency_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
|
||||
pkgconf_pkg_parser_dependency_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const char *warnprefix, const ptrdiff_t offset, const char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
|
||||
pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset);
|
||||
|
||||
if (dest->tail != NULL)
|
||||
{
|
||||
pkgconf_warn(client, "%s: warning: merging duplicate field '%s' (undefined behavior)\n",
|
||||
warnprefix, keyword);
|
||||
}
|
||||
|
||||
pkgconf_dependency_parse(client, pkg, dest, value, 0);
|
||||
}
|
||||
|
||||
/* a variant of pkgconf_pkg_parser_dependency_func which colors the dependency node as an "internal" dependency. */
|
||||
static void
|
||||
pkgconf_pkg_parser_internal_dependency_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
|
||||
pkgconf_pkg_parser_internal_dependency_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const char *warnprefix, const ptrdiff_t offset, const char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
|
||||
pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset);
|
||||
|
||||
if (dest->tail != NULL)
|
||||
{
|
||||
pkgconf_warn(client, "%s: warning: merging duplicate field '%s' (undefined behavior)\n",
|
||||
warnprefix, keyword);
|
||||
}
|
||||
|
||||
pkgconf_dependency_parse(client, pkg, dest, value, PKGCONF_PKG_DEPF_INTERNAL);
|
||||
}
|
||||
|
||||
/* a variant of pkgconf_pkg_parser_dependency_func which colors the dependency node as a "private" dependency. */
|
||||
static void
|
||||
pkgconf_pkg_parser_private_dependency_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const size_t lineno, const ptrdiff_t offset, const char *value)
|
||||
pkgconf_pkg_parser_private_dependency_func(pkgconf_client_t *client, pkgconf_pkg_t *pkg, const char *keyword, const char *warnprefix, const ptrdiff_t offset, const char *value)
|
||||
{
|
||||
(void) keyword;
|
||||
(void) lineno;
|
||||
|
||||
pkgconf_list_t *dest = (pkgconf_list_t *)((char *) pkg + offset);
|
||||
|
||||
if (dest->tail != NULL)
|
||||
{
|
||||
pkgconf_warn(client, "%s: warning: merging duplicate field '%s' (undefined behavior)\n",
|
||||
warnprefix, keyword);
|
||||
}
|
||||
|
||||
pkgconf_dependency_parse(client, pkg, dest, value, PKGCONF_PKG_DEPF_PRIVATE);
|
||||
}
|
||||
|
||||
@ -175,18 +250,20 @@ static const pkgconf_pkg_parser_keyword_pair_t pkgconf_pkg_parser_keyword_funcs[
|
||||
{"LIBS", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, libs)},
|
||||
{"LIBS.private", pkgconf_pkg_parser_fragment_func, offsetof(pkgconf_pkg_t, libs_private)},
|
||||
{"License", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, license)},
|
||||
{"License.file", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, license_file)},
|
||||
{"Maintainer", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, maintainer)},
|
||||
{"Name", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, realname)},
|
||||
{"Provides", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, provides)},
|
||||
{"Requires", pkgconf_pkg_parser_dependency_func, offsetof(pkgconf_pkg_t, required)},
|
||||
{"Requires.internal", pkgconf_pkg_parser_internal_dependency_func, offsetof(pkgconf_pkg_t, requires_private)},
|
||||
{"Requires.private", pkgconf_pkg_parser_private_dependency_func, offsetof(pkgconf_pkg_t, requires_private)},
|
||||
{"Source", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, source)},
|
||||
{"URL", pkgconf_pkg_parser_tuple_func, offsetof(pkgconf_pkg_t, url)},
|
||||
{"Version", pkgconf_pkg_parser_version_func, offsetof(pkgconf_pkg_t, version)},
|
||||
};
|
||||
|
||||
static void
|
||||
pkgconf_pkg_parser_keyword_set(void *opaque, const size_t lineno, const char *keyword, const char *value)
|
||||
pkgconf_pkg_parser_keyword_set(void *opaque, const char *warnprefix, const char *keyword, const char *value)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = opaque;
|
||||
|
||||
@ -197,7 +274,7 @@ pkgconf_pkg_parser_keyword_set(void *opaque, const size_t lineno, const char *ke
|
||||
if (pair == NULL || pair->func == NULL)
|
||||
return;
|
||||
|
||||
pair->func(pkg->owner, pkg, keyword, lineno, pair->offset, value);
|
||||
pair->func(pkg->owner, pkg, keyword, warnprefix, pair->offset, value);
|
||||
}
|
||||
|
||||
static const char *
|
||||
@ -251,6 +328,9 @@ static char *
|
||||
convert_path_to_value(const char *path)
|
||||
{
|
||||
char *buf = calloc(1, (strlen(path) + 1) * 2);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
char *bptr = buf;
|
||||
const char *i;
|
||||
|
||||
@ -305,13 +385,40 @@ is_path_prefix_equal(const char *path1, const char *path2, size_t path2_len)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
lookup_val_from_env(const pkgconf_client_t *client, const char *pkg_id, const char *keyword)
|
||||
{
|
||||
char env_var[PKGCONF_ITEM_SIZE];
|
||||
char *c;
|
||||
|
||||
snprintf(env_var, sizeof env_var, "PKG_CONFIG_%s_%s", pkg_id, keyword);
|
||||
|
||||
for (c = env_var; *c; c++)
|
||||
{
|
||||
*c = toupper((unsigned char) *c);
|
||||
|
||||
if (!isalnum((unsigned char) *c))
|
||||
*c = '_';
|
||||
}
|
||||
|
||||
return pkgconf_client_getenv(client, env_var);
|
||||
}
|
||||
|
||||
static void
|
||||
pkgconf_pkg_parser_value_set(void *opaque, const size_t lineno, const char *keyword, const char *value)
|
||||
pkgconf_pkg_parser_value_set(void *opaque, const char *warnprefix, const char *keyword, const char *value)
|
||||
{
|
||||
char canonicalized_value[PKGCONF_ITEM_SIZE];
|
||||
pkgconf_pkg_t *pkg = opaque;
|
||||
const char *env_content;
|
||||
|
||||
(void) lineno;
|
||||
(void) warnprefix;
|
||||
|
||||
env_content = lookup_val_from_env(pkg->owner, pkg->id, keyword);
|
||||
if (env_content != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(pkg->owner, "overriding %s from environment", keyword);
|
||||
value = env_content;
|
||||
}
|
||||
|
||||
pkgconf_strlcpy(canonicalized_value, value, sizeof canonicalized_value);
|
||||
canonicalize_path(canonicalized_value);
|
||||
@ -399,10 +506,74 @@ pkgconf_pkg_validate(const pkgconf_client_t *client, const pkgconf_pkg_t *pkg)
|
||||
return valid;
|
||||
}
|
||||
|
||||
static void
|
||||
pkg_free_object(pkgconf_pkg_t *pkg)
|
||||
{
|
||||
if (pkg->flags & PKGCONF_PKG_PROPF_PRELOADED)
|
||||
pkgconf_node_delete(&pkg->preload_node, &pkg->owner->preloaded_pkgs);
|
||||
|
||||
if (pkg->id != NULL)
|
||||
free(pkg->id);
|
||||
|
||||
if (pkg->filename != NULL)
|
||||
free(pkg->filename);
|
||||
|
||||
if (pkg->realname != NULL)
|
||||
free(pkg->realname);
|
||||
|
||||
if (pkg->version != NULL)
|
||||
free(pkg->version);
|
||||
|
||||
if (pkg->description != NULL)
|
||||
free(pkg->description);
|
||||
|
||||
if (pkg->url != NULL)
|
||||
free(pkg->url);
|
||||
|
||||
if (pkg->pc_filedir != NULL)
|
||||
free(pkg->pc_filedir);
|
||||
|
||||
if (pkg->license != NULL)
|
||||
free(pkg->license);
|
||||
|
||||
if (pkg->license_file != NULL)
|
||||
free(pkg->license_file);
|
||||
|
||||
if (pkg->maintainer != NULL)
|
||||
free(pkg->maintainer);
|
||||
|
||||
if (pkg->copyright != NULL)
|
||||
free(pkg->copyright);
|
||||
|
||||
if (pkg->why != NULL)
|
||||
free(pkg->why);
|
||||
|
||||
if (pkg->source != NULL)
|
||||
free(pkg->source);
|
||||
|
||||
free(pkg);
|
||||
}
|
||||
|
||||
static void
|
||||
pkg_free_lists(pkgconf_pkg_t *pkg)
|
||||
{
|
||||
pkgconf_dependency_free(&pkg->required);
|
||||
pkgconf_dependency_free(&pkg->requires_private);
|
||||
pkgconf_dependency_free(&pkg->conflicts);
|
||||
pkgconf_dependency_free(&pkg->provides);
|
||||
|
||||
pkgconf_fragment_free(&pkg->cflags);
|
||||
pkgconf_fragment_free(&pkg->cflags_private);
|
||||
pkgconf_fragment_free(&pkg->libs);
|
||||
pkgconf_fragment_free(&pkg->libs_private);
|
||||
|
||||
pkgconf_tuple_free(&pkg->vars);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_pkg_t *pkgconf_pkg_new_from_file(const pkgconf_client_t *client, const char *filename, FILE *f, unsigned int flags)
|
||||
* .. c:function:: pkgconf_pkg_t *pkgconf_pkg_new_from_path(const pkgconf_client_t *client, const char *filename, unsigned int flags)
|
||||
*
|
||||
* Parse a .pc file into a pkgconf_pkg_t object structure.
|
||||
*
|
||||
@ -414,17 +585,46 @@ pkgconf_pkg_validate(const pkgconf_client_t *client, const pkgconf_pkg_t *pkg)
|
||||
* :rtype: pkgconf_pkg_t *
|
||||
*/
|
||||
pkgconf_pkg_t *
|
||||
pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *f, unsigned int flags)
|
||||
pkgconf_pkg_new_from_path(pkgconf_client_t *client, const char *filename, unsigned int flags)
|
||||
{
|
||||
pkgconf_pkg_t *pkg;
|
||||
char *idptr;
|
||||
FILE *f;
|
||||
|
||||
/* make sure we only load .pc files */
|
||||
if (!str_has_suffix(filename, PKG_CONFIG_EXT))
|
||||
return NULL;
|
||||
|
||||
f = fopen(filename, "r");
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
||||
pkg = calloc(1, sizeof(pkgconf_pkg_t));
|
||||
if (pkg == NULL)
|
||||
{
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkg->owner = client;
|
||||
pkg->filename = strdup(filename);
|
||||
pkg->pc_filedir = pkg_get_parent_dir(pkg);
|
||||
pkg->flags = flags;
|
||||
|
||||
pkg->filename = strdup(filename);
|
||||
if (pkg->filename == NULL)
|
||||
{
|
||||
fclose(f);
|
||||
pkg_free_object(pkg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkg->pc_filedir = pkg_get_parent_dir(pkg);
|
||||
if (pkg->pc_filedir == NULL)
|
||||
{
|
||||
fclose(f);
|
||||
pkg_free_object(pkg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *pc_filedir_value = convert_path_to_value(pkg->pc_filedir);
|
||||
pkgconf_tuple_add(client, &pkg->vars, "pcfiledir", pc_filedir_value, true, pkg->flags);
|
||||
free(pc_filedir_value);
|
||||
@ -433,7 +633,8 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
|
||||
* package.
|
||||
* See https://github.com/pkgconf/pkgconf/issues/213
|
||||
*/
|
||||
if (client->sysroot_dir && strncmp(pkg->pc_filedir, client->sysroot_dir, strlen(client->sysroot_dir)))
|
||||
if (client->sysroot_dir != NULL && strncmp(pkg->pc_filedir, client->sysroot_dir, strlen(client->sysroot_dir)) &&
|
||||
!(client->flags & PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES))
|
||||
pkgconf_tuple_add(client, &pkg->vars, "pc_sysrootdir", "", false, pkg->flags);
|
||||
|
||||
/* make module id */
|
||||
@ -453,6 +654,14 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
|
||||
#endif
|
||||
|
||||
pkg->id = strdup(idptr);
|
||||
if (pkg->id == NULL)
|
||||
{
|
||||
fclose(f);
|
||||
pkg_free_lists(pkg);
|
||||
pkg_free_object(pkg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idptr = strrchr(pkg->id, '.');
|
||||
if (idptr)
|
||||
*idptr = '\0';
|
||||
@ -465,6 +674,7 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
|
||||
}
|
||||
|
||||
pkgconf_parser_parse(f, pkg, pkg_parser_funcs, (pkgconf_parser_warn_func_t) pkg_warn_func, pkg->filename);
|
||||
fclose(f);
|
||||
|
||||
if (!pkgconf_pkg_validate(client, pkg))
|
||||
{
|
||||
@ -501,55 +711,12 @@ pkgconf_pkg_free(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
|
||||
pkgconf_cache_remove(client, pkg);
|
||||
|
||||
pkgconf_dependency_free(&pkg->required);
|
||||
pkgconf_dependency_free(&pkg->requires_private);
|
||||
pkgconf_dependency_free(&pkg->conflicts);
|
||||
pkgconf_dependency_free(&pkg->provides);
|
||||
|
||||
pkgconf_fragment_free(&pkg->cflags);
|
||||
pkgconf_fragment_free(&pkg->cflags_private);
|
||||
pkgconf_fragment_free(&pkg->libs);
|
||||
pkgconf_fragment_free(&pkg->libs_private);
|
||||
|
||||
pkgconf_tuple_free(&pkg->vars);
|
||||
pkg_free_lists(pkg);
|
||||
|
||||
if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL)
|
||||
return;
|
||||
|
||||
if (pkg->id != NULL)
|
||||
free(pkg->id);
|
||||
|
||||
if (pkg->filename != NULL)
|
||||
free(pkg->filename);
|
||||
|
||||
if (pkg->realname != NULL)
|
||||
free(pkg->realname);
|
||||
|
||||
if (pkg->version != NULL)
|
||||
free(pkg->version);
|
||||
|
||||
if (pkg->description != NULL)
|
||||
free(pkg->description);
|
||||
|
||||
if (pkg->url != NULL)
|
||||
free(pkg->url);
|
||||
|
||||
if (pkg->pc_filedir != NULL)
|
||||
free(pkg->pc_filedir);
|
||||
|
||||
if (pkg->license != NULL)
|
||||
free(pkg->license);
|
||||
|
||||
if (pkg->maintainer != NULL)
|
||||
free(pkg->maintainer);
|
||||
|
||||
if (pkg->copyright != NULL)
|
||||
free(pkg->copyright);
|
||||
|
||||
if (pkg->why != NULL)
|
||||
free(pkg->why);
|
||||
|
||||
free(pkg);
|
||||
pkg_free_object(pkg);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -590,6 +757,11 @@ pkgconf_pkg_ref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
void
|
||||
pkgconf_pkg_unref(pkgconf_client_t *client, pkgconf_pkg_t *pkg)
|
||||
{
|
||||
if (pkg == NULL) {
|
||||
PKGCONF_TRACE(client, "WTF: client %p unrefs a NULL package", client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pkg->owner != NULL && pkg->owner != client)
|
||||
PKGCONF_TRACE(client, "WTF: client %p unrefs package %p owned by other client %p", client, pkg, pkg->owner);
|
||||
|
||||
@ -604,7 +776,6 @@ static inline pkgconf_pkg_t *
|
||||
pkgconf_pkg_try_specific_path(pkgconf_client_t *client, const char *path, const char *name)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = NULL;
|
||||
FILE *f;
|
||||
char locbuf[PKGCONF_ITEM_SIZE];
|
||||
char uninst_locbuf[PKGCONF_ITEM_SIZE];
|
||||
|
||||
@ -613,16 +784,14 @@ pkgconf_pkg_try_specific_path(pkgconf_client_t *client, const char *path, const
|
||||
snprintf(locbuf, sizeof locbuf, "%s%c%s" PKG_CONFIG_EXT, path, PKG_DIR_SEP_S, name);
|
||||
snprintf(uninst_locbuf, sizeof uninst_locbuf, "%s%c%s-uninstalled" PKG_CONFIG_EXT, path, PKG_DIR_SEP_S, name);
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_NO_UNINSTALLED) && (f = fopen(uninst_locbuf, "r")) != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "found (uninstalled): %s", uninst_locbuf);
|
||||
pkg = pkgconf_pkg_new_from_file(client, uninst_locbuf, f, PKGCONF_PKG_PROPF_UNINSTALLED);
|
||||
}
|
||||
else if ((f = fopen(locbuf, "r")) != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "found: %s", locbuf);
|
||||
pkg = pkgconf_pkg_new_from_file(client, locbuf, f, 0);
|
||||
}
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_NO_UNINSTALLED))
|
||||
pkg = pkgconf_pkg_new_from_path(client, uninst_locbuf, PKGCONF_PKG_PROPF_UNINSTALLED);
|
||||
|
||||
if (pkg == NULL)
|
||||
pkg = pkgconf_pkg_new_from_path(client, locbuf, 0);
|
||||
|
||||
if (pkg != NULL)
|
||||
PKGCONF_TRACE(client, "found%s: %s", pkg->flags & PKGCONF_PKG_PROPF_UNINSTALLED ? " (uninstalled)" : "", uninst_locbuf);
|
||||
|
||||
return pkg;
|
||||
}
|
||||
@ -644,7 +813,6 @@ pkgconf_pkg_scan_dir(pkgconf_client_t *client, const char *path, void *data, pkg
|
||||
{
|
||||
char filebuf[PKGCONF_ITEM_SIZE];
|
||||
pkgconf_pkg_t *pkg;
|
||||
FILE *f;
|
||||
|
||||
pkgconf_strlcpy(filebuf, path, sizeof filebuf);
|
||||
pkgconf_strlcat(filebuf, "/", sizeof filebuf);
|
||||
@ -655,11 +823,7 @@ pkgconf_pkg_scan_dir(pkgconf_client_t *client, const char *path, void *data, pkg
|
||||
|
||||
PKGCONF_TRACE(client, "trying file [%s]", filebuf);
|
||||
|
||||
f = fopen(filebuf, "r");
|
||||
if (f == NULL)
|
||||
continue;
|
||||
|
||||
pkg = pkgconf_pkg_new_from_file(client, filebuf, f, 0);
|
||||
pkg = pkgconf_pkg_new_from_path(client, filebuf, 0);
|
||||
if (pkg != NULL)
|
||||
{
|
||||
if (func(pkg, data))
|
||||
@ -698,6 +862,22 @@ pkgconf_scan_all(pkgconf_client_t *client, void *data, pkgconf_pkg_iteration_fun
|
||||
pkgconf_node_t *n;
|
||||
pkgconf_pkg_t *pkg;
|
||||
|
||||
PKGCONF_TRACE(client, "scanning preloaded list");
|
||||
PKGCONF_FOREACH_LIST_ENTRY(client->preloaded_pkgs.head, n)
|
||||
{
|
||||
pkg = n->data;
|
||||
|
||||
/* add an additional reference to ensure preloaded packages have the same
|
||||
* object ownership semantics as non-preloaded packages
|
||||
*/
|
||||
pkgconf_pkg_ref(client, pkg);
|
||||
|
||||
if (func(pkg, data))
|
||||
return pkg;
|
||||
|
||||
pkgconf_pkg_unref(client, pkg);
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n)
|
||||
{
|
||||
pkgconf_path_t *pnode = n->data;
|
||||
@ -711,43 +891,24 @@ pkgconf_scan_all(pkgconf_client_t *client, void *data, pkgconf_pkg_iteration_fun
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static pkgconf_pkg_t *
|
||||
pkgconf_pkg_find_in_registry_key(pkgconf_client_t *client, HKEY hkey, const char *name)
|
||||
search_preload_list(pkgconf_client_t *client, const char *name)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = NULL;
|
||||
pkgconf_node_t *n;
|
||||
|
||||
HKEY key;
|
||||
int i = 0;
|
||||
|
||||
char buf[16384]; /* per registry limits */
|
||||
DWORD bufsize = sizeof buf;
|
||||
if (RegOpenKeyEx(hkey, PKG_CONFIG_REG_KEY,
|
||||
0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
while (RegEnumValue(key, i++, buf, &bufsize, NULL, NULL, NULL, NULL)
|
||||
== ERROR_SUCCESS)
|
||||
PKGCONF_FOREACH_LIST_ENTRY(client->preloaded_pkgs.head, n)
|
||||
{
|
||||
char pathbuf[PKGCONF_ITEM_SIZE];
|
||||
DWORD type;
|
||||
DWORD pathbuflen = sizeof pathbuf;
|
||||
pkgconf_pkg_t *pkg = n->data;
|
||||
|
||||
if (RegQueryValueEx(key, buf, NULL, &type, (LPBYTE) pathbuf, &pathbuflen)
|
||||
== ERROR_SUCCESS && type == REG_SZ)
|
||||
if (!strcmp(pkg->id, name))
|
||||
{
|
||||
pkg = pkgconf_pkg_try_specific_path(client, pathbuf, name);
|
||||
if (pkg != NULL)
|
||||
break;
|
||||
pkgconf_pkg_ref(client, pkg);
|
||||
return pkg;
|
||||
}
|
||||
|
||||
bufsize = sizeof buf;
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
return pkg;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* !doc
|
||||
@ -766,31 +927,26 @@ pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
|
||||
{
|
||||
pkgconf_pkg_t *pkg = NULL;
|
||||
pkgconf_node_t *n;
|
||||
FILE *f;
|
||||
|
||||
PKGCONF_TRACE(client, "looking for: %s", name);
|
||||
|
||||
/* name might actually be a filename. */
|
||||
if (str_has_suffix(name, PKG_CONFIG_EXT))
|
||||
{
|
||||
if ((f = fopen(name, "r")) != NULL)
|
||||
if (client->unveil_handler != NULL)
|
||||
client->unveil_handler(client, name, "r");
|
||||
|
||||
pkg = pkgconf_pkg_new_from_path(client, name, 0);
|
||||
if (pkg != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "%s is a file", name);
|
||||
|
||||
pkg = pkgconf_pkg_new_from_file(client, name, f, 0);
|
||||
if (pkg != NULL)
|
||||
{
|
||||
pkgconf_path_add(pkg->pc_filedir, &client->dir_list, true);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (client->unveil_handler != NULL)
|
||||
client->unveil_handler(client, pkg->pc_filedir, "r");
|
||||
|
||||
/* check builtins */
|
||||
if ((pkg = pkgconf_builtin_pkg_get(name)) != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "%s is a builtin", name);
|
||||
return pkg;
|
||||
pkgconf_path_add(pkg->pc_filedir, &client->dir_list, true);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* check cache */
|
||||
@ -803,6 +959,13 @@ pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
/* check preload list */
|
||||
if ((pkg = search_preload_list(client, name)) != NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "%s is preloaded", name);
|
||||
return pkg;
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(client->dir_list.head, n)
|
||||
{
|
||||
pkgconf_path_t *pnode = n->data;
|
||||
@ -812,13 +975,6 @@ pkgconf_pkg_find(pkgconf_client_t *client, const char *name)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* support getting PKG_CONFIG_PATH from registry */
|
||||
pkg = pkgconf_pkg_find_in_registry_key(client, HKEY_CURRENT_USER, name);
|
||||
if (!pkg)
|
||||
pkg = pkgconf_pkg_find_in_registry_key(client, HKEY_LOCAL_MACHINE, name);
|
||||
#endif
|
||||
|
||||
out:
|
||||
pkgconf_cache_add(client, pkg);
|
||||
|
||||
@ -960,105 +1116,6 @@ pkgconf_compare_version(const char *a, const char *b)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static pkgconf_pkg_t pkg_config_virtual = {
|
||||
.id = "pkg-config",
|
||||
.realname = "pkg-config",
|
||||
.description = "virtual package defining pkg-config API version supported",
|
||||
.url = PACKAGE_BUGREPORT,
|
||||
.version = PACKAGE_VERSION,
|
||||
.flags = PKGCONF_PKG_PROPF_STATIC,
|
||||
.vars = {
|
||||
.head = &(pkgconf_node_t){
|
||||
.next = &(pkgconf_node_t){
|
||||
.next = &(pkgconf_node_t){
|
||||
.data = &(pkgconf_tuple_t){
|
||||
.key = "pc_system_libdirs",
|
||||
.value = SYSTEM_LIBDIR,
|
||||
}
|
||||
},
|
||||
.data = &(pkgconf_tuple_t){
|
||||
.key = "pc_system_includedirs",
|
||||
.value = SYSTEM_INCLUDEDIR,
|
||||
}
|
||||
},
|
||||
.data = &(pkgconf_tuple_t){
|
||||
.key = "pc_path",
|
||||
.value = PKG_DEFAULT_PATH,
|
||||
},
|
||||
},
|
||||
.tail = NULL,
|
||||
}
|
||||
};
|
||||
|
||||
static pkgconf_pkg_t pkgconf_virtual = {
|
||||
.id = "pkgconf",
|
||||
.realname = "pkgconf",
|
||||
.description = "virtual package defining pkgconf API version supported",
|
||||
.url = PACKAGE_BUGREPORT,
|
||||
.version = PACKAGE_VERSION,
|
||||
.license = "ISC",
|
||||
.flags = PKGCONF_PKG_PROPF_STATIC,
|
||||
.vars = {
|
||||
.head = &(pkgconf_node_t){
|
||||
.next = &(pkgconf_node_t){
|
||||
.next = &(pkgconf_node_t){
|
||||
.data = &(pkgconf_tuple_t){
|
||||
.key = "pc_system_libdirs",
|
||||
.value = SYSTEM_LIBDIR,
|
||||
}
|
||||
},
|
||||
.data = &(pkgconf_tuple_t){
|
||||
.key = "pc_system_includedirs",
|
||||
.value = SYSTEM_INCLUDEDIR,
|
||||
}
|
||||
},
|
||||
.data = &(pkgconf_tuple_t){
|
||||
.key = "pc_path",
|
||||
.value = PKG_DEFAULT_PATH,
|
||||
},
|
||||
},
|
||||
.tail = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
pkgconf_pkg_t *pkg;
|
||||
} pkgconf_builtin_pkg_pair_t;
|
||||
|
||||
/* keep these in alphabetical order */
|
||||
static const pkgconf_builtin_pkg_pair_t pkgconf_builtin_pkg_pair_set[] = {
|
||||
{"pkg-config", &pkg_config_virtual},
|
||||
{"pkgconf", &pkgconf_virtual},
|
||||
};
|
||||
|
||||
static int pkgconf_builtin_pkg_pair_cmp(const void *key, const void *ptr)
|
||||
{
|
||||
const pkgconf_builtin_pkg_pair_t *pair = ptr;
|
||||
return strcasecmp(key, pair->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: pkgconf_pkg_t *pkgconf_builtin_pkg_get(const char *name)
|
||||
*
|
||||
* Looks up a built-in package. The package should not be freed or dereferenced.
|
||||
*
|
||||
* :param char* name: An atom corresponding to a built-in package to search for.
|
||||
* :return: the built-in package if present, else ``NULL``.
|
||||
* :rtype: pkgconf_pkg_t *
|
||||
*/
|
||||
pkgconf_pkg_t *
|
||||
pkgconf_builtin_pkg_get(const char *name)
|
||||
{
|
||||
const pkgconf_builtin_pkg_pair_t *pair = bsearch(name, pkgconf_builtin_pkg_pair_set,
|
||||
PKGCONF_ARRAY_SIZE(pkgconf_builtin_pkg_pair_set), sizeof(pkgconf_builtin_pkg_pair_t),
|
||||
pkgconf_builtin_pkg_pair_cmp);
|
||||
|
||||
return (pair != NULL) ? pair->pkg : NULL;
|
||||
}
|
||||
|
||||
typedef bool (*pkgconf_vercmp_res_func_t)(const char *a, const char *b);
|
||||
|
||||
typedef struct {
|
||||
@ -1196,7 +1253,7 @@ static const pkgconf_pkg_provides_vermatch_rule_t pkgconf_pkg_provides_vermatch_
|
||||
},
|
||||
.depcmp = {
|
||||
[PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
|
||||
},
|
||||
},
|
||||
},
|
||||
[PKGCONF_CMP_LESS_THAN] = {
|
||||
.rulecmp = {
|
||||
@ -1270,7 +1327,7 @@ static const pkgconf_pkg_provides_vermatch_rule_t pkgconf_pkg_provides_vermatch_
|
||||
},
|
||||
.depcmp = {
|
||||
[PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
|
||||
},
|
||||
},
|
||||
},
|
||||
[PKGCONF_CMP_NOT_EQUAL] = {
|
||||
.rulecmp = {
|
||||
@ -1284,7 +1341,7 @@ static const pkgconf_pkg_provides_vermatch_rule_t pkgconf_pkg_provides_vermatch_
|
||||
},
|
||||
.depcmp = {
|
||||
[PKGCONF_CMP_ANY] = pkgconf_pkg_comparator_none,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -1446,7 +1503,7 @@ pkgconf_pkg_report_graph_error(pkgconf_client_t *client, pkgconf_pkg_t *parent,
|
||||
{
|
||||
if (eflags & PKGCONF_PKG_ERRF_PACKAGE_NOT_FOUND)
|
||||
{
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS) & !client->already_sent_notice)
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS) && !client->already_sent_notice)
|
||||
{
|
||||
pkgconf_error(client, "Package %s was not found in the pkg-config search path.\n", node->package);
|
||||
pkgconf_error(client, "Perhaps you should add the directory containing `%s.pc'\n", node->package);
|
||||
@ -1477,6 +1534,18 @@ pkgconf_pkg_report_graph_error(pkgconf_client_t *client, pkgconf_pkg_t *parent,
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
missing_node_is_tolerable(const pkgconf_client_t *client, const pkgconf_dependency_t *dep)
|
||||
{
|
||||
if (!(dep->flags & PKGCONF_PKG_DEPF_INTERNAL))
|
||||
return false;
|
||||
|
||||
if ((client->flags & PKGCONF_PKG_PKGF_REQUIRE_INTERNAL))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
pkgconf_pkg_walk_list(pkgconf_client_t *client,
|
||||
pkgconf_pkg_t *parent,
|
||||
@ -1501,15 +1570,17 @@ pkgconf_pkg_walk_list(pkgconf_client_t *client,
|
||||
continue;
|
||||
|
||||
pkgdep = pkgconf_pkg_verify_dependency(client, depnode, &eflags_local);
|
||||
|
||||
eflags |= eflags_local;
|
||||
if (eflags_local != PKGCONF_PKG_ERRF_OK && !(client->flags & PKGCONF_PKG_PKGF_SKIP_ERRORS))
|
||||
if (eflags_local != PKGCONF_PKG_ERRF_OK)
|
||||
{
|
||||
pkgconf_pkg_report_graph_error(client, parent, pkgdep, depnode, eflags_local);
|
||||
if (missing_node_is_tolerable(client, depnode))
|
||||
continue;
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_ERRORS))
|
||||
pkgconf_pkg_report_graph_error(client, parent, pkgdep, depnode, eflags_local);
|
||||
|
||||
eflags |= eflags_local;
|
||||
continue;
|
||||
}
|
||||
if (pkgdep == NULL)
|
||||
continue;
|
||||
|
||||
if((pkgdep->flags & PKGCONF_PKG_PROPF_ANCESTOR) != 0)
|
||||
{
|
||||
@ -1550,7 +1621,7 @@ next:
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
unsigned int
|
||||
pkgconf_pkg_walk_conflicts_list(pkgconf_client_t *client,
|
||||
pkgconf_pkg_t *root, pkgconf_list_t *deplist)
|
||||
{
|
||||
@ -1576,7 +1647,7 @@ pkgconf_pkg_walk_conflicts_list(pkgconf_client_t *client,
|
||||
if (eflags == PKGCONF_PKG_ERRF_OK)
|
||||
{
|
||||
pkgconf_error(client, "Version '%s' of '%s' conflicts with '%s' due to satisfying conflict rule '%s %s%s%s'.\n",
|
||||
pkgdep->version, pkgdep->realname, root->realname, parentnode->package, pkgconf_pkg_get_comparator(parentnode),
|
||||
pkgdep->version, pkgdep->id, parentnode->why, parentnode->package, pkgconf_pkg_get_comparator(parentnode),
|
||||
parentnode->version != NULL ? " " : "", parentnode->version != NULL ? parentnode->version : "");
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_SIMPLIFY_ERRORS))
|
||||
@ -1658,18 +1729,15 @@ pkgconf_pkg_traverse_main(pkgconf_client_t *client,
|
||||
if (eflags != PKGCONF_PKG_ERRF_OK)
|
||||
return eflags;
|
||||
|
||||
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
|
||||
{
|
||||
PKGCONF_TRACE(client, "%s: walking 'Requires.private' list", root->id);
|
||||
PKGCONF_TRACE(client, "%s: walking 'Requires.private' list", root->id);
|
||||
|
||||
/* XXX: ugly */
|
||||
client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
|
||||
eflags = pkgconf_pkg_walk_list(client, root, &root->requires_private, func, data, maxdepth, skip_flags);
|
||||
client->flags &= ~PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
|
||||
/* XXX: ugly */
|
||||
client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
|
||||
eflags = pkgconf_pkg_walk_list(client, root, &root->requires_private, func, data, maxdepth, skip_flags);
|
||||
client->flags &= ~PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
|
||||
|
||||
if (eflags != PKGCONF_PKG_ERRF_OK)
|
||||
return eflags;
|
||||
}
|
||||
if (eflags != PKGCONF_PKG_ERRF_OK)
|
||||
return eflags;
|
||||
|
||||
return eflags;
|
||||
}
|
||||
@ -1761,6 +1829,9 @@ pkgconf_pkg_libs_collect(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *dat
|
||||
pkgconf_list_t *list = data;
|
||||
pkgconf_node_t *node;
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE) && pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE)
|
||||
return;
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(pkg->libs.head, node)
|
||||
{
|
||||
pkgconf_fragment_t *frag = node->data;
|
||||
|
||||
@ -29,6 +29,32 @@
|
||||
* Using the `queue` module functions is the recommended way of working with dependency graphs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
* .. c:function:: void pkgconf_queue_push_dependency(pkgconf_list_t *list, const pkgconf_dependency_t *dep)
|
||||
*
|
||||
* Pushes a requested dependency onto the dependency resolver's queue which is described by
|
||||
* a pkgconf_dependency_t node.
|
||||
*
|
||||
* :param pkgconf_list_t* list: the dependency resolution queue to add the package request to.
|
||||
* :param pkgconf_dependency_t* dep: the dependency requested
|
||||
* :return: nothing
|
||||
*/
|
||||
void
|
||||
pkgconf_queue_push_dependency(pkgconf_list_t *list, const pkgconf_dependency_t *dep)
|
||||
{
|
||||
pkgconf_buffer_t depbuf = PKGCONF_BUFFER_INITIALIZER;
|
||||
pkgconf_queue_t *pkgq = calloc(1, sizeof(pkgconf_queue_t));
|
||||
|
||||
pkgconf_buffer_append(&depbuf, dep->package);
|
||||
if (dep->version != NULL)
|
||||
pkgconf_buffer_append_fmt(&depbuf, " %s %s", pkgconf_pkg_get_comparator(dep), dep->version);
|
||||
|
||||
pkgq->package = pkgconf_buffer_freeze(&depbuf);
|
||||
pkgconf_node_insert_tail(&pkgq->iter, pkgq, list);
|
||||
}
|
||||
|
||||
/*
|
||||
* !doc
|
||||
*
|
||||
@ -151,7 +177,7 @@ pkgconf_queue_collect_dependencies_walk(pkgconf_client_t *client,
|
||||
if (pkg == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package);
|
||||
abort();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pkg->serial == client->serial)
|
||||
@ -189,18 +215,15 @@ pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client,
|
||||
|
||||
root->serial = client->serial;
|
||||
|
||||
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
|
||||
{
|
||||
PKGCONF_TRACE(client, "%s: collecting private dependencies, level %d", root->id, maxdepth);
|
||||
PKGCONF_TRACE(client, "%s: collecting private dependencies, level %d", root->id, maxdepth);
|
||||
|
||||
/* XXX: ugly */
|
||||
const unsigned int saved_flags = client->flags;
|
||||
client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
|
||||
eflags = pkgconf_queue_collect_dependencies_walk(client, &root->requires_private, data, maxdepth);
|
||||
client->flags = saved_flags;
|
||||
if (eflags != PKGCONF_PKG_ERRF_OK)
|
||||
return eflags;
|
||||
}
|
||||
/* XXX: ugly */
|
||||
const unsigned int saved_flags = client->flags;
|
||||
client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
|
||||
eflags = pkgconf_queue_collect_dependencies_walk(client, &root->requires_private, data, maxdepth);
|
||||
client->flags = saved_flags;
|
||||
if (eflags != PKGCONF_PKG_ERRF_OK)
|
||||
return eflags;
|
||||
|
||||
PKGCONF_TRACE(client, "%s: collecting public dependencies, level %d", root->id, maxdepth);
|
||||
|
||||
@ -223,6 +246,45 @@ pkgconf_queue_collect_dependencies(pkgconf_client_t *client,
|
||||
return pkgconf_queue_collect_dependencies_main(client, root, data, maxdepth);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
pkgconf_queue_collect_conflicts(pkgconf_client_t *client,
|
||||
pkgconf_pkg_t *root,
|
||||
pkgconf_pkg_t *world,
|
||||
int maxdepth)
|
||||
{
|
||||
unsigned int eflags = PKGCONF_PKG_ERRF_OK;
|
||||
pkgconf_node_t *node;
|
||||
|
||||
PKGCONF_TRACE(client, "%s: collecting conflicts, level %d", root->id, maxdepth);
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(root->required.head, node)
|
||||
{
|
||||
pkgconf_dependency_t *dep = node->data;
|
||||
pkgconf_pkg_t *pkg = dep->match;
|
||||
pkgconf_node_t *cnode;
|
||||
|
||||
if (*dep->package == '\0')
|
||||
continue;
|
||||
|
||||
if (pkg == NULL)
|
||||
{
|
||||
PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package);
|
||||
continue;
|
||||
}
|
||||
|
||||
PKGCONF_FOREACH_LIST_ENTRY(pkg->conflicts.head, cnode)
|
||||
{
|
||||
pkgconf_dependency_t *conflict = cnode->data;
|
||||
pkgconf_dependency_t *flattened_conflict = pkgconf_dependency_copy(client, conflict);
|
||||
|
||||
flattened_conflict->why = strdup(pkg->id);
|
||||
pkgconf_node_insert(&flattened_conflict->iter, flattened_conflict, &world->conflicts);
|
||||
}
|
||||
}
|
||||
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth)
|
||||
{
|
||||
@ -256,6 +318,13 @@ pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_lis
|
||||
return result;
|
||||
}
|
||||
|
||||
result = pkgconf_queue_collect_conflicts(client, world, world, maxdepth);
|
||||
if (result != PKGCONF_PKG_ERRF_OK)
|
||||
{
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
|
||||
{
|
||||
PKGCONF_TRACE(client, "marking public deps");
|
||||
@ -270,6 +339,18 @@ pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_lis
|
||||
}
|
||||
}
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_CONFLICTS))
|
||||
{
|
||||
PKGCONF_TRACE(client, "checking for conflicts");
|
||||
|
||||
result = pkgconf_pkg_walk_conflicts_list(client, world, &world->conflicts);
|
||||
if (result != PKGCONF_PKG_ERRF_OK)
|
||||
{
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* free the initial solution */
|
||||
pkgconf_solution_free(client, &initial_world);
|
||||
|
||||
@ -296,6 +377,7 @@ pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world)
|
||||
{
|
||||
pkgconf_dependency_free(&world->required);
|
||||
pkgconf_dependency_free(&world->requires_private);
|
||||
pkgconf_dependency_free(&world->conflicts);
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,7 +402,13 @@ pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_
|
||||
if (!maxdepth)
|
||||
maxdepth = -1;
|
||||
|
||||
return pkgconf_queue_verify(client, world, list, maxdepth) == PKGCONF_PKG_ERRF_OK;
|
||||
unsigned int flags = client->flags;
|
||||
client->flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
|
||||
|
||||
unsigned int ret = pkgconf_queue_verify(client, world, list, maxdepth);
|
||||
client->flags = flags;
|
||||
|
||||
return ret == PKGCONF_PKG_ERRF_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -25,14 +25,21 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <malloc.h>
|
||||
# include <io.h> /* for _setmode() */
|
||||
# include <fcntl.h>
|
||||
# define PATH_DEV_NULL "nul"
|
||||
# ifdef _WIN64
|
||||
# define SIZE_FMT_SPECIFIER "%I64u"
|
||||
# ifndef __MINGW32__
|
||||
# define SIZE_FMT_SPECIFIER "%I64u"
|
||||
# else
|
||||
# define SIZE_FMT_SPECIFIER "%llu"
|
||||
# endif
|
||||
# else
|
||||
# define SIZE_FMT_SPECIFIER "%u"
|
||||
# endif
|
||||
@ -47,9 +54,14 @@
|
||||
# ifndef __MINGW32__
|
||||
# include "win-dirent.h"
|
||||
# else
|
||||
# include <dirent.h>
|
||||
# include <dirent.h>
|
||||
# endif
|
||||
# define PKGCONF_ITEM_SIZE (_MAX_PATH + 1024)
|
||||
# define PKG_CONFIG_PATH_SEP_S ";"
|
||||
# define PKG_DIR_SEP_S '\\'
|
||||
# define strcasecmp _stricmp
|
||||
# define strncasecmp _strnicmp
|
||||
# define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
|
||||
#else
|
||||
# define PATH_DEV_NULL "/dev/null"
|
||||
# define SIZE_FMT_SPECIFIER "%zu"
|
||||
@ -60,11 +72,18 @@
|
||||
# include <unistd.h>
|
||||
# include <limits.h>
|
||||
# include <strings.h>
|
||||
# include <fcntl.h> // open
|
||||
# include <libgen.h> // basename/dirname
|
||||
# include <sys/stat.h> // lstat, S_ISLNK
|
||||
# include <unistd.h> // close, readlinkat
|
||||
# include <string.h>
|
||||
# ifdef PATH_MAX
|
||||
# define PKGCONF_ITEM_SIZE (PATH_MAX + 1024)
|
||||
# else
|
||||
# define PKGCONF_ITEM_SIZE (4096 + 1024)
|
||||
# endif
|
||||
# define PKG_CONFIG_PATH_SEP_S ":"
|
||||
# define PKG_DIR_SEP_S '/'
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -199,7 +199,7 @@ should_rewrite_sysroot(const pkgconf_client_t *client, pkgconf_list_t *vars, con
|
||||
return false;
|
||||
|
||||
sysroot_dir = find_sysroot(client, vars);
|
||||
if (sysroot_dir == NULL)
|
||||
if (sysroot_dir == NULL || !*sysroot_dir)
|
||||
return false;
|
||||
|
||||
if (*buf != '/')
|
||||
@ -238,8 +238,6 @@ pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const ch
|
||||
char *dequote_value;
|
||||
pkgconf_tuple_t *tuple = calloc(1, sizeof(pkgconf_tuple_t));
|
||||
|
||||
pkgconf_tuple_find_delete(list, key);
|
||||
|
||||
dequote_value = dequote(value);
|
||||
|
||||
tuple->key = strdup(key);
|
||||
@ -250,6 +248,8 @@ pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *list, const ch
|
||||
|
||||
PKGCONF_TRACE(client, "adding tuple to @%p: %s => %s (parsed? %d)", list, key, tuple->value, parse);
|
||||
|
||||
pkgconf_tuple_find_delete(list, key);
|
||||
|
||||
pkgconf_node_insert(&tuple->iter, tuple, list);
|
||||
|
||||
free(dequote_value);
|
||||
@ -314,12 +314,13 @@ pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *vars, const
|
||||
char buf[PKGCONF_BUFSIZE];
|
||||
const char *ptr;
|
||||
char *bptr = buf;
|
||||
const char *sysroot_dir = find_sysroot(client, vars);
|
||||
|
||||
if (!(client->flags & PKGCONF_PKG_PKGF_FDO_SYSROOT_RULES) &&
|
||||
(!(flags & PKGCONF_PKG_PROPF_UNINSTALLED) || (client->flags & PKGCONF_PKG_PKGF_PKGCONF1_SYSROOT_RULES)))
|
||||
{
|
||||
if (*value == '/' && client->sysroot_dir != NULL && strncmp(value, client->sysroot_dir, strlen(client->sysroot_dir)))
|
||||
bptr += pkgconf_strlcpy(buf, client->sysroot_dir, sizeof buf);
|
||||
if (*value == '/' && sysroot_dir != NULL && *sysroot_dir && strncmp(value, sysroot_dir, strlen(sysroot_dir)))
|
||||
bptr += pkgconf_strlcpy(buf, sysroot_dir, sizeof buf);
|
||||
}
|
||||
|
||||
for (ptr = value; *ptr != '\0' && bptr - buf < PKGCONF_BUFSIZE; ptr++)
|
||||
@ -421,7 +422,6 @@ pkgconf_tuple_parse(const pkgconf_client_t *client, pkgconf_list_t *vars, const
|
||||
if (should_rewrite_sysroot(client, vars, buf, flags))
|
||||
{
|
||||
char cleanpath[PKGCONF_ITEM_SIZE];
|
||||
const char *sysroot_dir = find_sysroot(client, vars);
|
||||
|
||||
pkgconf_strlcpy(cleanpath, buf + strlen(sysroot_dir), sizeof cleanpath);
|
||||
pkgconf_path_relocate(cleanpath, sizeof cleanpath);
|
||||
|
||||
100
man/bomtool.1
Normal file
100
man/bomtool.1
Normal file
@ -0,0 +1,100 @@
|
||||
.\" Copyright (c) 2025 pkgconf authors (see AUTHORS).
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and/or distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" This software is provided 'as is' and without any warranty, express or
|
||||
.\" implied. In no event shall the authors be liable for any damages arising
|
||||
.\" from the use of this software.
|
||||
.Dd June 4, 2025
|
||||
.Dt BOMTOOL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm bomtool
|
||||
.Nd a tool for generating SPDX-based software bills of material
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar options
|
||||
.Ar module ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a program which generates a textual SPDX 2.0 software bill of
|
||||
materials (SBOM) for a given set of pkg-config modules.
|
||||
The output of this tool can then be translated into other SBOM
|
||||
formats as necessary.
|
||||
.Pp
|
||||
The
|
||||
.Ar options
|
||||
are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl -about
|
||||
Print the version number, the Copyright notice, and the license of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -version
|
||||
Print the version number of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width indent
|
||||
.It Ev PKG_CONFIG_DEBUG_SPEW
|
||||
If set, print debugging messages to stderr.
|
||||
.It Ev PKG_CONFIG_IGNORE_CONFLICTS
|
||||
If set, ignore
|
||||
.Ic Conflicts
|
||||
rules in modules.
|
||||
Has the same effect as the
|
||||
.Fl -ignore-conflicts
|
||||
option in
|
||||
.Xr pkgconf 1
|
||||
.
|
||||
.It Ev PKG_CONFIG_LIBDIR
|
||||
A colon-separated list of low-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
The module search path is constructed by appending this list to
|
||||
.Ev PKG_CONFIG_PATH ,
|
||||
which enjoys higher priority.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv PKG_DEFAULT_PATH
|
||||
preprocessor macro is appended instead.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is defined but empty, nothing is appended.
|
||||
.It Ev PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH
|
||||
Impose a limit on the allowed depth in the dependency graph.
|
||||
.It Ev PKG_CONFIG_PATH
|
||||
A colon-separated list of high-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
.It Ev PKG_CONFIG_PRELOADED_FILES
|
||||
Colon-separated list of
|
||||
.Xr pc 5
|
||||
files which are loaded before any other pkg-config files.
|
||||
These packages are given highest priority over any other
|
||||
.Xr pc 5
|
||||
files that would otherwise provide a given package.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
Generating an SBOM for the package named foo:
|
||||
.Dl $ bomtool foo
|
||||
.Dl SPDXVersion: SPDX-2.2
|
||||
.Dl DataLicense: CC0-1.0
|
||||
.Dl SPDXID: SPDXRef-DOCUMENT
|
||||
.Dl DocumentName: SBOM-SPDX-fooC641.2.3
|
||||
.Dl DocumentNamespace: https://spdx.org/spdxdocs/bomtool-2.4.3
|
||||
.Dl Creator: Tool: bomtool 2.4.3
|
||||
.Dl [...]
|
||||
.Sh SEE ALSO
|
||||
.Xr pc 5 ,
|
||||
.Xr pkgconf 1
|
||||
16
man/pc.5
16
man/pc.5
@ -116,15 +116,31 @@ not described as dependencies should be specified here.
|
||||
.It License
|
||||
The asserted SPDX license tag that should be applied to the given package.
|
||||
(optional; literal; pkgconf extension)
|
||||
.It License.file
|
||||
License file location for whole license text.
|
||||
(optional; literal; pkgconf extension)
|
||||
.It Maintainer
|
||||
The preferred contact for the maintainer. This should be in the format of a
|
||||
name followed by an e-mail address or website.
|
||||
(optional; literal; pkgconf extension)
|
||||
.It Source
|
||||
The asserted SPDX downloadLocation tag that should be applied to the given package.
|
||||
Source should be URI contain tarball with exact version or Repository that contains
|
||||
tag with version same as mentioned in version tag. It can be also be URI with hash
|
||||
that is exact release point of the source.
|
||||
(optional; literal; pkgconf extension)
|
||||
.It Requires
|
||||
Required dependencies that must be met for the package to be usable.
|
||||
All dependencies must be satisfied or the pkg-config implementation must not use
|
||||
the package.
|
||||
(optional; dependency list)
|
||||
.It Requires.internal
|
||||
Required dependencies that must be met for the package to be usable for
|
||||
static linking.
|
||||
The main differences verses Requires.private are that CFLAGS will not be
|
||||
included and the solver will not consider the dependency when solving for
|
||||
CFLAGS only.
|
||||
(optional; dependency list; pkgconf extension)
|
||||
.It Requires.private
|
||||
Required dependencies that must be met for the package to be usable for header
|
||||
inclusion and static linking.
|
||||
|
||||
889
man/pkgconf.1
889
man/pkgconf.1
@ -16,212 +16,745 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar options
|
||||
.Op Ar list of modules
|
||||
.Ar module ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
is a program which helps to configure compiler and linker flags for
|
||||
development libraries.
|
||||
This allows build systems to detect other dependencies and use them with the
|
||||
system toolchain.
|
||||
.Sh GENERAL OPTIONS
|
||||
program retrieves configuration information related to the
|
||||
.Ar module
|
||||
arguments from
|
||||
.Xr pc 5
|
||||
files installed on the system and prints parts of the retrieved
|
||||
information depending on the specified
|
||||
.Ar options .
|
||||
The most common use is printing the compiler and linker flags needed
|
||||
to build software that uses the libraries given by the
|
||||
.Ar module
|
||||
arguments.
|
||||
.Pp
|
||||
The
|
||||
.Xr pc 5
|
||||
files are searched for along a path constructed from the
|
||||
.Fl -with-path
|
||||
option, the
|
||||
.Ev PKG_CONFIG_PATH
|
||||
and
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
environment variables, and some compiled-in default directories.
|
||||
The
|
||||
.Ar module
|
||||
arguments correspond to the file names, but without the
|
||||
.Pa .pc
|
||||
filename extension.
|
||||
.Pp
|
||||
Several of the
|
||||
.Ar options
|
||||
cause immediate exit.
|
||||
If multiple of these options are given, only the option with the
|
||||
highest priority takes effect and those with lower priority are
|
||||
silently ignored.
|
||||
These options are, ordered by descending priority:
|
||||
.Bl -enum
|
||||
.It
|
||||
No-module options:
|
||||
.Fl -relocate ,
|
||||
.Fl -dump-personality ,
|
||||
.Fl -about ,
|
||||
.Fl -version ,
|
||||
.Fl -help ,
|
||||
.Fl -atleast-pkgconfig-version ,
|
||||
.Fl -list-all ,
|
||||
and
|
||||
.Fl -list-package-names :
|
||||
These options cause all arguments to be ignored.
|
||||
.It
|
||||
Argument-only options:
|
||||
.Fl -atleast-version ,
|
||||
.Fl -exact-version ,
|
||||
and
|
||||
.Fl -max-version :
|
||||
These options only inspect modules explicitly specified on the
|
||||
command line and do not look at dependencies.
|
||||
.It
|
||||
Limited-output options:
|
||||
.Fl -validate ,
|
||||
.Fl -license ,
|
||||
.Fl -license-file ,
|
||||
.Fl -source ,
|
||||
.Fl -uninstalled ,
|
||||
and
|
||||
.Fl -env :
|
||||
These options perform dependency resolution, but exit after printing
|
||||
the information requested by the highest-priority option,
|
||||
ignoring other output options that may have been specified.
|
||||
.El
|
||||
.Pp
|
||||
Several other options require at least one
|
||||
.Ar module
|
||||
argument, produce output, do not cause early exit, can be combined
|
||||
with each other, but override and disable all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
options:
|
||||
.Bl -enum
|
||||
.It
|
||||
Single-module output options:
|
||||
.Fl -path ,
|
||||
.Fl -print-variables ,
|
||||
.Fl -variable :
|
||||
If any of these options is specified, only the first
|
||||
.Ar module
|
||||
argument is used, all other arguments are silently ignored,
|
||||
and no dependency resolution is attempted.
|
||||
.It
|
||||
Depth-one output options:
|
||||
.Fl -print-provides ,
|
||||
.Fl -modversion ,
|
||||
.Fl -print-requires ,
|
||||
and
|
||||
.Fl -print-requires-private :
|
||||
If any of these options is specified, only modules
|
||||
explicitly specified on the command line are inspected
|
||||
and no dependency resolution is attempted.
|
||||
.It
|
||||
General output options:
|
||||
.Fl -simulate ,
|
||||
.Fl -digraph ,
|
||||
.Fl -solution ,
|
||||
.Fl -fragment-tree ,
|
||||
.Fl -newlines :
|
||||
These options do not limit dependency resolution.
|
||||
.El
|
||||
.Pp
|
||||
The most important output options
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
can be combined with each other, but are overridden and ignored if
|
||||
any of the options listed above are specified.
|
||||
.Pp
|
||||
The complete list of
|
||||
.Ar options
|
||||
is as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl -version
|
||||
Display the supported pkg-config version and exit.
|
||||
.It Fl -atleast-pkgconfig-version Ns = Ns Ar VERSION
|
||||
Exit with error if we do not support the requested pkg-config version.
|
||||
.It Fl -errors-to-stdout
|
||||
Print all errors on the main output stream instead of the error output stream.
|
||||
.It Fl -silence-errors
|
||||
Do not display any errors at all.
|
||||
.It Fl -list-all
|
||||
Walk all directories listed in the
|
||||
.Va PKG_CONFIG_PATH
|
||||
environmental variable and display information on packages which have registered
|
||||
information there.
|
||||
.It Fl -simulate
|
||||
Simulates resolving a dependency graph based on the requested modules on the
|
||||
command line.
|
||||
Dumps a series of trees denoting pkgconf's resolver state.
|
||||
.It Fl -no-cache
|
||||
Skip caching packages when they are loaded into the internal resolver.
|
||||
This may result in an alternate dependency graph being computed.
|
||||
.It Fl -ignore-conflicts
|
||||
Ignore
|
||||
.Sq Conflicts
|
||||
rules in modules.
|
||||
.It Fl -env-only
|
||||
Learn about pkgconf's configuration strictly from environmental variables.
|
||||
.It Fl -validate Ar package ...
|
||||
Validate specific
|
||||
.Sq .pc
|
||||
files for correctness.
|
||||
.It Fl -maximum-traverse-depth Ns = Ns Ar DEPTH
|
||||
Impose a limit on the allowed depth in the dependency graph.
|
||||
For example, a depth of 2 will restrict the resolver from acting on child
|
||||
dependencies of modules added to the resolver's solution.
|
||||
.It Fl -static
|
||||
Compute a deeper dependency graph and use compiler/linker flags intended for
|
||||
static linking.
|
||||
.It Fl -shared
|
||||
Compute a simple dependency graph that is only suitable for shared linking.
|
||||
.It Fl -pure
|
||||
Treats the computed dependency graph as if it were pure.
|
||||
This is mainly intended for use with the
|
||||
.Fl -static
|
||||
flag.
|
||||
.It Fl -no-provides
|
||||
Ignore
|
||||
.Sq Provides
|
||||
rules in modules when resolving dependencies.
|
||||
.It Fl -with-path Ns = Ns Ar PATH
|
||||
Adds a new module search path to pkgconf's dependency resolver.
|
||||
Paths added in this way are given preference before other paths.
|
||||
.It Fl -about
|
||||
Print the version number, the Copyright notice, and the license of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -atleast-pkgconfig-version Ns = Ns Ar version
|
||||
Exit with error if the requested
|
||||
.Ar version
|
||||
number is greater than the version number of the
|
||||
.Nm
|
||||
program, or with success otherwise.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -atleast-version Ns = Ns Ar version
|
||||
Check the
|
||||
.Ar module
|
||||
arguments in the given order.
|
||||
Exit with error as soon as a
|
||||
.Ar module
|
||||
does not exist, and exit with success as soon as the version number of a
|
||||
.Ar module
|
||||
is greater than or equal to the requested
|
||||
.Ar version
|
||||
number.
|
||||
Exit with error if the version number of each
|
||||
.Ar module
|
||||
is less than the requested
|
||||
.Ar version
|
||||
number.
|
||||
.It Fl -cflags , Fl -cflags-only-I , Fl -cflags-only-other
|
||||
Print all compiler flags required to compile against the
|
||||
.Ar module ,
|
||||
or only the include path
|
||||
.Pq Fl I
|
||||
flags, or only the compiler flags that are not include path flags,
|
||||
respectively.
|
||||
These options imply
|
||||
.Fl -print-errors .
|
||||
.It Fl -debug
|
||||
Print some non-fatal warning messages to standard error output
|
||||
that would otherwise silently be ignored.
|
||||
This option also implies
|
||||
.Fl -print-errors .
|
||||
If
|
||||
.Nm
|
||||
was compiled without defining the preprocessor macro
|
||||
.Dv PKGCONF_LITE ,
|
||||
this option also prints many debugging messages to standard error output.
|
||||
.It Fl -define-prefix
|
||||
Attempts to determine the prefix variable to use for CFLAGS and LIBS entry relocations.
|
||||
This is mainly useful for platforms where framework SDKs are relocatable, such as Windows.
|
||||
.It Fl -dont-define-prefix
|
||||
Disables the
|
||||
.Sq define-prefix
|
||||
feature.
|
||||
.It Fl -prefix-variable Ns = Ns Ar VARIABLE
|
||||
Sets the
|
||||
.Sq prefix
|
||||
variable used by the
|
||||
.Sq define-prefix
|
||||
feature.
|
||||
.It Fl -relocate Ns = Ns Ar PATH
|
||||
Relocates a path using the pkgconf_path_relocate API.
|
||||
This is mainly used by the testsuite to provide a guaranteed interface
|
||||
to the system's path relocation backend.
|
||||
.It Fl -dont-relocate-paths
|
||||
Disables the path relocation feature.
|
||||
.El
|
||||
.Sh MODULE-SPECIFIC OPTIONS
|
||||
.Bl -tag -width indent
|
||||
.It Fl -atleast-version Ns = Ns Ar VERSION
|
||||
Exit with error if a module's version is less than the specified version.
|
||||
.It Fl -exact-version Ns = Ns Ar VERSION
|
||||
Exit with error if a module's version is not exactly the specified version.
|
||||
.It Fl -max-version Ns = Ns Ar VERSION
|
||||
Exit with error if a module's version is greater than the specified version.
|
||||
.It Fl -exists
|
||||
Exit with a non-zero result if the dependency resolver was unable to find all of
|
||||
the requested modules.
|
||||
.It Fl -uninstalled
|
||||
Exit with a non-zero result if the dependency resolver uses an
|
||||
.Sq uninstalled
|
||||
module as part of its solution.
|
||||
.It Fl -no-uninstalled
|
||||
Forbids the dependency resolver from considering 'uninstalled' modules as part
|
||||
of a solution.
|
||||
.El
|
||||
.Sh QUERY-SPECIFIC OPTIONS
|
||||
.Bl -tag -width indent
|
||||
.It Fl -cflags , Fl -cflags-only-I , Fl -cflags-only-other
|
||||
Display either all CFLAGS, only
|
||||
.Fl I
|
||||
CFLAGS or only CFLAGS that are not
|
||||
.Fl I .
|
||||
.It Fl -libs , Fl -libs-only-L , Fl -libs-only-l , Fl -libs-only-other
|
||||
Display either all linker flags, only
|
||||
.Fl L
|
||||
linker flags, only
|
||||
.Fl l
|
||||
linker flags or only linker flags that are not
|
||||
.Fl L
|
||||
or
|
||||
.Fl l .
|
||||
.It Fl -keep-system-cflags , Fl -keep-system-libs
|
||||
Keep CFLAGS or linker flag fragments that would be filtered due to being
|
||||
included by default in the compiler.
|
||||
.It Fl -define-variable Ns = Ns Ar VARNAME Ns = Ns Ar VALUE
|
||||
.It Fl -define-variable Ns = Ns Ar varname Ns = Ns Ar value
|
||||
Define
|
||||
.Va VARNAME
|
||||
.Ar varname
|
||||
as
|
||||
.Va VALUE .
|
||||
.Ar value .
|
||||
Variables are used in query output, and some modules' results may change based
|
||||
on the presence of a variable definition.
|
||||
.It Fl -print-variables
|
||||
Print all seen variables for a module to the output channel.
|
||||
.It Fl -print-provides
|
||||
Print all relevant
|
||||
.Sq Provides
|
||||
entries for a module to the output channel.
|
||||
.It Fl -variable Ns = Ns Ar VARNAME
|
||||
Print the value of
|
||||
.Va VARNAME .
|
||||
.It Fl -print-requires , Fl -print-requires-private
|
||||
Print the modules included in either the
|
||||
.Va Requires
|
||||
field or the
|
||||
.Va Requires.private
|
||||
field.
|
||||
.It Fl -digraph
|
||||
Dump the dependency resolver's solution as a graphviz
|
||||
.Sq dot
|
||||
file.
|
||||
This can be used with graphviz to visualize module interdependencies.
|
||||
.It Fl -path
|
||||
Display the filenames of the
|
||||
.Sq .pc
|
||||
files used by the dependency resolver for a given dependency set.
|
||||
.It Fl -env Ns = Ns Ar VARNAME
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -dont-define-prefix
|
||||
Disables the
|
||||
.Sq define-prefix
|
||||
feature.
|
||||
.It Fl -dont-relocate-paths
|
||||
Disables the path relocation feature.
|
||||
.It Fl -dump-personality
|
||||
Print some default settings to standard output, in particular
|
||||
the default module search path that is used when
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is not defined, the default list of include paths that are filtered out when
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH
|
||||
is not defined,
|
||||
and the default list of library paths that are filtered out when
|
||||
.Ev PKG_CONFIG_SYSTEM_LIBRARY_PATH
|
||||
is not defined, and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -env Ns = Ns Ar varname
|
||||
Print the requested values as variable declarations in a similar format as the
|
||||
.Xr env 1
|
||||
command.
|
||||
.It Fl -fragment-filter Ns = Ns Ar TYPES
|
||||
Filter the fragment lists for the specified types.
|
||||
.It Fl -env-only
|
||||
Initialize the module search path from
|
||||
.Fl -with-path
|
||||
and
|
||||
.Ev PKG_CONFIG_PATH
|
||||
only, ignoring
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
and the compiled-in default directories.
|
||||
.It Fl -errors-to-stdout
|
||||
Print all error, warning, and debugging messages to standard output
|
||||
instead of to standard error output.
|
||||
.It Fl -exact-version Ns = Ns Ar version
|
||||
Check the
|
||||
.Ar module
|
||||
arguments in the given order.
|
||||
Exit with error as soon as a
|
||||
.Ar module
|
||||
does not exist, and exit with success as soon as the version number of a
|
||||
.Ar module
|
||||
is exactly the requested
|
||||
.Ar version
|
||||
number.
|
||||
Exit with error if the version number of each
|
||||
.Ar module
|
||||
differs from the requested
|
||||
.Ar version
|
||||
number.
|
||||
.It Fl -exists
|
||||
Exit with a non-zero exit status
|
||||
if the dependency resolver is unable to find all of the requested
|
||||
.Ar module Ns s .
|
||||
This option is active by default and cannot be disabled.
|
||||
However, various other options cause
|
||||
.Nm
|
||||
to exit and report success or failure before all arguments have been inspected.
|
||||
.It Fl -fragment-filter Ns = Ns Ar types
|
||||
Filter the fragment lists for the specified
|
||||
.Ar types .
|
||||
.It Fl -help
|
||||
Print a usage summary on standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -ignore-conflicts
|
||||
Ignore
|
||||
.Sq Conflicts
|
||||
rules in modules.
|
||||
.It Fl -keep-system-cflags , Fl -keep-system-libs
|
||||
Keep CFLAGS or linker flag fragments that would be filtered due to being
|
||||
included by default in the compiler.
|
||||
.It Fl -libs , Fl -libs-only-L , Fl -libs-only-l , Fl -libs-only-other
|
||||
Print all linker flags required to link against the
|
||||
.Ar module ,
|
||||
or only the library path
|
||||
.Pq Fl L
|
||||
flags, or only the library
|
||||
.Pq Fl l
|
||||
flags, or only the linker flags that are neither library path
|
||||
nor library flags, respectively.
|
||||
These options imply
|
||||
.Fl -print-errors .
|
||||
.It Fl -list-all
|
||||
Walk the module search path in the order of descending priority.
|
||||
For each
|
||||
.Xr pc 5
|
||||
file found, print one line to standard output,
|
||||
containing the basename of the file without the extension, the
|
||||
.Ic Name
|
||||
property, a dash
|
||||
.Pq Sq \- ,
|
||||
and the
|
||||
.Ic Description
|
||||
property.
|
||||
This option implies
|
||||
.Fl -print-errors .
|
||||
All command line arguments are ignored.
|
||||
.It Fl -list-package-names
|
||||
Perform the same search as
|
||||
.Fl -list-all ,
|
||||
but only print the basename of each
|
||||
.Xr pc 5
|
||||
file without the extension, not the module name and the description.
|
||||
This option implies
|
||||
.Fl -print-errors .
|
||||
All command line arguments are ignored.
|
||||
.It Fl -log-file Ns = Ns Ar file
|
||||
Set the name of the output
|
||||
.Ar file
|
||||
where information about selected modules is logged,
|
||||
both about those selected by arguments and as dependencies.
|
||||
For each selected module, one line is printed,
|
||||
containing the basename of the
|
||||
.Xr pc 5
|
||||
file without the extension, optionally an operator and version number
|
||||
describing the desired range of versions, and either the actual version
|
||||
number in square brackets or the string
|
||||
.Qq NOT-FOUND .
|
||||
If this option is not provided, the name of the output file
|
||||
is instead taken from the
|
||||
.Ev PKG_CONFIG_LOG
|
||||
environment variable, and if that is not provided either,
|
||||
this kind of logging is disabled.
|
||||
.It Fl -max-version Ns = Ns Ar version
|
||||
Check the
|
||||
.Ar module
|
||||
arguments in the given order.
|
||||
Exit with error as soon as a
|
||||
.Ar module
|
||||
does not exist, and exit with success as soon as the version number of a
|
||||
.Ar module
|
||||
is less than or equal to the requested
|
||||
.Ar version
|
||||
number.
|
||||
Exit with error if the version number of each
|
||||
.Ar module
|
||||
is greater than the requested
|
||||
.Ar version
|
||||
number.
|
||||
.It Fl -maximum-traverse-depth Ns = Ns Ar depth
|
||||
Impose a limit on the allowed depth in the dependency graph.
|
||||
For example, a
|
||||
.Ar depth
|
||||
of 2 restricts the resolver from acting on child
|
||||
dependencies of modules added to the resolver's solution.
|
||||
This option is overridden by the
|
||||
.Ev PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH
|
||||
environment variable and by the options
|
||||
.Fl -modversion ,
|
||||
.Fl -path ,
|
||||
.Fl -print-provides ,
|
||||
.Fl -print-requires ,
|
||||
.Fl -print-requires-private ,
|
||||
.Fl -print-variables ,
|
||||
and
|
||||
.Fl -variable .
|
||||
.It Fl -modversion
|
||||
Print the version of the queried module.
|
||||
For each specified
|
||||
.Ar module ,
|
||||
print the version number to standard output.
|
||||
If the
|
||||
.Fl -verbose
|
||||
option is also specified, the name of the respective
|
||||
.Ar module
|
||||
and a colon is printed before each version number.
|
||||
This option implies
|
||||
.Fl -print-errors
|
||||
and
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -msvc-syntax
|
||||
Use MSVC syntax for
|
||||
.Fl -cflags ,
|
||||
.Fl -env ,
|
||||
and
|
||||
.Fl -libs
|
||||
output.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -newlines
|
||||
Use newlines to separate individual CFLAGS or linker flag fragments
|
||||
instead of spaces.
|
||||
.It Fl -no-cache
|
||||
Skip caching packages when they are loaded into the internal resolver.
|
||||
This may result in an alternate dependency graph being computed.
|
||||
.It Fl -no-provides
|
||||
Ignore
|
||||
.Sq Provides
|
||||
rules in modules when resolving dependencies.
|
||||
.It Fl -no-uninstalled
|
||||
Forbids the dependency resolver from considering 'uninstalled' modules as part
|
||||
of a solution.
|
||||
.It Fl -path
|
||||
For the first
|
||||
.Ar module
|
||||
given on the command line, let the dependency resolver find the
|
||||
.Xr pc 5
|
||||
file describing that module, print the absolute pathname of that file
|
||||
to standard output, and exit immediately,
|
||||
ignoring most other options and all other arguments.
|
||||
.It Fl -prefix-variable Ns = Ns Ar variable
|
||||
Sets the
|
||||
.Sq prefix
|
||||
variable used by the
|
||||
.Sq define-prefix
|
||||
feature.
|
||||
.It Fl -print-errors
|
||||
Print some messages about fatal errors to standard error output
|
||||
that would otherwise be omitted.
|
||||
This option is implied by many other options, but not by all.
|
||||
It can be overridden with
|
||||
.Fl -silence-errors .
|
||||
.It Fl -print-provides
|
||||
For each specified
|
||||
.Ar module ,
|
||||
print one line to standard output containing the
|
||||
.Ic Name
|
||||
property, an equal sign
|
||||
.Pq Sq = ,
|
||||
and the
|
||||
.Ic Version
|
||||
property.
|
||||
If the
|
||||
.Ar module
|
||||
contains one or more
|
||||
.Ic Provides
|
||||
properties, print additional lines in dependency list format, one name
|
||||
per line, each name optionally followed by an operator and a version.
|
||||
This option implies
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -print-requires , Fl -print-requires-private
|
||||
For each specified
|
||||
.Ar module ,
|
||||
print the
|
||||
.Ic Requires
|
||||
or
|
||||
.Ic Requires.private
|
||||
properties, respectively, in dependency list format to standard output.
|
||||
Both of these options imply
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and override and disable all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -print-variables
|
||||
For the first
|
||||
.Ar module
|
||||
given on the command line, print the names of all seen variables
|
||||
to standard output, one per line.
|
||||
Any subsequent arguments are silently ignored.
|
||||
This option implies
|
||||
.Fl -print-errors
|
||||
and
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -pure
|
||||
Treats the computed dependency graph as if it were pure.
|
||||
This is mainly intended for use with the
|
||||
.Fl -static
|
||||
flag and has no effect if
|
||||
.Fl -shared
|
||||
is also specified.
|
||||
.It Fl -relocate Ns = Ns Ar path
|
||||
Relocates a path using the pkgconf_path_relocate API.
|
||||
This is mainly used by the testsuite to provide a guaranteed interface
|
||||
to the system's path relocation backend.
|
||||
.It Fl -shared
|
||||
Compute a simple dependency graph that is only suitable for shared linking.
|
||||
This option overrides
|
||||
.Fl -static .
|
||||
.It Fl -short-errors
|
||||
When printing error messages about modules that are not found
|
||||
or conflict with each other, avoid printing additional, verbose
|
||||
instructions explaining potential methods for solving the problem.
|
||||
.It Fl -silence-errors
|
||||
Do not print any error, warning, or debugging messages at all.
|
||||
Overrides all of
|
||||
.Fl -debug ,
|
||||
.Fl -errors-to-stdout ,
|
||||
and
|
||||
.Fl -print-errors .
|
||||
This option is overridden and disabled if the
|
||||
.Ev PKG_CONFIG_DEBUG_SPEW
|
||||
environment variable is set.
|
||||
.It Fl -simulate
|
||||
Simulates resolving a dependency graph based on the requested modules on the
|
||||
command line.
|
||||
Dumps a series of trees denoting pkgconf's resolver state.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -solution
|
||||
Print the names of the modules requested with
|
||||
.Ar module
|
||||
arguments and their dependencies to standard output.
|
||||
This option is only available if the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was not defined during compilation.
|
||||
.It Fl -static
|
||||
Compute a deeper dependency graph and use compiler/linker flags intended for
|
||||
static linking.
|
||||
This option is overridden by
|
||||
.Fl -shared .
|
||||
.It Fl -uninstalled
|
||||
Exit with a non-zero result if the dependency resolver uses an
|
||||
.Sq uninstalled
|
||||
module as part of its solution.
|
||||
.It Fl -validate Ar package ...
|
||||
Validate specific
|
||||
.Sq .pc
|
||||
files for correctness.
|
||||
This option implies
|
||||
.Fl -print-errors
|
||||
and
|
||||
.Fl -errors-to-stdout .
|
||||
.It Fl -variable Ns = Ns Ar varname
|
||||
For the first
|
||||
.Ar module
|
||||
given on the command line, print the value of the variable with the name
|
||||
.Ar varname
|
||||
to standard output.
|
||||
Any subsequent arguments are silently ignored.
|
||||
This option implies
|
||||
.Fl -maximum-traverse-depth Ns =1
|
||||
and overrides and disables all
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -libs
|
||||
flags.
|
||||
.It Fl -verbose
|
||||
This option only has an effect if
|
||||
.Fl -modversion
|
||||
is also specified.
|
||||
It prints the name of the respective
|
||||
.Ar module
|
||||
and a colon before each version number.
|
||||
.It Fl -version
|
||||
Print the version number of the
|
||||
.Nm
|
||||
program to standard output and exit.
|
||||
Most other options and all command line arguments are ignored.
|
||||
.It Fl -with-path Ns = Ns Ar path
|
||||
Prepend the directory
|
||||
.Ar path
|
||||
to the module search path,
|
||||
giving it priority over all other directories including those from
|
||||
.Ev PKG_CONFIG_PATH
|
||||
and
|
||||
.Ev PKG_CONFIG_LIBDIR .
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width indent
|
||||
.It Va PKG_CONFIG_PATH
|
||||
List of secondary directories where
|
||||
.Sq .pc
|
||||
files are looked up.
|
||||
.It Va PKG_CONFIG_LIBDIR
|
||||
List of primary directories where
|
||||
.Sq .pc
|
||||
files are looked up.
|
||||
.It Va PKG_CONFIG_SYSROOT_DIR
|
||||
.Sq sysroot
|
||||
directory, will be prepended to every path defined in
|
||||
.Va PKG_CONFIG_PATH .
|
||||
Useful for cross compilation.
|
||||
.It Va PKG_CONFIG_TOP_BUILD_DIR
|
||||
Provides an alternative setting for the
|
||||
.Sq pc_top_builddir
|
||||
global variable.
|
||||
.It Va PKG_CONFIG_PURE_DEPGRAPH
|
||||
If set, enables the same behaviour as the
|
||||
.Fl -pure
|
||||
flag.
|
||||
.It Va PKG_CONFIG_SYSTEM_INCLUDE_PATH
|
||||
List of paths that are considered system include paths by the toolchain.
|
||||
This is a pkgconf-specific extension.
|
||||
.It Va PKG_CONFIG_SYSTEM_LIBRARY_PATH
|
||||
List of paths that are considered system library paths by the toolchain.
|
||||
This is a pkgconf-specific extension.
|
||||
.It Va PKG_CONFIG_DISABLE_UNINSTALLED
|
||||
.It Ev CPATH
|
||||
First supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev CPLUS_INCLUDE_PATH
|
||||
Third supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev C_INCLUDE_PATH
|
||||
Second supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev DESTDIR
|
||||
If set to the same value as
|
||||
.Ev PKG_CONFIG_SYSROOT_DIR ,
|
||||
behave in the same way as if
|
||||
.Ev PKG_CONFIG_FDO_SYSROOT_RULES
|
||||
is set.
|
||||
If
|
||||
.Ev PKG_CONFIG_SYSROOT_DIR
|
||||
is not set or set to a different value,
|
||||
.Ev DESTDIR
|
||||
is ignored.
|
||||
.It Ev LIBRARY_PATH
|
||||
Supplementary colon-separated list of library paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_LIBRARY_PATH .
|
||||
.It Ev OBJC_INCLUDE_PATH
|
||||
Fourth supplementary colon-separated list of include paths filtered out
|
||||
in the same way as
|
||||
.Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH .
|
||||
.It Ev PKG_CONFIG_ALLOW_SYSTEM_CFLAGS
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -keep-system-cflags
|
||||
option.
|
||||
.It Ev PKG_CONFIG_ALLOW_SYSTEM_LIBS
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -keep-system-libs
|
||||
option.
|
||||
.It Ev PKG_CONFIG_DEBUG_SPEW
|
||||
If set, override and disable the
|
||||
.Fl -silence-errors
|
||||
option.
|
||||
.It Ev PKG_CONFIG_DISABLE_UNINSTALLED
|
||||
If set, enables the same behaviour as the
|
||||
.Fl -no-uninstalled
|
||||
flag.
|
||||
.It Va PKG_CONFIG_LOG
|
||||
.Sq logfile
|
||||
which is used for dumping audit information concerning installed module versions.
|
||||
.It Va PKG_CONFIG_DEBUG_SPEW
|
||||
If set, enables additional debug logging.
|
||||
The format of the debug log messages is implementation-specific.
|
||||
.It Va PKG_CONFIG_DONT_RELOCATE_PATHS
|
||||
.It Ev PKG_CONFIG_DONT_DEFINE_PREFIX
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -dont-define-prefix
|
||||
option.
|
||||
.It Ev PKG_CONFIG_DONT_RELOCATE_PATHS
|
||||
If set, disables the path relocation feature.
|
||||
.It Va PKG_CONFIG_MSVC_SYNTAX
|
||||
If set, uses MSVC syntax for fragments.
|
||||
.It Va PKG_CONFIG_FDO_SYSROOT_RULES
|
||||
.It Ev PKG_CONFIG_FDO_SYSROOT_RULES
|
||||
If set, follow the sysroot prefixing rules that freedesktop.org pkg-config uses.
|
||||
.It Va DESTDIR
|
||||
If set to PKG_CONFIG_SYSROOT_DIR, assume that PKG_CONFIG_FDO_SYSROOT_RULES is set.
|
||||
.It Ev PKG_CONFIG_IGNORE_CONFLICTS
|
||||
If set, ignore
|
||||
.Ic Conflicts
|
||||
rules in modules.
|
||||
Has the same effect as the
|
||||
.Fl -ignore-conflicts
|
||||
option.
|
||||
.It Ev PKG_CONFIG_LIBDIR
|
||||
A colon-separated list of low-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
The module search path is constructed by appending this list to
|
||||
.Ev PKG_CONFIG_PATH ,
|
||||
which enjoys higher priority.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv PKG_DEFAULT_PATH
|
||||
preprocessor macro is appended instead.
|
||||
If
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
is defined but empty, nothing is appended.
|
||||
.It Ev PKG_CONFIG_LOG
|
||||
If set, log information about selected modules
|
||||
to the file with the name stored in this variable.
|
||||
For more details, see the
|
||||
.Fl -log-file
|
||||
command line option, which overrides this variable.
|
||||
.It Ev PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH
|
||||
Impose a limit on the allowed depth in the dependency graph.
|
||||
This variable overrides the
|
||||
.Fl -maximum-traverse-depth
|
||||
option, but is overridden by the other options mentioned there.
|
||||
.It Ev PKG_CONFIG_MSVC_SYNTAX
|
||||
If set, use MSVC syntax for
|
||||
.Fl -cflags ,
|
||||
.Fl -env ,
|
||||
and
|
||||
.Fl -libs
|
||||
output.
|
||||
This variable has the same effect as the
|
||||
.Fl -msvc-syntax
|
||||
option.
|
||||
If the preprocessor macro
|
||||
.Dv PKGCONF_LITE
|
||||
was defined during compilation, this variable is ignored.
|
||||
.It Ev PKG_CONFIG_PATH
|
||||
A colon-separated list of high-priority directories where
|
||||
.Xr pc 5
|
||||
files are looked up.
|
||||
The module search path is constructed
|
||||
by prepending the directory specified with
|
||||
.Fl -with-path ,
|
||||
if any, and unless
|
||||
.Fl -env-only
|
||||
is specified, by appending either
|
||||
.Ev PKG_CONFIG_LIBDIR
|
||||
or the compiled-in default directories with lower priority.
|
||||
.It Ev PKG_CONFIG_PRELOADED_FILES
|
||||
Colon-separated list of
|
||||
.Xr pc 5
|
||||
files which are loaded before any other pkg-config files.
|
||||
These packages are given highest priority over any other
|
||||
.Xr pc 5
|
||||
files that would otherwise provide a given package.
|
||||
.It Ev PKG_CONFIG_PURE_DEPGRAPH
|
||||
If set, enables the same behaviour as the
|
||||
.Fl -pure
|
||||
flag.
|
||||
.It Ev PKG_CONFIG_RELOCATE_PATHS
|
||||
If set, this variable has the same effect as the
|
||||
.Fl -define-prefix
|
||||
option.
|
||||
.It Ev PKG_CONFIG_SYSROOT_DIR
|
||||
If set, this variable defines a
|
||||
.Sq sysroot
|
||||
directory, which will be prepended to every path variable
|
||||
beginning with the prefix variable in a given
|
||||
.Xr pc 5
|
||||
file.
|
||||
Useful for cross compilation.
|
||||
The value of this environment variable is also copied into the global variable
|
||||
.Va pc_sysrootdir .
|
||||
.It Ev PKG_CONFIG_SYSTEM_INCLUDE_PATH
|
||||
Colon-separated list of include paths that are filtered out
|
||||
and not printed by the
|
||||
.Fl -cflags
|
||||
and
|
||||
.Fl -cflags-only-I
|
||||
options because they are considered system include paths.
|
||||
If not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv SYSTEM_INCLUDEDIR
|
||||
preprocessor macro is used instead.
|
||||
This variable is a pkgconf-specific extension.
|
||||
Any directories listed in the environment variables
|
||||
.Ev CPATH ,
|
||||
.Ev C_INCLUDE_PATH ,
|
||||
.Ev CPLUS_INCLUDE_PATH ,
|
||||
and
|
||||
.Ev OBJC_INCLUDE_PATH
|
||||
are also filtered out.
|
||||
.It Ev PKG_CONFIG_SYSTEM_LIBRARY_PATH
|
||||
Colon-separated list of library paths that are filtered out
|
||||
and not printed by the
|
||||
.Fl -libs
|
||||
and
|
||||
.Fl -libs-only-L
|
||||
options because they are considered system library paths.
|
||||
If not defined, the default list compiled into the
|
||||
.Nm
|
||||
program from the
|
||||
.Dv SYSTEM_LIBDIR
|
||||
preprocessor macro is used instead.
|
||||
This variable is a pkgconf-specific extension.
|
||||
.It Ev PKG_CONFIG_TOP_BUILD_DIR
|
||||
The value of the
|
||||
.Va pc_top_builddir
|
||||
global variable.
|
||||
If this environment variable is not defined, the string
|
||||
.Qq $(top_builddir)
|
||||
is used as the value of
|
||||
.Va pc_top_builddir .
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
Displaying the CFLAGS of a package:
|
||||
.Dl $ pkgconf --cflags foo
|
||||
|
||||
110
meson.build
110
meson.build
@ -1,15 +1,17 @@
|
||||
project('pkgconf', 'c',
|
||||
version : '2.3.0',
|
||||
version : '2.5.1',
|
||||
license : 'ISC',
|
||||
meson_version : '>=0.49',
|
||||
default_options : ['c_std=c99'],
|
||||
meson_version: '>=0.52',
|
||||
)
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
add_project_arguments(
|
||||
'-D_BSD_SOURCE',
|
||||
'-D_DARWIN_C_SOURCE',
|
||||
'-D_DEFAULT_SOURCE',
|
||||
'-D_POSIX_C_SOURCE=200809L',
|
||||
cc.get_supported_arguments(
|
||||
'-Wimplicit-function-declaration',
|
||||
'-Wmisleading-indentation',
|
||||
@ -27,11 +29,14 @@ check_functions = [
|
||||
['strncasecmp', 'strings.h'],
|
||||
['strcasecmp', 'strings.h'],
|
||||
['reallocarray', 'stdlib.h'],
|
||||
['pledge', 'unistd.h'],
|
||||
['unveil', 'unistd.h'],
|
||||
['readlinkat', 'unistd.h'],
|
||||
]
|
||||
|
||||
foreach f : check_functions
|
||||
name = f[0].to_upper().underscorify()
|
||||
if cc.has_function(f[0], prefix : '#define _BSD_SOURCE\n#include <@0@>'.format(f[1])) and cc.has_header_symbol(f[1], f[0], prefix : '#define _BSD_SOURCE')
|
||||
if cc.has_function(f[0], prefix : '#define _BSD_SOURCE\n#define _DARWIN_C_SOURCE\n#define _DEFAULT_SOURCE\n#define _POSIX_C_SOURCE 200809L\n#include <@0@>'.format(f[1])) and cc.has_header_symbol(f[1], f[0], prefix : '#define _BSD_SOURCE\n#define _DARWIN_C_SOURCE\n#define _DEFAULT_SOURCE\n#define _POSIX_C_SOURCE 200809L')
|
||||
cdata.set('HAVE_@0@'.format(name), 1)
|
||||
cdata.set('HAVE_DECL_@0@'.format(name), 1)
|
||||
else
|
||||
@ -82,12 +87,14 @@ endif
|
||||
libpkgconf = library('pkgconf',
|
||||
'libpkgconf/argvsplit.c',
|
||||
'libpkgconf/audit.c',
|
||||
'libpkgconf/buffer.c',
|
||||
'libpkgconf/bsdstubs.c',
|
||||
'libpkgconf/cache.c',
|
||||
'libpkgconf/client.c',
|
||||
'libpkgconf/dependency.c',
|
||||
'libpkgconf/fileio.c',
|
||||
'libpkgconf/fragment.c',
|
||||
'libpkgconf/output.c',
|
||||
'libpkgconf/parser.c',
|
||||
'libpkgconf/path.c',
|
||||
'libpkgconf/personality.c',
|
||||
@ -96,8 +103,8 @@ libpkgconf = library('pkgconf',
|
||||
'libpkgconf/tuple.c',
|
||||
c_args: ['-DLIBPKGCONF_EXPORT', build_static],
|
||||
install : true,
|
||||
version : '5.0.0',
|
||||
soversion : '5',
|
||||
version : '7.0.0',
|
||||
soversion : '7',
|
||||
)
|
||||
|
||||
# For other projects using libpkgconfig as a subproject
|
||||
@ -122,22 +129,72 @@ pkg.generate(libpkgconf,
|
||||
extra_cflags : build_static
|
||||
)
|
||||
|
||||
cli_include = include_directories('cli')
|
||||
|
||||
pkgconf_exe = executable('pkgconf',
|
||||
'cli/main.c',
|
||||
'cli/core.c',
|
||||
'cli/getopt_long.c',
|
||||
'cli/renderer-msvc.c',
|
||||
link_with : libpkgconf,
|
||||
c_args: build_static,
|
||||
c_args : build_static,
|
||||
include_directories : cli_include,
|
||||
install : true)
|
||||
|
||||
bomtool_exe = executable('bomtool',
|
||||
'cli/bomtool/main.c',
|
||||
'cli/getopt_long.c',
|
||||
link_with : libpkgconf,
|
||||
c_args : build_static,
|
||||
include_directories : cli_include,
|
||||
install : true)
|
||||
|
||||
spdxtool_exe = executable('spdxtool',
|
||||
'cli/spdxtool/main.c',
|
||||
'cli/spdxtool/core.c',
|
||||
'cli/spdxtool/software.c',
|
||||
'cli/spdxtool/serialize.c',
|
||||
'cli/spdxtool/simplelicensing.c',
|
||||
'cli/spdxtool/util.c',
|
||||
'cli/getopt_long.c',
|
||||
link_with : libpkgconf,
|
||||
c_args : build_static,
|
||||
include_directories : include_directories('cli', 'cli/spdxtool'),
|
||||
install : true)
|
||||
|
||||
test_runner_exe = executable('test-runner',
|
||||
'cli/core.c',
|
||||
'cli/getopt_long.c',
|
||||
'cli/renderer-msvc.c',
|
||||
'tests/test-runner.c',
|
||||
link_with : libpkgconf,
|
||||
c_args : build_static,
|
||||
include_directories : cli_include,
|
||||
install : true)
|
||||
|
||||
fixtures_dir = '@0@/tests'.format(meson.current_source_dir())
|
||||
test_suites = [
|
||||
'basic',
|
||||
'ordering',
|
||||
'parser',
|
||||
'solver',
|
||||
'sbom',
|
||||
'sysroot',
|
||||
'tuple',
|
||||
]
|
||||
|
||||
foreach t : test_suites
|
||||
test(t, test_runner_exe, args : ['--test-fixtures', fixtures_dir, '@0@/t/@1@'.format(meson.current_source_dir(), t)])
|
||||
endforeach
|
||||
|
||||
with_tests = get_option('tests')
|
||||
kyua_exe = find_program('kyua', required : with_tests, disabler : true)
|
||||
atf_sh_exe = find_program('atf-sh', required : with_tests, disabler : true)
|
||||
kyua_exe = find_program('kyua', required : with_tests, disabler : true, native : true)
|
||||
atf_sh_exe = find_program('atf-sh', required : with_tests, disabler : true, native : true)
|
||||
kyuafile = configure_file(input : 'Kyuafile.in', output : 'Kyuafile', configuration : cdata)
|
||||
test('kyua', kyua_exe, args : ['--config=none', 'test', '--kyuafile', kyuafile, '--build-root', meson.current_build_dir()])
|
||||
subdir('tests')
|
||||
|
||||
install_man('man/bomtool.1')
|
||||
install_man('man/pkgconf.1')
|
||||
install_man('man/pkg.m4.7')
|
||||
install_man('man/pc.5')
|
||||
@ -145,3 +202,40 @@ install_man('man/pkgconf-personality.5')
|
||||
install_data('pkg.m4', install_dir: 'share/aclocal')
|
||||
install_data('AUTHORS', install_dir: 'share/doc/pkgconf')
|
||||
install_data('README.md', install_dir: 'share/doc/pkgconf')
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
conf_data = configuration_data()
|
||||
conf_data.set('VERSION', meson.project_version())
|
||||
conf_data.set('EXE', pkgconf_exe.full_path())
|
||||
conf_data.set('DLL', libpkgconf.full_path())
|
||||
if host_machine.cpu() != 'x86_64'
|
||||
wixl_arch = 'x86'
|
||||
else
|
||||
wixl_arch = 'x64'
|
||||
endif
|
||||
conf_data.set('WIXL_ARCH', wixl_arch)
|
||||
|
||||
python = find_program('python3')
|
||||
wixl = find_program('wixl', required: false, version: '>= 0.105')
|
||||
msi_filename = 'pkgconf-@0@-@1@.msi'.format(wixl_arch, meson.project_version())
|
||||
|
||||
wxsfile = configure_file(input: 'pkgconf.wxs.in', output: 'pkgconf.wxs', configuration: conf_data)
|
||||
|
||||
if wixl.found()
|
||||
licensefile = custom_target(
|
||||
'License.rtf',
|
||||
input: 'COPYING',
|
||||
output: 'License.rtf',
|
||||
command: [python, files('txt2rtf.py'), '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
|
||||
msi = custom_target(
|
||||
msi_filename,
|
||||
input: [wxsfile, licensefile, pkgconf_exe],
|
||||
output: msi_filename,
|
||||
command: [wixl, '--arch', wixl_arch, '--ext', 'ui', '-o', msi_filename, wxsfile],
|
||||
)
|
||||
|
||||
alias_target('msi', msi)
|
||||
endif
|
||||
endif
|
||||
|
||||
25
pkg.m4
25
pkg.m4
@ -1,5 +1,5 @@
|
||||
# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*-
|
||||
# serial 12 (pkg-config-0.29.2)
|
||||
# serial 16 (pkgconf)
|
||||
|
||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||
@ -15,9 +15,7 @@ dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
dnl General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
dnl along with this program; if not, write to the Free Software
|
||||
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
dnl 02111-1307, USA.
|
||||
dnl along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
dnl
|
||||
dnl As a special exception to the GNU General Public License, if you
|
||||
dnl distribute this file as part of a program that contains a
|
||||
@ -46,8 +44,8 @@ m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
|
||||
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
|
||||
])dnl PKG_PREREQ
|
||||
|
||||
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND])
|
||||
dnl ---------------------------------------------------------
|
||||
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
dnl ----------------------------------
|
||||
dnl Since: 0.16
|
||||
dnl
|
||||
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
|
||||
@ -55,12 +53,6 @@ dnl first found in the path. Checks that the version of pkg-config found
|
||||
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
|
||||
dnl used since that's the first version where most current features of
|
||||
dnl pkg-config existed.
|
||||
dnl
|
||||
dnl If pkg-config is not found or older than specified, it will result
|
||||
dnl in an empty PKG_CONFIG variable. To avoid widespread issues with
|
||||
dnl scripts not checking it, ACTION-IF-NOT-FOUND defaults to aborting.
|
||||
dnl You can specify [PKG_CONFIG=false] as an action instead, which would
|
||||
dnl result in pkg-config tests failing, but no bogus error messages.
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||
@ -81,9 +73,6 @@ if test -n "$PKG_CONFIG"; then
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi
|
||||
if test -z "$PKG_CONFIG"; then
|
||||
m4_default([$2], [AC_MSG_ERROR([pkg-config not found])])
|
||||
fi[]dnl
|
||||
])dnl PKG_PROG_PKG_CONFIG
|
||||
|
||||
@ -184,13 +173,13 @@ _PKG_TEXT])[]dnl
|
||||
elif test $pkg_failed = untried; then
|
||||
AC_MSG_RESULT([no])
|
||||
m4_default([$4], [AC_MSG_FAILURE(
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
[A pkg-config implementation could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
|
||||
To get a pkg-config implementation, see <http://github.com/pkgconf/pkgconf>.])[]dnl
|
||||
])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
@ -311,7 +300,7 @@ AC_ARG_WITH(with_arg,
|
||||
[AS_TR_SH([with_]with_arg)=def_arg])
|
||||
|
||||
AS_CASE([$AS_TR_SH([with_]with_arg)],
|
||||
[yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
|
||||
[yes],[PKG_CHECK_MODULES([$1],[$2],[$3],[$4])],
|
||||
[auto],[PKG_CHECK_MODULES([$1],[$2],
|
||||
[m4_n([def_action_if_found]) $3],
|
||||
[m4_n([def_action_if_not_found]) $4])])
|
||||
|
||||
64
pkgconf.wxs.in
Normal file
64
pkgconf.wxs.in
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
|
||||
<?define Arch = "@WIXL_ARCH@"?>
|
||||
<?if $(var.Arch) = "x64"?>
|
||||
<?define GLIB_ARCH = "win64"?>
|
||||
<?define ArchString = "64-bit"?>
|
||||
<?define ArchProgramFilesFolder = "ProgramFiles64Folder"?>
|
||||
<?define Win64 = "yes"?>
|
||||
<?else?>
|
||||
<?define GLIB_ARCH = "win32"?>
|
||||
<?define ArchString = "32-bit"?>
|
||||
<?define ArchProgramFilesFolder = "ProgramFilesFolder"?>
|
||||
<?define Win64 = "no"?>
|
||||
<?endif?>
|
||||
|
||||
|
||||
<Product Id="*"
|
||||
Name="pkgconf @VERSION@ ($(var.ArchString))"
|
||||
Language="1033"
|
||||
Version="@VERSION@"
|
||||
Manufacturer="pkgconf"
|
||||
UpgradeCode="4faedad2-3f9d-45cc-89a7-3732ad2db0f7">
|
||||
|
||||
<Package InstallerVersion="200"
|
||||
Compressed="yes"
|
||||
InstallScope="perMachine" />
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Feature Id="ProductFeature" Title="pkgconf" Level="1">
|
||||
<ComponentGroupRef Id="ProductComponents" />
|
||||
</Feature>
|
||||
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="$(var.ArchProgramFilesFolder)">
|
||||
<Directory Id="INSTALLFOLDER" Name="pkgconf @VERSION@" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
|
||||
<Component Id="PkgconfExe" Guid="*" Win64="$(var.Win64)">
|
||||
<File Id="PkgconfExeFile"
|
||||
Source="@EXE@"
|
||||
KeyPath="yes" />
|
||||
<File Id="PkgconfigExeFile"
|
||||
Name="pkg-config.exe"
|
||||
Source="@EXE@"/>
|
||||
<File Id="PkgconfDllFile"
|
||||
Source="@DLL@"/>
|
||||
<Environment Id="PATH"
|
||||
Name="PATH"
|
||||
Value="[INSTALLFOLDER]"
|
||||
Permanent="no"
|
||||
Part="last"
|
||||
Action="set"
|
||||
System="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
<UIRef Id="WixUI_Minimal" />
|
||||
</Product>
|
||||
</Wix>
|
||||
3
t/basic/arbitrary-path.test
Normal file
3
t/basic/arbitrary-path.test
Normal file
@ -0,0 +1,3 @@
|
||||
Query: %TEST_FIXTURES_DIR%/lib1/foo.pc
|
||||
WantedFlags: libs
|
||||
ExpectedStdout: -L/test/lib -lfoo
|
||||
3
t/basic/builtin-pkg-config-exists.test
Normal file
3
t/basic/builtin-pkg-config-exists.test
Normal file
@ -0,0 +1,3 @@
|
||||
Query: pkgconf
|
||||
WantedFlags: exists
|
||||
ExpectedExitCode: 0
|
||||
5
t/basic/builtin-pkg-config-pc_path-variable.test
Normal file
5
t/basic/builtin-pkg-config-pc_path-variable.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: pkg-config
|
||||
WantVariable: pc_path
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: %TEST_FIXTURES_DIR%/lib1
|
||||
3
t/basic/builtin-pkgconf-exists.test
Normal file
3
t/basic/builtin-pkgconf-exists.test
Normal file
@ -0,0 +1,3 @@
|
||||
Query: pkgconf
|
||||
WantedFlags: exists
|
||||
ExpectedExitCode: 0
|
||||
5
t/basic/builtin-pkgconf-pc_path-variable.test
Normal file
5
t/basic/builtin-pkgconf-pc_path-variable.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: pkgconf
|
||||
WantVariable: pc_path
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: %TEST_FIXTURES_DIR%/lib1
|
||||
5
t/basic/define-prefix-child-prefix-env.test
Normal file
5
t/basic/define-prefix-child-prefix-env.test
Normal file
@ -0,0 +1,5 @@
|
||||
Environment: PKG_CONFIG_PATH=%TEST_FIXTURES_DIR%/lib1/child-prefix/pkgconfig
|
||||
Environment: PKG_CONFIG_RELOCATE_PATHS=1
|
||||
WantedFlags: cflags libs
|
||||
Query: child-prefix-1
|
||||
ExpectedStdout: -I%TEST_FIXTURES_DIR%/lib1/include/child-prefix-1 -L%TEST_FIXTURES_DIR%/lib1/lib64 -lchild-prefix-1
|
||||
4
t/basic/define-prefix-child-prefix.test
Normal file
4
t/basic/define-prefix-child-prefix.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1/child-prefix/pkgconfig
|
||||
WantedFlags: define-prefix cflags libs
|
||||
Query: child-prefix-1
|
||||
ExpectedStdout: -I%TEST_FIXTURES_DIR%/lib1/include/child-prefix-1 -L%TEST_FIXTURES_DIR%/lib1/lib64 -lchild-prefix-1
|
||||
4
t/basic/define-prefix.test
Normal file
4
t/basic/define-prefix.test
Normal file
@ -0,0 +1,4 @@
|
||||
WantVariable: prefix
|
||||
WantedFlags: define-prefix
|
||||
Query: %TEST_FIXTURES_DIR%/lib-relocatable/lib/pkgconfig/foo.pc
|
||||
ExpectedStdout: %TEST_FIXTURES_DIR%/lib-relocatable
|
||||
4
t/basic/direct-query-with-pkg_config_path.test
Normal file
4
t/basic/direct-query-with-pkg_config_path.test
Normal file
@ -0,0 +1,4 @@
|
||||
Environment: PKG_CONFIG_PATH=%TEST_FIXTURES_DIR%/lib2
|
||||
Query: %TEST_FIXTURES_DIR%/lib3/bar.pc
|
||||
WantedFlags: cflags
|
||||
ExpectedStdout: -fPIC -I/test/include/foo
|
||||
5
t/basic/env-tuple.test
Normal file
5
t/basic/env-tuple.test
Normal file
@ -0,0 +1,5 @@
|
||||
Environment: PKG_CONFIG_DUPLICATE_TUPLE_PREFIX=/bar
|
||||
PackageSearchPath: lib1
|
||||
WantVariable: prefix
|
||||
Query: duplicate-tuple
|
||||
ExpectedStdout: /bar
|
||||
8
t/basic/exists-cflags-env.test
Normal file
8
t/basic/exists-cflags-env.test
Normal file
@ -0,0 +1,8 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantedFlags: cflags exists-cflags
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: FOO_CFLAGS='-DHAVE_FOO'
|
||||
MatchStdout: partial
|
||||
WantEnvPrefix: FOO
|
||||
FragmentFilter: D
|
||||
6
t/basic/exists-cflags.test
Normal file
6
t/basic/exists-cflags.test
Normal file
@ -0,0 +1,6 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantedFlags: cflags exists-cflags
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: -DHAVE_FOO
|
||||
MatchStdout: partial
|
||||
4
t/basic/exists-nonexistent.test
Normal file
4
t/basic/exists-nonexistent.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: nonexistent
|
||||
WantedFlags: exists
|
||||
ExpectedExitCode: 1
|
||||
3
t/basic/exists-version-greater-than-with-tilde.test
Normal file
3
t/basic/exists-version-greater-than-with-tilde.test
Normal file
@ -0,0 +1,3 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: tilde >= 1.0.0
|
||||
ExpectedExitCode: 1
|
||||
4
t/basic/exists-version-greater-than.test
Normal file
4
t/basic/exists-version-greater-than.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo > 1.2.3
|
||||
WantedFlags: exists
|
||||
ExpectedExitCode: 1
|
||||
3
t/basic/exists-version-less-than-with-tilde.test
Normal file
3
t/basic/exists-version-less-than-with-tilde.test
Normal file
@ -0,0 +1,3 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: tilde <= 1.0.0
|
||||
ExpectedExitCode: 0
|
||||
4
t/basic/exists-version-malformed.test
Normal file
4
t/basic/exists-version-malformed.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo >=
|
||||
WantedFlags: exists
|
||||
ExpectedExitCode: 1
|
||||
4
t/basic/exists-version-minimum.test
Normal file
4
t/basic/exists-version-minimum.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo > 1.2
|
||||
WantedFlags: exists
|
||||
ExpectedExitCode: 0
|
||||
3
t/basic/exists-version-with-tilde.test
Normal file
3
t/basic/exists-version-with-tilde.test
Normal file
@ -0,0 +1,3 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: tilde = 1.0.0~rc1
|
||||
ExpectedExitCode: 0
|
||||
4
t/basic/incomplete-cflags.test
Normal file
4
t/basic/incomplete-cflags.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: incomplete
|
||||
WantedFlags: cflags
|
||||
ExpectedStdout:
|
||||
4
t/basic/incomplete-libs.test
Normal file
4
t/basic/incomplete-libs.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: incomplete
|
||||
WantedFlags: libs
|
||||
ExpectedStdout:
|
||||
4
t/basic/keep-system-libs-2.test
Normal file
4
t/basic/keep-system-libs-2.test
Normal file
@ -0,0 +1,4 @@
|
||||
Environment: PKG_CONFIG_SYSTEM_LIBRARY_PATH=/test/local/lib
|
||||
PackageSearchPath: lib1
|
||||
WantedFlags: libs-only-ldpath keep-system-libs
|
||||
Query: cflags-libs-only
|
||||
6
t/basic/keep-system-libs.test
Normal file
6
t/basic/keep-system-libs.test
Normal file
@ -0,0 +1,6 @@
|
||||
Environment: PKG_CONFIG_SYSTEM_LIBRARY_PATH=/test/local/lib
|
||||
PackageSearchPath: lib1
|
||||
WantedFlags: libs-only-ldpath
|
||||
ExpectedStdout:
|
||||
MatchStdout: empty
|
||||
Query: cflags-libs-only
|
||||
5
t/basic/libs-cflags-version-multiple-comma.test
Normal file
5
t/basic/libs-cflags-version-multiple-comma.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo > 1.2,bar >= 1.3
|
||||
WantedFlags: libs cflags
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: -fPIC -I/test/include/foo -L/test/lib -lbar -lfoo
|
||||
5
t/basic/libs-cflags-version-multiple.test
Normal file
5
t/basic/libs-cflags-version-multiple.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo > 1.2 bar >= 1.3
|
||||
WantedFlags: libs cflags
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: -fPIC -I/test/include/foo -L/test/lib -lbar -lfoo
|
||||
6
t/basic/libs-cflags-version-not-provided.test
Normal file
6
t/basic/libs-cflags-version-not-provided.test
Normal file
@ -0,0 +1,6 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo != 1.2.3
|
||||
WantedFlags: libs cflags
|
||||
ExpectedExitCode: 1
|
||||
MatchStderr: partial
|
||||
ExpectedStderr: Package 'foo' has version '1.2.3', required version is '!= 1.2.3'
|
||||
5
t/basic/libs-cflags-version-not.test
Normal file
5
t/basic/libs-cflags-version-not.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo != 1.3.0
|
||||
WantedFlags: libs cflags
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: -fPIC -I/test/include/foo -L/test/lib -lfoo
|
||||
5
t/basic/libs-cflags-version.test
Normal file
5
t/basic/libs-cflags-version.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo > 1.2
|
||||
WantedFlags: libs cflags
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: -fPIC -I/test/include/foo -L/test/lib -lfoo
|
||||
5
t/basic/libs-cflags.test
Normal file
5
t/basic/libs-cflags.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantedFlags: libs cflags
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: -fPIC -I/test/include/foo -L/test/lib -lfoo
|
||||
6
t/basic/libs-env.test
Normal file
6
t/basic/libs-env.test
Normal file
@ -0,0 +1,6 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantedFlags: libs
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: FOO_LIBS='-L/test/lib -lfoo'
|
||||
WantEnvPrefix: FOO
|
||||
4
t/basic/libs-only.test
Normal file
4
t/basic/libs-only.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: cflags-libs-only
|
||||
WantedFlags: libs-only-ldpath libs-only-libname
|
||||
ExpectedStdout: -L/test/local/lib -lfoo
|
||||
5
t/basic/libs.test
Normal file
5
t/basic/libs.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantedFlags: libs
|
||||
ExpectedExitCode: 0
|
||||
ExpectedStdout: -L/test/lib -lfoo
|
||||
3
t/basic/malformed-empty-package.test
Normal file
3
t/basic/malformed-empty-package.test
Normal file
@ -0,0 +1,3 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: , foo
|
||||
ExpectedExitCode: 0
|
||||
3
t/basic/modversion-fullpath.test
Normal file
3
t/basic/modversion-fullpath.test
Normal file
@ -0,0 +1,3 @@
|
||||
WantedFlags: modversion
|
||||
Query: %TEST_FIXTURES_DIR%/lib1/bar.pc
|
||||
ExpectedStdout: 1.3
|
||||
4
t/basic/modversion-noflatten.test
Normal file
4
t/basic/modversion-noflatten.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
WantedFlags: modversion
|
||||
Query: bar
|
||||
ExpectedStdout: 1.3
|
||||
4
t/basic/modversion-uninstalled.test
Normal file
4
t/basic/modversion-uninstalled.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
WantedFlags: modversion
|
||||
Query: omg
|
||||
ExpectedStdout: 1.2.3
|
||||
7
t/basic/modversion-verbose-prefix.test
Normal file
7
t/basic/modversion-verbose-prefix.test
Normal file
@ -0,0 +1,7 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo, foobar
|
||||
WantedFlags: modversion
|
||||
VerbosityLevel: 1
|
||||
ExpectedStdout: foo: 1.2.3
|
||||
ExpectedStdout: foobar: 3.2.1
|
||||
MatchStdout: partial
|
||||
3
t/basic/noargs.test
Normal file
3
t/basic/noargs.test
Normal file
@ -0,0 +1,3 @@
|
||||
Query:
|
||||
ExpectedExitCode: 1
|
||||
ExpectedStderr: Please specify at least one package name on the command line.
|
||||
5
t/basic/nocflags.test
Normal file
5
t/basic/nocflags.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: nocflag
|
||||
WantedFlags: cflags
|
||||
ExpectedStdout:
|
||||
ExpectedExitCode: 0
|
||||
5
t/basic/nolibs.test
Normal file
5
t/basic/nolibs.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: nolib
|
||||
WantedFlags: libs
|
||||
ExpectedStdout:
|
||||
ExpectedExitCode: 0
|
||||
4
t/basic/pkg-config-path.test
Normal file
4
t/basic/pkg-config-path.test
Normal file
@ -0,0 +1,4 @@
|
||||
Environment: PKG_CONFIG_PATH=%TEST_FIXTURES_DIR%/lib1%DIR_SEP%%TEST_FIXTURES_DIR%/lib2
|
||||
WantedFlags: libs
|
||||
Query: bar
|
||||
ExpectedStdout: -L/test/lib -lbar -lfoo
|
||||
12
t/basic/print-variables-env.test
Normal file
12
t/basic/print-variables-env.test
Normal file
@ -0,0 +1,12 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantedFlags: print-variables cflags libs
|
||||
WantEnvPrefix: FOO
|
||||
ExpectedStdout: FOO_CFLAGS='-fPIC -I/test/include/foo'
|
||||
ExpectedStdout: FOO_LIBS='-L/test/lib -lfoo'
|
||||
ExpectedStdout: FOO_INCLUDEDIR='/test/include'
|
||||
ExpectedStdout: FOO_LIBDIR='/test/lib'
|
||||
ExpectedStdout: FOO_EXEC_PREFIX='/test'
|
||||
ExpectedStdout: FOO_PREFIX='/test'
|
||||
ExpectedStdout: FOO_PCFILEDIR='%TEST_FIXTURES_DIR%/lib1'
|
||||
MatchStdout: partial
|
||||
5
t/basic/single-depth-selectors.test
Normal file
5
t/basic/single-depth-selectors.test
Normal file
@ -0,0 +1,5 @@
|
||||
Environment: PKG_CONFIG_MAXIMUM_TRAVERSE_DEPTH=1
|
||||
PackageSearchPath: lib3
|
||||
WantedFlags: print-requires
|
||||
Query: bar
|
||||
ExpectedStdout: foo
|
||||
4
t/basic/static-archive-libs.test
Normal file
4
t/basic/static-archive-libs.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
WantedFlags: libs
|
||||
Query: static-archive-libs
|
||||
ExpectedStdout: /libfoo.a -pthread
|
||||
4
t/basic/uninstalled-not.test
Normal file
4
t/basic/uninstalled-not.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantedFlags: uninstalled
|
||||
ExpectedExitCode: 1
|
||||
4
t/basic/uninstalled.test
Normal file
4
t/basic/uninstalled.test
Normal file
@ -0,0 +1,4 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: omg
|
||||
WantedFlags: uninstalled
|
||||
ExpectedExitCode: 0
|
||||
5
t/basic/variable-env.test
Normal file
5
t/basic/variable-env.test
Normal file
@ -0,0 +1,5 @@
|
||||
PackageSearchPath: lib1
|
||||
Query: foo
|
||||
WantVariable: includedir
|
||||
WantEnvPrefix: FOO
|
||||
ExpectedStdout: FOO_INCLUDEDIR='/test/include'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user