# vim: filetype=yaml sw=2
debug: '[% GET ! ENV.RBM_NO_DEBUG %]'
output_dir: "out/[% project %]"
tmp_dir: '[% c("basedir") %]/tmp'
build_log: '[% GET ENV.RBM_LOGS_DIR ? ENV.RBM_LOGS_DIR : "logs" %]/[% project %][% IF c("var/osname") %]-[% c("var/osname") %][% END %].log'

pkg_type: build

compress_tar: zst

container:
  disable_network:
    # disable network in the build scripts
    build: 1

steps:
  list_toolchain_updates:
    build_log: '-'
    list_toolchain_updates: '[% INCLUDE list_toolchain_updates %]'

  cargo_vendor:
    filename: '[% project %]-vendor-[% c("version") %]-[% c("var/build_id") %].tar.[% c("compress_tar") %]'
    output_dir: "out/[% project %]/cargo_vendor"
    compress_tar: gz
    cargo_vendor: |
      #!/bin/bash
      [% c("var/set_default_env") %]
      mkdir /var/tmp/dist
      tar -C /var/tmp/dist -xf [% c('input_files_by_name/rust') %]
      export PATH="/var/tmp/dist/rust/bin:$PATH"
      tar -xf [% project %]-[% c('version') %].tar.[% c('compress_tar') %]
      cd [% project %]-[% c('version') %]
      cargo vendor --locked vendor --manifest-path [% IF c('var/cargo_vendor_subdir') %][% c('var/cargo_vendor_subdir') %]/[% END %]Cargo.toml
      [% c('tar', {
        tar_src => [ 'vendor' ],
        tar_args => '-caf ' _ dest_dir _ '/' _ c('filename'),
        }) %]

    input_files:
      - project: container-image
        pkg_type: build
      - name: rust
        project: rust
        pkg_type: build

  go_vendor:
    filename: '[% project %]-vendor-[% c("version") %]-[% c("var/build_id") %].tar.[% c("compress_tar") %]'
    output_dir: "out/[% project %]/go_vendor"
    go_vendor: |
      #!/bin/bash
      [% c("var/set_default_env") %]
      [% pc('go', 'var/setup', { go_tarfile => c('input_files_by_name/go') }) %]
      mkdir -p /var/tmp/build
      tar -C /var/tmp/build -xf [% project %]-[% c('version') %].tar.[% c('compress_tar') %]
      cd /var/tmp/build/[% project %]-[% c('version') %]
      go mod vendor
      [% c('tar', {
        tar_src => [ 'vendor' ],
        tar_args => '-caf ' _ dest_dir _ '/' _ c('filename'),
        }) %]

    input_files:
      - project: container-image
        pkg_type: build
      - name: go
        project: go
        pkg_type: build

# buildconf contains build options that the user can change in rbm.local.conf
# When adding a new option to buildconf, a default value should be defined
# in var/build_id, so that changing this option does not affect the build_id.
buildconf:
  git_signtag_opt: '-s'

