4 # The Meson build system is an alternative to our Makefile that you can use to
5 # build, test and install Git. Using Meson results in a couple of benefits:
7 # - Out-of-tree builds.
8 # - Better integration into IDEs.
9 # - Easy-to-use autoconfiguration of available features on your system.
11 # To use Meson from the command line you need to have both Meson and Ninja
12 # installed. Alternatively, if you do not have Python available on your system,
13 # you can also use Muon instead of Meson and Samurai instead of Ninja, both of
14 # which are drop-ins replacement that only depend on C.
19 # In the most trivial case, you can configure, build and install Git like this:
21 # 1. Set up the build directory. This only needs to happen once per build
22 # directory you want to have. You can also configure multiple different
23 # build directories with different configurations.
25 # $ meson setup build/
27 # The build directory gets ignored by Git automatically as Meson will write
28 # a ".gitignore" file into it. From hereon, we will assume that you execute
29 # commands inside this build directory.
31 # 2. Compile Git. You can either use Meson, Ninja or Samurai to do this, so all
32 # of the following invocations are equivalent:
38 # The different invocations should ultimately not make much of a difference.
39 # Using Meson also works with other generators though, like when the build
40 # directory has been set up for use with Microsoft Visual Studio.
42 # Ninja and Samurai use multiple jobs by default, scaling with the number of
43 # processor cores available. You can pass the `-jN` flag to change this.
45 # Meson automatically picks up ccache and sccache when these are installed
46 # when setting up the build directory. You can override this behaviour when
47 # setting up the build directory by setting the `CC` environment variable to
48 # your desired compiler.
50 # 3. Execute tests. Again, you can either use Meson, Ninja or Samurai to do this:
56 # It is recommended to use Meson in this case though as it also provides you
57 # additional features that the other build systems don't have available.
58 # You can e.g. pass additional arguments to the test executables or run
61 # # Execute the t0000-basic integration test and t-reftable-stack unit test.
62 # $ meson test t0000-basic t-reftable-stack
64 # # Execute all reftable unit tests.
65 # $ meson test t-reftable-*
67 # # Execute all tests and stop with the first failure.
68 # $ meson test --maxfail 1
70 # # Execute single test interactively such that features like `debug ()` work.
71 # $ meson test -i --test-args='-ix' t1400-update-ref
73 # Test execution is parallelized by default and scales with the number of
74 # processor cores available. You can change the number of processes by passing
75 # the `-jN` flag to `meson test`.
77 # 4. Install the Git distribution. Again, this can be done via Meson, Ninja or
84 # The prefix into which Git shall be installed is defined when setting up
85 # the build directory. More on that in the "Configuration" section.
87 # Meson supports multiple backends. The default backend generates Ninja build
88 # instructions, but it also supports the generation of Microsoft Visual
89 # Studio solutions as well as Xcode projects by passing the `--backend` option
90 # to `meson setup`. IDEs like Eclipse and Visual Studio Code provide plugins to
91 # import Meson files directly.
96 # The exact configuration of Git is determined when setting up the build
97 # directory via `meson setup`. Unless told otherwise, Meson will automatically
98 # detect the availability of various bits and pieces. There are two different
99 # kinds of options that can be used to further tweak the build:
101 # - Built-in options provided by Meson.
103 # - Options defined by the project in the "meson_options.txt" file.
105 # Both kinds of options can be inspected by running `meson configure` in the
106 # build directory, which will give you a list of the current value for all
109 # Options can be configured either when setting up the build directory or can
110 # be changed in preexisting build directories:
112 # # Set up a new build directory with optimized settings that will be
113 # # installed into an alternative prefix.
114 # $ meson setup --buildtype release --optimization 3 --strip --prefix=/home/$USER build
116 # # Set up a new build directory with a higher warning level. Level 2 is
117 # # mostly equivalent to setting DEVELOPER=1, level 3 and "everything"
118 # # will enable even more warnings.
119 # $ meson setup -Dwarning_level=2 build
121 # # Set up a new build directory with 'address' and 'undefined' sanitizers
123 # $ CC=clang meson setup -Db_sanitize=address,undefined build
125 # # Disable tests in a preexisting build directory.
126 # $ meson configure -Dtests=false
128 # # Disable features based on Python
129 # $ meson configure -Dpython=disabled
131 # Options have a type like booleans, choices, strings or features. Features are
132 # somewhat special as they can have one of three values: enabled, disabled or
133 # auto. While the first two values are self-explanatory, "auto" will enable or
134 # disable the feature based on the availability of prerequisites to support it.
135 # Python-based features for example will be enabled automatically when a Python
136 # interpreter could be found. The default value of such features can be changed
137 # via `meson setup --auto-features={enabled,disabled,auto}`, which will set the
138 # value of all features with a value of "auto" to the provided one by default.
140 # It is also possible to store a set of configuration options in machine files.
141 # This can be useful in case you regularly want to reuse the same set of options:
148 # gettext = 'disabled'
149 # default_editor = 'vim'
153 # b_sanitize = 'address,undefined'
155 # These machine files can be passed to `meson setup` via the `--native-file`
158 # Subproject wrappers
159 # ===================
161 # Subproject wrappers are a feature provided by Meson that allows the automatic
162 # fallback to a "wrapped" dependency in case the dependency is not provided by
163 # the system. For example if the system is lacking curl, then Meson will use
164 # "subprojects/curl.wrap" to set up curl as a subproject and compile and link
165 # the dependency into Git itself. This is especially helpful on systems like
166 # Windows, where you typically don't have such dependencies installed.
168 # The use of subproject wrappers can be disabled by executing `meson setup`
169 # with the `--wrap-mode nofallback` option.
172 meson_version: '>=0.61.0',
173 # The version is only of cosmetic nature, so if we cannot find a shell yet we
174 # simply don't set up a version at all. This may be the case for example on
175 # Windows systems, where we first have to bootstrap the host environment.
176 version: find_program('sh', required: false).found() ? run_command(
177 'GIT-VERSION-GEN', meson.current_source_dir(), '--format=@GIT_VERSION@',
180 ).stdout().strip() : 'unknown',
182 # Git requires C99 with GNU extensions, which of course isn't supported by
183 # MSVC. Funny enough, C99 doesn't work with MSVC either, as it has only
184 # learned to define __STDC_VERSION__ with C11 and later. We thus require
185 # GNU C99 and fall back to C11. Meson only learned to handle the fallback
186 # with version 1.3.0, so on older versions we use GNU C99 unconditionally.
187 'c_std=' + (meson.version().version_compare('>=1.3.0') ? 'gnu99,c11' : 'gnu99'),
194 # Git for Windows provides all the tools we need to build Git.
195 if host_machine.system() == 'windows'
196 program_path += [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ]
199 cygpath = find_program('cygpath', dirs: program_path, required: false)
200 diff = find_program('diff', dirs: program_path)
201 shell = find_program('sh', dirs: program_path)
202 tar = find_program('tar', dirs: program_path)
204 script_environment = environment()
205 foreach tool : ['cat', 'cut', 'grep', 'sed', 'sort', 'tr', 'uname']
206 program = find_program(tool, dirs: program_path)
207 script_environment.prepend('PATH', fs.parent(program.full_path()))
210 git = find_program('git', dirs: program_path, required: false)
212 script_environment.prepend('PATH', fs.parent(git.full_path()))
215 if get_option('sane_tool_path') != ''
216 script_environment.prepend('PATH', get_option('sane_tool_path'))
219 # The environment used by GIT-VERSION-GEN. Note that we explicitly override
220 # environment variables that might be set by the user. This is by design so
221 # that we always use whatever Meson has configured instead of what is present
222 # in the environment.
223 version_gen_environment = script_environment
224 version_gen_environment.set('GIT_BUILT_FROM_COMMIT', get_option('built_from_commit'))
225 version_gen_environment.set('GIT_DATE', get_option('build_date'))
226 version_gen_environment.set('GIT_USER_AGENT', get_option('user_agent'))
227 version_gen_environment.set('GIT_VERSION', get_option('version'))
229 compiler = meson.get_compiler('c')
266 'compat/zlib-uncompress2.c',
287 'diffcore-pickaxe.c',
296 'ewah/ewah_bitmap.c',
300 'fetch-negotiator.c',
306 'fsmonitor-settings.c',
324 'linear-assignment.c',
325 'list-objects-filter-options.c',
326 'list-objects-filter.c',
339 'merge-ort-wrappers.c',
345 'negotiator/default.c',
347 'negotiator/skipping.c',
352 'object-file-convert.c',
360 'pack-bitmap-write.c',
369 'parallel-checkout.c',
371 'parse-options-cb.c',
393 'rebase-interactive.c',
400 'refs/files-backend.c',
401 'refs/reftable-backend.c',
403 'refs/packed-backend.c',
409 'reftable/blocksource.c',
446 'submodule-config.c',
456 'trace2/tr2_cmd_name.c',
460 'trace2/tr2_sysenv.c',
462 'trace2/tr2_tgt_event.c',
463 'trace2/tr2_tgt_normal.c',
464 'trace2/tr2_tgt_perf.c',
468 'transport-helper.c',
492 'xdiff/xhistogram.c',
499 libgit_sources += custom_target(
500 input: 'command-list.txt',
501 output: 'command-list.h',
502 command: [shell, meson.current_source_dir() + '/generate-cmdlist.sh', meson.current_source_dir(), '@OUTPUT@'],
503 env: script_environment,
509 'builtin/annotate.c',
515 'builtin/bugreport.c',
517 'builtin/cat-file.c',
518 'builtin/check-attr.c',
519 'builtin/check-ignore.c',
520 'builtin/check-mailmap.c',
521 'builtin/check-ref-format.c',
522 'builtin/checkout--worker.c',
523 'builtin/checkout-index.c',
524 'builtin/checkout.c',
528 'builtin/commit-graph.c',
529 'builtin/commit-tree.c',
532 'builtin/count-objects.c',
533 'builtin/credential-cache--daemon.c',
534 'builtin/credential-cache.c',
535 'builtin/credential-store.c',
536 'builtin/credential.c',
537 'builtin/describe.c',
538 'builtin/diagnose.c',
539 'builtin/diff-files.c',
540 'builtin/diff-index.c',
541 'builtin/diff-tree.c',
543 'builtin/difftool.c',
544 'builtin/fast-export.c',
545 'builtin/fast-import.c',
546 'builtin/fetch-pack.c',
548 'builtin/fmt-merge-msg.c',
549 'builtin/for-each-ref.c',
550 'builtin/for-each-repo.c',
552 'builtin/fsmonitor--daemon.c',
554 'builtin/get-tar-commit-id.c',
556 'builtin/hash-object.c',
559 'builtin/index-pack.c',
561 'builtin/interpret-trailers.c',
563 'builtin/ls-files.c',
564 'builtin/ls-remote.c',
566 'builtin/mailinfo.c',
567 'builtin/mailsplit.c',
568 'builtin/merge-base.c',
569 'builtin/merge-file.c',
570 'builtin/merge-index.c',
571 'builtin/merge-ours.c',
572 'builtin/merge-recursive.c',
573 'builtin/merge-tree.c',
577 'builtin/multi-pack-index.c',
579 'builtin/name-rev.c',
581 'builtin/pack-objects.c',
582 'builtin/pack-redundant.c',
583 'builtin/pack-refs.c',
584 'builtin/patch-id.c',
585 'builtin/prune-packed.c',
589 'builtin/range-diff.c',
590 'builtin/read-tree.c',
592 'builtin/receive-pack.c',
595 'builtin/remote-ext.c',
596 'builtin/remote-fd.c',
603 'builtin/rev-list.c',
604 'builtin/rev-parse.c',
607 'builtin/send-pack.c',
608 'builtin/shortlog.c',
609 'builtin/show-branch.c',
610 'builtin/show-index.c',
611 'builtin/show-ref.c',
612 'builtin/sparse-checkout.c',
614 'builtin/stripspace.c',
615 'builtin/submodule--helper.c',
616 'builtin/symbolic-ref.c',
618 'builtin/unpack-file.c',
619 'builtin/unpack-objects.c',
620 'builtin/update-index.c',
621 'builtin/update-ref.c',
622 'builtin/update-server-info.c',
623 'builtin/upload-archive.c',
624 'builtin/upload-pack.c',
626 'builtin/verify-commit.c',
627 'builtin/verify-pack.c',
628 'builtin/verify-tag.c',
629 'builtin/worktree.c',
630 'builtin/write-tree.c',
633 builtin_sources += custom_target(
634 output: 'config-list.h',
637 meson.current_source_dir() + '/generate-configlist.sh',
638 meson.current_source_dir(),
641 env: script_environment,
644 builtin_sources += custom_target(
645 input: 'Documentation/githooks.txt',
646 output: 'hook-list.h',
649 meson.current_source_dir() + '/generate-hooklist.sh',
650 meson.current_source_dir(),
653 env: script_environment,
656 # This contains the variables for GIT-BUILD-OPTIONS, which we use to propagate
657 # build options to our tests.
658 build_options_config = configuration_data()
659 build_options_config.set('GIT_INTEROP_MAKE_OPTS', '')
660 build_options_config.set('GIT_PERF_LARGE_REPO', '')
661 build_options_config.set('GIT_PERF_MAKE_COMMAND', '')
662 build_options_config.set('GIT_PERF_MAKE_OPTS', '')
663 build_options_config.set('GIT_PERF_REPEAT_COUNT', '')
664 build_options_config.set('GIT_PERF_REPO', '')
665 build_options_config.set('GIT_TEST_CMP_USE_COPIED_CONTEXT', '')
666 build_options_config.set('GIT_TEST_INDEX_VERSION', '')
667 build_options_config.set('GIT_TEST_OPTS', '')
668 build_options_config.set('GIT_TEST_PERL_FATAL_WARNINGS', '')
669 build_options_config.set('GIT_TEST_UTF8_LOCALE', '')
670 build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir')))
671 build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb'))
673 if get_option('breaking_changes')
674 build_options_config.set('WITH_BREAKING_CHANGES', 'YesPlease')
676 build_options_config.set('WITH_BREAKING_CHANGES', '')
679 if get_option('sane_tool_path') != ''
680 build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + get_option('sane_tool_path') + '"|')
682 build_options_config.set_quoted('BROKEN_PATH_FIX', '/^\# @BROKEN_PATH_FIX@$/d')
685 test_output_directory = get_option('test_output_directory')
686 if test_output_directory == ''
687 test_output_directory = meson.project_build_root() / 'test-output'
690 # These variables are used for building libgit.a.
692 '-DBINDIR="' + get_option('bindir') + '"',
693 '-DDEFAULT_EDITOR="' + get_option('default_editor') + '"',
694 '-DDEFAULT_GIT_TEMPLATE_DIR="' + get_option('datadir') / 'git-core/templates' + '"',
695 '-DDEFAULT_HELP_FORMAT="' + get_option('default_help_format') + '"',
696 '-DDEFAULT_PAGER="' + get_option('default_pager') + '"',
697 '-DETC_GITATTRIBUTES="' + get_option('gitattributes') + '"',
698 '-DETC_GITCONFIG="' + get_option('gitconfig') + '"',
699 '-DFALLBACK_RUNTIME_PREFIX="' + get_option('prefix') + '"',
700 '-DGIT_EXEC_PATH="' + get_option('prefix') / get_option('libexecdir') / 'git-core"',
701 '-DGIT_HOST_CPU="' + host_machine.cpu_family() + '"',
702 '-DGIT_HTML_PATH="' + get_option('datadir') / 'doc/git-doc"',
703 '-DGIT_INFO_PATH="' + get_option('infodir') + '"',
704 '-DGIT_LOCALE_PATH="' + get_option('localedir') + '"',
705 '-DGIT_MAN_PATH="' + get_option('mandir') + '"',
706 '-DPAGER_ENV="' + get_option('pager_environment') + '"',
707 '-DSHELL_PATH="' + fs.as_posix(shell.full_path()) + '"',
709 libgit_include_directories = [ '.' ]
710 libgit_dependencies = [ ]
712 # Treat any warning level above 1 the same as we treat DEVELOPER=1 in our
714 if get_option('warning_level') in ['2','3', 'everything'] and compiler.get_argument_syntax() == 'gcc'
716 '-Wdeclaration-after-statement',
718 '-Wold-style-definition',
721 '-Wstrict-prototypes',
726 '-Wtautological-constant-out-of-range-compare',
727 # If a function is public, there should be a prototype and the right
728 # header file should be included. If not, it should be static.
729 '-Wmissing-prototypes',
730 # These are disabled because we have these all over the place.
732 '-Wno-missing-field-initializers',
734 if compiler.has_argument(cflag)
735 libgit_c_args += cflag
740 if get_option('b_sanitize').contains('address')
741 build_options_config.set('SANITIZE_ADDRESS', 'YesCompiledWithIt')
743 build_options_config.set('SANITIZE_ADDRESS', '')
745 if get_option('b_sanitize').contains('leak')
746 build_options_config.set('SANITIZE_LEAK', 'YesCompiledWithIt')
748 build_options_config.set('SANITIZE_LEAK', '')
750 if get_option('b_sanitize').contains('undefined')
751 libgit_c_args += '-DSHA1DC_FORCE_ALIGNED_ACCESS'
754 executable_suffix = ''
755 if host_machine.system() == 'cygwin' or host_machine.system() == 'windows'
756 executable_suffix = '.exe'
757 libgit_c_args += '-DSTRIP_EXTENSION="' + executable_suffix + '"'
759 build_options_config.set_quoted('X', executable_suffix)
761 python = import('python').find_installation('python3', required: get_option('python'))
763 build_options_config.set('NO_PYTHON', '')
765 libgit_c_args += '-DNO_PYTHON'
766 build_options_config.set('NO_PYTHON', '1')
769 # Perl is used for two different things: our test harness and to provide some
770 # features. It is optional if you want to neither execute tests nor use any of
771 # these optional features.
772 perl_required = get_option('perl')
773 if get_option('tests') or get_option('gitweb').enabled()
777 # Note that we only set NO_PERL if the Perl features were disabled by the user.
778 # It may not be set when we have found Perl, but only use it to run tests.
779 perl = find_program('perl', version: '>=5.8.1', dirs: program_path, required: perl_required)
780 perl_features_enabled = perl.found() and get_option('perl').allowed()
781 if perl_features_enabled
782 build_options_config.set('NO_PERL', '')
784 if get_option('runtime_prefix')
785 build_options_config.set('PERL_LOCALEDIR', '')
787 build_options_config.set_quoted('PERL_LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir')))
790 if get_option('perl_cpan_fallback')
791 build_options_config.set('NO_PERL_CPAN_FALLBACKS', '')
793 build_options_config.set_quoted('NO_PERL_CPAN_FALLBACKS', 'YesPlease')
796 libgit_c_args += '-DNO_PERL'
797 build_options_config.set('NO_PERL', '1')
798 build_options_config.set('PERL_LOCALEDIR', '')
799 build_options_config.set('NO_PERL_CPAN_FALLBACKS', '')
802 zlib = dependency('zlib', default_options: ['default_library=static', 'tests=disabled'])
803 if zlib.version().version_compare('<1.2.0')
804 libgit_c_args += '-DNO_DEFLATE_BOUND'
806 libgit_dependencies += zlib
808 threads = dependency('threads', required: false)
810 libgit_dependencies += threads
811 build_options_config.set('NO_PTHREADS', '')
813 libgit_c_args += '-DNO_PTHREADS'
814 build_options_config.set('NO_PTHREADS', '1')
817 msgfmt = find_program('msgfmt', dirs: program_path, required: false)
818 gettext_option = get_option('gettext').disable_auto_if(not msgfmt.found())
819 if not msgfmt.found() and gettext_option.enabled()
820 error('Internationalization via libintl requires msgfmt')
823 if gettext_option.allowed() and host_machine.system() == 'darwin' and get_option('macos_use_homebrew_gettext')
824 if host_machine.cpu_family() == 'x86_64'
825 libintl_prefix = '/usr/local'
826 elif host_machine.cpu_family() == 'aarch64'
827 libintl_prefix = '/opt/homebrew'
829 error('Homebrew workaround not supported on current architecture')
832 intl = compiler.find_library('intl', dirs: libintl_prefix / 'lib', required: gettext_option)
834 intl = declare_dependency(
836 include_directories: libintl_prefix / 'include',
840 intl = dependency('intl', required: gettext_option)
843 libgit_dependencies += intl
844 build_options_config.set('NO_GETTEXT', '')
845 build_options_config.set('USE_GETTEXT_SCHEME', '')
847 # POSIX nowadays requires `nl_langinfo()`, but some systems still don't have
848 # the function available. On such systems we instead fall back to libcharset.
849 # On native Windows systems we use our own emulation.
850 if host_machine.system() != 'windows' and not compiler.has_function('nl_langinfo')
851 libcharset = compiler.find_library('charset', required: true)
852 libgit_dependencies += libcharset
853 libgit_c_args += '-DHAVE_LIBCHARSET_H'
856 libgit_c_args += '-DNO_GETTEXT'
857 build_options_config.set('NO_GETTEXT', '1')
858 build_options_config.set('USE_GETTEXT_SCHEME', 'fallthrough')
861 iconv = dependency('iconv', required: get_option('iconv'))
863 libgit_dependencies += iconv
864 build_options_config.set('NO_ICONV', '')
866 have_old_iconv = false
867 if not compiler.compiles('''
870 extern size_t iconv(iconv_t cd,
871 char **inbuf, size_t *inbytesleft,
872 char **outbuf, size_t *outbytesleft);
873 ''', name: 'old iconv interface', dependencies: [iconv])
874 libgit_c_args += '-DOLD_ICONV'
875 have_old_iconv = true
878 iconv_omits_bom_source = '''#
881 int main(int argc, const char **argv)
885 iconv_omits_bom_source += '''
886 typedef const char *iconv_ibp;
889 iconv_omits_bom_source += '''
890 typedef char *iconv_ibp;
893 iconv_omits_bom_source += '''
896 char in[] = "a"; iconv_ibp pin = in;
897 char out[20] = ""; char *pout = out;
898 size_t isz = sizeof in;
899 size_t osz = sizeof out;
901 conv = iconv_open("UTF-16", "UTF-8");
902 iconv(conv, &pin, &isz, &pout, &osz);
904 v = (unsigned char)(out[0]) + (unsigned char)(out[1]);
905 return v != 0xfe + 0xff;
909 if compiler.run(iconv_omits_bom_source,
911 name: 'iconv omits BOM',
913 libgit_c_args += '-DICONV_OMITS_BOM'
916 libgit_c_args += '-DNO_ICONV'
917 build_options_config.set('NO_ICONV', '1')
920 pcre2 = dependency('libpcre2-8', required: get_option('pcre2'), default_options: ['default_library=static', 'test=false'])
922 libgit_dependencies += pcre2
923 libgit_c_args += '-DUSE_LIBPCRE2'
924 build_options_config.set('USE_LIBPCRE2', '1')
926 build_options_config.set('USE_LIBPCRE2', '')
929 curl = dependency('libcurl', version: '>=7.21.3', required: get_option('curl'), default_options: ['default_library=static', 'tests=disabled', 'tool=disabled'])
930 use_curl_for_imap_send = false
932 if curl.version().version_compare('>=7.34.0')
933 libgit_c_args += '-DUSE_CURL_FOR_IMAP_SEND'
934 use_curl_for_imap_send = true
937 libgit_dependencies += curl
938 libgit_c_args += '-DCURL_DISABLE_TYPECHECK'
939 build_options_config.set('NO_CURL', '')
941 libgit_c_args += '-DNO_CURL'
942 build_options_config.set('NO_CURL', '1')
945 expat = dependency('expat', required: get_option('expat'), default_options: ['default_library=static', 'build_tests=false'])
947 libgit_dependencies += expat
949 if expat.version().version_compare('<=1.2')
950 libgit_c_args += '-DEXPAT_NEEDS_XMLPARSE_H'
952 build_options_config.set('NO_EXPAT', '')
954 libgit_c_args += '-DNO_EXPAT'
955 build_options_config.set('NO_EXPAT', '1')
958 if not compiler.has_header('sys/select.h')
959 libgit_c_args += '-DNO_SYS_SELECT_H'
962 has_poll_h = compiler.has_header('poll.h')
964 libgit_c_args += '-DNO_POLL_H'
967 has_sys_poll_h = compiler.has_header('sys/poll.h')
968 if not has_sys_poll_h
969 libgit_c_args += '-DNO_SYS_POLL_H'
972 if not has_poll_h and not has_sys_poll_h
973 libgit_c_args += '-DNO_POLL'
974 libgit_sources += 'compat/poll/poll.c'
975 libgit_include_directories += 'compat/poll'
978 if not compiler.has_header('inttypes.h')
979 libgit_c_args += '-DNO_INTTYPES_H'
982 if compiler.has_header('alloca.h')
983 libgit_c_args += '-DHAVE_ALLOCA_H'
986 if compiler.has_header('sys/sysinfo.h')
987 libgit_c_args += '-DHAVE_SYSINFO'
990 # Windows has libgen.h and a basename implementation, but we still need our own
991 # implementation to threat things like drive prefixes specially.
992 if host_machine.system() == 'windows' or not compiler.has_header('libgen.h')
993 libgit_c_args += '-DNO_LIBGEN_H'
994 libgit_sources += 'compat/basename.c'
997 if compiler.has_header('paths.h')
998 libgit_c_args += '-DHAVE_PATHS_H'
1001 if compiler.has_header('strings.h')
1002 libgit_c_args += '-DHAVE_STRINGS_H'
1005 networking_dependencies = [ ]
1006 if host_machine.system() == 'windows'
1007 winsock = compiler.find_library('ws2_32', required: false)
1009 networking_dependencies += winsock
1012 libresolv = compiler.find_library('resolv', required: false)
1013 if libresolv.found()
1014 networking_dependencies += libresolv
1017 libgit_dependencies += networking_dependencies
1019 foreach symbol : ['inet_ntop', 'inet_pton', 'strerror']
1020 if not compiler.has_function(symbol, dependencies: networking_dependencies)
1021 libgit_c_args += '-DNO_' + symbol.to_upper()
1025 has_ipv6 = compiler.has_function('getaddrinfo', dependencies: networking_dependencies)
1027 libgit_c_args += '-DNO_IPV6'
1030 if not compiler.compiles('''
1032 # include <winsock2.h>
1034 # include <sys/types.h>
1035 # include <sys/socket.h>
1040 struct sockaddr_storage x;
1042 ''', name: 'struct sockaddr_storage')
1044 libgit_c_args += '-Dsockaddr_storage=sockaddr_in6'
1046 libgit_c_args += '-Dsockaddr_storage=sockaddr_in'
1050 if compiler.has_function('socket', dependencies: networking_dependencies)
1053 'unix-stream-server.c',
1055 build_options_config.set('NO_UNIX_SOCKETS', '')
1057 libgit_c_args += '-DNO_UNIX_SOCKETS'
1058 build_options_config.set('NO_UNIX_SOCKETS', '1')
1061 if not compiler.has_function('pread')
1062 libgit_c_args += '-DNO_PREAD'
1063 libgit_sources += 'compat/pread.c'
1066 if host_machine.system() == 'darwin'
1067 libgit_sources += 'compat/precompose_utf8.c'
1068 libgit_c_args += '-DPRECOMPOSE_UNICODE'
1069 libgit_c_args += '-DPROTECT_HFS_DEFAULT'
1072 # Configure general compatibility wrappers.
1073 if host_machine.system() == 'cygwin'
1075 'compat/win32/path-utils.c',
1077 elif host_machine.system() == 'windows'
1081 'compat/win32/flush.c',
1082 'compat/win32/path-utils.c',
1083 'compat/win32/pthread.c',
1084 'compat/win32/syslog.c',
1085 'compat/win32/dirent.c',
1086 'compat/win32mmap.c',
1087 'compat/nedmalloc/nedmalloc.c',
1091 '-DDETECT_MSYS_TTY',
1092 '-DENSURE_MSYSTEM_IS_SET',
1095 '-DNO_POSIX_GOODIES',
1098 '-D_CONSOLE_DETECT_MSYS_TTY',
1099 '-D__USE_MINGW_ANSI_STDIO=0',
1102 libgit_dependencies += compiler.find_library('ntdll')
1103 libgit_include_directories += 'compat/win32'
1104 if compiler.get_id() == 'msvc'
1105 libgit_include_directories += 'compat/vcbuild/include'
1109 if host_machine.system() == 'linux'
1110 libgit_sources += 'compat/linux/procinfo.c'
1111 elif host_machine.system() == 'windows'
1112 libgit_sources += 'compat/win32/trace2_win32_process_info.c'
1114 libgit_sources += 'compat/stub/procinfo.c'
1117 if host_machine.system() == 'cygwin' or host_machine.system() == 'windows'
1119 '-DUNRELIABLE_FSTAT',
1120 '-DMMAP_PREVENTS_DELETE',
1121 '-DOBJECT_CREATION_MODE=1',
1125 # Configure the simple-ipc subsystem required fro the fsmonitor.
1126 if host_machine.system() == 'windows'
1128 'compat/simple-ipc/ipc-shared.c',
1129 'compat/simple-ipc/ipc-win32.c',
1131 libgit_c_args += '-DSUPPORTS_SIMPLE_IPC'
1134 'compat/simple-ipc/ipc-shared.c',
1135 'compat/simple-ipc/ipc-unix-socket.c',
1137 libgit_c_args += '-DSUPPORTS_SIMPLE_IPC'
1140 fsmonitor_backend = ''
1141 if host_machine.system() == 'windows'
1142 fsmonitor_backend = 'win32'
1143 elif host_machine.system() == 'darwin'
1144 fsmonitor_backend = 'darwin'
1145 libgit_dependencies += dependency('CoreServices')
1147 if fsmonitor_backend != ''
1148 libgit_c_args += '-DHAVE_FSMONITOR_DAEMON_BACKEND'
1149 libgit_c_args += '-DHAVE_FSMONITOR_OS_SETTINGS'
1152 'compat/fsmonitor/fsm-health-' + fsmonitor_backend + '.c',
1153 'compat/fsmonitor/fsm-ipc-' + fsmonitor_backend + '.c',
1154 'compat/fsmonitor/fsm-listen-' + fsmonitor_backend + '.c',
1155 'compat/fsmonitor/fsm-path-utils-' + fsmonitor_backend + '.c',
1156 'compat/fsmonitor/fsm-settings-' + fsmonitor_backend + '.c',
1159 build_options_config.set_quoted('FSMONITOR_DAEMON_BACKEND', fsmonitor_backend)
1160 build_options_config.set_quoted('FSMONITOR_OS_SETTINGS', fsmonitor_backend)
1162 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>') != ''
1163 build_options_config.set('NO_REGEX', '')
1165 if compiler.get_define('REG_ENHANCED', prefix: '#include <regex.h>') != ''
1166 libgit_c_args += '-DUSE_ENHANCED_BASIC_REGULAR_EXPRESSIONS'
1167 libgit_sources += 'compat/regcomp_enhanced.c'
1169 elif not get_option('regex').enabled()
1175 build_options_config.set('NO_REGEX', '1')
1176 libgit_sources += 'compat/regex/regex.c'
1177 libgit_include_directories += 'compat/regex'
1179 error('Native regex support requested but not found')
1182 # setitimer and friends are provided by compat/mingw.c.
1183 if host_machine.system() != 'windows'
1184 if not compiler.compiles('''
1185 #include <sys/time.h>
1188 struct itimerval value;
1190 ''', name: 'struct itimerval')
1191 libgit_c_args += '-DNO_STRUCT_ITIMERVAL'
1192 libgit_c_args += '-DNO_SETITIMER'
1193 elif not compiler.has_function('setitimer')
1194 libgit_c_args += '-DNO_SETITIMER'
1198 if compiler.has_member('struct stat', 'st_mtimespec.tv_nsec', prefix: '#include <sys/stat.h>')
1199 libgit_c_args += '-DUSE_ST_TIMESPEC'
1200 elif not compiler.has_member('struct stat', 'st_mtim.tv_nsec', prefix: '#include <sys/stat.h>')
1201 libgit_c_args += '-DNO_NSEC'
1204 if not compiler.has_member('struct stat', 'st_blocks', prefix: '#include <sys/stat.h>')
1205 libgit_c_args += '-DNO_ST_BLOCKS_IN_STRUCT_STAT'
1208 if not compiler.has_member('struct dirent', 'd_type', prefix: '#include <dirent.h>')
1209 libgit_c_args += '-DNO_D_TYPE_IN_DIRENT'
1212 if not compiler.has_member('struct passwd', 'pw_gecos', prefix: '#include <pwd.h>')
1213 libgit_c_args += '-DNO_GECOS_IN_PWENT'
1216 if compiler.has_function('sync_file_range')
1217 libgit_c_args += '-DHAVE_SYNC_FILE_RANGE'
1220 if not compiler.has_function('strcasestr')
1221 libgit_c_args += '-DNO_STRCASESTR'
1222 libgit_sources += 'compat/strcasestr.c'
1225 if not compiler.has_function('memmem')
1226 libgit_c_args += '-DNO_MEMMEM'
1227 libgit_sources += 'compat/memmem.c'
1230 if not compiler.has_function('strlcpy')
1231 libgit_c_args += '-DNO_STRLCPY'
1232 libgit_sources += 'compat/strlcpy.c'
1235 if not compiler.has_function('strdup')
1236 libgit_c_args += '-DOVERRIDE_STRDUP'
1237 libgit_sources += 'compat/strdup.c'
1240 if not compiler.has_function('strtoumax')
1241 libgit_c_args += '-DNO_STRTOUMAX'
1243 'compat/strtoumax.c',
1244 'compat/strtoimax.c',
1248 if not compiler.has_function('strtoull')
1249 libgit_c_args += '-DNO_STRTOULL'
1252 if not compiler.has_function('setenv')
1253 libgit_c_args += '-DNO_SETENV'
1254 libgit_sources += 'compat/setenv.c'
1257 if not compiler.has_function('qsort')
1258 libgit_c_args += '-DINTERNAL_QSORT'
1260 libgit_sources += 'compat/qsort_s.c'
1262 # unsetenv is provided by compat/mingw.c.
1263 if host_machine.system() != 'windows' and not compiler.has_function('unsetenv')
1264 libgit_c_args += '-DNO_UNSETENV'
1265 libgit_sources += 'compat/unsetenv.c'
1268 if not compiler.has_function('mkdtemp')
1269 libgit_c_args += '-DNO_MKDTEMP'
1270 libgit_sources += 'compat/mkdtemp.c'
1273 if not compiler.has_function('initgroups')
1274 libgit_c_args += '-DNO_INITGROUPS'
1277 if compiler.has_function('getdelim')
1278 libgit_c_args += '-DHAVE_GETDELIM'
1281 if host_machine.system() == 'windows'
1282 libgit_c_args += '-DUSE_WIN32_MMAP'
1283 elif not compiler.has_function('mmap')
1284 libgit_c_args += '-DNO_MMAP'
1285 libgit_sources += 'compat/mmap.c'
1288 if compiler.has_function('clock_gettime')
1289 libgit_c_args += '-DHAVE_CLOCK_GETTIME'
1292 if compiler.compiles('''
1297 clockid_t id = CLOCK_MONOTONIC;
1299 ''', name: 'monotonic clock')
1300 libgit_c_args += '-DHAVE_CLOCK_MONOTONIC'
1303 if not compiler.compiles('''
1304 #include <inttypes.h>
1310 ''', name: 'uintmax_t')
1311 libgit_c_args += '-DNO_UINTMAX_T'
1314 has_bsd_sysctl = false
1315 if compiler.has_header('sys/sysctl.h')
1316 if compiler.compiles('''
1318 #include <sys/sysctl.h>
1322 int val, mib[2] = { 0 };
1323 size_t len = sizeof(val);
1324 sysctl(mib, 2, &val, &len, NULL, 0);
1326 ''', name: 'BSD sysctl')
1327 libgit_c_args += '-DHAVE_BSD_SYSCTL'
1328 has_bsd_sysctl = true
1332 if not meson.is_cross_build() and compiler.run('''
1335 int main(int argc, const char **argv)
1337 FILE *f = fopen(".", "r");
1340 ''', name: 'fread reads directories').returncode() == 0
1341 libgit_c_args += '-DFREAD_READS_DIRECTORIES'
1342 libgit_sources += 'compat/fopen.c'
1345 if not meson.is_cross_build() and fs.exists('/dev/tty')
1346 libgit_c_args += '-DHAVE_DEV_TTY'
1349 csprng_backend = get_option('csprng_backend')
1350 https_backend = get_option('https_backend')
1351 sha1_backend = get_option('sha1_backend')
1352 sha1_unsafe_backend = get_option('sha1_unsafe_backend')
1353 sha256_backend = get_option('sha256_backend')
1355 security_framework = dependency('Security', required: 'CommonCrypto' in [https_backend, sha1_backend, sha1_unsafe_backend])
1356 core_foundation_framework = dependency('CoreFoundation', required: security_framework.found())
1357 if https_backend == 'auto' and security_framework.found()
1358 https_backend = 'CommonCrypto'
1361 openssl_required = 'openssl' in [csprng_backend, https_backend, sha1_backend, sha1_unsafe_backend, sha256_backend]
1362 openssl = dependency('openssl', required: openssl_required, default_options: ['default_library=static'])
1363 if https_backend == 'auto' and openssl.found()
1364 https_backend = 'openssl'
1367 if https_backend == 'CommonCrypto'
1368 libgit_dependencies += security_framework
1369 libgit_dependencies += core_foundation_framework
1370 libgit_c_args += '-DAPPLE_COMMON_CRYPTO'
1371 elif https_backend == 'openssl'
1372 libgit_dependencies += openssl
1374 # We either couldn't find any dependencies with 'auto' or the user requested
1375 # 'none'. Both cases are benign.
1378 if https_backend != 'openssl'
1379 libgit_c_args += '-DNO_OPENSSL'
1382 if sha1_backend == 'sha1dc'
1383 libgit_c_args += '-DSHA1_DC'
1384 libgit_c_args += '-DSHA1DC_NO_STANDARD_INCLUDES=1'
1385 libgit_c_args += '-DSHA1DC_INIT_SAFE_HASH_DEFAULT=0'
1386 libgit_c_args += '-DSHA1DC_CUSTOM_INCLUDE_SHA1_C="git-compat-util.h"'
1387 libgit_c_args += '-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C="git-compat-util.h"'
1392 'sha1dc/ubc_check.c',
1395 if sha1_backend == 'CommonCrypto' or sha1_unsafe_backend == 'CommonCrypto'
1396 if sha1_backend == 'CommonCrypto'
1397 libgit_c_args += '-DSHA1_APPLE'
1399 if sha1_unsafe_backend == 'CommonCrypto'
1400 libgit_c_args += '-DSHA1_APPLE_UNSAFE'
1403 libgit_c_args += '-DCOMMON_DIGEST_FOR_OPENSSL'
1404 # Apple CommonCrypto requires chunking
1405 libgit_c_args += '-DSHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L'
1407 if sha1_backend == 'openssl' or sha1_unsafe_backend == 'openssl'
1408 if sha1_backend == 'openssl'
1409 libgit_c_args += '-DSHA1_OPENSSL'
1411 if sha1_unsafe_backend == 'openssl'
1412 libgit_c_args += '-DSHA1_OPENSSL_UNSAFE'
1415 libgit_dependencies += openssl
1417 if sha1_backend == 'block' or sha1_unsafe_backend == 'block'
1418 if sha1_backend == 'block'
1419 libgit_c_args += '-DSHA1_BLK'
1421 if sha1_unsafe_backend == 'block'
1422 libgit_c_args += '-DSHA1_BLK_UNSAFE'
1425 libgit_sources += 'block-sha1/sha1.c'
1428 if sha256_backend == 'openssl'
1429 libgit_c_args += '-DSHA256_OPENSSL'
1430 libgit_dependencies += openssl
1431 elif sha256_backend == 'nettle'
1432 nettle = dependency('nettle')
1433 libgit_dependencies += nettle
1434 libgit_c_args += '-DSHA256_NETTLE'
1435 elif sha256_backend == 'gcrypt'
1436 gcrypt = dependency('gcrypt')
1437 libgit_dependencies += gcrypt
1438 libgit_c_args += '-DSHA256_GCRYPT'
1439 elif sha256_backend == 'block'
1440 libgit_c_args += '-DSHA256_BLK'
1441 libgit_sources += 'sha256/block/sha256.c'
1443 error('Unhandled SHA256 backend ' + sha256_backend)
1446 # Backends are ordered to reflect our preference for more secure and faster
1447 # ones over the ones that are less so.
1448 if csprng_backend in ['auto', 'arc4random'] and compiler.has_header_symbol('stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random')
1449 libgit_c_args += '-DHAVE_ARC4RANDOM'
1450 csprng_backend = 'arc4random'
1451 elif csprng_backend in ['auto', 'arc4random_bsd'] and compiler.has_header_symbol('bsd/stdlib.h', 'arc4random_buf', required: csprng_backend == 'arc4random_bsd')
1452 libgit_c_args += '-DHAVE_ARC4RANDOM_BSD'
1453 csprng_backend = 'arc4random_bsd'
1454 elif csprng_backend in ['auto', 'getrandom'] and compiler.has_header_symbol('sys/random.h', 'getrandom', required: csprng_backend == 'getrandom')
1455 libgit_c_args += '-DHAVE_GETRANDOM'
1456 csprng_backend = 'getrandom'
1457 elif csprng_backend in ['auto', 'getentropy'] and compiler.has_header_symbol('unistd.h', 'getentropy', required: csprng_backend == 'getentropy')
1458 libgit_c_args += '-DHAVE_GETENTROPY'
1459 csprng_backend = 'getentropy'
1460 elif csprng_backend in ['auto', 'rtlgenrandom'] and compiler.has_header_symbol('ntsecapi.h', 'RtlGenRandom', prefix: '#include <windows.h>', required: csprng_backend == 'rtlgenrandom')
1461 libgit_c_args += '-DHAVE_RTLGENRANDOM'
1462 csprng_backend = 'rtlgenrandom'
1463 elif csprng_backend in ['auto', 'openssl'] and openssl.found()
1464 libgit_c_args += '-DHAVE_OPENSSL_CSPRNG'
1465 csprng_backend = 'openssl'
1466 elif csprng_backend in ['auto', 'urandom']
1467 csprng_backend = 'urandom'
1469 error('Unsupported CSPRNG backend: ' + csprng_backend)
1472 if get_option('runtime_prefix')
1473 libgit_c_args += '-DRUNTIME_PREFIX'
1474 build_options_config.set('RUNTIME_PREFIX', 'true')
1476 if compiler.has_header('mach-o/dyld.h')
1477 libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH'
1480 if has_bsd_sysctl and compiler.compiles('''
1481 #include <sys/sysctl.h>
1485 KERN_PROC_PATHNAME; KERN_PROC;
1487 ''', name: 'BSD KERN_PROC_PATHNAME')
1488 libgit_c_args += '-DHAVE_NS_GET_EXECUTABLE_PATH'
1491 if host_machine.system() == 'linux'
1492 libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="/proc/self/exe' + '"'
1493 elif host_machine.system() == 'openbsd'
1494 libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="' + '/proc/curproc/file' + '"'
1495 elif host_machine.system() == 'netbsd'
1496 libgit_c_args += '-DPROCFS_EXECUTABLE_PATH="' + '/proc/curproc/exe' + '"'
1499 if host_machine.system() == 'windows' and compiler.compiles('''
1506 ''', name: 'Win32 _wpgmptr')
1507 libgit_c_args += '-DHAVE_WPGMPTR'
1510 build_options_config.set('RUNTIME_PREFIX', 'false')
1513 git_version_file = custom_target(
1516 meson.current_source_dir() / 'GIT-VERSION-GEN',
1517 meson.current_source_dir(),
1521 input: meson.current_source_dir() / 'GIT-VERSION-FILE.in',
1522 output: 'GIT-VERSION-FILE',
1523 env: version_gen_environment,
1524 build_always_stale: true,
1527 version_def_h = custom_target(
1530 meson.current_source_dir() / 'GIT-VERSION-GEN',
1531 meson.current_source_dir(),
1535 input: meson.current_source_dir() / 'version-def.h.in',
1536 output: 'version-def.h',
1537 # Depend on GIT-VERSION-FILE so that we don't always try to rebuild this
1538 # target for the same commit.
1539 depends: [git_version_file],
1540 env: version_gen_environment,
1543 # Build a separate library for "version.c" so that we do not have to rebuild
1544 # everything when the current Git commit changes.
1545 libgit_version_library = static_library('git-version',
1550 c_args: libgit_c_args + [
1551 '-DGIT_VERSION_H="' + version_def_h.full_path() + '"',
1553 dependencies: libgit_dependencies,
1554 include_directories: libgit_include_directories,
1557 libgit_library = static_library('git',
1558 sources: libgit_sources,
1559 c_args: libgit_c_args,
1560 link_with: libgit_version_library,
1561 dependencies: libgit_dependencies,
1562 include_directories: libgit_include_directories,
1565 libgit = declare_dependency(
1566 compile_args: libgit_c_args,
1567 link_with: libgit_library,
1568 dependencies: libgit_dependencies,
1569 include_directories: libgit_include_directories,
1572 common_main_sources = ['common-main.c']
1573 common_main_link_args = [ ]
1574 if host_machine.system() == 'windows'
1575 git_rc = custom_target(
1578 meson.current_source_dir() / 'GIT-VERSION-GEN',
1579 meson.current_source_dir(),
1583 input: meson.current_source_dir() / 'git.rc.in',
1585 depends: [git_version_file],
1586 env: version_gen_environment,
1589 common_main_sources += import('windows').compile_resources(git_rc,
1590 include_directories: [meson.current_source_dir()],
1592 if compiler.get_argument_syntax() == 'gcc'
1593 common_main_link_args += [
1597 '-Wl,-pic-executable,-e,mainCRTStartup',
1599 elif compiler.get_argument_syntax() == 'msvc'
1600 common_main_link_args += [
1601 '/ENTRY:wmainCRTStartup',
1602 'invalidcontinue.obj',
1605 error('Unsupported compiler ' + compiler.get_id())
1608 common_main_library = static_library('common-main',
1609 sources: common_main_sources,
1610 c_args: libgit_c_args,
1611 dependencies: libgit_dependencies,
1612 include_directories: libgit_include_directories,
1614 common_main = declare_dependency(
1615 link_with: common_main_library,
1616 link_args: common_main_link_args,
1620 test_dependencies = [ ]
1622 git = executable('git',
1623 sources: builtin_sources + 'git.c',
1624 dependencies: [libgit, common_main],
1626 install_dir: get_option('libexecdir') / 'git-core',
1630 test_dependencies += executable('git-daemon',
1631 sources: 'daemon.c',
1632 dependencies: [libgit, common_main],
1634 install_dir: get_option('libexecdir') / 'git-core',
1637 test_dependencies += executable('git-sh-i18n--envsubst',
1638 sources: 'sh-i18n--envsubst.c',
1639 dependencies: [libgit, common_main],
1641 install_dir: get_option('libexecdir') / 'git-core',
1644 bin_wrappers += executable('git-shell',
1646 dependencies: [libgit, common_main],
1648 install_dir: get_option('libexecdir') / 'git-core',
1651 test_dependencies += executable('git-http-backend',
1652 sources: 'http-backend.c',
1653 dependencies: [libgit, common_main],
1655 install_dir: get_option('libexecdir') / 'git-core',
1658 bin_wrappers += executable('scalar',
1659 sources: 'scalar.c',
1660 dependencies: [libgit, common_main],
1662 install_dir: get_option('libexecdir') / 'git-core',
1665 if get_option('curl').enabled()
1671 git_remote_http = executable('git-remote-http',
1672 sources: curl_sources + 'remote-curl.c',
1673 dependencies: [libgit, common_main],
1675 install_dir: get_option('libexecdir') / 'git-core',
1677 test_dependencies += git_remote_http
1679 test_dependencies += executable('git-http-fetch',
1680 sources: curl_sources + 'http-fetch.c',
1681 dependencies: [libgit, common_main],
1683 install_dir: get_option('libexecdir') / 'git-core',
1687 test_dependencies += executable('git-http-push',
1688 sources: curl_sources + 'http-push.c',
1689 dependencies: [libgit, common_main],
1691 install_dir: get_option('libexecdir') / 'git-core',
1695 foreach alias : [ 'git-remote-https', 'git-remote-ftp', 'git-remote-ftps' ]
1696 test_dependencies += executable(alias,
1697 objects: git_remote_http.extract_all_objects(recursive: false),
1698 dependencies: [libgit, common_main],
1701 install_symlink(alias + executable_suffix,
1702 install_dir: get_option('libexecdir') / 'git-core',
1703 pointing_to: 'git-remote-http',
1708 imap_send_sources = ['imap-send.c']
1709 if use_curl_for_imap_send
1710 imap_send_sources += curl_sources
1713 test_dependencies += executable('git-imap-send',
1714 sources: imap_send_sources,
1715 dependencies: [libgit, common_main],
1717 install_dir: get_option('libexecdir') / 'git-core',
1720 foreach alias : [ 'git-receive-pack', 'git-upload-archive', 'git-upload-pack' ]
1721 bin_wrappers += executable(alias,
1722 objects: git.extract_all_objects(recursive: false),
1723 dependencies: [libgit, common_main],
1726 install_symlink(alias + executable_suffix,
1727 install_dir: get_option('libexecdir') / 'git-core',
1736 'git-upload-archive',
1740 if meson.version().version_compare('>=1.3.0')
1741 pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / symlink, get_option('bindir'))
1743 pointing_to = '../libexec/git-core' / symlink
1746 install_symlink(symlink,
1747 install_dir: get_option('bindir'),
1748 pointing_to: pointing_to,
1753 'git-difftool--helper.sh',
1754 'git-filter-branch.sh',
1755 'git-merge-octopus.sh',
1756 'git-merge-one-file.sh',
1757 'git-merge-resolve.sh',
1758 'git-mergetool--lib.sh',
1760 'git-quiltimport.sh',
1761 'git-request-pull.sh',
1765 'git-web--browse.sh',
1767 if perl_features_enabled
1768 scripts_sh += 'git-instaweb.sh'
1771 foreach script : scripts_sh
1772 test_dependencies += custom_target(
1774 output: fs.stem(script),
1777 meson.project_source_root() / 'generate-script.sh',
1780 meson.project_build_root() / 'GIT-BUILD-OPTIONS',
1783 install_dir: get_option('libexecdir') / 'git-core',
1787 if perl_features_enabled
1789 'git-archimport.perl',
1790 'git-cvsexportcommit.perl',
1791 'git-cvsimport.perl',
1792 'git-cvsserver.perl',
1793 'git-send-email.perl',
1798 if host_machine.system() == 'windows'
1802 perl_header_template = 'perl/header_templates/fixed_prefix.template.pl'
1803 if get_option('runtime_prefix')
1804 perl_header_template = 'perl/header_templates/runtime_prefix.template.pl'
1807 perl_header = configure_file(
1808 input: perl_header_template,
1809 output: 'GIT-PERL-HEADER',
1811 'GITEXECDIR_REL': get_option('libexecdir') / 'git-core',
1812 'PERLLIBDIR_REL': get_option('datadir') / 'perl5',
1813 'LOCALEDIR_REL': get_option('datadir') / 'locale',
1814 'INSTLIBDIR': get_option('datadir') / 'perl5',
1819 generate_perl_command = [
1821 meson.project_source_root() / 'generate-perl.sh',
1822 meson.project_build_root() / 'GIT-BUILD-OPTIONS',
1823 git_version_file.full_path(),
1829 foreach script : scripts_perl
1830 generated_script = custom_target(
1832 output: fs.stem(script),
1833 command: generate_perl_command,
1835 install_dir: get_option('libexecdir') / 'git-core',
1836 depends: [git_version_file],
1838 test_dependencies += generated_script
1840 if script == 'git-cvsserver.perl'
1841 bin_wrappers += generated_script
1843 if meson.version().version_compare('>=1.3.0')
1844 pointing_to = fs.relative_to(get_option('libexecdir') / 'git-core' / fs.stem(script), get_option('bindir'))
1846 pointing_to = '../libexec/git-core' / fs.stem(script)
1849 install_symlink(fs.stem(script),
1850 install_dir: get_option('bindir'),
1851 pointing_to: pointing_to,
1864 foreach script : scripts_python
1865 generated_python = custom_target(
1867 output: fs.stem(script),
1870 meson.project_source_root() / 'generate-python.sh',
1871 meson.project_build_root() / 'GIT-BUILD-OPTIONS',
1876 install_dir: get_option('libexecdir') / 'git-core',
1878 test_dependencies += generated_python
1883 'mergetools/araxis',
1885 'mergetools/codecompare',
1886 'mergetools/deltawalker',
1887 'mergetools/diffmerge',
1888 'mergetools/diffuse',
1889 'mergetools/ecmerge',
1890 'mergetools/emerge',
1891 'mergetools/examdiff',
1892 'mergetools/guiffy',
1893 'mergetools/gvimdiff',
1894 'mergetools/kdiff3',
1895 'mergetools/kompare',
1897 'mergetools/nvimdiff',
1898 'mergetools/opendiff',
1899 'mergetools/p4merge',
1900 'mergetools/smerge',
1901 'mergetools/tkdiff',
1902 'mergetools/tortoisemerge',
1903 'mergetools/vimdiff',
1904 'mergetools/vscode',
1905 'mergetools/winmerge',
1906 'mergetools/xxdiff',
1909 foreach mergetool : mergetools
1910 install_data(mergetool, install_dir: get_option('libexecdir') / 'git-core' / 'mergetools')
1917 # Gitweb requires Perl, so we disable the auto-feature if Perl was not found.
1918 # We make sure further up that Perl is required in case the gitweb option is
1920 gitweb_option = get_option('gitweb').disable_auto_if(not perl.found())
1921 if gitweb_option.allowed()
1923 build_options_config.set('NO_GITWEB', '')
1925 build_options_config.set('NO_GITWEB', '1')
1930 # Everything but the bin-wrappers need to come before this target such that we
1931 # can properly set up test dependencies. The bin-wrappers themselves are set up
1932 # at configuration time, so these are fine.
1933 if get_option('tests')
1937 if get_option('fuzzers')
1941 subdir('bin-wrappers')
1942 if get_option('docs') != []
1943 subdir('Documentation')
1948 foreach key, value : {
1949 'DIFF': diff.full_path(),
1950 'GIT_TEST_CMP': diff.full_path() + ' -u',
1951 'GIT_TEST_GITPERLLIB': meson.project_build_root() / 'perl',
1952 'GIT_TEST_MERGE_TOOLS_DIR': meson.project_source_root() / 'mergetools',
1953 'GIT_TEST_POPATH': meson.project_source_root() / 'po',
1954 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates',
1955 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po',
1956 'PAGER_ENV': get_option('pager_environment'),
1957 'PERL_PATH': perl.found() ? perl.full_path() : '',
1958 'PYTHON_PATH': python.found () ? python.full_path() : '',
1959 'SHELL_PATH': shell.full_path(),
1960 'TAR': tar.full_path(),
1961 'TEST_OUTPUT_DIRECTORY': test_output_directory,
1962 'TEST_SHELL_PATH': shell.full_path(),
1964 if value != '' and cygpath.found()
1965 value = run_command(cygpath, value, check: true).stdout().strip()
1967 build_options_config.set_quoted(key, value)
1971 input: 'GIT-BUILD-OPTIONS.in',
1972 output: 'GIT-BUILD-OPTIONS',
1973 configuration: build_options_config,
1976 # Development environments can be used via `meson devenv -C <builddir>`. This
1977 # allows you to execute test scripts directly with the built Git version and
1978 # puts the built version of Git in your PATH.
1979 devenv = environment()
1980 devenv.set('GIT_BUILD_DIR', meson.current_build_dir())
1981 devenv.prepend('PATH', meson.current_build_dir() / 'bin-wrappers')
1982 meson.add_devenv(devenv)
1984 # Generate the 'version' file in the distribution tarball. This is used via
1985 # `meson dist -C <builddir>` to populate the source archive with the Git
1986 # version that the archive is being generated from.
1987 meson.add_dist_script(
1990 '"$1" "$2" "$3" --format="@GIT_VERSION@" "$MESON_DIST_ROOT/version"',
1993 meson.current_source_dir() / 'GIT-VERSION-GEN',
1994 meson.current_source_dir(),
1998 'curl': curl.found(),
1999 'expat': expat.found(),
2000 'gettext': intl.found(),
2001 'gitweb': gitweb_option.allowed(),
2002 'https': https_backend,
2003 'iconv': iconv.found(),
2004 'pcre2': pcre2.found(),
2005 'perl': perl_features_enabled,
2006 'python': python.found(),
2007 }, section: 'Auto-detected features')
2010 'csprng': csprng_backend,
2011 'https': https_backend,
2012 'sha1': sha1_backend,
2013 'sha1_unsafe': sha1_unsafe_backend,
2014 'sha256': sha256_backend,
2015 }, section: 'Backends')