aboutsummaryrefslogtreecommitdiff
path: root/windows/build.bash
blob: fa7b938c3eac8e2a15f84143612e4b813b9d90ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#!/bin/bash
# SPDX-License-Identifier: 0BSD

###############################################################################
#
# This build a XZ Utils binary package using the GNU Autotools build system
#
# NOTE: This requires files that are generated as part of "make mydist".
#       So if building from xz.git, create a distribution tarball first,
#       extract it, and run this script from there.
#
# These were tested and known to work:
#   - Cross-compilation with MinGW-w64 v10.0.0 and GCC 12.2.0 from
#     GNU/Linux ("make check" will be skipped)
#   - MSYS2 with MinGW-w64 and GCC
#   - MSYS 1.0.11 (from 2009) with MinGW-w64 v11.0.0 and GCC 13.1.0
#
# Optionally, 7-Zip is used to create the final .zip and .7z packages.
# If the 7z tool is in PATH or if you have installed it in the default
# directory on Windows, this script should find it automatically.
#
# Before running this script, copy COPYING.MinGW-w64-runtime.txt to
# the 'windows' directory.
#
# NOTE: MinGW-w64 includes getopt_long(). The GNU getopt_long() (LGPLv2.1)
#       included in XZ Utils isn't used when building with MinGW-w64.
#
###############################################################################
#
# Author: Lasse Collin
#
###############################################################################

# Abort immediately if something goes wrong.
set -e

# White spaces in directory names may break things so catch them immediately.
case $(pwd) in
	' ' | '	' | '
') echo "Error: White space in the directory name" >&2; exit 1 ;;
esac

# This script can be run either at the top-level directory of the package
# or in the same directory containing this script.
if [ ! -f windows/build.bash ]; then
	cd ..
	if [ ! -f windows/build.bash ]; then
		echo "ERROR: You are in a wrong directory. This script" >&2
		echo "can be run either at the top-level directory of" >&2
		echo "the package or in the same directory containing" >&2
		echo "this script." >&2
		exit 1
	fi
fi

# COPYING.MinGW-w64-runtime.txt needs to be manually copied from MinGW-w64.
if [ ! -f windows/COPYING.MinGW-w64-runtime.txt ]; then
	echo "ERROR: The file 'windows/COPYING.MinGW-w64-runtime.txt'" >&2
	echo "doesn't exists. Copy it from MinGW-w64 so that the" >&2
	echo "copyright and license notices of the MinGW-w64 runtime" >&2
	echo "can be included in the package." >&2
	echo "(Or create an empty file if only doing a test build.)" >&2
	exit 1
fi

# Number of jobs for "make":
MAKE_JOBS=$(nproc 2> /dev/null || echo 1)

# "make check" has to be skipped when cross-compiling.
if [ "x$(uname -o)" = xMsys ]; then
	IS_NATIVE_BUILD=true
else
	IS_NATIVE_BUILD=false
fi