var:
  torbrowser_version: '14.5a5'
  torbrowser_build: 'build1'
  # This should be the date of when the build is started. For the build
  # to be reproducible, browser_release_date should always be in the past.
  browser_release_date: '2025/03/20 18:10:00'
  browser_release_date_timestamp: '[% USE date; date.format(c("var/browser_release_date"), "%s") %]'
  browser_default_channel: alpha
  browser_platforms:
    is_android_release: '[% c("var/tor-browser") %]'
    is_desktop_release: '1'
    android-armv7: '[% c("var/browser_platforms/is_android_release") %]'
    android-x86: '[% c("var/browser_platforms/is_android_release") %]'
    android-x86_64: '[% c("var/browser_platforms/is_android_release") %]'
    android-aarch64: '[% c("var/browser_platforms/is_android_release") %]'
    linux-x86_64: '[% c("var/browser_platforms/is_desktop_release") %]'
    linux-i686: '[% c("var/browser_platforms/is_desktop_release") && c("var/tor-browser") %]'
    linux-aarch64: '[% c("var/browser_platforms/is_desktop_release") && ( c("var/testbuild") || c("var/nightly") ) %]'
    windows-i686: '[% c("var/browser_platforms/is_desktop_release") && c("var/tor-browser") %]'
    windows-x86_64: '[% c("var/browser_platforms/is_desktop_release") %]'
    macos: '[% c("var/browser_platforms/is_desktop_release") %]'
  updater_enabled: 1
  build_mar: 1
  torbrowser_incremental_from:
    - 14.5a4
    - 14.5a3
    - 14.5a2
  mar_channel_id: '[% c("var/projectname") %]-torproject-[% c("var/channel") %]'

  # By default, we sort the list of installed packages. This allows sharing
  # containers with identical list of packages, even if they are not listed
  # in the same order. In the cases where the installation order is
  # important, sort_deps should be set to 0.
  sort_deps: 1
  build_id: '[% sha256(c("var/build_id_txt", { num_procs => 4 })).substr(0, 6) %]'
  build_id_txt: |
    [% c("version") %]
    [% IF c("git_url") || c("hg_url"); GET c("abbrev"); END; %]
    [% IF c("container/use_container") && ! c("container/global_disable") -%]
    [% c("var/container/suite") %]
    [% c("var/container/arch") %]
    [% END -%]
    input_files: [% c("input_files_id") %]
    build:
    [% SET step = c("step") -%]
    [% c(step, { filename => 'f', output_dir => '/out', norec => {} }) %]

  Project_Name_Channel: '[% c("var/Project_Name") %] [% c("var/channel") FILTER ucfirst %]'
  display_name: '[% c("var/Project_Name_Channel") %]'
  exe_name: firefox
  faketime_date: "[% USE date; GET date.format(c('timestamp'), format = '%Y-%m-%d %H:%M:%S') %]"
  faketime_setup: |
    export LD_PRELOAD=[% c("var/faketime_path") %]
    export FAKETIME='[% c("var/faketime_date") %]'

  locale_ja: ja
  # When adding new languages, add the equivalent NSIS name to
  # projects/browser/windows-installer/add-strings.py.
  locales:
    - ar
    - be
    - bg
    - ca
    - cs
    - da
    - de
    - el
    - es-ES
    - fa
    - fi
    - fr
    - ga-IE
    - he
    - hu
    - id
    - is
    - it
    - '[% c("var/locale_ja") %]'
    - ka
    - ko
    - lt
    - mk
    - ms
    - my
    - nb-NO
    - nl
    - pl
    - pt-BR
    - pt-PT
    - ro
    - ru
    - sq
    - sv-SE
    - th
    - tr
    - uk
    - vi
    - zh-CN
    - zh-TW
  locales_mobile:
    - ar
    - be
    - bg
    - ca
    - cs
    - da
    - de
    - el
    - es-rES
    - fa
    - fi
    - fr
    - ga-rIE
    - hu
    # Indonesian (id in var/locales)
    - in
    - is
    - it
    # Modern Hebrew (he in var/locales)
    - iw
    - ja
    - ka
    - ko
    - lt
    - my
    - nb-rNO
    - nl
    - pl
    - pt-rBR
    - pt-rPT
    - ro
    - ru
    - sq
    - sv-rSE
    - th
    - tr
    - uk
    - vi
    - zh-rCN
    - zh-rTW

  rlbox: 1

  sign_build: '[% ENV.RBM_SIGN_BUILD %]'
  sign_build_gpg_opts: '[% ENV.RBM_GPG_OPTS %]'

  set_default_env: |
    set -e
    [% FOREACH env = c('ENV') -%]
    export [% env.key %]="[% env.value %]"
    [% END -%]
    rootdir=$(pwd)
    export SHELL=/bin/bash
    export HOME=$rootdir
    export SOURCE_DATE_EPOCH='[% c("timestamp") %]'
    umask 0022
    [% IF c("container/global_disable") -%]
      rm -Rf /var/tmp/build /var/tmp/dist
    [% END -%]
    [% IF c("compress_tar") == 'zst' -%]
      # Always set ZSTD_NBTHREADS > 1 to make archives reproducible
      # (single vs multi-threaded might produce different results)
      export ZSTD_NBTHREADS=[% c("num_procs") > 1 ? c("num_procs") : '2' %]
    [% END -%]


  DOCSDIR_project: '[% project %]'
  set_MOZ_BUILD_DATE: 'export MOZ_BUILD_DATE=[% c("var/MOZ_BUILD_DATE") %]'
  MOZ_BUILD_DATE: '[% USE date; date.format(c("var/browser_release_date"), "%Y%m%d%H%M%S") %]'

  # var/essential_deps is the same as var/deps, except that we never
  # redefine it in projects config. This is for the packages we want to
  # include in every container (even those of projects where we redefine var/deps).
  essential_deps:
    - less
    - patch
    - zip
    - unzip
    - xz-utils
    - zstd

