Skip to content

Commit ee10984

Browse files
committed
Merge branch 'ps/build-meson-fixes' into ps/zlib-ng
* ps/build-meson-fixes: ci: wire up Visual Studio build with Meson ci: raise error when Meson generates warnings meson: fix compilation with Visual Studio meson: make the CSPRNG backend configurable meson: wire up fuzzers meson: wire up generation of distribution archive meson: wire up development environments meson: fix dependencies for generated headers meson: populate project version via GIT-VERSION-GEN GIT-VERSION-GEN: allow running without input and output files GIT-VERSION-GEN: simplify computing the dirty marker
2 parents 6415658 + 7304bd2 commit ee10984

File tree

7 files changed

+218
-38
lines changed

7 files changed

+218
-38
lines changed

.github/workflows/main.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,58 @@ jobs:
248248
with:
249249
name: failed-tests-windows-vs-${{ matrix.nr }}
250250
path: ${{env.FAILED_TEST_ARTIFACTS}}
251+
252+
windows-meson-build:
253+
name: win+Meson build
254+
needs: ci-config
255+
if: needs.ci-config.outputs.enabled == 'yes'
256+
runs-on: windows-latest
257+
concurrency:
258+
group: windows-meson-build-${{ github.ref }}
259+
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
260+
steps:
261+
- uses: actions/checkout@v4
262+
- uses: actions/setup-python@v5
263+
- name: Set up dependencies
264+
shell: pwsh
265+
run: pip install meson ninja
266+
- name: Setup
267+
shell: pwsh
268+
run: meson setup build -Dperl=disabled
269+
- name: Compile
270+
shell: pwsh
271+
run: meson compile -C build
272+
- name: Upload build artifacts
273+
uses: actions/upload-artifact@v4
274+
with:
275+
name: windows-meson-artifacts
276+
path: build
277+
windows-meson-test:
278+
name: win+Meson test
279+
runs-on: windows-latest
280+
needs: [ci-config, windows-meson-build]
281+
strategy:
282+
fail-fast: false
283+
matrix:
284+
nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
285+
concurrency:
286+
group: windows-meson-test-${{ matrix.nr }}-${{ github.ref }}
287+
cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
288+
steps:
289+
- uses: actions/checkout@v4
290+
- uses: actions/setup-python@v5
291+
- name: Set up dependencies
292+
shell: pwsh
293+
run: pip install meson ninja
294+
- name: Download build artifacts
295+
uses: actions/download-artifact@v4
296+
with:
297+
name: windows-meson-artifacts
298+
path: build
299+
- name: Test
300+
shell: pwsh
301+
run: meson test -C build --list | Select-Object -Skip 1 | Select-String .* | Group-Object -Property { $_.LineNumber % 10 } | Where-Object Name -EQ ${{ matrix.nr }} | ForEach-Object { meson test -C build --no-rebuild --print-errorlogs $_.Group }
302+
251303
regular:
252304
name: ${{matrix.vector.jobname}} (${{matrix.vector.pool}})
253305
needs: ci-config

.gitlab-ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,44 @@ test:mingw64:
149149
- git-sdk/usr/bin/bash.exe -l -c 'ci/print-test-failures.sh'
150150
parallel: 10
151151

152+
.msvc-meson:
153+
tags:
154+
- saas-windows-medium-amd64
155+
before_script:
156+
- choco install -y git meson ninja openssl
157+
- Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
158+
- refreshenv
159+
# The certificate store for Python on Windows is broken and fails to fetch
160+
# certificates, see https://bugs.python.org/issue36011. This seems to
161+
# mostly be an issue with how the GitLab image is set up as it is a
162+
# non-issue on GitHub Actions. Work around the issue by importing
163+
# cetrificates manually.
164+
- Invoke-WebRequest https://curl.haxx.se/ca/cacert.pem -OutFile cacert.pem
165+
- openssl pkcs12 -export -nokeys -in cacert.pem -out certs.pfx -passout "pass:"
166+
- Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath certs.pfx
167+
168+
build:msvc-meson:
169+
extends: .msvc-meson
170+
stage: build
171+
script:
172+
- meson setup build -Dperl=disabled
173+
- meson compile -C build
174+
artifacts:
175+
paths:
176+
- build
177+
178+
test:msvc-meson:
179+
extends: .msvc-meson
180+
stage: test
181+
when: manual
182+
timeout: 6h
183+
needs:
184+
- job: "build:msvc-meson"
185+
artifacts: true
186+
script:
187+
- meson test -C build --list | Select-Object -Skip 1 | Select-String .* | Group-Object -Property { $_.LineNumber % $Env:CI_NODE_TOTAL + 1 } | Where-Object Name -EQ $Env:CI_NODE_INDEX | ForEach-Object { meson test -C build --no-rebuild --print-errorlogs $_.Group }
188+
parallel: 10
189+
152190
test:fuzz-smoke-tests:
153191
image: ubuntu:latest
154192
stage: test