# Run configure and copy the binaries to the given directory.
#
# The first argument is the directory where to copy the binaries.
# The rest of the arguments are passed to configure.
buildit()
{
	DESTDIR=$1
	TRIPLET=$2
	CFLAGS=$3

	# In the MinGW-w64 + GCC toolchains running natively on Windows,
	# $TRIPLET-windres and $TRIPLET-strip commands might not exist.
	# Only the short names "windres" and "strip" might be available.
	# If both i686 and x86_64 toolchains are in PATH, wrong windres.exe
	# will be used for one of the builds, making the build fail. The
	# workaround is to put the directory of $TRIPLET-gcc to the front
	# of PATH if $TRIPLET-windres or $TRIPLET-strip is missing.
	OLD_PATH=$PATH
	if type -P "$TRIPLET-windres" > /dev/null \
			&& type -P "$TRIPLET-strip" > /dev/null; then
		STRIP=$TRIPLET-strip
	else
		STRIP=strip
		GCC_DIR=$(type -P "$TRIPLET-gcc")
		PATH=${GCC_DIR%/*}:$PATH
	fi

	# Clean up if it was already configured.
	[ -f Makefile ] && make distclean

	# Build the size-optimized binaries. Providing size-optimized liblzma
	# could be considered but I don't know if it should only use -Os or
	# should it also use --enable-small and if it should support
	# threading. So I don't include a size-optimized liblzma for now.
	./configure \
		--prefix= \
		--enable-silent-rules \
		--disable-dependency-tracking \
		--disable-nls \
		--disable-scripts \
		--disable-threads \
		--disable-shared \
		--enable-small \
		--host="$TRIPLET" \
		CFLAGS="$CFLAGS -Os"
	make -j"$MAKE_JOBS"

	if "$IS_NATIVE_BUILD"; then
		make -j"$MAKE_JOBS" check
	fi

	mkdir -pv "$DESTDIR"
	cp -v src/xzdec/{xz,lzma}dec.exe src/lzmainfo/lzmainfo.exe "$DESTDIR"

	make distclean

	# Build the normal speed-optimized binaries. The type of threading
	# (win95 vs. vista) will be autodetect from the target architecture.
	./configure \
		--prefix= \
		--enable-silent-rules \
		--disable-dependency-tracking \
		--disable-nls \
		--disable-scripts \
		--host="$TRIPLET" \
		CFLAGS="$CFLAGS -O2"
	make -j"$MAKE_JOBS" -C src/liblzma
	make -j"$MAKE_JOBS" -C src/xz LDFLAGS=-static

	if "$IS_NATIVE_BUILD"; then
		make -j"$MAKE_JOBS" -C tests check
	fi

	cp -v src/xz/xz.exe "$DESTDIR"
	cp -v src/liblzma/.libs/liblzma-5.dll "$DESTDIR/liblzma.dll"
	"$STRIP" -v "$DESTDIR/"*.{exe,dll}

	PATH=$OLD_PATH
}

# Copy files and convert newlines from LF to CR+LF. Optionally add a suffix
# to the destination filename.
#
# The first argument is the destination directory. The second argument is
# the suffix to append to the filenames; use empty string if no extra suffix
# is wanted. The rest of the arguments are the actual filenames.
txtcp()
{
	DESTDIR=$1
	SUFFIX=$2
	shift 2
	for SRCFILE; do
		DESTFILE="$DESTDIR/${SRCFILE##*/}$SUFFIX"
		echo "Converting '$SRCFILE' -> '$DESTFILE'"
		sed s/\$/$'\r'/ < "$SRCFILE" > "$DESTFILE"
	done
}

if type -P i686-w64-mingw32-gcc > /dev/null; then
	# 32-bit x86, Win2k or later
	buildit pkg/bin_i686 i686-w64-mingw32 \
			'-march=i686 -mtune=generic'

	# 32-bit x86 with SSE2, Win2k or later
	buildit pkg/bin_i686-sse2 i686-w64-mingw32 \
			'-march=i686 -msse2 -mtune=generic'
else
	echo
	echo "i686-w64-mingw32-gcc is not in PATH, skipping 32-bit x86 builds"
	echo
fi

if type -P x86_64-w64-mingw32-gcc > /dev/null; then
	# x86-64, Windows Vista or later
	buildit pkg/bin_x86-64 x86_64-w64-mingw32 \
			'-march=x86-64 -mtune=generic'
else
	echo
	echo "x86_64-w64-mingw32-gcc is not in PATH, skipping x86-64 build"
	echo
fi

# Copy the headers, the .def file, and the docs.
# They are the same for all architectures and builds.
mkdir -pv pkg/{include/lzma,doc/{api,manuals,examples}}
txtcp pkg/include "" src/liblzma/api/lzma.h
txtcp pkg/include/lzma "" src/liblzma/api/lzma/*.h
txtcp pkg/doc "" src/liblzma/liblzma.def
txtcp pkg/doc .txt AUTHORS COPYING COPYING.0BSD NEWS README THANKS
txtcp pkg/doc "" doc/*.txt \
	windows/README-Windows.txt \
	windows/liblzma-crt-mixing.txt \
	windows/COPYING.MinGW-w64-runtime.txt
txtcp pkg/doc/manuals "" doc/man/txt/{xz,xzdec,lzmainfo}.txt
cp -v doc/man/pdf-*/{xz,xzdec,lzmainfo}-*.pdf pkg/doc/manuals
cp -v doc/api/* pkg/doc/api
txtcp pkg/doc/examples "" doc/examples/*

# Create the package. This requires 7z from 7-Zip.
# If it isn't found, this step is skipped.
for SEVENZ in "$(type -P 7z || true)" \
		"$PROGRAMW6432/7-Zip/7z.exe" "$PROGRAMFILES/7-Zip/7z.exe" \
		"/c/Program Files/7-Zip/7z.exe"
do
	[ -x "$SEVENZ" ] && break
done

if [ -x "$SEVENZ" ]; then
	VER=$(sh build-aux/version.sh)
	cd pkg
	"$SEVENZ" a -tzip ../xz-$VER-windows.zip *
	"$SEVENZ" a ../xz-$VER-windows.7z *
else
	echo
	echo "NOTE: 7z was not found. xz-$VER-windows.zip"
	echo "      and xz-$VER-windows.7z were not created."
	echo "      You can create them yourself from the pkg directory."
fi

echo
echo "Build completed successfully."
echo