targets:
  notarget: linux-x86_64
  noint:
    debug: 0

  release:
    var:
      release: 1
      channel: release
      display_name: '[% c("var/Project_Name") %]'
  alpha:
    var:
      alpha: 1
      channel: alpha
  nightly:
    var:
      nightly: 1
      channel: nightly
      torbrowser_version: |
        [%
           IF ENV.TORBROWSER_NIGHTLY_VERSION;
                GET ENV.TORBROWSER_NIGHTLY_VERSION;
           ELSIF c("var/testbuild");
                GET "testbuild";
           ELSE;
                GET c("var_p/nightly_torbrowser_version");
           END;
        -%]
      browser_release_date: |
        [%
          IF (matches = c("var/torbrowser_version").match('^tbb-nightly\.(\d\d\d\d)\.(\d\d)\.(\d\d)$'));
            GET matches.0 _ "/" _ matches.1 _ "/" _ matches.2 _ " 01:01:01";
          ELSE;
            GET "2024/01/01 01:01:01";
          END
          -%]
      max_torbrowser_incremental_from: 2
      build_infos_json: 1

  torbrowser:
    var:
      tor-browser: 1
      project-name: tor-browser
      projectname: torbrowser
      Project_Name: 'Tor Browser'
      ProjectName: TorBrowser
      project_initials: tb

  basebrowser:
    var:
      base-browser: 1
      project-name: base-browser
      projectname: basebrowser
      Project_Name: 'Base Browser'
      ProjectName: BaseBrowser
      updater_enabled: '[% c("var/nightly") %]'

  mullvadbrowser:
    var:
      mullvad-browser: 1
      project-name: mullvad-browser
      projectname: mullvadbrowser
      Project_Name: 'Mullvad Browser'
      ProjectName: MullvadBrowser
      project_initials: mb
      exe_name: mullvadbrowser
      mar_channel_id: '[% c("var/projectname") %]-mullvad-[% c("var/channel") %]'
      locales:
        - ar
        - da
        - de
        - es-ES
        - fa
        - fi
        - fr
        - it
        - '[% c("var/locale_ja") %]'
        - ko
        - my
        - nb-NO
        - nl
        - pl
        - pt-BR
        - ru
        - sv-SE
        - th
        - tr
        - zh-CN
        - zh-TW

  torbrowser-testbuild:
    - testbuild
    - alpha
    - torbrowser
  basebrowser-testbuild:
    - testbuild
    - alpha
    - basebrowser
  mullvadbrowser-testbuild:
    - testbuild
    - alpha
    - mullvadbrowser
  testbuild:
    var:
      testbuild: 1
      # Don't create mar files to save time
      build_mar: 0
      # Building only one architecture saves a lot of time
      android_single_arch: 1

  torbrowser-android-armv7:
    - android-armv7
    - android
    - torbrowser
  basebrowser-android-armv7:
    - android-armv7
    - android
    - basebrowser
  android-armv7:
    arch: armv7
    var:
      android-armv7: 1
      osname: android-armv7
      toolchain_arch: arm
      abi: armeabi-v7a
      cross_prefix: armv7a-linux-androideabi
  torbrowser-android-x86:
    - android-x86
    - android
    - torbrowser
  basebrowser-android-x86:
    - android-x86
    - android
    - basebrowser
  android-x86:
    arch: x86
    var:
      android-x86: 1
      osname: android-x86
      toolchain_arch: x86
      abi: x86
      cross_prefix: i686-linux-android
  torbrowser-android-x86_64:
    - android-x86_64
    - android
    - torbrowser
  basebrowser-android-x86_64:
    - android-x86_64
    - android
    - basebrowser
  android-x86_64:
    arch: x86_64
    var:
      android-x86_64: 1
      osname: android-x86_64
      toolchain_arch: x86_64
      abi: x86_64
      cross_prefix: x86_64-linux-android
  torbrowser-android-aarch64:
    - android-aarch64
    - android
    - torbrowser
  basebrowser-android-aarch64:
    - android-aarch64
    - android
    - basebrowser
  android-aarch64:
    arch: aarch64
    var:
      android-aarch64: 1
      osname: android-aarch64
      toolchain_arch: arm64
      abi: arm64-v8a
      cross_prefix: aarch64-linux-android
  android:
    var:
      android: 1
      platform: android
      compiler: android-toolchain
      android_min_api: 21
      CC: '[% c("var/cross_prefix") %][% c("var/android_min_api") %]-clang'
      CXX: '[% c("var/cross_prefix") %][% c("var/android_min_api") %]-clang'
      container:
        suite: bookworm
        arch: amd64
      deps:
        - build-essential
        - openjdk-17-jdk-headless
        - bison
        - ca-certificates
        - python3
        - python3-distutils
        - python3-venv
        - automake
        - libtool
        - libtinfo5
        - libssl-dev
        - pkg-config
        - zlib1g-dev
      configure_opt: '--host=[% c("var/cross_prefix") %] CC=[% c("var/CC") %] [% c("var/configure_opt_project") %]'

  torbrowser-linux-x86_64:
    - linux-x86_64
    - linux
    - torbrowser
  basebrowser-linux-x86_64:
    - linux-x86_64
    - linux
    - basebrowser
  mullvadbrowser-linux-x86_64:
    - linux-x86_64
    - linux
    - mullvadbrowser
  torbrowser-linux-x86_64-asan:
    - linux-asan
    - linux-x86_64
    - linux
    - torbrowser
  basebrowser-linux-x86_64-asan:
    - linux-asan
    - linux-x86_64
    - linux
    - basebrowser
  mullvadbrowser-linux-x86_64-asan:
    - linux-asan
    - linux-x86_64
    - linux
    - mullvadbrowser
  torbrowser-linux-i686:
    - linux-i686
    - linux
    - torbrowser
  basebrowser-linux-i686:
    - linux-i686
    - linux
    - basebrowser
  torbrowser-linux-aarch64:
    - linux-cross
    - linux-aarch64
    - linux
    - torbrowser
  basebrowser-linux-aarch64:
    - linux-cross
    - linux-aarch64
    - linux
    - basebrowser
  mullvadbrowser-linux-aarch64:
    - linux-cross
    - linux-aarch64
    - linux
    - mullvadbrowser
  torbrowser-linux-arm:
    - linux-cross
    - linux-arm
    - linux
    - torbrowser
  basebrowser-linux-arm:
    - linux-cross
    - linux-arm
    - linux
    - basebrowser
  linux-x86_64:
    arch: x86_64
    var:
      linux-x86_64: 1
      osname: linux-x86_64
      linux-cross: 0
      arch_debian: amd64
  linux-i686:
    arch: i686
    var:
      linux-i686: 1
      osname: linux-i686
      linux-cross: 0
      configure_opt: '--host=i686-linux-gnu CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 [% c("var/configure_opt_project") %]'
      arch_debian: i386
  linux-aarch64:
    arch: aarch64
    var:
      linux-aarch64: 1
      osname: linux-aarch64
      linux-cross: 1
      arch_debian: arm64
      crosstarget: aarch64-linux-gnu
  linux-arm:
    arch: arm
    var:
      linux-arm: 1
      osname: linux-arm
      linux-cross: 1
      arch_debian: armhf
      crosstarget: arm-linux-gnueabihf
  linux-cross:
    var:
      linux-cross: 1
      compiler: 'gcc[% IF ! c("var/no_crosscompile") %]-cross[% END %]'
      configure_opt: '--host=[% c("var/crosstarget") %] [% c("var/configure_opt_project") %]'
  linux:
    # tar in strech does not know how to extract tar.zst files
    # so we keep using gz
    compress_tar: gz
    var:
      linux: 1
      platform: linux
      compiler: gcc
      configure_opt: '[% c("var/configure_opt_project") %]'
      # Only build Namecoin for linux on nightly
      # Temporarily disabled until we have a fix for tor-browser-build#40845
      #namecoin: '[% c("var/nightly") && c("var/tor-browser") %]'
      container:
        suite: stretch
        arch: amd64
      pre_pkginst: dpkg --add-architecture i386
      deps:
        - ca-certificates
        - libc6-dev-i386
        - lib32stdc++6
        - pkg-config
        - libssl-dev
        - build-essential
        - ca-certificates
        - bison
        - automake
        - libtool
        - less
      set_hardened_build_flags: |
        export DEB_BUILD_HARDENING=1
        export DEB_BUILD_OPTIONS='hardening=+bindnow,+relro,+pie,+fortify,+stackprotector,+stackprotectorstrong,+format'
        mkdir -p /var/tmp/build
        eval $(cd /var/tmp/build; dpkg-buildflags --export=sh)
  linux-asan:
    var:
      asan: 1
      # RLBox needs clang to create .wasm files but we use mostly GCC for our
      # ASan builds. Thus, the compilation currently breaks with RLBox enabled.
      # See: tor-browser-build#40063.
      rlbox: 0

  torbrowser-windows-i686:
    - windows-i686
    - windows
    - torbrowser
  basebrowser-windows-i686:
    - windows-i686
    - windows
    - basebrowser
  torbrowser-windows-x86_64:
    - windows-x86_64
    - windows
    - torbrowser
  basebrowser-windows-x86_64:
    - windows-x86_64
    - windows
    - basebrowser
  mullvadbrowser-windows-x86_64:
    - windows-x86_64
    - windows
    - mullvadbrowser
  windows-x86_64:
    arch: x86_64
    var:
      windows-x86_64: 1
      windows-i686: 0
      osname: windows-x86_64
  windows-i686:
    arch: i686
    var:
      windows-i686: 1
      windows-x86_64: 0
      osname: windows-i686
      # mingw-w64 does not support SEH on 32bit systems. Be explicit about that.
      flag_noSEH: '-Wl,--no-seh'
  windows:
    var:
      windows: 1
      platform: windows
      container:
        suite: bookworm
        arch: amd64
      configure_opt: '--host=[% c("arch") %]-w64-mingw32 CFLAGS="[% c("var/CFLAGS") %]" LDFLAGS="[% c("var/LDFLAGS") %]" [% c("var/configure_opt_project") %]'
      CFLAGS: '-fstack-protector-strong -fno-strict-overflow -Wno-missing-field-initializers -Wformat -Wformat-security [% c("var/flag_mwindows") %]'
      LDFLAGS: '-Wl,--no-insert-timestamp [% c("var/flag_noSEH") %] [% c("var/flag_mwindows") %]'
      flag_mwindows: '-Wl,--subsystem,windows'
      compiler: mingw-w64-clang
      deps:
        - build-essential
        - ca-certificates
        - python3
        - python3-distutils
        - bison
        - automake
        - libtool
        - libssl-dev
        - zlib1g-dev

  torbrowser-macos:
    - macos-universal
    - macos-x86_64
    - macos
    - torbrowser
  torbrowser-macos-x86_64:
    - macos-x86_64
    - macos
    - torbrowser
  torbrowser-macos-aarch64:
    - macos-aarch64
    - macos
    - torbrowser
  basebrowser-macos:
    - macos-universal
    - macos-x86_64
    - macos
    - basebrowser
  basebrowser-macos-x86_64:
    - macos-x86_64
    - macos
    - basebrowser
  basebrowser-macos-aarch64:
    - macos-aarch64
    - macos
    - basebrowser
  mullvadbrowser-macos:
    - macos-universal
    - macos-x86_64
    - macos
    - mullvadbrowser
  mullvadbrowser-macos-x86_64:
    - macos-x86_64
    - macos
    - mullvadbrowser
  mullvadbrowser-macos-aarch64:
    - macos-aarch64
    - macos
    - mullvadbrowser
  macos-universal:
    var:
      macos_universal: 1
  macos-aarch64:
    arch: aarch64
    var:
      macos-aarch64: 1
      macos-x86_64: 0
      osname: macos-aarch64
      macos_arch: arm64
      build_target: aarch64-apple-darwin
      macosx_deployment_target: '11.0'
  macos-x86_64:
    arch: x86_64
    var:
      macos-x86_64: 1
      osname: macos-x86_64
      macos_arch: x86_64
      build_target: x86_64-apple-darwin
      macosx_deployment_target: '10.15'
  macos:
    var:
      macos: 1
      platform: macos
      osname: macos
      container:
        suite: bookworm
        arch: amd64
      compiler: 'macosx-toolchain'
      configure_opt: '--host=[% c("var/build_target") %] CC="[% c("var/build_target") %]-clang [% c("var/FLAGS") %]" CXX="[% c("var/build_target") %]-clang++ [% c("var/FLAGS") %]" [% c("var/configure_opt_project") %]'
      FLAGS: "-target [% c('var/build_target') %] -B $cctoolsdir -isysroot $sysrootdir [% IF c('var/macos-aarch64') %]-mcpu=apple-m1[% END %]"
      LDFLAGS: "-Wl,-syslibroot,$sysrootdir -Wl,-dead_strip -Wl,-pie"
      locale_ja: ja-JP-mac
      deps:
        - build-essential
        - ca-certificates
        - faketime
        - python3
        - python3-distutils
        - automake
        - bison
        - libtool
        - libssl-dev
        - zlib1g-dev
      faketime_path: /usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1

  # The no_build_id target can be useful if you want to quickly display
  # a build template or other option but don't want to spend time to
  # compute the various build ids
  no_build_id:
    # The defaut timestamp value will use the commit time of the
    # selected commit for the project, which will require cloning the
    # git repository if it is not present. When we use the no_build_id
    # target to display a script, we usually don't care about such
    # details, so we set timestamp to 0 to avoid unnecessary cloning.
    timestamp: 0
    var:
      build_id: 1

  no_containers:
    container:
      global_disable: 1