GIT-VERSION-GEN

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,29 @@ DEF_VER=v2.48.0
55
LF='
66
'
77

8-
if test "$#" -ne 3
8+
if test "$#" -lt 2 || test "$#" -gt 3
99
then
10-
echo >&2 "USAGE: $0 <SOURCE_DIR> <INPUT> <OUTPUT>"
10+
echo >&2 "USAGE: $0 <SOURCE_DIR> (--format=<STRING>|<INPUT>) [<OUTPUT>]"
1111
exit 1
1212
fi
1313

1414
SOURCE_DIR="$1"
15-
INPUT="$2"
16-
OUTPUT="$3"
1715

18-
if ! test -f "$INPUT"
19-
then
20-
echo >&2 "Input is not a file: $INPUT"
21-
exit 1
22-
fi
16+
case "$2" in
17+
--format=*)
18+
INPUT="${2#--format=}"
19+
;;
20+
*)
21+
if ! test -f "$2"
22+
then
23+
echo >&2 "Input is not a file: $2"
24+
exit 1
25+
fi
26+
INPUT=$(cat "$2")
27+
;;
28+
esac
29+
30+
OUTPUT="$3"
2331

2432
# Protect us from reading Git version information outside of the Git directory
2533
# in case it is not a repository itself, but embedded in an unrelated
@@ -39,13 +47,9 @@ then
3947
test -d "${GIT_DIR:-.git}" ||
4048
test -f "$SOURCE_DIR"/.git;
4149
} &&
42-
VN=$(git -C "$SOURCE_DIR" describe --match "v[0-9]*" HEAD 2>/dev/null) &&
50+
VN=$(git -C "$SOURCE_DIR" describe --dirty --match="v[0-9]*" 2>/dev/null) &&
4351
case "$VN" in
4452
*$LF*) (exit 1) ;;
45-
v[0-9]*)
46-
git -C "$SOURCE_DIR" update-index -q --refresh
47-
test -z "$(git -C "$SOURCE_DIR" diff-index --name-only HEAD --)" ||
48-
VN="$VN-dirty" ;;
4953
esac
5054
then
5155
VN=$(echo "$VN" | sed -e 's/-/./g');
@@ -78,19 +82,25 @@ read GIT_MAJOR_VERSION GIT_MINOR_VERSION GIT_MICRO_VERSION GIT_PATCH_LEVEL trail
7882
$(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ')
7983
EOF
8084

81-
sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \
85+
REPLACED=$(printf "%s" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \
8286
-e "s|@GIT_MAJOR_VERSION@|$GIT_MAJOR_VERSION|" \
8387
-e "s|@GIT_MINOR_VERSION@|$GIT_MINOR_VERSION|" \
8488
-e "s|@GIT_MICRO_VERSION@|$GIT_MICRO_VERSION|" \
8589
-e "s|@GIT_PATCH_LEVEL@|$GIT_PATCH_LEVEL|" \
8690
-e "s|@GIT_BUILT_FROM_COMMIT@|$GIT_BUILT_FROM_COMMIT|" \
8791
-e "s|@GIT_USER_AGENT@|$GIT_USER_AGENT|" \
88-
-e "s|@GIT_DATE@|$GIT_DATE|" \
89-
"$INPUT" >"$OUTPUT".$$+
92+
-e "s|@GIT_DATE@|$GIT_DATE|"
93+
)
9094

91-
if ! test -f "$OUTPUT" || ! cmp "$OUTPUT".$$+ "$OUTPUT" >/dev/null
95+
if test -z "$OUTPUT"
9296
then
93-
mv "$OUTPUT".$$+ "$OUTPUT"
97+
printf "%s\n" "$REPLACED"
9498
else
95-
rm "$OUTPUT".$$+
99+
printf "%s\n" "$REPLACED" >"$OUTPUT".$$+
100+
if ! test -f "$OUTPUT" || ! cmp "$OUTPUT".$$+ "$OUTPUT" >/dev/null
101+
then
102+
mv "$OUTPUT".$$+ "$OUTPUT"
103+
else
104+
rm "$OUTPUT".$$+
105+
fi
96106
fi

ci/run-build-and-tests.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ esac
5252
case "$jobname" in
5353
*-meson)
5454
group "Configure" meson setup build . \
55+
--fatal-meson-warnings \
5556
--warnlevel 2 --werror \
56-
--wrap-mode nofallback
57+
--wrap-mode nofallback \
58+
-Dfuzzers=true
5759
group "Build" meson compile -C build --
5860
if test -n "$run_tests"
5961
then

