1#!/bin/bash
2#===-- tag.sh - Tag the LLVM release candidates ----------------------------===#
3#
4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5# See https://llvm.org/LICENSE.txt for license information.
6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7#
8#===------------------------------------------------------------------------===#
9#
10# Create branches and release candidates for the LLVM release.
11#
12#===------------------------------------------------------------------------===#
13
14set -e
15
16projects="llvm bolt clang cmake compiler-rt libcxx libcxxabi libclc clang-tools-extra polly lldb lld openmp libunwind mlir flang third-party"
17
18release=""
19rc=""
20yyyymmdd=$(date +'%Y%m%d')
21snapshot=""
22template='${PROJECT}-${RELEASE}${RC}.src.tar.xz'
23
24usage() {
25cat <<EOF
26Export the Git sources and build tarballs from them.
27
28Usage: $(basename $0) [-release|--release <major>.<minor>.<patch>]
29                      [-rc|--rc <num>]
30                      [-final|--final]
31                      [-git-ref|--git-ref <git-ref>]
32                      [-template|--template <template>]
33
34Flags:
35
36  -release  | --release <major>.<minor>.<patch>    The version number of the release
37  -rc       | --rc <num>                           The release candidate number
38  -final    | --final                              When provided, this option will disable the rc flag
39  -git-ref  | --git-ref <git-ref>                  (optional) Use <git-ref> to determine the release and don't export the test-suite files
40  -template | --template <template>                (optional) Possible placeholders: \$PROJECT \$YYYYMMDD \$GIT_REF \$RELEASE \$RC.
41                                                   Defaults to '${template}'.
42
43The following list shows the filenames (with <placeholders>) for the artifacts
44that are being generated (given that you don't touch --template).
45
46$(echo "$projects "| sed 's/\([a-z-]\+\) /  * \1-<RELEASE><RC>.src.tar.xz \n/g')
47
48Additional files being generated:
49
50  * llvm-project-<RELEASE><RC>.src.tar.xz    (the complete LLVM source project)
51  * test-suite-<RELEASE><RC>.src.tar.xz      (only when not using --git-ref)
52
53To ease the creation of snapshot builds, we also provide these files
54
55  * llvm-release-<YYYYMMDD>.txt        (contains the <RELEASE> as a text)
56  * llvm-rc-<YYYYMMDD>.txt             (contains the rc version passed to the invocation of $(basename $0))
57  * llvm-git-revision-<YYYYMMDD>.txt   (contains the current git revision sha1)
58
59Example values for the placeholders:
60
61  * <RELEASE>  -> 13.0.0
62  * <YYYYMMDD> -> 20210414   (the date when executing this script)
63  * <RC>       -> rc4        (will be empty when using --git-ref)
64
65In order to generate snapshots of the upstream main branch you could do this for example:
66
67  $(basename $0) --git-ref upstream/main --template '\${PROJECT}-\${YYYYMMDD}.src.tar.xz'
68
69EOF
70}
71
72template_file() {
73    export PROJECT=$1 YYYYMMDD=$yyyymmdd RC=$rc RELEASE=$release GIT_REF=$git_rev
74    basename $(echo $template | envsubst '$PROJECT $RELEASE $RC $YYYYMMDD $GIT_REF')
75    unset PROJECT YYYYMMDD RC RELEASE GIT_REF
76}
77
78export_sources() {
79    local tag="llvmorg-$release"
80
81    llvm_src_dir=$(readlink -f $(dirname "$(readlink -f "$0")")/../../..)
82    [ -d $llvm_src_dir/.git ] || ( echo "No git repository at $llvm_src_dir" ; exit 1 )
83
84    # Determine the release by fetching the version from LLVM's CMakeLists.txt
85    # in the specified git ref.
86    if [ -n "$snapshot" ]; then
87        release=$(git -C $llvm_src_dir show $snapshot:llvm/CMakeLists.txt | grep -ioP 'set\(\s*LLVM_VERSION_(MAJOR|MINOR|PATCH)\s\K[0-9]+' | paste -sd '.')
88    fi
89    
90    tag="llvmorg-$release"
91
92    if [ "$rc" = "final" ]; then
93        rc=""
94    else
95        tag="$tag-$rc"
96    fi
97
98    target_dir=$(pwd)
99
100    echo "Creating tarball for llvm-project ..."
101    pushd $llvm_src_dir/
102    tree_id=$tag
103    [ -n "$snapshot" ] && tree_id="$snapshot"
104    echo "Tree ID to archive: $tree_id"
105
106    # This might be a surprise but a package like clang or compiler-rt don't
107    # know about the LLVM version itself. That's why we also export a the
108    # llvm-version*-<YYYYMMDD> and llvm-git*-<YYYYMMDD> files.
109    git_rev=$(git rev-parse $tree_id)
110    echo "git revision: $git_rev"
111    echo "$release" > $target_dir/llvm-release-$yyyymmdd.txt
112    echo "$rc" > $target_dir/llvm-rc-$yyyymmdd.txt
113    echo "$git_rev" > $target_dir/llvm-git-revision-$yyyymmdd.txt
114    
115    git archive --prefix=llvm-project-$release$rc.src/ $tree_id . | xz -T0 >$target_dir/$(template_file llvm-project)
116    popd
117
118    if [ -z "$snapshot" ]; then
119        if [ ! -d test-suite-$release$rc.src ]; then
120            echo "Fetching LLVM test-suite source ..."
121            mkdir -p test-suite-$release$rc.src
122            curl -L https://github.com/llvm/test-suite/archive/$tag.tar.gz | \
123                tar -C test-suite-$release$rc.src --strip-components=1 -xzf -
124        fi
125        echo "Creating tarball for test-suite ..."
126        tar --sort=name --owner=0 --group=0 \
127            --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \
128            -cJf test-suite-$release$rc.src.tar.xz test-suite-$release$rc.src
129    fi
130
131    for proj in $projects; do
132        echo "Creating tarball for $proj ..."
133        pushd $llvm_src_dir/$proj
134        git archive --prefix=$proj-$release$rc.src/ $tree_id . | xz -T0 >$target_dir/$(template_file $proj)
135        popd
136    done
137}
138
139while [ $# -gt 0 ]; do
140    case $1 in
141        -release | --release )
142            shift
143            release=$1
144            ;;
145        -rc | --rc )
146            shift
147            rc="rc$1"
148            ;;
149        -final | --final )
150            rc="final"
151            ;;
152        -git-ref | --git-ref )
153            shift
154            snapshot="$1"
155            ;;
156        -template | --template )
157            shift
158            template="$1"
159            ;;
160        -h | -help | --help )
161            usage
162            exit 0
163            ;;
164        * )
165            echo "unknown option: $1"
166            usage
167            exit 1
168            ;;
169    esac
170    shift
171done
172
173if [ -n "$snapshot" ]; then 
174    if [[ "$rc" != "" || "$release" != "" ]]; then
175        echo "error: must not specify -rc or -release when creating a snapshot"
176        exit 1
177    fi
178elif [ -z "$release" ]; then
179    echo "error: need to specify a release version"
180    exit 1
181fi
182
183# Make sure umask is not overly restrictive.
184umask 0022
185
186export_sources
187exit 0
188