# allow git tag signed using an expired key.
# https://bugs.torproject.org/19737
gpg_allow_expired_keys: 1

--- |
  # This part of the file contains options written in perl
  (
    var_p => {
      nightly_torbrowser_version => sub {
        state $version = '';
        return $version if $version;
        my (undef, undef, undef, $day, $mon, $year) = gmtime;
        $version = sprintf("tbb-nightly.%u.%02u.%02u", $year + 1900, $mon + 1, $day);
        return $version;
      },
      nightly_torbrowser_incremental_from => sub {
        my ($project, $options) = @_;
        my $nightly_dir = project_config($project, 'basedir', $options) . '/' .
                project_config($project, 'var/projectname', $options) . '/nightly';
        my $current_version = project_config($project, 'var/torbrowser_version', $options);
        use Path::Tiny;
        return [] unless -d $nightly_dir;
        my @dirs = sort map { $_->basename } path($nightly_dir)->children(qr/^tbb-nightly\./);
        my $nb_incr = project_config($project, ['var', 'max_torbrowser_incremental_from'], $options);
        my @res;
        while ($nb_incr > 0) {
          my $dir = pop @dirs;
          last unless $dir;
          next if $dir eq $current_version;
          $nb_incr--;
          push @res, $dir;
        }
        return [@res];
      },
    },
  )