meson.build

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,22 @@
170170

171171
project('git', 'c',
172172
meson_version: '>=0.61.0',
173-
version: 'v2.47.GIT',
173+
# The version is only of cosmetic nature, so if we cannot find a shell yet we
174+
# simply don't set up a version at all. This may be the case for example on
175+
# Windows systems, where we first have to bootstrap the host environment.
176+
version: find_program('sh', required: false).found() ? run_command(
177+
'GIT-VERSION-GEN', meson.current_source_dir(), '--format=@GIT_VERSION@',
178+
capture: true,
179+
check: true,
180+
).stdout().strip() : 'unknown',
181+
default_options: [
182+
# Git requires C99 with GNU extensions, which of course isn't supported by
183+
# MSVC. Funny enough, C99 doesn't work with MSVC either, as it has only
184+
# learned to define __STDC_VERSION__ with C11 and later. We thus require
185+
# GNU C99 and fall back to C11. Meson only learned to handle the fallback
186+
# with version 1.3.0, so on older versions we use GNU C99 unconditionally.
187+
'c_std=' + (meson.version().version_compare('>=1.3.0') ? 'gnu99,c11' : 'gnu99'),
188+
],
174189
)
175190

176191
fs = import('fs')
@@ -480,6 +495,13 @@ libgit_sources = [
480495
'xdiff/xutils.c',
481496
]
482497

