aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-01-30 14:33:55 -0800
committerJunio C Hamano <gitster@pobox.com>2025-01-30 14:53:50 -0800
commit72f1ddfbc95b47c6011bb423e6947418d1d72709 (patch)
tree049c52f496e58542d14fe922a9c475f50772cd1d
parentThe fifth batch (diff)
parentci: wire up Visual Studio build with Meson (diff)
downloadgit-72f1ddfbc95b47c6011bb423e6947418d1d72709.tar.gz
git-72f1ddfbc95b47c6011bb423e6947418d1d72709.zip
Merge branch 'ps/build-meson-fixes' into ps/build-meson-fixes-0130
* 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
-rw-r--r--.github/workflows/main.yml52
-rw-r--r--.gitlab-ci.yml38
-rwxr-xr-xGIT-VERSION-GEN50
-rwxr-xr-xci/run-build-and-tests.sh4
-rw-r--r--meson.build88
-rw-r--r--meson_options.txt4
-rw-r--r--oss-fuzz/meson.build20
7 files changed, 218 insertions, 38 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 900be9957a..7f55f8b3a9 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -248,6 +248,58 @@ jobs:
with:
name: failed-tests-windows-vs-${{ matrix.nr }}
path: ${{env.FAILED_TEST_ARTIFACTS}}
+
+ windows-meson-build:
+ name: win+Meson build
+ needs: ci-config
+ if: needs.ci-config.outputs.enabled == 'yes'
+ runs-on: windows-latest
+ concurrency:
+ group: windows-meson-build-${{ github.ref }}
+ cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ - name: Set up dependencies
+ shell: pwsh
+ run: pip install meson ninja
+ - name: Setup
+ shell: pwsh
+ run: meson setup build -Dperl=disabled
+ - name: Compile
+ shell: pwsh
+ run: meson compile -C build
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: windows-meson-artifacts
+ path: build
+ windows-meson-test:
+ name: win+Meson test
+ runs-on: windows-latest
+ needs: [ci-config, windows-meson-build]
+ strategy:
+ fail-fast: false
+ matrix:
+ nr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ concurrency:
+ group: windows-meson-test-${{ matrix.nr }}-${{ github.ref }}
+ cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ - name: Set up dependencies
+ shell: pwsh
+ run: pip install meson ninja
+ - name: Download build artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: windows-meson-artifacts
+ path: build
+ - name: Test
+ shell: pwsh
+ 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 }
+
regular:
name: ${{matrix.vector.jobname}} (${{matrix.vector.pool}})
needs: ci-config
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9254e01583..4976e18a05 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -149,6 +149,44 @@ test:mingw64:
- git-sdk/usr/bin/bash.exe -l -c 'ci/print-test-failures.sh'
parallel: 10
+.msvc-meson:
+ tags:
+ - saas-windows-medium-amd64
+ before_script:
+ - choco install -y git meson ninja openssl
+ - Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
+ - refreshenv
+ # The certificate store for Python on Windows is broken and fails to fetch
+ # certificates, see https://bugs.python.org/issue36011. This seems to
+ # mostly be an issue with how the GitLab image is set up as it is a
+ # non-issue on GitHub Actions. Work around the issue by importing
+ # cetrificates manually.
+ - Invoke-WebRequest https://curl.haxx.se/ca/cacert.pem -OutFile cacert.pem
+ - openssl pkcs12 -export -nokeys -in cacert.pem -out certs.pfx -passout "pass:"
+ - Import-PfxCertificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath certs.pfx
+
+build:msvc-meson:
+ extends: .msvc-meson
+ stage: build
+ script:
+ - meson setup build -Dperl=disabled
+ - meson compile -C build
+ artifacts:
+ paths:
+ - build
+
+test:msvc-meson:
+ extends: .msvc-meson
+ stage: test
+ when: manual
+ timeout: 6h
+ needs:
+ - job: "build:msvc-meson"
+ artifacts: true
+ script:
+ - 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 }
+ parallel: 10
+
test:fuzz-smoke-tests:
image: ubuntu:latest
stage: test
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 3704a1c39e..56b45333c1 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -5,21 +5,29 @@ DEF_VER=v2.48.GIT
LF='
'
-if test "$#" -ne 3
+if test "$#" -lt 2 || test "$#" -gt 3
then
- echo >&2 "USAGE: $0 <SOURCE_DIR> <INPUT> <OUTPUT>"
+ echo >&2 "USAGE: $0 <SOURCE_DIR> (--format=<STRING>|<INPUT>) [<OUTPUT>]"
exit 1
fi
SOURCE_DIR="$1"
-INPUT="$2"
-OUTPUT="$3"
-if ! test -f "$INPUT"
-then
- echo >&2 "Input is not a file: $INPUT"
- exit 1
-fi
+case "$2" in
+--format=*)
+ INPUT="${2#--format=}"
+ ;;
+*)
+ if ! test -f "$2"
+ then
+ echo >&2 "Input is not a file: $2"
+ exit 1
+ fi
+ INPUT=$(cat "$2")
+ ;;
+esac
+
+OUTPUT="$3"
# Protect us from reading Git version information outside of the Git directory
# in case it is not a repository itself, but embedded in an unrelated
@@ -39,13 +47,9 @@ then
test -d "${GIT_DIR:-.git}" ||
test -f "$SOURCE_DIR"/.git;
} &&
- VN=$(git -C "$SOURCE_DIR" describe --match "v[0-9]*" HEAD 2>/dev/null) &&
+ VN=$(git -C "$SOURCE_DIR" describe --dirty --match="v[0-9]*" 2>/dev/null) &&
case "$VN" in
*$LF*) (exit 1) ;;
- v[0-9]*)
- git -C "$SOURCE_DIR" update-index -q --refresh
- test -z "$(git -C "$SOURCE_DIR" diff-index --name-only HEAD --)" ||
- VN="$VN-dirty" ;;
esac
then
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
$(echo "$GIT_VERSION" 0 0 0 0 | tr '.a-zA-Z-' ' ')
EOF
-sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \
+REPLACED=$(printf "%s" "$INPUT" | sed -e "s|@GIT_VERSION@|$GIT_VERSION|" \
-e "s|@GIT_MAJOR_VERSION@|$GIT_MAJOR_VERSION|" \
-e "s|@GIT_MINOR_VERSION@|$GIT_MINOR_VERSION|" \
-e "s|@GIT_MICRO_VERSION@|$GIT_MICRO_VERSION|" \
-e "s|@GIT_PATCH_LEVEL@|$GIT_PATCH_LEVEL|" \
-e "s|@GIT_BUILT_FROM_COMMIT@|$GIT_BUILT_FROM_COMMIT|" \
-e "s|@GIT_USER_AGENT@|$GIT_USER_AGENT|" \
- -e "s|@GIT_DATE@|$GIT_DATE|" \
- "$INPUT" >"$OUTPUT".$$+
+ -e "s|@GIT_DATE@|$GIT_DATE|"
+)
-if ! test -f "$OUTPUT" || ! cmp "$OUTPUT".$$+ "$OUTPUT" >/dev/null
+if test -z "$OUTPUT"
then
- mv "$OUTPUT".$$+ "$OUTPUT"
+ printf "%s\n" "$REPLACED"
else
- rm "$OUTPUT".$$+
+ printf "%s\n" "$REPLACED" >"$OUTPUT".$$+
+ if ! test -f "$OUTPUT" || ! cmp "$OUTPUT".$$+ "$OUTPUT" >/dev/null
+ then
+ mv "$OUTPUT".$$+ "$OUTPUT"
+ else
+ rm "$OUTPUT".$$+
+ fi
fi
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index 76667a1277..964322055f 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -52,8 +52,10 @@ esac
case "$jobname" in
*-meson)
group "Configure" meson setup build . \
+ --fatal-meson-warnings \
--warnlevel 2 --werror \
- --wrap-mode nofallback
+ --wrap-mode nofallback \
+ -Dfuzzers=true
group "Build" meson compile -C build --
if test -n "$run_tests"
then
diff --git a/meson.build b/meson.build
index 548eac62b2..dbc1dab605 100644
--- a/meson.build
+++ b/meson.build
@@ -170,7 +170,22 @@
project('git', 'c',
meson_version: '>=0.61.0',
- version: 'v2.47.GIT',
+ # The version is only of cosmetic nature, so if we cannot find a shell yet we
+ # simply don't set up a version at all. This may be the case for example on
+ # Windows systems, where we first have to bootstrap the host environment.
+ version: find_program('sh', required: false).found() ? run_command(
+ 'GIT-VERSION-GEN', meson.current_source_dir(), '--format=@GIT_VERSION@',
+ capture: true,
+ check: true,
+ ).stdout().strip() : 'unknown',
+ default_options: [
+ # Git requires C99 with GNU extensions, which of course isn't supported by
+ # MSVC. Funny enough, C99 doesn't work with MSVC either, as it has only
+ # learned to define __STDC_VERSION__ with C11 and later. We thus require
+ # GNU C99 and fall back to C11. Meson only learned to handle the fallback
+ # with version 1.3.0, so on older versions we use GNU C99 unconditionally.
+ 'c_std=' + (meson.version().version_compare('>=1.3.0') ? 'gnu99,c11' : 'gnu99'),
+ ],
)
fs = import('fs')
@@ -481,6 +496,13 @@ libgit_sources = [
'xdiff/xutils.c',
]
+libgit_sources += custom_target(
+ input: 'command-list.txt',
+ output: 'command-list.h',
+ command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'],
+ env: script_environment,
+)
+
builtin_sources = [
'builtin/add.c',
'builtin/am.c',
@@ -608,14 +630,7 @@ builtin_sources = [
'builtin/write-tree.c',
]
-libgit_sources += custom_target(
- input: 'command-list.txt',
- output: 'command-list.h',
- command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'],
- env: script_environment,
-)
-
-libgit_sources += custom_target(
+builtin_sources += custom_target(
output: 'config-list.h',
command: [
shell,
@@ -626,7 +641,7 @@ libgit_sources += custom_target(
env: script_environment,
)
-libgit_sources += custom_target(
+builtin_sources += custom_target(
input: 'Documentation/githooks.txt',
output: 'hook-list.h',
command: [
@@ -1325,6 +1340,7 @@ if not meson.is_cross_build() and fs.exists('/dev/tty')
libgit_c_args += '-DHAVE_DEV_TTY'
endif
+csprng_backend = get_option('csprng_backend')
https_backend = get_option('https_backend')
sha1_backend = get_option('sha1_backend')
sha1_unsafe_backend = get_option('sha1_unsafe_backend')
@@ -1336,7 +1352,7 @@ if https_backend == 'auto' and security_framework.found()
https_backend = 'CommonCrypto'
endif
-openssl_required = 'openssl' in [https_backend, sha1_backend, sha1_unsafe_backend, sha256_backend]
+openssl_required = 'openssl' in [csprng_backend, https_backend, sha1_backend, sha1_unsafe_backend, sha256_backend]
openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static'])
if https_backend == 'auto' and openssl.found()
https_backend = 'openssl'
@@ -1421,18 +1437,30 @@ else
error('Unhandled SHA256 backend ' + sha256_backend)
endif
-if compiler.has_header_symbol('stdlib.h', 'arc4random_buf')
+# Backends are ordered to reflect our preference for more secure and faster
+# ones over the ones that are less so.
+if csprng_backend in ['auto', 'arc4random'] and compiler.has_header_symbol('stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random')
libgit_c_args += '-DHAVE_ARC4RANDOM'
-elif compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf')
+ csprng_backend = 'arc4random'
+elif csprng_backend in ['auto', 'arc4random_bsd'] and compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random_bsd')
libgit_c_args += '-DHAVE_ARC4RANDOM_BSD'
-elif compiler.has_function('getrandom', prefix: '#include <sys/random.h>')
+ csprng_backend = 'arc4random_bsd'
+elif csprng_backend in ['auto', 'getrandom'] and compiler.has_header_symbol('sys/random.h', 'getrandom', required: csprng_backend == 'getrandom')
libgit_c_args += '-DHAVE_GETRANDOM'
-elif compiler.has_function('getentropy', prefix: '#include <unistd.h>')
+ csprng_backend = 'getrandom'
+elif csprng_backend in ['auto', 'getentropy'] and compiler.has_header_symbol('unistd.h', 'getentropy', required: csprng_backend == 'getentropy')
libgit_c_args += '-DHAVE_GETENTROPY'
-elif compiler.has_function('RtlGenRandom', prefix: '#include <windows.h>\n#include <ntsecapi.h>')
+ csprng_backend = 'getentropy'
+elif csprng_backend in ['auto', 'rtlgenrandom'] and compiler.has_header_symbol('ntsecapi.h', 'RtlGenRandom', prefix: '#include <windows.h>', required: csprng_backend == 'rtlgenrandom')
libgit_c_args += '-DHAVE_RTLGENRANDOM'
-elif openssl.found()
+ csprng_backend = 'rtlgenrandom'
+elif csprng_backend in ['auto', 'openssl'] and openssl.found()
libgit_c_args += '-DHAVE_OPENSSL_CSPRNG'
+ csprng_backend = 'openssl'
+elif csprng_backend in ['auto', 'urandom']
+ csprng_backend = 'urandom'
+else
+ error('Unsupported CSPRNG backend: ' + csprng_backend)
endif
if get_option('runtime_prefix')
@@ -1900,6 +1928,10 @@ if get_option('tests')
subdir('t')
endif
+if get_option('fuzzers')
+ subdir('oss-fuzz')
+endif
+
subdir('bin-wrappers')
if get_option('docs') != []
subdir('Documentation')
@@ -1935,6 +1967,27 @@ configure_file(
configuration: build_options_config,
)
+# Development environments can be used via `meson devenv -C <builddir>`. This
+# allows you to execute test scripts directly with the built Git version and
+# puts the built version of Git in your PATH.
+devenv = environment()
+devenv.set('GIT_BUILD_DIR', meson.current_build_dir())
+devenv.prepend('PATH', meson.current_build_dir() / 'bin-wrappers')
+meson.add_devenv(devenv)
+
+# Generate the 'version' file in the distribution tarball. This is used via
+# `meson dist -C <builddir>` to populate the source archive with the Git
+# version that the archive is being generated from.
+meson.add_dist_script(
+ shell,
+ '-c',
+ '"$1" "$2" "$3" --format="@GIT_VERSION@" "$MESON_DIST_ROOT/version"',
+ 'GIT-VERSION-GEN',
+ shell,
+ meson.current_source_dir() / 'GIT-VERSION-GEN',
+ meson.current_source_dir(),
+)
+
summary({
'curl': curl.found(),
'expat': expat.found(),
@@ -1948,6 +2001,7 @@ summary({
}, section: 'Auto-detected features')
summary({
+ 'csprng': csprng_backend,
'https': https_backend,
'sha1': sha1_backend,
'sha1_unsafe': sha1_unsafe_backend,
diff --git a/meson_options.txt b/meson_options.txt
index c0d72d85a3..c102185ed5 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -49,6 +49,8 @@ option('regex', type: 'feature', value: 'auto',
description: 'Use the system-provided regex library instead of the bundled one.')
# Backends.
+option('csprng_backend', type: 'combo', value: 'auto', choices: ['auto', 'arc4random', 'arc4random_bsd', 'getrandom', 'getentropy', 'rtlgenrandom', 'openssl', 'urandom'],
+ description: 'The backend to use for generating cryptographically-secure pseudo-random numbers.')
option('https_backend', type: 'combo', value: 'auto', choices: ['auto', 'openssl', 'CommonCrypto', 'none'],
description: 'The HTTPS backend to use when connecting to remotes.')
option('sha1_backend', type: 'combo', choices: ['openssl', 'block', 'sha1dc', 'CommonCrypto'], value: 'sha1dc',
@@ -97,3 +99,5 @@ option('tests', type: 'boolean', value: true,
description: 'Enable building tests. This requires Perl, but is separate from the "perl" option such that you can build tests without Perl features enabled.')
option('test_output_directory', type: 'string',
description: 'Path to the directory used to store test outputs')
+option('fuzzers', type: 'boolean', value: false,
+ description: 'Enable building fuzzers.')
diff --git a/oss-fuzz/meson.build b/oss-fuzz/meson.build
new file mode 100644
index 0000000000..ed79665501
--- /dev/null
+++ b/oss-fuzz/meson.build
@@ -0,0 +1,20 @@
+fuzz_programs = [
+ 'fuzz-commit-graph.c',
+ 'fuzz-config.c',
+ 'fuzz-credential-from-url-gently.c',
+ 'fuzz-date.c',
+ 'fuzz-pack-headers.c',
+ 'fuzz-pack-idx.c',
+ 'fuzz-parse-attr-line.c',
+ 'fuzz-url-decode-mem.c',
+]
+
+foreach fuzz_program : fuzz_programs
+ executable(fs.stem(fuzz_program),
+ sources: [
+ 'dummy-cmd-main.c',
+ fuzz_program,
+ ],
+ dependencies: [libgit, common_main],
+ )
+endforeach