git/meson.build
Patrick Steinhardt ef8c3a1b8a 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 <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-01-22 12:37:34 -08:00

1999 lines
57 KiB
Meson

# 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',
# 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')
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
# 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 = [
'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',
]
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',
'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',
]
builtin_sources += custom_target(
output: 'config-list.h',
command: [
shell,
meson.current_source_dir() + '/generate-configlist.sh',
meson.current_source_dir(),
'@OUTPUT@',
],
env: script_environment,
)
builtin_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')
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') or get_option('gitweb').enabled()
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 <iconv.h>
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 <iconv.h>
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 <winsock2.h>
#else
# include <sys/types.h>
# include <sys/socket.h>
#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 <regex.h>') != ''
build_options_config.set('NO_REGEX', '')
if compiler.get_define('REG_ENHANCED', prefix: '#include <regex.h>') != ''
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 <sys/time.h>
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 <sys/stat.h>')
libgit_c_args += '-DUSE_ST_TIMESPEC'
elif not compiler.has_member('struct stat', 'st_mtim.tv_nsec', prefix: '#include <sys/stat.h>')
libgit_c_args += '-DNO_NSEC'
endif
if not compiler.has_member('struct stat', 'st_blocks', prefix: '#include <sys/stat.h>')
libgit_c_args += '-DNO_ST_BLOCKS_IN_STRUCT_STAT'
endif
if not compiler.has_member('struct dirent', 'd_type', prefix: '#include <dirent.h>')
libgit_c_args += '-DNO_D_TYPE_IN_DIRENT'
endif
if not compiler.has_member('struct passwd', 'pw_gecos', prefix: '#include <pwd.h>')
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 <time.h>
void func(void)
{
clockid_t id = CLOCK_MONOTONIC;
}
''', name: 'monotonic clock')
libgit_c_args += '-DHAVE_CLOCK_MONOTONIC'
endif
if not compiler.compiles('''
#include <inttypes.h>
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 <stddef.h>
#include <sys/sysctl.h>
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 <stdio.h>
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
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')
sha256_backend = get_option('sha256_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 [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'
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
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',
]
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'
# Apple CommonCrypto requires chunking
libgit_c_args += '-DSHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L'
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
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'
endif
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
# 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'
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'
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'
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'
csprng_backend = 'getentropy'
elif csprng_backend in ['auto', 'rtlgenrandom'] and compiler.has_header_symbol('ntsecapi.h', 'RtlGenRandom', prefix: '#include <windows.h>', required: csprng_backend == 'rtlgenrandom')
libgit_c_args += '-DHAVE_RTLGENRANDOM'
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')
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 <sys/sysctl.h>
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 <stdlib.h>
void func(void)
{
_wpgmptr;
}
''', name: 'Win32 _wpgmptr')
libgit_c_args += '-DHAVE_WPGMPTR'
endif
else
build_options_config.set('RUNTIME_PREFIX', 'false')
endif
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',
env: version_gen_environment,
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],
env: version_gen_environment,
)
# 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],
env: version_gen_environment,
)
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')
# 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.allowed()
subdir('gitweb')
build_options_config.set('NO_GITWEB', '')
else
build_options_config.set('NO_GITWEB', '1')
endif
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
if get_option('fuzzers')
subdir('oss-fuzz')
endif
subdir('bin-wrappers')
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,
)
# Development environments can be used via `meson devenv -C <builddir>`. This
# allows you to execute test scripts directly with the built Git version and
# puts the built version of Git in your PATH.
devenv = environment()
devenv.set('GIT_BUILD_DIR', meson.current_build_dir())
devenv.prepend('PATH', meson.current_build_dir() / 'bin-wrappers')
meson.add_devenv(devenv)
# Generate the 'version' file in the distribution tarball. This is used via
# `meson dist -C <builddir>` to populate the source archive with the Git
# version that the archive is being generated from.
meson.add_dist_script(
shell,
'-c',
'"$1" "$2" "$3" --format="@GIT_VERSION@" "$MESON_DIST_ROOT/version"',
'GIT-VERSION-GEN',
shell,
meson.current_source_dir() / 'GIT-VERSION-GEN',
meson.current_source_dir(),
)
summary({
'curl': curl.found(),
'expat': expat.found(),
'gettext': intl.found(),
'gitweb': gitweb_option.allowed(),
'https': https_backend,
'iconv': iconv.found(),
'pcre2': pcre2.found(),
'perl': perl_features_enabled,
'python': python.found(),
}, section: 'Auto-detected features')
summary({
'csprng': csprng_backend,
'https': https_backend,
'sha1': sha1_backend,
'sha1_unsafe': sha1_unsafe_backend,
'sha256': sha256_backend,
}, section: 'Backends')