498+
libgit_sources += custom_target(
499+
input: 'command-list.txt',
500+
output: 'command-list.h',
501+
command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'],
502+
env: script_environment,
503+
)
504+
483505
builtin_sources = [
484506
'builtin/add.c',
485507
'builtin/am.c',
@@ -607,14 +629,7 @@ builtin_sources = [
607629
'builtin/write-tree.c',
608630
]
609631

610-
libgit_sources += custom_target(
611-
input: 'command-list.txt',
612-
output: 'command-list.h',
613-
command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'],
614-
env: script_environment,
615-
)
616-
617-
libgit_sources += custom_target(
632+
builtin_sources += custom_target(
618633
output: 'config-list.h',
619634
command: [
620635
shell,
@@ -625,7 +640,7 @@ libgit_sources += custom_target(
625640
env: script_environment,
626641
)
627642

628-
libgit_sources += custom_target(
643+
builtin_sources += custom_target(
629644
input: 'Documentation/githooks.txt',
630645
output: 'hook-list.h',
631646
command: [
@@ -1325,6 +1340,7 @@ if not meson.is_cross_build() and fs.exists('/dev/tty')
13251340
libgit_c_args += '-DHAVE_DEV_TTY'
13261341
endif
13271342

1343+
csprng_backend = get_option('csprng_backend')
13281344
https_backend = get_option('https_backend')
13291345
sha1_backend = get_option('sha1_backend')
13301346
sha1_unsafe_backend = get_option('sha1_unsafe_backend')
@@ -1336,7 +1352,7 @@ if https_backend == 'auto' and security_framework.found()
13361352
https_backend = 'CommonCrypto'
13371353
endif
13381354

1339-
openssl_required = 'openssl' in [https_backend, sha1_backend, sha1_unsafe_backend, sha256_backend]
1355+
openssl_required = 'openssl' in [csprng_backend, https_backend, sha1_backend, sha1_unsafe_backend, sha256_backend]
13401356
openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static'])
13411357
if https_backend == 'auto' and openssl.found()
13421358
https_backend = 'openssl'
@@ -1421,18 +1437,30 @@ else
14211437
error('Unhandled SHA256 backend ' + sha256_backend)
14221438
endif
14231439

1424-
if compiler.has_header_symbol('stdlib.h', 'arc4random_buf')
1440+
# Backends are ordered to reflect our preference for more secure and faster
1441+
# ones over the ones that are less so.
1442+
if csprng_backend in ['auto', 'arc4random'] and compiler.has_header_symbol('stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random')
14251443
libgit_c_args += '-DHAVE_ARC4RANDOM'
1426-
elif compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf')
1444+
csprng_backend = 'arc4random'
1445+
elif csprng_backend in ['auto', 'arc4random_bsd'] and compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random_bsd')
14271446
libgit_c_args += '-DHAVE_ARC4RANDOM_BSD'
1428-
elif compiler.has_function('getrandom', prefix: '#include <sys/random.h>')
1447+
csprng_backend = 'arc4random_bsd'
1448+
elif csprng_backend in ['auto', 'getrandom'] and compiler.has_header_symbol('sys/random.h', 'getrandom', required: csprng_backend == 'getrandom')
14291449
libgit_c_args += '-DHAVE_GETRANDOM'
1430-
elif compiler.has_function('getentropy', prefix: '#include <unistd.h>')
1450+
csprng_backend = 'getrandom'
1451+
elif csprng_backend in ['auto', 'getentropy'] and compiler.has_header_symbol('unistd.h', 'getentropy', required: csprng_backend == 'getentropy')
14311452
libgit_c_args += '-DHAVE_GETENTROPY'
1432-
elif compiler.has_function('RtlGenRandom', prefix: '#include <windows.h>\n#include <ntsecapi.h>')
1453+
csprng_backend = 'getentropy'
1454+
elif csprng_backend in ['auto', 'rtlgenrandom'] and compiler.has_header_symbol('ntsecapi.h', 'RtlGenRandom', prefix: '#include <windows.h>', required: csprng_backend == 'rtlgenrandom')
14331455
libgit_c_args += '-DHAVE_RTLGENRANDOM'
1434-
elif openssl.found()
1456+
csprng_backend = 'rtlgenrandom'
1457+
elif csprng_backend in ['auto', 'openssl'] and openssl.found()
14351458
libgit_c_args += '-DHAVE_OPENSSL_CSPRNG'
1459+
csprng_backend = 'openssl'
1460+
elif csprng_backend in ['auto', 'urandom']
1461+
csprng_backend = 'urandom'
1462+
else
1463+
error('Unsupported CSPRNG backend: ' + csprng_backend)
14361464
endif
14371465

14381466
if get_option('runtime_prefix')
@@ -1899,6 +1927,10 @@ if get_option('tests')
18991927
subdir('t')
19001928
endif
19011929

1930+
if get_option('fuzzers')
1931+
subdir('oss-fuzz')
1932+
endif
1933+
19021934
subdir('bin-wrappers')
19031935
if get_option('docs') != []
19041936
subdir('Documentation')
@@ -1932,6 +1964,27 @@ configure_file(
19321964
configuration: build_options_config,
19331965
)
19341966

1967+
# Development environments can be used via `meson devenv -C <builddir>`. This
1968+
# allows you to execute test scripts directly with the built Git version and
1969+
# puts the built version of Git in your PATH.
1970+
devenv = environment()
1971+
devenv.set('GIT_BUILD_DIR', meson.current_build_dir())
1972+
devenv.prepend('PATH', meson.current_build_dir() / 'bin-wrappers')
1973+
meson.add_devenv(devenv)
1974+
1975+
# Generate the 'version' file in the distribution tarball. This is used via
1976+
# `meson dist -C <builddir>` to populate the source archive with the Git
1977+
# version that the archive is being generated from.
1978+
meson.add_dist_script(
1979+
shell,
1980+
'-c',
1981+
'"$1" "$2" "$3" --format="@GIT_VERSION@" "$MESON_DIST_ROOT/version"',
1982+
'GIT-VERSION-GEN',
1983+
shell,
1984+
meson.current_source_dir() / 'GIT-VERSION-GEN',
1985+
meson.current_source_dir(),
1986+
)
1987+
19351988
summary({
19361989
'curl': curl.found(),
19371990
'expat': expat.found(),
@@ -1945,6 +1998,7 @@ summary({
19451998
}, section: 'Auto-detected features')
19461999

19472000
summary({
2001+
'csprng': csprng_backend,
19482002
'https': https_backend,
19492003
'sha1': sha1_backend,
19502004
'sha1_unsafe': sha1_unsafe_backend,

meson_options.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ option('regex', type: 'feature', value: 'auto',
4747
description: 'Use the system-provided regex library instead of the bundled one.')
4848

4949
# Backends.
50+
option('csprng_backend', type: 'combo', value: 'auto', choices: ['auto', 'arc4random', 'arc4random_bsd', 'getrandom', 'getentropy', 'rtlgenrandom', 'openssl', 'urandom'],
51+
description: 'The backend to use for generating cryptographically-secure pseudo-random numbers.')
5052
option('https_backend', type: 'combo', value: 'auto', choices: ['auto', 'openssl', 'CommonCrypto', 'none'],
5153
description: 'The HTTPS backend to use when connecting to remotes.')
5254
option('sha1_backend', type: 'combo', choices: ['openssl', 'block', 'sha1dc', 'CommonCrypto'], value: 'sha1dc',
@@ -95,3 +97,5 @@ option('tests', type: 'boolean', value: true,
9597
description: 'Enable building tests. This requires Perl, but is separate from the "perl" option such that you can build tests without Perl features enabled.')
9698
option('test_output_directory', type: 'string',
9799
description: 'Path to the directory used to store test outputs')
100+
option('fuzzers', type: 'boolean', value: false,
101+
description: 'Enable building fuzzers.')

0 commit comments

Comments
 (0)