From 904339edbd80ec5676616af6e072b41804c1c8eb Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Dec 2024 14:24:59 +0100 Subject: Introduce support for the Meson build system Introduce support for the Meson build system, a "modern" meta build system that supports many different platforms, including Linux, macOS, Windows and BSDs. Meson supports different backends, including Ninja, Xcode and Microsoft Visual Studio. Several common IDEs provide an integration with it. The biggest contender compared to Meson is probably CMake as outlined in our "Documentation/technical/build-systems.txt" file. Based on my own personal experience from working with both build systems extensively I strongly favor Meson over CMake. In my opinion, it feels significantly easier to use with a syntax that feels more like a "real" programming language. The second big reason is that Meson supports Rust natively, which may prove to be important given that the project may pick up Rust as another language eventually. Using Meson is rather straight-forward. An example: ``` # Meson uses out-of-tree builds. You can set up multiple build # directories, how you name them is completely up to you. $ mkdir build $ cd build $ meson setup .. -Dprefix=/tmp/git-installation # Build the project. This also provides several other targets like e.g. `install` or `test`. $ ninja # Meson has been wired up to support execution of our test suites. # Both our unit tests and our integration tests are supported. # Running `meson test` without any arguments will execute all tests, # but the syntax supports globbing to select only some tests. $ meson test 't-*' # Execute single test interactively to allow for debugging. $ meson test 't0000-*' --interactive --test-args=-ix ``` The build instructions have been successfully tested on the following systems, tests are passing: - Apple macOS 10.15. - FreeBSD 14.1. - NixOS 24.11. - OpenBSD 7.6. - Ubuntu 24.04. - Windows 10 with Cygwin. - Windows 10 with MinGW64, except for t9700, which is also broken with our Makefile. - Windows 10 with Visual Studio 2022 toolchain, using the Native Tools Command Prompt with `meson setup --vsenv`. Tests pass, except for t9700. - Windows 10 with Visual Studio 2022 solution, using the Native Tools Command Prompt with `meson setup --backend vs2022`. Tests pass, except for t9700. - Windows 10 with VS Code, using the Meson plug-in. It is expected that there will still be rough edges in the current version. If this patch lands the expectation is that it will coexist with our other build systems for a while. Like this, distributions can slowly migrate over to Meson and report any findings they have to us such that we can continue to iterate. A potential cutoff date for other build systems may be Git 3.0. Some notes: - The installed distribution is structured somewhat differently than how it used to be the case. All of our binaries are installed into `$libexec/git-core`, while all binaries part of `$bindir` are now symbolic links pointing to the former. This rule is consistent in itself and thus easier to reason about. - We do not install dashed binaries into `$libexec/git-core` anymore, so there won't e.g. be a symlink for git-add(1). These are not required by modern Git and there isn't really much of a use case for those anymore. By not installing those symlinks we thus start the deprecation of this layout. - We're targeting Meson 1.3.0, which has been released relatively recently November 2023. The only feature we use from that version is `fs.relative_to()`, which we could replace if necessary. If so, we could start to target Meson 1.0.0 and newer, released in December 2022. - The whole build instructions count around 3300 lines, half of which is listing all of our code and test files. Our Makefiles are around 5000 lines, autoconf adds another 1300 lines. CMake in comparison has only 1200 linescode, but it avoids listing individual files and does not wire up auto-configuration as extensively as the Meson instructions do. - We bundle a set of subproject wrappers for curl, expat, openssl, pcre2 and zlib. This allows developers to build Git without these dependencies preinstalled, and Meson will fetch and build them automatically. This is especially helpful on Windows. Helped-by: Eli Schwartz Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 1901 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1901 insertions(+) create mode 100644 meson.build (limited to 'meson.build') diff --git a/meson.build b/meson.build new file mode 100644 index 0000000000..0dccebcdf1 --- /dev/null +++ b/meson.build @@ -0,0 +1,1901 @@ +# Meson build system +# ================== +# +# The Meson build system is an alternative to our Makefile that you can use to +# build, test and install Git. Using Meson results in a couple of benefits: +# +# - Out-of-tree builds. +# - Better integration into IDEs. +# - Easy-to-use autoconfiguration of available features on your system. +# +# To use Meson from the command line you need to have both Meson and Ninja +# installed. Alternatively, if you do not have Python available on your system, +# you can also use Muon instead of Meson and Samurai instead of Ninja, both of +# which are drop-ins replacement that only depend on C. +# +# Basic usage +# =========== +# +# In the most trivial case, you can configure, build and install Git like this: +# +# 1. Set up the build directory. This only needs to happen once per build +# directory you want to have. You can also configure multiple different +# build directories with different configurations. +# +# $ meson setup build/ +# +# The build directory gets ignored by Git automatically as Meson will write +# a ".gitignore" file into it. From hereon, we will assume that you execute +# commands inside this build directory. +# +# 2. Compile Git. You can either use Meson, Ninja or Samurai to do this, so all +# of the following invocations are equivalent: +# +# $ meson compile +# $ ninja +# $ samu +# +# The different invocations should ultimately not make much of a difference. +# Using Meson also works with other generators though, like when the build +# directory has been set up for use with Microsoft Visual Studio. +# +# Ninja and Samurai use multiple jobs by default, scaling with the number of +# processor cores available. You can pass the `-jN` flag to change this. +# +# Meson automatically picks up ccache and sccache when these are installed +# when setting up the build directory. You can override this behaviour when +# setting up the build directory by setting the `CC` environment variable to +# your desired compiler. +# +# 3. Execute tests. Again, you can either use Meson, Ninja or Samurai to do this: +# +# $ meson test +# $ ninja test +# $ samu test +# +# It is recommended to use Meson in this case though as it also provides you +# additional features that the other build systems don't have available. +# You can e.g. pass additional arguments to the test executables or run +# individual tests: +# +# # Execute the t0000-basic integration test and t-reftable-stack unit test. +# $ meson test t0000-basic t-reftable-stack +# +# # Execute all reftable unit tests. +# $ meson test t-reftable-* +# +# # Execute all tests and stop with the first failure. +# $ meson test --maxfail 1 +# +# # Execute single test interactively such that features like `debug ()` work. +# $ meson test -i --test-args='-ix' t1400-update-ref +# +# Test execution is parallelized by default and scales with the number of +# processor cores available. You can change the number of processes by passing +# the `-jN` flag to `meson test`. +# +# 4. Install the Git distribution. Again, this can be done via Meson, Ninja or +# Samurai: +# +# $ meson install +# $ ninja install +# $ samu install +# +# The prefix into which Git shall be installed is defined when setting up +# the build directory. More on that in the "Configuration" section. +# +# Meson supports multiple backends. The default backend generates Ninja build +# instructions, but it also supports the generation of Microsoft Visual +# Studio solutions as well as Xcode projects by passing the `--backend` option +# to `meson setup`. IDEs like Eclipse and Visual Studio Code provide plugins to +# import Meson files directly. +# +# Configuration +# ============= +# +# The exact configuration of Git is determined when setting up the build +# directory via `meson setup`. Unless told otherwise, Meson will automatically +# detect the availability of various bits and pieces. There are two different +# kinds of options that can be used to further tweak the build: +# +# - Built-in options provided by Meson. +# +# - Options defined by the project in the "meson_options.txt" file. +# +# Both kinds of options can be inspected by running `meson configure` in the +# build directory, which will give you a list of the current value for all +# options. +# +# Options can be configured either when setting up the build directory or can +# be changed in preexisting build directories: +# +# # Set up a new build directory with optimized settings that will be +# # installed into an alternative prefix. +# $ meson setup --buildtype release --optimization 3 --strip --prefix=/home/$USER build +# +# # Set up a new build directory with a higher warning level. Level 2 is +# # mostly equivalent to setting DEVELOPER=1, level 3 and "everything" +# # will enable even more warnings. +# $ meson setup -Dwarning_level=2 build +# +# # Set up a new build directory with 'address' and 'undefined' sanitizers +# # using Clang. +# $ CC=clang meson setup -Db_sanitize=address,undefined build +# +# # Disable tests in a preexisting build directory. +# $ meson configure -Dtests=false +# +# # Disable features based on Python +# $ meson configure -Dpython=disabled +# +# Options have a type like booleans, choices, strings or features. Features are +# somewhat special as they can have one of three values: enabled, disabled or +# auto. While the first two values are self-explanatory, "auto" will enable or +# disable the feature based on the availability of prerequisites to support it. +# Python-based features for example will be enabled automatically when a Python +# interpreter could be found. The default value of such features can be changed +# via `meson setup --auto-features={enabled,disabled,auto}`, which will set the +# value of all features with a value of "auto" to the provided one by default. +# +# It is also possible to store a set of configuration options in machine files. +# This can be useful in case you regularly want to reuse the same set of options: +# +# [binaries] +# c = ['clang'] +# ar = ['ar'] +# +# [project options] +# gettext = 'disabled' +# default_editor = 'vim' +# +# [built-in options] +# b_lto = true +# b_sanitize = 'address,undefined' +# +# These machine files can be passed to `meson setup` via the `--native-file` +# option. +# +# Subproject wrappers +# =================== +# +# Subproject wrappers are a feature provided by Meson that allows the automatic +# fallback to a "wrapped" dependency in case the dependency is not provided by +# the system. For example if the system is lacking curl, then Meson will use +# "subprojects/curl.wrap" to set up curl as a subproject and compile and link +# the dependency into Git itself. This is especially helpful on systems like +# Windows, where you typically don't have such dependencies installed. +# +# The use of subproject wrappers can be disabled by executing `meson setup` +# with the `--wrap-mode nofallback` option. + +project('git', 'c', + meson_version: '>=0.61.0', + version: 'v2.47.GIT', +) + +fs = import('fs') + +program_path = [] +# Git for Windows provides all the tools we need to build Git. +if host_machine.system() == 'windows' + program_path += [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] +endif + +cygpath = find_program('cygpath', dirs: program_path, required: false) +diff = find_program('diff', dirs: program_path) +shell = find_program('sh', dirs: program_path) +tar = find_program('tar', dirs: program_path) + +script_environment = environment() +foreach tool : ['cat', 'cut', 'grep', 'sed', 'sort', 'tr', 'uname'] + program = find_program(tool, dirs: program_path) + script_environment.prepend('PATH', fs.parent(program.full_path())) +endforeach + +git = find_program('git', dirs: program_path, required: false) +if git.found() + script_environment.prepend('PATH', fs.parent(git.full_path())) +endif + +if get_option('sane_tool_path') != '' + script_environment.prepend('PATH', get_option('sane_tool_path')) +endif + +compiler = meson.get_compiler('c') + +libgit_sources = [ + 'abspath.c', + 'add-interactive.c', + 'add-patch.c', + 'advice.c', + 'alias.c', + 'alloc.c', + 'apply.c', + 'archive-tar.c', + 'archive-zip.c', + 'archive.c', + 'attr.c', + 'base85.c', + 'bisect.c', + 'blame.c', + 'blob.c', + 'bloom.c', + 'branch.c', + 'bulk-checkin.c', + 'bundle-uri.c', + 'bundle.c', + 'cache-tree.c', + 'cbtree.c', + 'chdir-notify.c', + 'checkout.c', + 'chunk-format.c', + 'color.c', + 'column.c', + 'combine-diff.c', + 'commit-graph.c', + 'commit-reach.c', + 'commit.c', + 'compat/nonblock.c', + 'compat/obstack.c', + 'compat/terminal.c', + 'compat/zlib-uncompress2.c', + 'config.c', + 'connect.c', + 'connected.c', + 'convert.c', + 'copy.c', + 'credential.c', + 'csum-file.c', + 'ctype.c', + 'date.c', + 'decorate.c', + 'delta-islands.c', + 'diagnose.c', + 'diff-delta.c', + 'diff-merges.c', + 'diff-lib.c', + 'diff-no-index.c', + 'diff.c', + 'diffcore-break.c', + 'diffcore-delta.c', + 'diffcore-order.c', + 'diffcore-pickaxe.c', + 'diffcore-rename.c', + 'diffcore-rotate.c', + 'dir-iterator.c', + 'dir.c', + 'editor.c', + 'entry.c', + 'environment.c', + 'ewah/bitmap.c', + 'ewah/ewah_bitmap.c', + 'ewah/ewah_io.c', + 'ewah/ewah_rlw.c', + 'exec-cmd.c', + 'fetch-negotiator.c', + 'fetch-pack.c', + 'fmt-merge-msg.c', + 'fsck.c', + 'fsmonitor.c', + 'fsmonitor-ipc.c', + 'fsmonitor-settings.c', + 'gettext.c', + 'git-zlib.c', + 'gpg-interface.c', + 'graph.c', + 'grep.c', + 'hash-lookup.c', + 'hashmap.c', + 'help.c', + 'hex.c', + 'hex-ll.c', + 'hook.c', + 'ident.c', + 'json-writer.c', + 'kwset.c', + 'levenshtein.c', + 'line-log.c', + 'line-range.c', + 'linear-assignment.c', + 'list-objects-filter-options.c', + 'list-objects-filter.c', + 'list-objects.c', + 'lockfile.c', + 'log-tree.c', + 'loose.c', + 'ls-refs.c', + 'mailinfo.c', + 'mailmap.c', + 'match-trees.c', + 'mem-pool.c', + 'merge-blobs.c', + 'merge-ll.c', + 'merge-ort.c', + 'merge-ort-wrappers.c', + 'merge-recursive.c', + 'merge.c', + 'midx.c', + 'midx-write.c', + 'name-hash.c', + 'negotiator/default.c', + 'negotiator/noop.c', + 'negotiator/skipping.c', + 'notes-cache.c', + 'notes-merge.c', + 'notes-utils.c', + 'notes.c', + 'object-file-convert.c', + 'object-file.c', + 'object-name.c', + 'object.c', + 'oid-array.c', + 'oidmap.c', + 'oidset.c', + 'oidtree.c', + 'pack-bitmap-write.c', + 'pack-bitmap.c', + 'pack-check.c', + 'pack-mtimes.c', + 'pack-objects.c', + 'pack-revindex.c', + 'pack-write.c', + 'packfile.c', + 'pager.c', + 'parallel-checkout.c', + 'parse.c', + 'parse-options-cb.c', + 'parse-options.c', + 'patch-delta.c', + 'patch-ids.c', + 'path.c', + 'pathspec.c', + 'pkt-line.c', + 'preload-index.c', + 'pretty.c', + 'prio-queue.c', + 'progress.c', + 'promisor-remote.c', + 'prompt.c', + 'protocol.c', + 'protocol-caps.c', + 'prune-packed.c', + 'pseudo-merge.c', + 'quote.c', + 'range-diff.c', + 'reachable.c', + 'read-cache.c', + 'rebase-interactive.c', + 'rebase.c', + 'ref-filter.c', + 'reflog-walk.c', + 'reflog.c', + 'refs.c', + 'refs/debug.c', + 'refs/files-backend.c', + 'refs/reftable-backend.c', + 'refs/iterator.c', + 'refs/packed-backend.c', + 'refs/ref-cache.c', + 'refspec.c', + 'reftable/basics.c', + 'reftable/error.c', + 'reftable/block.c', + 'reftable/blocksource.c', + 'reftable/iter.c', + 'reftable/merged.c', + 'reftable/pq.c', + 'reftable/reader.c', + 'reftable/record.c', + 'reftable/stack.c', + 'reftable/system.c', + 'reftable/tree.c', + 'reftable/writer.c', + 'remote.c', + 'replace-object.c', + 'repo-settings.c', + 'repository.c', + 'rerere.c', + 'reset.c', + 'resolve-undo.c', + 'revision.c', + 'run-command.c', + 'send-pack.c', + 'sequencer.c', + 'serve.c', + 'server-info.c', + 'setup.c', + 'shallow.c', + 'sideband.c', + 'sigchain.c', + 'sparse-index.c', + 'split-index.c', + 'stable-qsort.c', + 'statinfo.c', + 'strbuf.c', + 'streaming.c', + 'string-list.c', + 'strmap.c', + 'strvec.c', + 'sub-process.c', + 'submodule-config.c', + 'submodule.c', + 'symlinks.c', + 'tag.c', + 'tempfile.c', + 'thread-utils.c', + 'tmp-objdir.c', + 'trace.c', + 'trace2.c', + 'trace2/tr2_cfg.c', + 'trace2/tr2_cmd_name.c', + 'trace2/tr2_ctr.c', + 'trace2/tr2_dst.c', + 'trace2/tr2_sid.c', + 'trace2/tr2_sysenv.c', + 'trace2/tr2_tbuf.c', + 'trace2/tr2_tgt_event.c', + 'trace2/tr2_tgt_normal.c', + 'trace2/tr2_tgt_perf.c', + 'trace2/tr2_tls.c', + 'trace2/tr2_tmr.c', + 'trailer.c', + 'transport-helper.c', + 'transport.c', + 'tree-diff.c', + 'tree-walk.c', + 'tree.c', + 'unpack-trees.c', + 'upload-pack.c', + 'url.c', + 'urlmatch.c', + 'usage.c', + 'userdiff.c', + 'utf8.c', + 'varint.c', + 'versioncmp.c', + 'walker.c', + 'wildmatch.c', + 'worktree.c', + 'wrapper.c', + 'write-or-die.c', + 'ws.c', + 'wt-status.c', + 'xdiff-interface.c', + 'xdiff/xdiffi.c', + 'xdiff/xemit.c', + 'xdiff/xhistogram.c', + 'xdiff/xmerge.c', + 'xdiff/xpatience.c', + 'xdiff/xprepare.c', + 'xdiff/xutils.c', +] + +builtin_sources = [ + 'builtin/add.c', + 'builtin/am.c', + 'builtin/annotate.c', + 'builtin/apply.c', + 'builtin/archive.c', + 'builtin/bisect.c', + 'builtin/blame.c', + 'builtin/branch.c', + 'builtin/bugreport.c', + 'builtin/bundle.c', + 'builtin/cat-file.c', + 'builtin/check-attr.c', + 'builtin/check-ignore.c', + 'builtin/check-mailmap.c', + 'builtin/check-ref-format.c', + 'builtin/checkout--worker.c', + 'builtin/checkout-index.c', + 'builtin/checkout.c', + 'builtin/clean.c', + 'builtin/clone.c', + 'builtin/column.c', + 'builtin/commit-graph.c', + 'builtin/commit-tree.c', + 'builtin/commit.c', + 'builtin/config.c', + 'builtin/count-objects.c', + 'builtin/credential-cache--daemon.c', + 'builtin/credential-cache.c', + 'builtin/credential-store.c', + 'builtin/credential.c', + 'builtin/describe.c', + 'builtin/diagnose.c', + 'builtin/diff-files.c', + 'builtin/diff-index.c', + 'builtin/diff-tree.c', + 'builtin/diff.c', + 'builtin/difftool.c', + 'builtin/fast-export.c', + 'builtin/fast-import.c', + 'builtin/fetch-pack.c', + 'builtin/fetch.c', + 'builtin/fmt-merge-msg.c', + 'builtin/for-each-ref.c', + 'builtin/for-each-repo.c', + 'builtin/fsck.c', + 'builtin/fsmonitor--daemon.c', + 'builtin/gc.c', + 'builtin/get-tar-commit-id.c', + 'builtin/grep.c', + 'builtin/hash-object.c', + 'builtin/help.c', + 'builtin/hook.c', + 'builtin/index-pack.c', + 'builtin/init-db.c', + 'builtin/interpret-trailers.c', + 'builtin/log.c', + 'builtin/ls-files.c', + 'builtin/ls-remote.c', + 'builtin/ls-tree.c', + 'builtin/mailinfo.c', + 'builtin/mailsplit.c', + 'builtin/merge-base.c', + 'builtin/merge-file.c', + 'builtin/merge-index.c', + 'builtin/merge-ours.c', + 'builtin/merge-recursive.c', + 'builtin/merge-tree.c', + 'builtin/merge.c', + 'builtin/mktag.c', + 'builtin/mktree.c', + 'builtin/multi-pack-index.c', + 'builtin/mv.c', + 'builtin/name-rev.c', + 'builtin/notes.c', + 'builtin/pack-objects.c', + 'builtin/pack-redundant.c', + 'builtin/pack-refs.c', + 'builtin/patch-id.c', + 'builtin/prune-packed.c', + 'builtin/prune.c', + 'builtin/pull.c', + 'builtin/push.c', + 'builtin/range-diff.c', + 'builtin/read-tree.c', + 'builtin/rebase.c', + 'builtin/receive-pack.c', + 'builtin/reflog.c', + 'builtin/refs.c', + 'builtin/remote-ext.c', + 'builtin/remote-fd.c', + 'builtin/remote.c', + 'builtin/repack.c', + 'builtin/replace.c', + 'builtin/replay.c', + 'builtin/rerere.c', + 'builtin/reset.c', + 'builtin/rev-list.c', + 'builtin/rev-parse.c', + 'builtin/revert.c', + 'builtin/rm.c', + 'builtin/send-pack.c', + 'builtin/shortlog.c', + 'builtin/show-branch.c', + 'builtin/show-index.c', + 'builtin/show-ref.c', + 'builtin/sparse-checkout.c', + 'builtin/stash.c', + 'builtin/stripspace.c', + 'builtin/submodule--helper.c', + 'builtin/symbolic-ref.c', + 'builtin/tag.c', + 'builtin/unpack-file.c', + 'builtin/unpack-objects.c', + 'builtin/update-index.c', + 'builtin/update-ref.c', + 'builtin/update-server-info.c', + 'builtin/upload-archive.c', + 'builtin/upload-pack.c', + 'builtin/var.c', + 'builtin/verify-commit.c', + 'builtin/verify-pack.c', + 'builtin/verify-tag.c', + 'builtin/worktree.c', + '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( + output: 'config-list.h', + command: [ + shell, + meson.current_source_dir() + '/generate-configlist.sh', + meson.current_source_dir(), + '@OUTPUT@', + ], + env: script_environment, +) + +libgit_sources += custom_target( + input: 'Documentation/githooks.txt', + output: 'hook-list.h', + command: [ + shell, + meson.current_source_dir() + '/generate-hooklist.sh', + meson.current_source_dir(), + '@OUTPUT@', + ], + env: script_environment, +) + +# This contains the variables for GIT-BUILD-OPTIONS, which we use to propagate +# build options to our tests. +build_options_config = configuration_data() +build_options_config.set('GIT_INTEROP_MAKE_OPTS', '') +build_options_config.set('GIT_PERF_LARGE_REPO', '') +build_options_config.set('GIT_PERF_MAKE_COMMAND', '') +build_options_config.set('GIT_PERF_MAKE_OPTS', '') +build_options_config.set('GIT_PERF_REPEAT_COUNT', '') +build_options_config.set('GIT_PERF_REPO', '') +build_options_config.set('GIT_TEST_CMP_USE_COPIED_CONTEXT', '') +build_options_config.set('GIT_TEST_INDEX_VERSION', '') +build_options_config.set('GIT_TEST_OPTS', '') +build_options_config.set('GIT_TEST_PERL_FATAL_WARNINGS', '') +build_options_config.set('GIT_TEST_UTF8_LOCALE', '') +build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) +build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) + +if get_option('sane_tool_path') != '' + build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + get_option('sane_tool_path') + '"|') +else + build_options_config.set_quoted('BROKEN_PATH_FIX', '/^\# @BROKEN_PATH_FIX@$/d') +endif + +test_output_directory = get_option('test_output_directory') +if test_output_directory == '' + test_output_directory = meson.project_build_root() / 'test-output' +endif + +# These variables are used for building libgit.a. +libgit_c_args = [ + '-DBINDIR="' + get_option('bindir') + '"', + '-DDEFAULT_EDITOR="' + get_option('default_editor') + '"', + '-DDEFAULT_GIT_TEMPLATE_DIR="' + get_option('datadir') / 'git-core/templates' + '"', + '-DDEFAULT_HELP_FORMAT="' + get_option('default_help_format') + '"', + '-DDEFAULT_PAGER="' + get_option('default_pager') + '"', + '-DETC_GITATTRIBUTES="' + get_option('gitattributes') + '"', + '-DETC_GITCONFIG="' + get_option('gitconfig') + '"', + '-DFALLBACK_RUNTIME_PREFIX="' + get_option('prefix') + '"', + '-DGIT_EXEC_PATH="' + get_option('prefix') / get_option('libexecdir') / 'git-core"', + '-DGIT_HOST_CPU="' + host_machine.cpu_family() + '"', + '-DGIT_HTML_PATH="' + get_option('datadir') / 'doc/git-doc"', + '-DGIT_INFO_PATH="' + get_option('infodir') + '"', + '-DGIT_LOCALE_PATH="' + get_option('localedir') + '"', + '-DGIT_MAN_PATH="' + get_option('mandir') + '"', + '-DPAGER_ENV="' + get_option('pager_environment') + '"', + '-DSHELL_PATH="' + fs.as_posix(shell.full_path()) + '"', +] +libgit_include_directories = [ '.' ] +libgit_dependencies = [ ] + +# Treat any warning level above 1 the same as we treat DEVELOPER=1 in our +# Makefile. +if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argument_syntax() == 'gcc' + foreach cflag : [ + '-Wdeclaration-after-statement', + '-Wformat-security', + '-Wold-style-definition', + '-Woverflow', + '-Wpointer-arith', + '-Wstrict-prototypes', + '-Wunused', + '-Wvla', + '-Wwrite-strings', + '-fno-common', + '-Wtautological-constant-out-of-range-compare', + # If a function is public, there should be a prototype and the right + # header file should be included. If not, it should be static. + '-Wmissing-prototypes', + # These are disabled because we have these all over the place. + '-Wno-empty-body', + '-Wno-missing-field-initializers', + '-Wno-sign-compare', + ] + if compiler.has_argument(cflag) + libgit_c_args += cflag + endif + endforeach +endif + +if get_option('b_sanitize').contains('address') + build_options_config.set('SANITIZE_ADDRESS', 'YesCompiledWithIt') +else + build_options_config.set('SANITIZE_ADDRESS', '') +endif +if get_option('b_sanitize').contains('leak') + libgit_c_args += '-DSUPPRESS_ANNOTATED_LEAKS' + build_options_config.set('SANITIZE_LEAK', 'YesCompiledWithIt') +else + build_options_config.set('SANITIZE_LEAK', '') +endif +if get_option('b_sanitize').contains('undefined') + libgit_c_args += '-DSHA1DC_FORCE_ALIGNED_ACCESS' +endif + +executable_suffix = '' +if host_machine.system() == 'cygwin' or host_machine.system() == 'windows' + executable_suffix = '.exe' + libgit_c_args += '-DSTRIP_EXTENSION="' + executable_suffix + '"' +endif +build_options_config.set_quoted('X', executable_suffix) + +python = import('python').find_installation('python3', required: get_option('python')) +if python.found() + build_options_config.set('NO_PYTHON', '') +else + libgit_c_args += '-DNO_PYTHON' + build_options_config.set('NO_PYTHON', '1') +endif + +# Perl is used for two different things: our test harness and to provide some +# features. It is optional if you want to neither execute tests nor use any of +# these optional features. +perl_required = get_option('perl') +if get_option('tests') + perl_required = true +endif + +# Note that we only set NO_PERL if the Perl features were disabled by the user. +# It may not be set when we have found Perl, but only use it to run tests. +perl = find_program('perl', version: '>=5.8.1', dirs: program_path, required: perl_required) +perl_features_enabled = perl.found() and get_option('perl').allowed() +if perl_features_enabled + build_options_config.set('NO_PERL', '') + + if get_option('runtime_prefix') + build_options_config.set('PERL_LOCALEDIR', '') + else + build_options_config.set_quoted('PERL_LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) + endif + + if get_option('perl_cpan_fallback') + build_options_config.set('NO_PERL_CPAN_FALLBACKS', '') + else + build_options_config.set_quoted('NO_PERL_CPAN_FALLBACKS', 'YesPlease') + endif +else + libgit_c_args += '-DNO_PERL' + build_options_config.set('NO_PERL', '1') + build_options_config.set('PERL_LOCALEDIR', '') + build_options_config.set('NO_PERL_CPAN_FALLBACKS', '') +endif + +zlib = dependency('zlib', default_options: ['default_library=static', 'tests=disabled']) +if zlib.version().version_compare('<1.2.0') + libgit_c_args += '-DNO_DEFLATE_BOUND' +endif +libgit_dependencies += zlib + +threads = dependency('threads', required: false) +if threads.found() + libgit_dependencies += threads + build_options_config.set('NO_PTHREADS', '') +else + libgit_c_args += '-DNO_PTHREADS' + build_options_config.set('NO_PTHREADS', '1') +endif + +msgfmt = find_program('msgfmt', dirs: program_path, required: false) +gettext_option = get_option('gettext').disable_auto_if(not msgfmt.found()) +if not msgfmt.found() and gettext_option.enabled() + error('Internationalization via libintl requires msgfmt') +endif + +if gettext_option.allowed() and host_machine.system() == 'darwin' and get_option('macos_use_homebrew_gettext') + if host_machine.cpu_family() == 'x86_64' + libintl_prefix = '/usr/local' + elif host_machine.cpu_family() == 'aarch64' + libintl_prefix = '/opt/homebrew' + else + error('Homebrew workaround not supported on current architecture') + endif + + intl = compiler.find_library('intl', dirs: libintl_prefix / 'lib', required: gettext_option) + if intl.found() + intl = declare_dependency( + dependencies: intl, + include_directories: libintl_prefix / 'include', + ) + endif +else + intl = dependency('intl', required: gettext_option) +endif +if intl.found() + libgit_dependencies += intl + build_options_config.set('NO_GETTEXT', '') + build_options_config.set('USE_GETTEXT_SCHEME', '') + + # POSIX nowadays requires `nl_langinfo()`, but some systems still don't have + # the function available. On such systems we instead fall back to libcharset. + # On native Windows systems we use our own emulation. + if host_machine.system() != 'windows' and not compiler.has_function('nl_langinfo') + libcharset = compiler.find_library('charset', required: true) + libgit_dependencies += libcharset + libgit_c_args += '-DHAVE_LIBCHARSET_H' + endif +else + libgit_c_args += '-DNO_GETTEXT' + build_options_config.set('NO_GETTEXT', '1') + build_options_config.set('USE_GETTEXT_SCHEME', 'fallthrough') +endif + +iconv = dependency('iconv', required: get_option('iconv')) +if iconv.found() + libgit_dependencies += iconv + build_options_config.set('NO_ICONV', '') + + have_old_iconv = false + if not compiler.compiles(''' + #include + + extern size_t iconv(iconv_t cd, + char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft); + ''', name: 'old iconv interface', dependencies: [iconv]) + libgit_c_args += '-DOLD_ICONV' + have_old_iconv = true + endif + + iconv_omits_bom_source = '''# + #include + + int main(int argc, const char **argv) + { + ''' + if have_old_iconv + iconv_omits_bom_source += ''' + typedef const char *iconv_ibp; + ''' + else + iconv_omits_bom_source += ''' + typedef char *iconv_ibp; + ''' + endif + iconv_omits_bom_source += ''' + int v; + iconv_t conv; + char in[] = "a"; iconv_ibp pin = in; + char out[20] = ""; char *pout = out; + size_t isz = sizeof in; + size_t osz = sizeof out; + + conv = iconv_open("UTF-16", "UTF-8"); + iconv(conv, &pin, &isz, &pout, &osz); + iconv_close(conv); + v = (unsigned char)(out[0]) + (unsigned char)(out[1]); + return v != 0xfe + 0xff; + } + ''' + + if compiler.run(iconv_omits_bom_source, + dependencies: iconv, + name: 'iconv omits BOM', + ).returncode() != 0 + libgit_c_args += '-DICONV_OMITS_BOM' + endif +else + libgit_c_args += '-DNO_ICONV' + build_options_config.set('NO_ICONV', '1') +endif + +pcre2 = dependency('libpcre2-8', required: get_option('pcre2'), default_options: ['default_library=static', 'test=false']) +if pcre2.found() + libgit_dependencies += pcre2 + libgit_c_args += '-DUSE_LIBPCRE2' + build_options_config.set('USE_LIBPCRE2', '1') +else + build_options_config.set('USE_LIBPCRE2', '') +endif + +curl = dependency('libcurl', version: '>=7.21.3', required: get_option('curl'), default_options: ['default_library=static', 'tests=disabled', 'tool=disabled']) +use_curl_for_imap_send = false +if curl.found() + if curl.version().version_compare('>=7.34.0') + libgit_c_args += '-DUSE_CURL_FOR_IMAP_SEND' + use_curl_for_imap_send = true + endif + + libgit_dependencies += curl + libgit_c_args += '-DCURL_DISABLE_TYPECHECK' + build_options_config.set('NO_CURL', '') +else + libgit_c_args += '-DNO_CURL' + build_options_config.set('NO_CURL', '1') +endif + +expat = dependency('expat', required: get_option('expat'), default_options: ['default_library=static', 'build_tests=false']) +if expat.found() + libgit_dependencies += expat + + if expat.version().version_compare('<=1.2') + libgit_c_args += '-DEXPAT_NEEDS_XMLPARSE_H' + endif + build_options_config.set('NO_EXPAT', '') +else + libgit_c_args += '-DNO_EXPAT' + build_options_config.set('NO_EXPAT', '1') +endif + +if not compiler.has_header('sys/select.h') + libgit_c_args += '-DNO_SYS_SELECT_H' +endif + +has_poll_h = compiler.has_header('poll.h') +if not has_poll_h + libgit_c_args += '-DNO_POLL_H' +endif + +has_sys_poll_h = compiler.has_header('sys/poll.h') +if not has_sys_poll_h + libgit_c_args += '-DNO_SYS_POLL_H' +endif + +if not has_poll_h and not has_sys_poll_h + libgit_c_args += '-DNO_POLL' + libgit_sources += 'compat/poll/poll.c' + libgit_include_directories += 'compat/poll' +endif + +if not compiler.has_header('inttypes.h') + libgit_c_args += '-DNO_INTTYPES_H' +endif + +if compiler.has_header('alloca.h') + libgit_c_args += '-DHAVE_ALLOCA_H' +endif + +if compiler.has_header('sys/sysinfo.h') + libgit_c_args += '-DHAVE_SYSINFO' +endif + +# Windows has libgen.h and a basename implementation, but we still need our own +# implementation to threat things like drive prefixes specially. +if host_machine.system() == 'windows' or not compiler.has_header('libgen.h') + libgit_c_args += '-DNO_LIBGEN_H' + libgit_sources += 'compat/basename.c' +endif + +if compiler.has_header('paths.h') + libgit_c_args += '-DHAVE_PATHS_H' +endif + +if compiler.has_header('strings.h') + libgit_c_args += '-DHAVE_STRINGS_H' +endif + +networking_dependencies = [ ] +if host_machine.system() == 'windows' + winsock = compiler.find_library('ws2_32', required: false) + if winsock.found() + networking_dependencies += winsock + endif +else + libresolv = compiler.find_library('resolv', required: false) + if libresolv.found() + networking_dependencies += libresolv + endif +endif +libgit_dependencies += networking_dependencies + +foreach symbol : ['inet_ntop', 'inet_pton', 'strerror'] + if not compiler.has_function(symbol, dependencies: networking_dependencies) + libgit_c_args += '-DNO_' + symbol.to_upper() + endif +endforeach + +has_ipv6 = compiler.has_function('getaddrinfo', dependencies: networking_dependencies) +if not has_ipv6 + libgit_c_args += '-DNO_IPV6' +endif + +if not compiler.compiles(''' + #ifdef _WIN32 + # include + #else + # include + # include + #endif + + void func(void) + { + struct sockaddr_storage x; + } +''', name: 'struct sockaddr_storage') + if has_ipv6 + libgit_c_args += '-Dsockaddr_storage=sockaddr_in6' + else + libgit_c_args += '-Dsockaddr_storage=sockaddr_in' + endif +endif + +if compiler.has_function('socket', dependencies: networking_dependencies) + libgit_sources += [ + 'unix-socket.c', + 'unix-stream-server.c', + ] + build_options_config.set('NO_UNIX_SOCKETS', '') +else + libgit_c_args += '-DNO_UNIX_SOCKETS' + build_options_config.set('NO_UNIX_SOCKETS', '1') +endif + +if not compiler.has_function('pread') + libgit_c_args += '-DNO_PREAD' + libgit_sources += 'compat/pread.c' +endif + +if host_machine.system() == 'darwin' + libgit_sources += 'compat/precompose_utf8.c' + libgit_c_args += '-DPRECOMPOSE_UNICODE' + libgit_c_args += '-DPROTECT_HFS_DEFAULT' +endif + +# Configure general compatibility wrappers. +if host_machine.system() == 'cygwin' + libgit_sources += [ + 'compat/win32/path-utils.c', + ] +elif host_machine.system() == 'windows' + libgit_sources += [ + 'compat/mingw.c', + 'compat/winansi.c', + 'compat/win32/flush.c', + 'compat/win32/path-utils.c', + 'compat/win32/pthread.c', + 'compat/win32/syslog.c', + 'compat/win32/dirent.c', + 'compat/win32mmap.c', + 'compat/nedmalloc/nedmalloc.c', + ] + + libgit_c_args += [ + '-DDETECT_MSYS_TTY', + '-DENSURE_MSYSTEM_IS_SET', + '-DNATIVE_CRLF', + '-DNOGDI', + '-DNO_POSIX_GOODIES', + '-DWIN32', + '-D_CONSOLE', + '-D_CONSOLE_DETECT_MSYS_TTY', + '-D__USE_MINGW_ANSI_STDIO=0', + ] + + libgit_dependencies += compiler.find_library('ntdll') + libgit_include_directories += 'compat/win32' + if compiler.get_id() == 'msvc' + libgit_include_directories += 'compat/vcbuild/include' + endif +endif + +if host_machine.system() == 'linux' + libgit_sources += 'compat/linux/procinfo.c' +elif host_machine.system() == 'windows' + libgit_sources += 'compat/win32/trace2_win32_process_info.c' +else + libgit_sources += 'compat/stub/procinfo.c' +endif + +if host_machine.system() == 'cygwin' or host_machine.system() == 'windows' + libgit_c_args += [ + '-DUNRELIABLE_FSTAT', + '-DMMAP_PREVENTS_DELETE', + '-DOBJECT_CREATION_MODE=1', + ] +endif + +# Configure the simple-ipc subsystem required fro the fsmonitor. +if host_machine.system() == 'windows' + libgit_sources += [ + 'compat/simple-ipc/ipc-shared.c', + 'compat/simple-ipc/ipc-win32.c', + ] + libgit_c_args += '-DSUPPORTS_SIMPLE_IPC' +else + libgit_sources += [ + 'compat/simple-ipc/ipc-shared.c', + 'compat/simple-ipc/ipc-unix-socket.c', + ] + libgit_c_args += '-DSUPPORTS_SIMPLE_IPC' +endif + +fsmonitor_backend = '' +if host_machine.system() == 'windows' + fsmonitor_backend = 'win32' +elif host_machine.system() == 'darwin' + fsmonitor_backend = 'darwin' + libgit_dependencies += dependency('CoreServices') +endif +if fsmonitor_backend != '' + libgit_c_args += '-DHAVE_FSMONITOR_DAEMON_BACKEND' + libgit_c_args += '-DHAVE_FSMONITOR_OS_SETTINGS' + + libgit_sources += [ + 'compat/fsmonitor/fsm-health-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-ipc-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-listen-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-path-utils-' + fsmonitor_backend + '.c', + 'compat/fsmonitor/fsm-settings-' + fsmonitor_backend + '.c', + ] +endif +build_options_config.set_quoted('FSMONITOR_DAEMON_BACKEND', fsmonitor_backend) +build_options_config.set_quoted('FSMONITOR_OS_SETTINGS', fsmonitor_backend) + +if not get_option('b_sanitize').contains('address') and get_option('regex').allowed() and compiler.has_header('regex.h') and compiler.get_define('REG_STARTEND', prefix: '#include ') != '' + build_options_config.set('NO_REGEX', '') + + if compiler.get_define('REG_ENHANCED', prefix: '#include ') != '' + libgit_c_args += '-DUSE_ENHANCED_BASIC_REGULAR_EXPRESSIONS' + libgit_sources += 'compat/regcomp_enhanced.c' + endif +elif not get_option('regex').enabled() + libgit_c_args += [ + '-DNO_REGEX', + '-DGAWK', + '-DNO_MBSUPPORT', + ] + build_options_config.set('NO_REGEX', '1') + libgit_sources += 'compat/regex/regex.c' + libgit_include_directories += 'compat/regex' +else + error('Native regex support requested but not found') +endif + +# setitimer and friends are provided by compat/mingw.c. +if host_machine.system() != 'windows' + if not compiler.compiles(''' + #include + void func(void) + { + struct itimerval value; + } + ''', name: 'struct itimerval') + libgit_c_args += '-DNO_STRUCT_ITIMERVAL' + libgit_c_args += '-DNO_SETITIMER' + elif not compiler.has_function('setitimer') + libgit_c_args += '-DNO_SETITIMER' + endif +endif + +if compiler.has_member('struct stat', 'st_mtimespec.tv_nsec', prefix: '#include ') + libgit_c_args += '-DUSE_ST_TIMESPEC' +elif not compiler.has_member('struct stat', 'st_mtim.tv_nsec', prefix: '#include ') + libgit_c_args += '-DNO_NSEC' +endif + +if not compiler.has_member('struct stat', 'st_blocks', prefix: '#include ') + libgit_c_args += '-DNO_ST_BLOCKS_IN_STRUCT_STAT' +endif + +if not compiler.has_member('struct dirent', 'd_type', prefix: '#include ') + libgit_c_args += '-DNO_D_TYPE_IN_DIRENT' +endif + +if not compiler.has_member('struct passwd', 'pw_gecos', prefix: '#include ') + libgit_c_args += '-DNO_GECOS_IN_PWENT' +endif + +if compiler.has_function('sync_file_range') + libgit_c_args += '-DHAVE_SYNC_FILE_RANGE' +endif + +if not compiler.has_function('strcasestr') + libgit_c_args += '-DNO_STRCASESTR' + libgit_sources += 'compat/strcasestr.c' +endif + +if not compiler.has_function('memmem') + libgit_c_args += '-DNO_MEMMEM' + libgit_sources += 'compat/memmem.c' +endif + +if not compiler.has_function('strlcpy') + libgit_c_args += '-DNO_STRLCPY' + libgit_sources += 'compat/strlcpy.c' +endif + +if not compiler.has_function('strdup') + libgit_c_args += '-DOVERRIDE_STRDUP' + libgit_sources += 'compat/strdup.c' +endif + +if not compiler.has_function('strtoumax') + libgit_c_args += '-DNO_STRTOUMAX' + libgit_sources += [ + 'compat/strtoumax.c', + 'compat/strtoimax.c', + ] +endif + +if not compiler.has_function('strtoull') + libgit_c_args += '-DNO_STRTOULL' +endif + +if not compiler.has_function('setenv') + libgit_c_args += '-DNO_SETENV' + libgit_sources += 'compat/setenv.c' +endif + +if not compiler.has_function('qsort') + libgit_c_args += '-DINTERNAL_QSORT' +endif +libgit_sources += 'compat/qsort_s.c' + +# unsetenv is provided by compat/mingw.c. +if host_machine.system() != 'windows' and not compiler.has_function('unsetenv') + libgit_c_args += '-DNO_UNSETENV' + libgit_sources += 'compat/unsetenv.c' +endif + +if not compiler.has_function('mkdtemp') + libgit_c_args += '-DNO_MKDTEMP' + libgit_sources += 'compat/mkdtemp.c' +endif + +if not compiler.has_function('initgroups') + libgit_c_args += '-DNO_INITGROUPS' +endif + +if compiler.has_function('getdelim') + libgit_c_args += '-DHAVE_GETDELIM' +endif + +if host_machine.system() == 'windows' + libgit_c_args += '-DUSE_WIN32_MMAP' +elif not compiler.has_function('mmap') + libgit_c_args += '-DNO_MMAP' + libgit_sources += 'compat/mmap.c' +endif + +if compiler.has_function('clock_gettime') + libgit_c_args += '-DHAVE_CLOCK_GETTIME' +endif + +if compiler.compiles(''' + #include + + void func(void) + { + clockid_t id = CLOCK_MONOTONIC; + } +''', name: 'monotonic clock') + libgit_c_args += '-DHAVE_CLOCK_MONOTONIC' +endif + +if not compiler.compiles(''' + #include + + void func(void) + { + uintmax_t x = 0; + } +''', name: 'uintmax_t') + libgit_c_args += '-DNO_UINTMAX_T' +endif + +has_bsd_sysctl = false +if compiler.has_header('sys/sysctl.h') + if compiler.compiles(''' + #include + #include + + void func(void) + { + int val, mib[2] = { 0 }; + size_t len = sizeof(val); + sysctl(mib, 2, &val, &len, NULL, 0); + } + ''', name: 'BSD sysctl') + libgit_c_args += '-DHAVE_BSD_SYSCTL' + has_bsd_sysctl = true + endif +endif + +if not meson.is_cross_build() and compiler.run(''' + #include + + int main(int argc, const char **argv) + { + FILE *f = fopen(".", "r"); + return f ? 0 : 1; + } +''', name: 'fread reads directories').returncode() == 0 + libgit_c_args += '-DFREAD_READS_DIRECTORIES' + libgit_sources += 'compat/fopen.c' +endif + +if not meson.is_cross_build() and fs.exists('/dev/tty') + libgit_c_args += '-DHAVE_DEV_TTY' +endif + +https_backend = get_option('https_backend') + +security_framework = dependency('Security', required: https_backend == 'CommonCrypto') +core_foundation_framework = dependency('CoreFoundation', required: security_framework.found()) +if https_backend == 'auto' and security_framework.found() + https_backend = 'CommonCrypto' +endif + +openssl_required = https_backend == 'openssl' or get_option('sha1_backend') == 'openssl' or get_option('sha256_backend') == 'openssl' +openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static']) +if https_backend == 'auto' and openssl.found() + https_backend = 'openssl' +endif + +if https_backend == 'CommonCrypto' + libgit_dependencies += security_framework + libgit_dependencies += core_foundation_framework + libgit_c_args += '-DAPPLE_COMMON_CRYPTO' +elif https_backend == 'openssl' + libgit_dependencies += openssl +else + # We either couldn't find any dependencies with 'auto' or the user requested + # 'none'. Both cases are benign. +endif + +if https_backend != 'openssl' + libgit_c_args += '-DNO_OPENSSL' +endif + +sha1_backend = get_option('sha1_backend') +if sha1_backend == 'sha1dc' + libgit_c_args += '-DSHA1_DC' + libgit_c_args += '-DSHA1DC_NO_STANDARD_INCLUDES=1' + libgit_c_args += '-DSHA1DC_INIT_SAFE_HASH_DEFAULT=0' + libgit_c_args += '-DSHA1DC_CUSTOM_INCLUDE_SHA1_C="git-compat-util.h"' + libgit_c_args += '-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="git-compat-util.h"' + + libgit_sources += [ + 'sha1dc_git.c', + 'sha1dc/sha1.c', + 'sha1dc/ubc_check.c', + ] +elif sha1_backend == 'common-crypto' + libgit_c_args += '-DCOMMON_DIGEST_FOR_OPENSSL' + libgit_c_args += '-DSHA1_APPLE' + # Apple CommonCrypto requires chunking + libgit_c_args += '-DSHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' +elif sha1_backend == 'openssl' + libgit_c_args += '-DSHA1_OPENSSL' + libgit_dependencies += openssl +elif sha1_backend == 'block' + libgit_c_args += '-DSHA1_BLK' + libgit_sources += 'block-sha1/sha1.c' +else + error('Unhandled SHA1 backend ' + sha1_backend) +endif + +sha256_backend = get_option('sha256_backend') +if sha256_backend == 'openssl' + libgit_c_args += '-DSHA256_OPENSSL' + libgit_dependencies += openssl +elif sha256_backend == 'nettle' + nettle = dependency('nettle') + libgit_dependencies += nettle + libgit_c_args += '-DSHA256_NETTLE' +elif sha256_backend == 'gcrypt' + gcrypt = dependency('gcrypt') + libgit_dependencies += gcrypt + libgit_c_args += '-DSHA256_GCRYPT' +elif sha256_backend == 'block' + libgit_c_args += '-DSHA256_BLK' + libgit_sources += 'sha256/block/sha256.c' +else + error('Unhandled SHA256 backend ' + sha256_backend) +endif + +if compiler.has_header_symbol('stdlib.h', 'arc4random_buf') + libgit_c_args += '-DHAVE_ARC4RANDOM' +elif compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf') + libgit_c_args += '-DHAVE_ARC4RANDOM_BSD' +elif compiler.has_function('getrandom', prefix: '#include ') + libgit_c_args += '-DHAVE_GETRANDOM' +elif compiler.has_function('getentropy', prefix: '#include ') + libgit_c_args += '-DHAVE_GETENTROPY' +elif compiler.has_function('RtlGenRandom', prefix: '#include \n#include ') + libgit_c_args += '-DHAVE_RTLGENRANDOM' +elif openssl.found() + libgit_c_args += '-DHAVE_OPENSSL_CSPRNG' +endif + +if get_option('runtime_prefix') + libgit_c_args += '-DRUNTIME_PREFIX' + build_options_config.set('RUNTIME_PREFIX', 'true') + + if compiler.has_header('mach-o/dyld.h') + libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH' + endif + + if has_bsd_sysctl and compiler.compiles(''' + #include + + void func(void) + { + KERN_PROC_PATHNAME; KERN_PROC; + } + ''', name: 'BSD KERN_PROC_PATHNAME') + libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH' + endif + + if host_machine.system() == 'linux' + libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="/proc/self/exe' + '"' + elif host_machine.system() == 'openbsd' + libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="' + '/proc/curproc/file' + '"' + elif host_machine.system() == 'netbsd' + libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="' + '/proc/curproc/exe' + '"' + endif + + if host_machine.system() == 'windows' and compiler.compiles(''' + #include + + void func(void) + { + _wpgmptr; + } + ''', name: 'Win32 _wpgmptr') + libgit_c_args += '-DHAVE_WPGMPTR' + endif +else + build_options_config.set('RUNTIME_PREFIX', 'false') +endif + +foreach key, value : { + 'DIFF': diff.full_path(), + 'GIT_TEST_CMP': diff.full_path() + ' -u', + 'GIT_TEST_GITPERLLIB': meson.project_build_root() / 'perl', + 'GIT_TEST_MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools', + 'GIT_TEST_POPATH': meson.project_source_root() / 'po', + 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', + 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', + 'PAGER_ENV': get_option('pager_environment'), + 'PERL_PATH': perl.found() ? perl.full_path() : '', + 'PYTHON_PATH': python.found () ? python.full_path() : '', + 'SHELL_PATH': shell.full_path(), + 'TAR': tar.full_path(), + 'TEST_OUTPUT_DIRECTORY': test_output_directory, + 'TEST_SHELL_PATH': shell.full_path(), +} + if value != '' and cygpath.found() + value = run_command(cygpath, value, check: true).stdout().strip() + endif + build_options_config.set_quoted(key, value) +endforeach + +configure_file( + input: 'GIT-BUILD-OPTIONS.in', + output: 'GIT-BUILD-OPTIONS', + configuration: build_options_config, +) + +git_version_file = custom_target( + command: [ + shell, + meson.current_source_dir() / 'GIT-VERSION-GEN', + meson.current_source_dir(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'GIT-VERSION-FILE.in', + output: 'GIT-VERSION-FILE', + build_always_stale: true, +) + +version_def_h = custom_target( + command: [ + shell, + meson.current_source_dir() / 'GIT-VERSION-GEN', + meson.current_source_dir(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'version-def.h.in', + output: 'version-def.h', + # Depend on GIT-VERSION-FILE so that we don't always try to rebuild this + # target for the same commit. + depends: [git_version_file], +) + +# Build a separate library for "version.c" so that we do not have to rebuild +# everything when the current Git commit changes. +libgit_version_library = static_library('git-version', + sources: [ + 'version.c', + version_def_h, + ], + c_args: libgit_c_args, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) + +libgit_library = static_library('git', + sources: libgit_sources, + c_args: libgit_c_args, + link_with: libgit_version_library, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) + +libgit = declare_dependency( + compile_args: libgit_c_args, + link_with: libgit_library, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) + +common_main_sources = ['common-main.c'] +common_main_link_args = [ ] +if host_machine.system() == 'windows' + git_rc = custom_target( + command: [ + shell, + meson.current_source_dir() / 'GIT-VERSION-GEN', + meson.current_source_dir(), + '@INPUT@', + '@OUTPUT@', + ], + input: meson.current_source_dir() / 'git.rc.in', + output: 'git.rc', + depends: [git_version_file], + ) + + common_main_sources += import('windows').compile_resources(git_rc, + include_directories: [meson.current_source_dir()], + ) + if compiler.get_argument_syntax() == 'gcc' + common_main_link_args += [ + '-municode', + '-Wl,-nxcompat', + '-Wl,-dynamicbase', + '-Wl,-pic-executable,-e,mainCRTStartup', + ] + elif compiler.get_argument_syntax() == 'msvc' + common_main_link_args += [ + '/ENTRY:wmainCRTStartup', + 'invalidcontinue.obj', + ] + else + error('Unsupported compiler ' + compiler.get_id()) + endif +endif +common_main_library = static_library('common-main', + sources: common_main_sources, + c_args: libgit_c_args, + dependencies: libgit_dependencies, + include_directories: libgit_include_directories, +) +common_main = declare_dependency( + link_with: common_main_library, + link_args: common_main_link_args, +) + +bin_wrappers = [ ] +test_dependencies = [ ] + +git = executable('git', + sources: builtin_sources + 'git.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) +bin_wrappers += git + +test_dependencies += executable('git-daemon', + sources: 'daemon.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +test_dependencies += executable('git-sh-i18n--envsubst', + sources: 'sh-i18n--envsubst.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +bin_wrappers += executable('git-shell', + sources: 'shell.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +test_dependencies += executable('git-http-backend', + sources: 'http-backend.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +bin_wrappers += executable('scalar', + sources: 'scalar.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +if get_option('curl').enabled() + curl_sources = [ + 'http.c', + 'http-walker.c', + ] + + git_remote_http = executable('git-remote-http', + sources: curl_sources + 'remote-curl.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + test_dependencies += git_remote_http + + test_dependencies += executable('git-http-fetch', + sources: curl_sources + 'http-fetch.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + + if expat.found() + test_dependencies += executable('git-http-push', + sources: curl_sources + 'http-push.c', + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + endif + + foreach alias : [ 'git-remote-https', 'git-remote-ftp', 'git-remote-ftps' ] + test_dependencies += executable(alias, + objects: git_remote_http.extract_all_objects(recursive: false), + dependencies: [libgit, common_main], + ) + + install_symlink(alias + executable_suffix, + install_dir: get_option('libexecdir') / 'git-core', + pointing_to: 'git-remote-http', + ) + endforeach +endif + +imap_send_sources = ['imap-send.c'] +if use_curl_for_imap_send + imap_send_sources += curl_sources +endif + +test_dependencies += executable('git-imap-send', + sources: imap_send_sources, + dependencies: [libgit, common_main], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +foreach alias : [ 'git-receive-pack', 'git-upload-archive', 'git-upload-pack' ] + bin_wrappers += executable(alias, + objects: git.extract_all_objects(recursive: false), + dependencies: [libgit, common_main], + ) + + install_symlink(alias + executable_suffix, + install_dir: get_option('libexecdir') / 'git-core', + pointing_to: 'git', + ) +endforeach + +foreach symlink : [ + 'git', + 'git-receive-pack', + 'git-shell', + 'git-upload-archive', + 'git-upload-pack', + 'scalar', +] + if meson.version().version_compare('>=1.3.0') + pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / symlink, get_option('bindir')) + else + pointing_to = '../libexec/git-core' / symlink + endif + + install_symlink(symlink, + install_dir: get_option('bindir'), + pointing_to: pointing_to, + ) +endforeach + +scripts_sh = [ + 'git-difftool--helper.sh', + 'git-filter-branch.sh', + 'git-merge-octopus.sh', + 'git-merge-one-file.sh', + 'git-merge-resolve.sh', + 'git-mergetool--lib.sh', + 'git-mergetool.sh', + 'git-quiltimport.sh', + 'git-request-pull.sh', + 'git-sh-i18n.sh', + 'git-sh-setup.sh', + 'git-submodule.sh', + 'git-web--browse.sh', +] +if perl_features_enabled + scripts_sh += 'git-instaweb.sh' +endif + +foreach script : scripts_sh + test_dependencies += custom_target( + input: script, + output: fs.stem(script), + command: [ + shell, + meson.project_source_root() / 'generate-script.sh', + '@INPUT@', + '@OUTPUT@', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) +endforeach + +if perl_features_enabled + scripts_perl = [ + 'git-archimport.perl', + 'git-cvsexportcommit.perl', + 'git-cvsimport.perl', + 'git-cvsserver.perl', + 'git-send-email.perl', + 'git-svn.perl', + ] + + pathsep = ':' + if host_machine.system() == 'windows' + pathsep = ';' + endif + + perl_header_template = 'perl/header_templates/fixed_prefix.template.pl' + if get_option('runtime_prefix') + perl_header_template = 'perl/header_templates/runtime_prefix.template.pl' + endif + + perl_header = configure_file( + input: perl_header_template, + output: 'GIT-PERL-HEADER', + configuration: { + 'GITEXECDIR_REL': get_option('libexecdir') / 'git-core', + 'PERLLIBDIR_REL': get_option('datadir') / 'perl5', + 'LOCALEDIR_REL': get_option('datadir') / 'locale', + 'INSTLIBDIR': get_option('datadir') / 'perl5', + 'PATHSEP': pathsep, + }, + ) + + generate_perl_command = [ + shell, + meson.project_source_root() / 'generate-perl.sh', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + git_version_file.full_path(), + perl_header, + '@INPUT@', + '@OUTPUT@', + ] + + foreach script : scripts_perl + generated_script = custom_target( + input: script, + output: fs.stem(script), + command: generate_perl_command, + install: true, + install_dir: get_option('libexecdir') / 'git-core', + depends: [git_version_file], + ) + test_dependencies += generated_script + + if script == 'git-cvsserver.perl' + bin_wrappers += generated_script + + if meson.version().version_compare('>=1.3.0') + pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / fs.stem(script), get_option('bindir')) + else + pointing_to = '../libexec/git-core' / fs.stem(script) + endif + + install_symlink(fs.stem(script), + install_dir: get_option('bindir'), + pointing_to: pointing_to, + ) + endif + endforeach + + subdir('perl') +endif + +if python.found() + scripts_python = [ + 'git-p4.py' + ] + + foreach script : scripts_python + generated_python = custom_target( + input: script, + output: fs.stem(script), + command: [ + shell, + meson.project_source_root() / 'generate-python.sh', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + '@INPUT@', + '@OUTPUT@', + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) + test_dependencies += generated_python + endforeach +endif + +mergetools = [ + 'mergetools/araxis', + 'mergetools/bc', + 'mergetools/codecompare', + 'mergetools/deltawalker', + 'mergetools/diffmerge', + 'mergetools/diffuse', + 'mergetools/ecmerge', + 'mergetools/emerge', + 'mergetools/examdiff', + 'mergetools/guiffy', + 'mergetools/gvimdiff', + 'mergetools/kdiff3', + 'mergetools/kompare', + 'mergetools/meld', + 'mergetools/nvimdiff', + 'mergetools/opendiff', + 'mergetools/p4merge', + 'mergetools/smerge', + 'mergetools/tkdiff', + 'mergetools/tortoisemerge', + 'mergetools/vimdiff', + 'mergetools/vscode', + 'mergetools/winmerge', + 'mergetools/xxdiff', +] + +foreach mergetool : mergetools + install_data(mergetool, install_dir: get_option('libexecdir') / 'git-core' / 'mergetools') +endforeach + +if intl.found() + subdir('po') +endif +subdir('contrib') +subdir('gitweb') +subdir('templates') + +# Everything but the bin-wrappers need to come before this target such that we +# can properly set up test dependencies. The bin-wrappers themselves are set up +# at configuration time, so these are fine. +if get_option('tests') + subdir('t') +endif + +subdir('bin-wrappers') +if get_option('docs') != [] + subdir('Documentation') +endif + +summary({ + 'curl': curl.found(), + 'expat': expat.found(), + 'gettext': intl.found(), + 'https': https_backend, + 'iconv': iconv.found(), + 'pcre2': pcre2.found(), + 'perl': perl_features_enabled, + 'python': python.found(), +}, section: 'Auto-detected features') -- cgit v1.3 From 23eeee08d6a22de197b17e791508ddcb3a953dc7 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 13 Dec 2024 11:41:17 +0100 Subject: Makefile: drop -DSUPPRESS_ANNOTATED_LEAKS The -DSUPPRESS_ANNOTATED_LEAKS preprocessor directive was used to enable our `UNLEAK()` macro in the past, which marks memory as still-reachable so that the leak sanitizer does not complain. Starting with 52c7dbd036 (git-compat-util: drop now-unused `UNLEAK()` macro, 2024-11-20) this macro has been removed, and thus the preprocessor directive is not required anymore, either. Drop it. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Makefile | 1 - meson.build | 1 - 2 files changed, 2 deletions(-) (limited to 'meson.build') diff --git a/Makefile b/Makefile index 06f01149ec..2506f3b7e3 100644 --- a/Makefile +++ b/Makefile @@ -1490,7 +1490,6 @@ ifneq ($(filter undefined,$(SANITIZERS)),) BASIC_CFLAGS += -DSHA1DC_FORCE_ALIGNED_ACCESS endif ifneq ($(filter leak,$(SANITIZERS)),) -BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS BASIC_CFLAGS += -O0 SANITIZE_LEAK = YesCompiledWithIt endif diff --git a/meson.build b/meson.build index 0dccebcdf1..1af25af5cc 100644 --- a/meson.build +++ b/meson.build @@ -712,7 +712,6 @@ else build_options_config.set('SANITIZE_ADDRESS', '') endif if get_option('b_sanitize').contains('leak') - libgit_c_args += '-DSUPPRESS_ANNOTATED_LEAKS' build_options_config.set('SANITIZE_LEAK', 'YesCompiledWithIt') else build_options_config.set('SANITIZE_LEAK', '') -- cgit v1.3 From 7d549fe317f8c4eea25f5212bc9f8e73b4b2608e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 20 Dec 2024 17:30:35 +0100 Subject: meson: skip gitweb build when Perl is disabled It is possible to configure a Git build without Perl when disabling both our test suite and all Perl-based features. In Meson, this can be achieved with `meson setup -Dperl=disabled -Dtests=false`. It was reported by a user that this breaks the Meson build because gitweb gets built even if Perl was not discovered in such a build: $ meson setup .. -Dtests=false -Dperl=disabled ... ../gitweb/meson.build:2:43: ERROR: Unable to get the path of a not-found external program Fix this issue by introducing a new feature-option that allows the user to configure whether or not to build Gitweb. The feature is set to 'auto' by default and will be disabled automatically in case Perl was not found on the system. Reported-by: Daniel Engberg Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 13 +++++++++++-- meson_options.txt | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 0dccebcdf1..8e34a895dc 100644 --- a/meson.build +++ b/meson.build @@ -740,7 +740,7 @@ endif # features. It is optional if you want to neither execute tests nor use any of # these optional features. perl_required = get_option('perl') -if get_option('tests') +if get_option('tests') or get_option('gitweb').enabled() perl_required = true endif @@ -1874,7 +1874,15 @@ if intl.found() subdir('po') endif subdir('contrib') -subdir('gitweb') + +# Gitweb requires Perl, so we disable the auto-feature if Perl was not found. +# We make sure further up that Perl is required in case the gitweb option is +# enabled. +gitweb_option = get_option('gitweb').disable_auto_if(not perl.found()) +if gitweb_option.enabled() + subdir('gitweb') +endif + subdir('templates') # Everything but the bin-wrappers need to come before this target such that we @@ -1893,6 +1901,7 @@ summary({ 'curl': curl.found(), 'expat': expat.found(), 'gettext': intl.found(), + 'gitweb': gitweb_option.enabled(), 'https': https_backend, 'iconv': iconv.found(), 'pcre2': pcre2.found(), diff --git a/meson_options.txt b/meson_options.txt index 32a72139ba..c374345b1a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -23,6 +23,8 @@ option('expat', type: 'feature', value: 'enabled', description: 'Build helpers used to push to remotes with the HTTP transport.') option('gettext', type: 'feature', value: 'auto', description: 'Build translation files.') +option('gitweb', type: 'feature', value: 'auto', + description: 'Build Git web interface. Requires Perl.') option('iconv', type: 'feature', value: 'auto', description: 'Support reencoding strings with different encodings.') option('pcre2', type: 'feature', value: 'enabled', -- cgit v1.3 From 1bc815c3d0eff054c7a032130206d16839bb331a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 20 Dec 2024 20:44:26 +0100 Subject: meson: add options to override build information We inject various different kinds of build information into build artifacts, like the version string or the commit from which Git was built. Add options to let users explicitly override this information with Meson. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- Documentation/meson.build | 1 + meson.build | 13 +++++++++++++ meson_options.txt | 10 ++++++++++ 3 files changed, 24 insertions(+) (limited to 'meson.build') diff --git a/Documentation/meson.build b/Documentation/meson.build index f2426ccaa3..fca3eab1f1 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -219,6 +219,7 @@ asciidoc_conf = custom_target( input: meson.current_source_dir() / 'asciidoc.conf.in', output: 'asciidoc.conf', depends: [git_version_file], + env: version_gen_environment, ) asciidoc_common_options = [ diff --git a/meson.build b/meson.build index 0dccebcdf1..be32d60e84 100644 --- a/meson.build +++ b/meson.build @@ -201,6 +201,16 @@ if get_option('sane_tool_path') != '' script_environment.prepend('PATH', get_option('sane_tool_path')) endif +# The environment used by GIT-VERSION-GEN. Note that we explicitly override +# environment variables that might be set by the user. This is by design so +# that we always use whatever Meson has configured instead of what is present +# in the environment. +version_gen_environment = script_environment +version_gen_environment.set('GIT_BUILT_FROM_COMMIT', get_option('built_from_commit')) +version_gen_environment.set('GIT_DATE', get_option('build_date')) +version_gen_environment.set('GIT_USER_AGENT', get_option('user_agent')) +version_gen_environment.set('GIT_VERSION', get_option('version')) + compiler = meson.get_compiler('c') libgit_sources = [ @@ -1485,6 +1495,7 @@ git_version_file = custom_target( ], input: meson.current_source_dir() / 'GIT-VERSION-FILE.in', output: 'GIT-VERSION-FILE', + env: version_gen_environment, build_always_stale: true, ) @@ -1501,6 +1512,7 @@ version_def_h = custom_target( # Depend on GIT-VERSION-FILE so that we don't always try to rebuild this # target for the same commit. depends: [git_version_file], + env: version_gen_environment, ) # Build a separate library for "version.c" so that we do not have to rebuild @@ -1544,6 +1556,7 @@ if host_machine.system() == 'windows' input: meson.current_source_dir() / 'git.rc.in', output: 'git.rc', depends: [git_version_file], + env: version_gen_environment, ) common_main_sources += import('windows').compile_resources(git_rc, diff --git a/meson_options.txt b/meson_options.txt index 32a72139ba..8ead134955 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -16,6 +16,16 @@ option('runtime_prefix', type: 'boolean', value: false, option('sane_tool_path', type: 'string', value: '', description: 'A colon-separated list of paths to prepend to PATH if your tools in /usr/bin are broken.') +# Build information compiled into Git and other parts like documentation. +option('build_date', type: 'string', value: '', + description: 'Build date reported by our documentation.') +option('built_from_commit', type: 'string', value: '', + description: 'Commit that Git was built from reported by git-version(1).') +option('user_agent', type: 'string', value: '', + description: 'User agent reported to remote servers.') +option('version', type: 'string', value: '', + description: 'Version string reported by git-version(1) and other tools.') + # Features supported by Git. option('curl', type: 'feature', value: 'enabled', description: 'Build helpers used to access remotes with the HTTP transport.') -- cgit v1.3 From cbcc2f79117ded0161b012dc5107f181b5d87b09 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 13:10:18 +0100 Subject: GIT-BUILD-OPTIONS: wire up NO_GITWEB option Building our "gitweb" interface is optional in our Makefile and in Meson and not wired up at all with CMake, but disabling it causes a couple of tests in the t950* range that pull in "t/lib-gitweb.sh". This is because the test library knows to execute gitweb-tests based on whether or not Perl is available, but we may have Perl available and still end up not building gitweb e.g. with `make test NO_GITWEB=YesPlease`. Fix this issue by wiring up a new "NO_GITWEB" build option so that we can skip these tests in case gitweb is not built. Note that this new build option requires us to move the configuration of GIT-BUILD-OPTIONS to a later point in our Meson build instructions. But as that file is only consumed by our tests at runtime this change does not cause any issues. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- GIT-BUILD-OPTIONS.in | 1 + Makefile | 1 + contrib/buildsystems/CMakeLists.txt | 1 + meson.build | 59 +++++++++++++++++++------------------ t/lib-gitweb.sh | 5 ++++ t/test-lib.sh | 1 + 6 files changed, 40 insertions(+), 28 deletions(-) (limited to 'meson.build') diff --git a/GIT-BUILD-OPTIONS.in b/GIT-BUILD-OPTIONS.in index 162cc39190..edff75ae16 100644 --- a/GIT-BUILD-OPTIONS.in +++ b/GIT-BUILD-OPTIONS.in @@ -24,6 +24,7 @@ LOCALEDIR=@LOCALEDIR@ NO_CURL=@NO_CURL@ NO_EXPAT=@NO_EXPAT@ NO_GETTEXT=@NO_GETTEXT@ +NO_GITWEB=@NO_GITWEB@ NO_ICONV=@NO_ICONV@ NO_PERL=@NO_PERL@ NO_PERL_CPAN_FALLBACKS=@NO_PERL_CPAN_FALLBACKS@ diff --git a/Makefile b/Makefile index f80e70702f..97e8385b66 100644 --- a/Makefile +++ b/Makefile @@ -3171,6 +3171,7 @@ GIT-BUILD-OPTIONS: FORCE -e "s|@NO_CURL@|\'$(NO_CURL)\'|" \ -e "s|@NO_EXPAT@|\'$(NO_EXPAT)\'|" \ -e "s|@NO_GETTEXT@|\'$(NO_GETTEXT)\'|" \ + -e "s|@NO_GITWEB@|\'$(NO_GITWEB)\'|" \ -e "s|@NO_ICONV@|\'$(NO_ICONV)\'|" \ -e "s|@NO_PERL@|\'$(NO_PERL)\'|" \ -e "s|@NO_PERL_CPAN_FALLBACKS@|\'$(NO_PERL_CPAN_FALLBACKS_SQ)\'|" \ diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index f45407b060..10dc54fdcb 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -1184,6 +1184,7 @@ string(REPLACE "@LOCALEDIR@" "'${LOCALEDIR}'" git_build_options "${git_build_opt string(REPLACE "@NO_CURL@" "${NO_CURL}" git_build_options "${git_build_options}") string(REPLACE "@NO_EXPAT@" "${NO_EXPAT}" git_build_options "${git_build_options}") string(REPLACE "@NO_GETTEXT@" "${NO_GETTEXT}" git_build_options "${git_build_options}") +string(REPLACE "@NO_GITWEB@" "1" git_build_options "${git_build_options}") string(REPLACE "@NO_ICONV@" "${NO_ICONV}" git_build_options "${git_build_options}") string(REPLACE "@NO_PERL@" "${NO_PERL}" git_build_options "${git_build_options}") string(REPLACE "@NO_PERL_CPAN_FALLBACKS@" "" git_build_options "${git_build_options}") diff --git a/meson.build b/meson.build index a0654a3f24..3e57793862 100644 --- a/meson.build +++ b/meson.build @@ -1456,34 +1456,6 @@ else build_options_config.set('RUNTIME_PREFIX', 'false') endif -foreach key, value : { - 'DIFF': diff.full_path(), - 'GIT_TEST_CMP': diff.full_path() + ' -u', - 'GIT_TEST_GITPERLLIB': meson.project_build_root() / 'perl', - 'GIT_TEST_MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools', - 'GIT_TEST_POPATH': meson.project_source_root() / 'po', - 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', - 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', - 'PAGER_ENV': get_option('pager_environment'), - 'PERL_PATH': perl.found() ? perl.full_path() : '', - 'PYTHON_PATH': python.found () ? python.full_path() : '', - 'SHELL_PATH': shell.full_path(), - 'TAR': tar.full_path(), - 'TEST_OUTPUT_DIRECTORY': test_output_directory, - 'TEST_SHELL_PATH': shell.full_path(), -} - if value != '' and cygpath.found() - value = run_command(cygpath, value, check: true).stdout().strip() - endif - build_options_config.set_quoted(key, value) -endforeach - -configure_file( - input: 'GIT-BUILD-OPTIONS.in', - output: 'GIT-BUILD-OPTIONS', - configuration: build_options_config, -) - git_version_file = custom_target( command: [ shell, @@ -1893,6 +1865,9 @@ subdir('contrib') gitweb_option = get_option('gitweb').disable_auto_if(not perl.found()) if gitweb_option.enabled() subdir('gitweb') + build_options_config.set('NO_GITWEB', '') +else + build_options_config.set('NO_GITWEB', '1') endif subdir('templates') @@ -1909,6 +1884,34 @@ if get_option('docs') != [] subdir('Documentation') endif +foreach key, value : { + 'DIFF': diff.full_path(), + 'GIT_TEST_CMP': diff.full_path() + ' -u', + 'GIT_TEST_GITPERLLIB': meson.project_build_root() / 'perl', + 'GIT_TEST_MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools', + 'GIT_TEST_POPATH': meson.project_source_root() / 'po', + 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', + 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', + 'PAGER_ENV': get_option('pager_environment'), + 'PERL_PATH': perl.found() ? perl.full_path() : '', + 'PYTHON_PATH': python.found () ? python.full_path() : '', + 'SHELL_PATH': shell.full_path(), + 'TAR': tar.full_path(), + 'TEST_OUTPUT_DIRECTORY': test_output_directory, + 'TEST_SHELL_PATH': shell.full_path(), +} + if value != '' and cygpath.found() + value = run_command(cygpath, value, check: true).stdout().strip() + endif + build_options_config.set_quoted(key, value) +endforeach + +configure_file( + input: 'GIT-BUILD-OPTIONS.in', + output: 'GIT-BUILD-OPTIONS', + configuration: build_options_config, +) + summary({ 'curl': curl.found(), 'expat': expat.found(), diff --git a/t/lib-gitweb.sh b/t/lib-gitweb.sh index 7f9808ec20..a6e3dd11b3 100644 --- a/t/lib-gitweb.sh +++ b/t/lib-gitweb.sh @@ -105,6 +105,11 @@ if ! test_have_prereq PERL; then test_done fi +if ! test_have_prereq GITWEB; then + skip_all='skipping gitweb tests, gitweb not available' + test_done +fi + perl -MEncode -e '$e="";decode_utf8($e, Encode::FB_CROAK)' >/dev/null 2>&1 || { skip_all='skipping gitweb tests, perl version is too old' test_done diff --git a/t/test-lib.sh b/t/test-lib.sh index 62dfcc4aaf..1a67adb207 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1687,6 +1687,7 @@ esac ( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1 test -z "$NO_CURL" && test_set_prereq LIBCURL +test -z "$NO_GITWEB" && test_set_prereq GITWEB test -z "$NO_ICONV" && test_set_prereq ICONV test -z "$NO_PERL" && test_set_prereq PERL test -z "$NO_PTHREADS" && test_set_prereq PTHREADS -- cgit v1.3 From d963ac98ec94fd2003722a794f0168a70ea1b815 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Dec 2024 13:10:19 +0100 Subject: meson: enable auto-discovered "gitweb" In 7d549fe317 (meson: skip gitweb build when Perl is disabled, 2024-12-20) we have started to conditionally enable "gitweb" based on whether or not Perl is enabled. By accident though that change causes us to not build gitweb in case its feature flag is set to "auto" even if autoconfiguration determines that it could be built. This is because we use "gitweb_option.enabled()", which only checks whether the feature has been explicitly enabled. Fix the issue by using `gitweb_option.allowed()` instead, which returns true in case it is either explicitly enabled or set to "auto". This also works for the case where the feature becomes auto-disabled due to Perl not being present because we use `disable_auto_if(not perl.found())`. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 3e57793862..0064eb64f5 100644 --- a/meson.build +++ b/meson.build @@ -1863,7 +1863,7 @@ subdir('contrib') # We make sure further up that Perl is required in case the gitweb option is # enabled. gitweb_option = get_option('gitweb').disable_auto_if(not perl.found()) -if gitweb_option.enabled() +if gitweb_option.allowed() subdir('gitweb') build_options_config.set('NO_GITWEB', '') else @@ -1916,7 +1916,7 @@ summary({ 'curl': curl.found(), 'expat': expat.found(), 'gettext': intl.found(), - 'gitweb': gitweb_option.enabled(), + 'gitweb': gitweb_option.allowed(), 'https': https_backend, 'iconv': iconv.found(), 'pcre2': pcre2.found(), -- cgit v1.3 From 8214e27d275915079ddf7c294c379515e34e8efb Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 30 Dec 2024 15:24:04 +0100 Subject: meson: consistenlty spell 'CommonCrypto' The 'CommonCrypto' backend can be specified as HTTPS and SHA1 backends, but the value that one needs to use is inconsistent across those two build options. Unify it to 'CommonCrypto'. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 2 +- meson_options.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 0064eb64f5..9da58dafe0 100644 --- a/meson.build +++ b/meson.build @@ -1367,7 +1367,7 @@ if sha1_backend == 'sha1dc' 'sha1dc/sha1.c', 'sha1dc/ubc_check.c', ] -elif sha1_backend == 'common-crypto' +elif sha1_backend == 'CommonCrypto' libgit_c_args += '-DCOMMON_DIGEST_FOR_OPENSSL' libgit_c_args += '-DSHA1_APPLE' # Apple CommonCrypto requires chunking diff --git a/meson_options.txt b/meson_options.txt index 4be7eab399..a7f308d217 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -49,7 +49,7 @@ option('regex', type: 'feature', value: 'auto', # Backends. 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', 'common-crypto'], value: 'sha1dc', +option('sha1_backend', type: 'combo', choices: ['openssl', 'block', 'sha1dc', 'CommonCrypto'], value: 'sha1dc', description: 'The backend used for hashing objects with the SHA1 object format') option('sha256_backend', type: 'combo', choices: ['openssl', 'nettle', 'gcrypt', 'block'], value: 'block', description: 'The backend used for hashing objects with the SHA256 object format') -- cgit v1.3 From 31eb6d7cf09c3fa668c1839d8c5759ab7cdf280c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 30 Dec 2024 15:24:05 +0100 Subject: meson: deduplicate access to SHA1/SHA256 backend options We've got a couple of repeated calls to `get_option()` for the SHA1 and SHA256 backend options. While not an issue, it makes the code needlessly verbose. Fix this by consistently using a local variable. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 9da58dafe0..6fa4d900ee 100644 --- a/meson.build +++ b/meson.build @@ -1326,6 +1326,8 @@ if not meson.is_cross_build() and fs.exists('/dev/tty') endif https_backend = get_option('https_backend') +sha1_backend = get_option('sha1_backend') +sha256_backend = get_option('sha256_backend') security_framework = dependency('Security', required: https_backend == 'CommonCrypto') core_foundation_framework = dependency('CoreFoundation', required: security_framework.found()) @@ -1333,7 +1335,7 @@ if https_backend == 'auto' and security_framework.found() https_backend = 'CommonCrypto' endif -openssl_required = https_backend == 'openssl' or get_option('sha1_backend') == 'openssl' or get_option('sha256_backend') == 'openssl' +openssl_required = https_backend == 'openssl' or sha1_backend == 'openssl' or sha256_backend == 'openssl' openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static']) if https_backend == 'auto' and openssl.found() https_backend = 'openssl' @@ -1354,7 +1356,6 @@ if https_backend != 'openssl' libgit_c_args += '-DNO_OPENSSL' endif -sha1_backend = get_option('sha1_backend') if sha1_backend == 'sha1dc' libgit_c_args += '-DSHA1_DC' libgit_c_args += '-DSHA1DC_NO_STANDARD_INCLUDES=1' @@ -1382,7 +1383,6 @@ else error('Unhandled SHA1 backend ' + sha1_backend) endif -sha256_backend = get_option('sha256_backend') if sha256_backend == 'openssl' libgit_c_args += '-DSHA256_OPENSSL' libgit_dependencies += openssl -- cgit v1.3 From d6787d975147a74f1560fffc09dcb2a1f92460bb Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 30 Dec 2024 15:24:06 +0100 Subject: meson: require SecurityFramework when it's used as SHA1 backend The Security framework is required when we use CommonCrypto either as HTTPS or SHA1 backend, but we only require it in case it is set up as HTTPS backend. Fix this. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 6fa4d900ee..bc75ad954a 100644 --- a/meson.build +++ b/meson.build @@ -1329,7 +1329,7 @@ https_backend = get_option('https_backend') sha1_backend = get_option('sha1_backend') sha256_backend = get_option('sha256_backend') -security_framework = dependency('Security', required: https_backend == 'CommonCrypto') +security_framework = dependency('Security', required: https_backend == 'CommonCrypto' or sha1_backend == 'CommonCrypto') core_foundation_framework = dependency('CoreFoundation', required: security_framework.found()) if https_backend == 'auto' and security_framework.found() https_backend = 'CommonCrypto' -- cgit v1.3 From 6d8aa2aec81abf4935c72745790bc5f9bf7541b9 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 30 Dec 2024 15:24:07 +0100 Subject: meson: simplify conditions for HTTPS and SHA1 dependencies The conditions used to figure out whteher the Security framework or OpenSSL library is required are a bit convoluted because they can be pulled in via the HTTPS, SHA1 or SHA256 backends. Refactor them to be easier to read. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index bc75ad954a..46f807899b 100644 --- a/meson.build +++ b/meson.build @@ -1329,13 +1329,13 @@ https_backend = get_option('https_backend') sha1_backend = get_option('sha1_backend') sha256_backend = get_option('sha256_backend') -security_framework = dependency('Security', required: https_backend == 'CommonCrypto' or sha1_backend == 'CommonCrypto') +security_framework = dependency('Security', required: 'CommonCrypto' in [https_backend, sha1_backend]) core_foundation_framework = dependency('CoreFoundation', required: security_framework.found()) if https_backend == 'auto' and security_framework.found() https_backend = 'CommonCrypto' endif -openssl_required = https_backend == 'openssl' or sha1_backend == 'openssl' or sha256_backend == 'openssl' +openssl_required = 'openssl' in [https_backend, sha1_backend, sha256_backend] openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static']) if https_backend == 'auto' and openssl.found() https_backend = 'openssl' -- cgit v1.3 From d2c0b6a86cb0f1a73d9ad5fcffda45497cd7ad42 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 30 Dec 2024 15:24:09 +0100 Subject: meson: wire up unsafe SHA1 backend In 06c92dafb8 (Makefile: allow specifying a SHA-1 for non-cryptographic uses, 2024-09-26), we have introduced a cryptographically-insecure backend for SHA1 that can optionally be used in some contexts where the processed data is not security relevant. This effort was in-flight with the effort to introduce Meson, so we don't have an equivalent here. Wire up a new build option that lets users pick an unsafe SHA1 backend. Note that for simplicity's sake we have to drop the error condition around an unhandled SHA1 backend. This should be fine though given that Meson verifies the value for combo-options for us. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 40 ++++++++++++++++++++++++++++++---------- meson_options.txt | 2 ++ 2 files changed, 32 insertions(+), 10 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 46f807899b..dc82c23cb4 100644 --- a/meson.build +++ b/meson.build @@ -1327,15 +1327,16 @@ endif https_backend = get_option('https_backend') sha1_backend = get_option('sha1_backend') +sha1_unsafe_backend = get_option('sha1_unsafe_backend') sha256_backend = get_option('sha256_backend') -security_framework = dependency('Security', required: 'CommonCrypto' in [https_backend, sha1_backend]) +security_framework = dependency('Security', required: 'CommonCrypto' in [https_backend, sha1_backend, sha1_unsafe_backend]) core_foundation_framework = dependency('CoreFoundation', required: security_framework.found()) if https_backend == 'auto' and security_framework.found() https_backend = 'CommonCrypto' endif -openssl_required = 'openssl' in [https_backend, sha1_backend, sha256_backend] +openssl_required = 'openssl' in [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' @@ -1368,19 +1369,38 @@ if sha1_backend == 'sha1dc' 'sha1dc/sha1.c', 'sha1dc/ubc_check.c', ] -elif sha1_backend == 'CommonCrypto' +endif +if sha1_backend == 'CommonCrypto' or sha1_unsafe_backend == 'CommonCrypto' + if sha1_backend == 'CommonCrypto' + libgit_c_args += '-DSHA1_APPLE' + endif + if sha1_unsafe_backend == 'CommonCrypto' + libgit_c_args += '-DSHA1_APPLE_UNSAFE' + endif + libgit_c_args += '-DCOMMON_DIGEST_FOR_OPENSSL' - libgit_c_args += '-DSHA1_APPLE' # Apple CommonCrypto requires chunking libgit_c_args += '-DSHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' -elif sha1_backend == 'openssl' - libgit_c_args += '-DSHA1_OPENSSL' +endif +if sha1_backend == 'openssl' or sha1_unsafe_backend == 'openssl' + if sha1_backend == 'openssl' + libgit_c_args += '-DSHA1_OPENSSL' + endif + if sha1_unsafe_backend == 'openssl' + libgit_c_args += '-DSHA1_OPENSSL_UNSAFE' + endif + libgit_dependencies += openssl -elif sha1_backend == 'block' - libgit_c_args += '-DSHA1_BLK' +endif +if sha1_backend == 'block' or sha1_unsafe_backend == 'block' + if sha1_backend == 'block' + libgit_c_args += '-DSHA1_BLK' + endif + if sha1_unsafe_backend == 'block' + libgit_c_args += '-DSHA1_BLK_UNSAFE' + endif + libgit_sources += 'block-sha1/sha1.c' -else - error('Unhandled SHA1 backend ' + sha1_backend) endif if sha256_backend == 'openssl' diff --git a/meson_options.txt b/meson_options.txt index d8d283982b..8282b1dea8 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -51,6 +51,8 @@ option('https_backend', type: 'combo', value: 'auto', choices: ['auto', 'openssl description: 'The HTTPS backend to use when connecting to remotes.') option('sha1_backend', type: 'combo', choices: ['openssl', 'block', 'sha1dc', 'CommonCrypto'], value: 'sha1dc', description: 'The backend used for hashing objects with the SHA1 object format.') +option('sha1_unsafe_backend', type: 'combo', choices: ['openssl', 'block', 'CommonCrypto', 'none'], value: 'none', + description: 'The backend used for hashing data with the SHA1 object format in case no cryptographic security is needed.') option('sha256_backend', type: 'combo', choices: ['openssl', 'nettle', 'gcrypt', 'block'], value: 'block', description: 'The backend used for hashing objects with the SHA256 object format.') -- cgit v1.3 From 6a0ee54f9a3ebf667e86f7110c36b2240df96166 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 30 Dec 2024 15:24:10 +0100 Subject: meson: provide a summary of configured backends There are a couple of backends from which the user can choose for HTTPS, SHA1, its unsafe variant as well as SHA256. Provide a summary of the configured values to make these more discoverable. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'meson.build') diff --git a/meson.build b/meson.build index dc82c23cb4..7361eb2eaa 100644 --- a/meson.build +++ b/meson.build @@ -1943,3 +1943,10 @@ summary({ 'perl': perl_features_enabled, 'python': python.found(), }, section: 'Auto-detected features') + +summary({ + 'https': https_backend, + 'sha1': sha1_backend, + 'sha1_unsafe': sha1_unsafe_backend, + 'sha256': sha256_backend, +}, section: 'Backends') -- cgit v1.3 From 4771501c0a125dd3560391cbd716c63a281e8244 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Tue, 14 Jan 2025 12:15:23 +0100 Subject: meson: ensure correct version-def.h is used To build the libgit-version library, Meson first generates `version-def.h` in the build directory. Then it compiles `version.c` into a library. During compilation, Meson tells to include both the build directory and the project root directory. However, when the user previously has compiled Git using Make, they will have a `version-def.h` file in project root directory as well. Because `version-def.h` is included in `version.c` using the #include directive with double quotes, some preprocessors will look for the header file in the same directory as the source file. This will cause compilation of `version.c` ran by Meson to include `version-def.h` previously made by Make, which might be out of date. To explicitly tell the preprocessor which `version-def.h` to use, pass the absolute path of this file as macro GIT_VERSION_H to the preprocessor using option `-D` and have `version.c` `#include GIT_VERSION_H`. To remain working with other build systems than Meson, include "version-def.h" if that macro is not defined. Co-authored-by: Patrick Steinhardt Signed-off-by: Toon Claes Signed-off-by: Junio C Hamano --- meson.build | 4 +++- version.c | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 0064eb64f5..db27afa999 100644 --- a/meson.build +++ b/meson.build @@ -1493,7 +1493,9 @@ libgit_version_library = static_library('git-version', 'version.c', version_def_h, ], - c_args: libgit_c_args, + c_args: libgit_c_args + [ + '-DGIT_VERSION_H="' + version_def_h.full_path() + '"', + ], dependencies: libgit_dependencies, include_directories: libgit_include_directories, ) diff --git a/version.c b/version.c index 4d763ab48d..4786c4e0a5 100644 --- a/version.c +++ b/version.c @@ -1,8 +1,13 @@ #include "git-compat-util.h" #include "version.h" -#include "version-def.h" #include "strbuf.h" +#ifndef GIT_VERSION_H +# include "version-def.h" +#else +# include GIT_VERSION_H +#endif + const char git_version_string[] = GIT_VERSION; const char git_built_from_commit_string[] = GIT_BUILT_FROM_COMMIT; -- cgit v1.3 From 8454b42f947e185a65b2950123493928558f2f5e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 17 Jan 2025 10:56:07 +0100 Subject: meson: wire up the git-subtree(1) command Wire up the git-subtree(1) command, which is part of "contrib/". Note that we have to move around the exact location where we include the "contrib/" subdirectory so that it comes after building the docs so that we have access to some of the common functionality. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- contrib/subtree/meson.build | 71 +++++++++++++++++++++++++++++++++++++++++++++ meson.build | 3 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 contrib/subtree/meson.build (limited to 'meson.build') diff --git a/contrib/subtree/meson.build b/contrib/subtree/meson.build new file mode 100644 index 0000000000..a752a188df --- /dev/null +++ b/contrib/subtree/meson.build @@ -0,0 +1,71 @@ +git_subtree = custom_target( + input: 'git-subtree.sh', + output: 'git-subtree', + command: [ + shell, + meson.project_source_root() / 'generate-script.sh', + '@INPUT@', + '@OUTPUT@', + meson.project_build_root() / 'GIT-BUILD-OPTIONS', + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', +) + +subtree_test_environment = test_environment +subtree_test_environment.prepend('PATH', meson.current_build_dir()) + +test('t7900-subtree', shell, + args: [ 't7900-subtree.sh' ], + env: subtree_test_environment, + workdir: meson.current_source_dir() / 't', + depends: test_dependencies + bin_wrappers + [ git_subtree ], + timeout: 0, +) + +if get_option('docs').contains('man') + subtree_xml = custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_docbook, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-subtree.txt', + output: 'git-subtree.xml', + ) + + custom_target( + command: [ + xmlto, + '-m', '@INPUT@', + 'man', + subtree_xml, + '-o', + meson.current_build_dir(), + ] + xmlto_extra, + input: [ + '../../Documentation/manpage-normal.xsl', + ], + output: 'git-subtree.1', + install: true, + install_dir: get_option('mandir') / 'man1', + ) +endif + +if get_option('docs').contains('html') + custom_target( + command: asciidoc_common_options + [ + '--backend=' + asciidoc_html, + '--doctype=manpage', + '--out-file=@OUTPUT@', + '@INPUT@', + ], + depends: documentation_deps, + input: 'git-subtree.txt', + output: 'git-subtree.html', + install: true, + install_dir: get_option('datadir') / 'doc/git-doc', + ) +endif diff --git a/meson.build b/meson.build index 0064eb64f5..ac7f6ef38b 100644 --- a/meson.build +++ b/meson.build @@ -1857,7 +1857,6 @@ endforeach if intl.found() subdir('po') endif -subdir('contrib') # Gitweb requires Perl, so we disable the auto-feature if Perl was not found. # We make sure further up that Perl is required in case the gitweb option is @@ -1884,6 +1883,8 @@ if get_option('docs') != [] subdir('Documentation') endif +subdir('contrib') + foreach key, value : { 'DIFF': diff.full_path(), 'GIT_TEST_CMP': diff.full_path() + ' -u', -- cgit v1.3 From eb8728d88ab92d866f454a5b981b7bbfe4e2235b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 20 Jan 2025 17:17:19 +0100 Subject: meson: stop disabling -Wsign-compare In 4f9264b0cd (config.mak.dev: drop `-Wno-sign-compare`, 2024-12-06) we have started an effort to make our codebase compile with -Wsign-compare. But while we removed the -Wno-sign-compare flag from "config.mak.dev", we didn't adjust the Meson build instructions in the same way. Fix this. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 1 - 1 file changed, 1 deletion(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 0064eb64f5..07744c73b1 100644 --- a/meson.build +++ b/meson.build @@ -708,7 +708,6 @@ if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argum # These are disabled because we have these all over the place. '-Wno-empty-body', '-Wno-missing-field-initializers', - '-Wno-sign-compare', ] if compiler.has_argument(cflag) libgit_c_args += cflag -- cgit v1.3 From c5bc9a7f94a41c3e719afebf4a6c3e04cba82e4d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 12:31:29 +0100 Subject: Makefile: wire up build option for deprecated features With 57ec9254eb (docs: introduce document to announce breaking changes, 2024-06-14), we have introduced a new document that tracks upcoming breaking changes in the Git project. In 2454970930 (BreakingChanges: early adopter option, 2024-10-11) we have amended the document a bit to mention that any introduced breaking changes must be accompanied by logic that allows us to enable the breaking change at compile-time. While we already have two breaking changes lined up, neither of them has such a switch because they predate those instructions. Introduce the proposed `WITH_BREAKING_CHANGES` preprocessor macro and wire it up with both our Makefiles and Meson. This does not yet wire up the build flag for existing deprecations. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- GIT-BUILD-OPTIONS.in | 1 + Makefile | 5 +++++ contrib/buildsystems/CMakeLists.txt | 1 + meson.build | 6 ++++++ meson_options.txt | 2 ++ t/test-lib.sh | 4 ++++ 6 files changed, 19 insertions(+) (limited to 'meson.build') diff --git a/GIT-BUILD-OPTIONS.in b/GIT-BUILD-OPTIONS.in index f651116102..f1d0ecf123 100644 --- a/GIT-BUILD-OPTIONS.in +++ b/GIT-BUILD-OPTIONS.in @@ -45,3 +45,4 @@ GITWEBDIR=@GITWEBDIR@ USE_GETTEXT_SCHEME=@USE_GETTEXT_SCHEME@ LOCALEDIR=@LOCALEDIR@ BROKEN_PATH_FIX=@BROKEN_PATH_FIX@ +WITH_BREAKING_CHANGES=@WITH_BREAKING_CHANGES@ diff --git a/Makefile b/Makefile index 06f01149ec..dc3c980aa7 100644 --- a/Makefile +++ b/Makefile @@ -2230,6 +2230,10 @@ ifdef FSMONITOR_OS_SETTINGS COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o endif +ifdef WITH_BREAKING_CHANGES + BASIC_CFLAGS += -DWITH_BREAKING_CHANGES +endif + ifeq ($(TCLTK_PATH),) NO_TCLTK = NoThanks endif @@ -3187,6 +3191,7 @@ GIT-BUILD-OPTIONS: FORCE -e "s|@USE_GETTEXT_SCHEME@|\'$(USE_GETTEXT_SCHEME)\'|" \ -e "s|@LOCALEDIR@|\'$(localedir_SQ)\'|" \ -e "s!@BROKEN_PATH_FIX@!\'$(BROKEN_PATH_FIX)\'!" \ + -e "s|@WITH_BREAKING_CHANGES@|\'$(WITH_BREAKING_CHANGES)\'|" \ GIT-BUILD-OPTIONS.in >$@+ @if grep -q '^[A-Z][A-Z_]*=@.*@$$' $@+; then echo "Unsubstituted build options in $@" >&2 && exit 1; fi @if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 49904ca8a9..63d0088928 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -1198,6 +1198,7 @@ string(REPLACE "@GITWEBDIR@" "'${GITWEBDIR}'" git_build_options "${git_build_opt string(REPLACE "@USE_GETTEXT_SCHEME@" "" git_build_options "${git_build_options}") string(REPLACE "@LOCALEDIR@" "'${LOCALEDIR}'" git_build_options "${git_build_options}") string(REPLACE "@BROKEN_PATH_FIX@" "" git_build_options "${git_build_options}") +string(REPLACE "@WITH_BREAKING_CHANGES@" "" git_build_options "${git_build_options}") if(USE_VCPKG) string(APPEND git_build_options "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/x64-windows/bin\"\n") endif() diff --git a/meson.build b/meson.build index 0dccebcdf1..316cd93264 100644 --- a/meson.build +++ b/meson.build @@ -644,6 +644,12 @@ build_options_config.set('GIT_TEST_UTF8_LOCALE', '') build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) +if get_option('breaking_changes') + build_options_config.set('WITH_BREAKING_CHANGES', 'YesPlease') +else + build_options_config.set('WITH_BREAKING_CHANGES', '') +endif + if get_option('sane_tool_path') != '' build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + get_option('sane_tool_path') + '"|') else diff --git a/meson_options.txt b/meson_options.txt index 32a72139ba..800e518d95 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -43,6 +43,8 @@ option('sha256_backend', type: 'combo', choices: ['openssl', 'nettle', 'gcrypt', description: 'The backend used for hashing objects with the SHA256 object format') # Build tweaks. +option('breaking_changes', type: 'boolean', value: false, + description: 'Enable upcoming breaking changes.') option('macos_use_homebrew_gettext', type: 'boolean', value: true, description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.') diff --git a/t/test-lib.sh b/t/test-lib.sh index 62dfcc4aaf..6e423f655d 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1864,6 +1864,10 @@ test_lazy_prereq CURL ' curl --version ' +test_lazy_prereq WITHOUT_BREAKING_CHANGES ' + test -z "$WITH_BREAKING_CHANGES" +' + # SHA1 is a test if the hash algorithm in use is SHA-1. This is both for tests # which will not work with other hash algorithms and tests that work but don't # test anything meaningful (e.g. special values which cause short collisions). -- cgit v1.3 From 6ff99174d152f0e1359c30e30ef08ab75b137037 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 13:05:46 +0100 Subject: meson: populate project version via GIT-VERSION-GEN The Git version for Meson is currently wired up manually. It can thus grow (and already has grown) stale quite easily, as having multiple sources of truth is never a good idea. This issue is mostly of cosmetic nature as we don't use the project version anywhere, and instead use the GIT-VERSION-GEN script to propagate the correct version into our build. But it is somewhat puzzling when `meson setup` announces to build an old Git release. There are a couple of alternatives for how to solve this: - We can keep the version undefined, but this makes Meson output "undefined" for the version, as well. - We can use GIT-VERSION-GEN to generate the version for us. At the point of configuring the project we haven't yet figured out host details though, and thus we didn't yet set up the shell environment. While not an issue for Unix-based systems, this would be an issue in Windows, where the shell typically gets provided via Git for Windows and thus requires some special setup. - We can pull the default version out of GIT-VERSION-GEN and move it into its own file. This likely requires some adjustments for scripts that bump the version, but allows Meson to read the version from that file trivially. Pick the second option and use GIT-VERSION-GEN as it gives us the most accurate version. In order to fix the bootstrapping issue on Windows systems we simply set the version to 'unknown' in case no shell was found. As the version is only of cosmetic value this isn't really much of an issue. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 7361eb2eaa..213998986e 100644 --- a/meson.build +++ b/meson.build @@ -170,7 +170,14 @@ 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', ) fs = import('fs') -- cgit v1.3 From 53d75bd3e4f1e1d6c721fd90f9754a80caa61fd5 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 13:05:47 +0100 Subject: meson: fix dependencies for generated headers We generate a couple of headers from our documentation. These headers are added to the libgit sources, but two of them aren't used by the library, but instead by our builtins. This can cause parallel builds to fail because the builtin object may be compiled before the header was generated. Fix the issue by adding both "config-list.h" and "hook-list.h" to the list of builtin sources. While "command-list.h" is generated similarly, it is used by "help.c" and thus part of the libgit sources indeed. Reported-by: Evan Martin Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 213998986e..4053024dad 100644 --- a/meson.build +++ b/meson.build @@ -487,6 +487,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', @@ -614,14 +621,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, @@ -632,7 +632,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: [ -- cgit v1.3 From 5d0cf6bb3a126725f70529f205a32b4720f81183 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 13:05:48 +0100 Subject: meson: wire up development environments The Meson build system is able to wire up development environments. The intent is to make build artifacts of the project available. This is typically used to export e.g. paths to linkable libraries, which isn't all that interesting in our context given that we don't have an official library interface. But what we can use this mechanism for is to expose the built Git executables as well as the build directory. This allows users to play around with the built Git version in the devenv, and allows them to execute our test scripts directly with the built distribution. Wire up this feature, which can then be used via `meson devenv` in the build directory. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 4053024dad..ab4f229436 100644 --- a/meson.build +++ b/meson.build @@ -1939,6 +1939,14 @@ configure_file( configuration: build_options_config, ) +# Development environments can be used via `meson devenv -C `. 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) + summary({ 'curl': curl.found(), 'expat': expat.found(), -- cgit v1.3 From 88d4bff8c376cae3029b7da94a21c4fd4ac0249e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 13:05:49 +0100 Subject: meson: wire up generation of distribution archive Meson knows to generate distribution archives via `meson dist`. In addition to generating the archive itself, this target also knows to compile and execute tests from that archive, which helps to ensure that the result is an adequate drop-in replacement for the versioned project. While this already works as-is, one omission is that we don't propagate the commit that this is built from into the resulting archive. This can be fixed though by adding a distribution script that propagates the version into the "version" file, which GIT-VERSION-GEN knows to read if present. Use GIT-VERSION-GEN to populate that file. As the script is executed in the build directory, not in the directory where we generate the archive, we have to use a shell to resolve the "MESON_DIST_ROOT" environment variable. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'meson.build') diff --git a/meson.build b/meson.build index ab4f229436..a59072edf5 100644 --- a/meson.build +++ b/meson.build @@ -1947,6 +1947,19 @@ 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 ` 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(), -- cgit v1.3 From 28911f7dcad1ccc6ac4f6939036de76bb4f4c09b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 13:05:50 +0100 Subject: meson: wire up fuzzers Meson does not yet know to build our fuzzers. Introduce a new build option "fuzzers" and wire up the fuzzers in case it is enabled. Adapt our CI jobs so that they build the fuzzers by default. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- ci/run-build-and-tests.sh | 3 ++- meson.build | 4 ++++ meson_options.txt | 2 ++ oss-fuzz/meson.build | 20 ++++++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 oss-fuzz/meson.build (limited to 'meson.build') diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index 76667a1277..6c828c3b75 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -53,7 +53,8 @@ case "$jobname" in *-meson) group "Configure" meson setup build . \ --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 a59072edf5..052bd80ac4 100644 --- a/meson.build +++ b/meson.build @@ -1906,6 +1906,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') diff --git a/meson_options.txt b/meson_options.txt index 89b01bad04..34ba679cf9 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -95,3 +95,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 -- cgit v1.3 From ef8c3a1b8aa04e09a00dffcfda24daec6908615c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 13:05:51 +0100 Subject: meson: make the CSPRNG backend configurable The CSPRNG backend is not configurable in Meson and isn't quite discoverable, either. Make it configurable and add the actual backend used to the summary. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 28 +++++++++++++++++++++------- meson_options.txt | 2 ++ 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 052bd80ac4..22dcd4aeee 100644 --- a/meson.build +++ b/meson.build @@ -1332,6 +1332,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') @@ -1343,7 +1344,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' @@ -1428,18 +1429,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 ') + 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 ') + 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 \n#include ') + csprng_backend = 'getentropy' +elif csprng_backend in ['auto', 'rtlgenrandom'] and compiler.has_header_symbol('ntsecapi.h', 'RtlGenRandom', prefix: '#include ', 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') @@ -1977,6 +1990,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 34ba679cf9..5429022f30 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -47,6 +47,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', -- cgit v1.3 From 13cb20fc4634029762e80d2858e081b0691ff50f Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 22 Jan 2025 13:05:52 +0100 Subject: meson: fix compilation with Visual Studio The Visual Studio compiler defaults to C89 unless explicitly asked to use a different version of the C standard. We don't specify any C standard at all though in our Meson build, and consequently compiling Git fails: ...\git\git-compat-util.h(14): fatal error C1189: #error: "Required C99 support is in a test phase. Please see git-compat-util.h for more details." Fix the issue by specifying the project's C standard. Funny enough, specifying C99 does not work because apparently, `__STDC_VERSION__` is not getting defined in that version at all. Instead, we have to specify C11 as the project's C standard, which is also done in our CMake build instructions. We don't want to generally enforce C11 though, as our requiremets only state that a C99 compiler is required. In fact, we don't even require plain C99, but rather the GNU variant thereof. Meson allows us to handle this case rather easily by specifying "gnu99,c11", which will cause it to fall back to C11 in case GNU C99 is unsupported. This feature has only been introduced with Meson 1.3.0 though, and we support 0.61.0 and newer. In case we use such an oldish version though we fall back to requiring GNU99 unconditionally. This means that Windows essentially requires Meson 1.3.0 and newer when using Visual Studio, but I doubt that this is ever going to be a real problem. Tested-by: M Hickford Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- meson.build | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'meson.build') diff --git a/meson.build b/meson.build index 22dcd4aeee..af7ca042b9 100644 --- a/meson.build +++ b/meson.build @@ -178,6 +178,14 @@ project('git', 'c', 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') -- cgit v1.3