1#!/bin/sh
2#
3
4
5# BUGS:
6#   - use
7#          cygcheck -c | grep mingw
8#     to  get a list of mingw packages installed.  See about
9#     extracting a runtime subset of the required ones because
10#     we really don't want to have a ton of extra stuff get in
11#     our installer.  Maybe also use cygcheck to get versions
12#     and see if we know what license those are under.
13#
14#  -  we don't have to do all the downloading of stuff here!
15#     cygwin has the packages we need already.
16
17
18# error out on failed commands whose return code wasn't explicitly
19# checked
20set -e
21
22AWK=${AWK:-awk}
23MAKE=${MAKE:-make}
24HOST="i686-w64-mingw32"
25
26usage() {
27cat << EOF
28
29$0 [options]
30
31Builds a non-cygwin version of pcb and create a standalone
32windows installer.
33
34Supported options:
35
36  --debug         - Omits the compiler flag which prevents
37                    a command window from being opened.  This
38                    is useful when trying to use debug printf's
39
40  --disable-doc   - Pass "--disable-doc" to the configure script.
41
42  --distcheck     - Run with --force-autogen and then build the
43                    distcheck target and exit.  This is generally
44                    only of interest for developers.
45
46  --enable-check  - enable the 'check' target after building.
47
48  --help          - Show this message and exit.
49
50  --host <host>   - Sets the host target.  [$HOST]
51
52  --force-autogen - Force running ./autogen.sh.  Normally this is
53                    only done if the configure script is not present.
54
55  --nsis-only     - Only run NSIS to create the installer.  This is
56                    shorthand for all of the following --skip-* options.
57
58  --skip-all      - Skip all steps of the process.
59
60  --skip-build    - Skip the "make" step of the process.
61
62  --skip-clean    - Skip the "make clean" step of the process.
63
64  --skip-config   - Skip the "./configure" step of the process.
65
66  --skip-deps     - Skip the "./configure" step of the process.
67
68  --skip-install  - Skip the "make install" step of the process.
69
70  --skip-dllinstall - Skip the step after "make install" that copies
71                    the run time DLLs to the staging area.
72
73  --with-make <gmake>
74		  - Set MAKE to the listed GNU make program
75
76  --with-tex      - Set TEX=tex
77
78  --with-etex     - set TEX=etex
79
80For the $0 script to work, you must have the gtk_win32 files
81as well as gdlib installed on your system in very specific
82locations.  Edit $0 to change these.  While you are at it, feel
83free to provide a patch to improve the documentation about
84those libraries.
85
86EOF
87}
88
89debug=no
90do_autogen=no
91do_config=yes
92do_build=yes
93do_check=no
94do_clean=yes
95do_deps=yes
96do_distcheck=no
97do_install=yes
98do_dllinstall=yes
99do_nsis=yes
100stop_after=none
101config_args=""
102tex_flag="TEX=tex"
103while test $# -ne 0 ; do
104	case $1 in
105		--debug)
106			debug=yes
107			shift
108			;;
109
110               --disable-doc)
111                       config_args="${config_args} --disable-doc"
112                       shift
113                       ;;
114
115		--distcheck)
116			do_autogen=yes
117			do_build=no
118			do_check=no
119			do_clean=no
120			do_config=no
121			do_deps=no
122			do_distcheck=yes
123			do_install=no
124			do_dllinstall=no
125			do_nsis=no
126			shift
127			;;
128
129		--enable-check)
130			do_check=yes
131			shift
132			;;
133
134		--help)
135			usage
136			exit 0
137			;;
138
139		--force-autogen)
140			do_autogen=yes
141			shift
142			;;
143
144		--host)
145			HOST=$2
146			shift 2
147			;;
148
149		--install-only)
150			do_build=no
151			do_clean=no
152			do_config=no
153			do_deps=no
154			do_install=yes
155			do_nsis=no
156			shift
157			;;
158
159		--nsis-only)
160			do_build=no
161			do_clean=no
162			do_config=no
163			do_deps=no
164			do_install=no
165			do_dllinstall=no
166			do_nsis=yes
167			shift
168			;;
169
170		--skip-all)
171			do_autogen=no
172			do_build=no
173			do_check=no
174			do_clean=no
175			do_config=no
176			do_deps=no
177			do_distcheck=no
178			do_install=no
179			do_dllinstall=no
180			do_nsis=no
181			shift
182			;;
183
184		--skip-build)
185			do_build=no
186			shift
187			;;
188
189		--skip-check)
190			do_check=no
191			shift
192			;;
193
194		--skip-clean)
195			do_clean=no
196			shift
197			;;
198
199		--skip-config)
200			do_config=no
201			shift
202			;;
203
204		--skip-deps)
205			do_deps=no
206			shift
207			;;
208
209		--skip-dllinstall)
210			do_dllinstall=no
211			shift
212			;;
213
214		--skip-install)
215			do_install=no
216			shift
217			;;
218
219		--skip-nsis)
220			do_nsis=no
221			shift
222			;;
223
224		--stop-after)
225			stop_after=$2
226			shift 2
227			;;
228
229		--with-etex)
230			tex_flag="TEX=etex"
231			shift
232			;;
233
234		--with-make)
235			MAKE="$2"
236			shift 2
237			;;
238
239		--with-tex)
240			tex_flag="TEX=tex"
241			shift
242			;;
243
244		-*)
245			echo "ERROR:  Unknown option $1"
246			usage
247			exit 1
248			;;
249
250		*)
251			break
252			;;
253	esac
254done
255
256# where only the runtime components are installed
257# oh, the joy of escaping...  \\ gets processed into \ by the
258# shell.  \\\\ gets processed into \\ by the shell and sed then
259# turns it into \.  So the big craziness is just to convert
260# a single \ into double \\ so when it later is stubstituted into
261# the pcb.nsi file we have single \.
262
263win32_runtime="/usr/$HOST/sys-root/mingw"
264win32_runtime_dos="`cygpath --windows ${win32_runtime} | sed 's;\\\\;\\\\\\\\;g'`"
265
266
267# pcb version
268
269if grep -q 'AC_INIT.*m4_esyscmd' ../configure.ac ; then
270	cat << EOF
271
272You appear to be building from git sources.  You may want to verify that
273the version extraction command in $0 matches the m4_esyscmd in the AC_INIT
274line of ../configure.ac.  They are shown here:
275EOF
276	grep 'AC_INIT.*m4_esyscmd' ../configure.ac /dev/null
277	awk '/git describe/ {if(p>0) {print} else { p = 1}}' $0 /dev/null
278	pcb_version=`git describe --abbrev=8 --always --tags | awk -F'-' '{printf "%s-%s", $1, $3}'`
279	slp=10
280else
281	pcb_version=`${AWK} '/AC_INIT/ {gsub(/.*,[ \t]*\[/, ""); gsub(/\]\).*/, ""); print}' ../configure.ac`
282	slp=0
283fi
284echo "pcb_version extracted from configure.ac = ${pcb_version}"
285
286# location of the NSIS makensis executible (see http://nsis.sourceforge.net)
287MAKENSIS="/cygdrive/c/Program Files (x86)/NSIS/makensis.exe"
288
289# where to install pcb
290pcb_inst=`pwd`/pcb_inst
291
292
293# DOS version
294pcb_inst_dos="`cygpath --windows ${pcb_inst} | sed 's;\\\\;\\\\\\\\;g'`"
295
296
297lic_inst=`pwd`/lic_inst
298lic_inst_dos="`cygpath --windows ${lic_inst}`"
299
300tmpdir="./tmpdir"
301mkdir -p -m 0700 $tmpdir
302rc=$?
303if test $rc -ne 0 ; then
304	echo "Couldn't generate secure temp directory"
305	exit 1
306fi
307tmp_sh="${tmpdir}/tmp.sh"
308${MAKE} -f pcb-win32-deps.mk DEPMK= config-variables > "${tmp_sh}"
309chmod 755 "${tmp_sh}"
310. "${tmp_sh}"
311rm "${tmp_sh}"
312
313
314
315if test "X${do_deps}" = "Xyes" ; then
316lic="${tmpdir}/license.tmp.1"
317lic2="${tmpdir}/license.tmp.2"
318if test -d "${lic_inst}" ; then
319       rm -fr "${lic_inst}"
320fi
321mkdir -p "${lic_inst}"
322
323echo "" > "${lic}"
324for f in setup/*.mk ; do
325	echo "Process $f"
326	#${MAKE} -f pcb-win32-deps.mk DEPMK=$f fetch
327	#${MAKE} -f pcb-win32-deps.mk DEPMK=$f checksum
328	#${MAKE} -f pcb-win32-deps.mk DEPMK=$f extract
329	#${MAKE} -f pcb-win32-deps.mk DEPMK=$f configure
330	#${MAKE} -f pcb-win32-deps.mk DEPMK=$f build
331	#${MAKE} -f pcb-win32-deps.mk DEPMK=$f install
332	${MAKE} -f pcb-win32-deps.mk DEPMK=$f show-license >> "${lic}"
333done
334
335sort "${lic}" > "${lic2}"
336
337lic_nsh=license_include.nsh
338echo "" > "${lic_nsh}"
339
340for l in `${AWK} '{print $1}' "${lic2}" | sort -u` ; do
341	lout="${lic_inst}/LICENSE-${l}"
342	echo "Creating ${lout}"
343cat << EOF > "${lout}"
344The following libraries are covered by the $l license:
345
346EOF
347	${AWK} '$1==lic {print $2}' lic=$l "${lic2}" >> "${lout}"
348cat << EOF >> "${lout}"
349
350-------------------------------------------------------------------
351EOF
352	cat licenses/LICENSE-${l} >> ${lout}
353cat << EOF >> ${lic_nsh}
354  !insertmacro MUI_PAGE_LICENSE "${lic_inst_dos}\LICENSE-${l}"
355EOF
356
357done
358fi
359
360
361if test ! -f ./build_pcb ; then
362	echo "$0:  ERROR.  This script must be run from the win32 level of the pcb source tree."
363	exit 1
364fi
365
366
367
368# ########################################################################
369#
370# The rest should be ok without editing
371#
372# ########################################################################
373
374check_stop() {
375	if test "X${stop_after}" = "X$1" ; then
376		echo "Exiting build because stop_after = ${stop_after}"
377		exit 0
378	fi
379}
380
381
382# source directory
383srcdir=`pwd.exe`
384top_srcdir=${srcdir}/..
385
386if test ! -f ../configure -o $do_autogen = yes ; then
387	echo "Bootstrapping autotools"
388	(cd .. && ./autogen.sh)
389fi
390check_stop autogen
391
392
393PKG_CONFIG=${HOST}-pkg-config
394
395#echo "Showing packages known to pkg-config (${PKG_CONFIG}:"
396#${PKG_CONFIG} --list-all
397
398
399# do not try and build the tk based QFP footprint
400# builder
401WISH=/usr/bin/true
402export WISH
403
404# add the gcc options to produce a native windows binary that
405# does not need cygwin to run
406if test "x${debug}" = "xno" ; then
407	EXTRA_FLAGS="-mwindows"
408fi
409
410CYGWIN_CFLAGS="-mms-bitfields ${EXTRA_FLAGS}"
411export CYGWIN_CFLAGS
412
413CYGWIN_CPPFLAGS="-mms-bitfields ${EXTRA_FLAGS}"
414export CYGWIN_CPPFLAGS
415
416cat << EOF
417
418PKG_CONFIG       =  ${PKG_CONFIG}
419PKG_CONFIG_PATH  =  ${PKG_CONFIG_PATH}
420
421EOF
422
423if test "$do_distcheck" = "yes" ; then
424	DISTCHECK_CONFIGURE_FLAGS="ac_cv_func_gdImageGif=yes ac_cv_func_gdImageJpeg=yes ac_cv_func_gdImagePng=yes"
425	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} --disable-dependency-tracking"
426	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} --disable-nls"
427	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} --disable-update-desktop-database"
428	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} --disable-update-mime-database"
429	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} --host ${HOST}"
430	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} CPPFLAGS=-DWIN32_LEAN_AND_MEAN"
431	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} WIN32=yes"
432	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} PCB_MAGIC_TEST_SKIP=yes"
433	DISTCHECK_CONFIGURE_FLAGS="${DISTCHECK_CONFIGURE_FLAGS} GERBV=/bin/true"
434	export DISTCHECK_CONFIGURE_FLAGS
435	WIN32=yes
436	export WIN32
437	PCB_MAGIC_TEST_SKIP=yes
438	export PCB_MAGIC_TEST_SKIP
439	echo "Distcheck for cygwin"
440	cd ${top_srcdir}
441	( ( ( \
442		${MAKE} distcheck
443		2>&1 ; echo $? >&4 ) | tee distcheck.log 1>&3) 4>&1 | (read a ; exit $a)) 3>&1
444
445	if test $? -ne 0 ; then
446		echo "**** ERROR **** Distcheck failed. See log in distcheck.log"
447		exit 1
448	fi
449
450	echo "Finished with distcheck, exiting."
451	exit 0
452fi
453
454
455# setting WIN32=yes will make sure that the desktop icon
456# gets compiled in
457if test "$do_config" = "yes" ; then
458	cd ${top_srcdir}
459
460	rm -fr src/.deps
461	echo "Configuring for cygwin"
462	( ( ( env WIN32=yes \
463		./configure \
464		--prefix=${pcb_inst} \
465		--docdir=${pcb_inst}/doc \
466		--pdfdir=${pcb_inst}/doc/pdf \
467		--htmldir=${pcb_inst}/doc/html \
468		--datadir=${pcb_inst}/share \
469		ac_cv_func_gdImageGif="yes" \
470		ac_cv_func_gdImageJpeg="yes" \
471		ac_cv_func_gdImagePng="yes" \
472		--disable-dependency-tracking \
473		--disable-nls \
474		--disable-update-desktop-database \
475		--disable-update-mime-database \
476		--host ${HOST} \
477		${config_args} \
478		CPPFLAGS="-DWIN32_LEAN_AND_MEAN" \
479		WIN32=yes \
480		2>&1 ; echo $? >&4 ) | tee c.log 1>&3) 4>&1 | (read a ; exit $a)) 3>&1
481
482	if test $? -ne 0 ; then
483		echo "**** ERROR **** Configure failed. See log in c.log"
484		exit 1
485	fi
486	check_stop config
487
488
489	if test "$do_clean" = "yes" ; then
490		cd ${top_srcdir}
491		echo "Cleaning"
492		( ( ( ${MAKE} clean 2>&1 ; echo $? >&4) | tee clean.log 1>&3) 4>&1 | (read a ; exit $a) ) 3>&1
493		if test $? -ne 0 ; then
494			echo "**** ERROR **** Clean failed. See log in clean.log"
495			exit 1
496		fi
497	fi
498	check_stop clean
499fi
500check_stop config
501check_stop clean
502
503if test "$do_build" = "yes" ; then
504	cd ${top_srcdir}
505	echo "Building for cygwin"
506	( ( ( ${MAKE} $tex_flag PCB="../src/pcbtest.bat"  2>&1 ; echo $? >&4) | tee m.log 1>&3) 4>&1 | (read a ; exit $a) ) 3>&1
507	if test $? -ne 0 ; then
508		echo "**** ERROR **** Build failed. See log in m.log"
509		exit 1
510	fi
511fi
512check_stop build
513
514if test "$do_check" = "yes" ; then
515	cd ${top_srcdir}
516	echo "Building for cygwin"
517	( ( ( ${MAKE} check PCB="../../src/pcbtest.bat"  2>&1 ; echo $? >&4) | tee check.log 1>&3) 4>&1 | (read a ; exit $a) ) 3>&1
518	if test $? -ne 0 ; then
519		echo "**** ERROR **** Build failed. See log in check.log"
520		exit 1
521	fi
522fi
523check_stop check
524
525if test "$do_install" = "yes" ; then
526	cd ${top_srcdir}
527	echo "Installing for cygwin"
528	# first clean out the installation directory to make sure
529	# we don't have old junk lying around.
530	if test -d ${pcb_inst} ; then
531		rm -fr ${pcb_inst}
532	fi
533	( ( ( ${MAKE} install 2>&1 ; echo $? >&4) | tee -a m.log 1>&3) 4>&1 | (read a ; exit $a) ) 3>&1
534	if test $? -ne 0 ; then
535		echo "**** ERROR **** Build failed. See log in m.log"
536		exit 1
537	fi
538	echo "Finished with install target.  Proceeding to runtime DLL install".
539fi
540check_stop install
541
542if test "$do_dllinstall" = "yes" ; then
543	cd ${srcdir}
544
545	# $ cygcheck -l mingw64-i686-jasper | grep "mingw/bin"
546	# /usr/i686-w64-mingw32/sys-root/mingw/bin/libjasper.dll
547
548	echo "Extracting runtime DLL list."
549	dll_list=""
550	for pkg in `${AWK} '/^[ \t]*$/ {next} {print $1}' mingw_required_pkgs` ; do
551		# grep won't always find something and this script has 'set -e'
552		# which will cause the script to quit if grep doesn't find anything
553		dll_add=`cygcheck -l ${pkg} | grep 'bin/.*\.dll$' || true`
554		bin_add=`cygcheck -l ${pkg} | grep 'bin/gdk-pixbuf-query-loaders.exe$' || true`
555		if test -n "${dll_add}"  -o -n "${bin_add}" ; then
556			for dll in ${dll_add} ${bin_add} ; do
557				dll_base="`basename ${dll}`"
558				dll_list="${dll_list} ${dll_base}"
559			done
560		fi
561	done
562
563	echo "Copying runtime libraries to staging area"
564	for f in ${dll_list} ; do
565		echo "${win32_runtime}/bin/${f} > ${pcb_inst}/bin/${f}"
566		cp "${win32_runtime}/bin/${f}" "${pcb_inst}/bin/${f}"
567	done
568
569	mkdir -p "${pcb_inst}/lib${pcb_inst}/lib"
570	cp -r "${win32_runtime}/lib/gdk-pixbuf-2.0"  "${pcb_inst}/lib/"
571fi
572check_stop dllinstall
573
574##########################################################################
575#
576# Create DOS batch file wrapper to allow running
577# the staged program before running the installer
578#
579
580bat=test_pcb.bat
581cat << EOF
582
583Creating DOS batch file wrapper to test the built
584pcb which has been installed into the staging
585area ${pcb_inst}.
586
587To test pcb before installing:
588
589./${bat}
590
591EOF
592
593win32_runtime_dos1="`cygpath --windows ${win32_runtime}`"
594
595cat > ${bat} << EOF
596
597PATH=${win32_runtime_dos1}\bin:%PATH%
598
599
600EOF
601cygpath --windows ${pcb_inst}/bin/pcb >> ${bat}
602
603chmod 755 ${bat}
604
605##########################################################################
606#
607# Build the installer
608#
609
610if test "$do_nsis" = "yes" ; then
611	cat << EOF
612
613Creating NSIS script
614
615srcdir = ${srcdir}
616src_dir = ${src_dir}
617top_srcdir = ${top_srcdir}
618top_src_dir = ${top_src_dir}
619
620win32_runtime     = ${win32_runtime}
621win32_runtime_dos = ${win32_runtime_dos}
622
623pcb_inst              = ${pcb_inst}
624pcb_inst_dos          = ${pcb_inst_dos}
625
626EOF
627
628	docdir="${pcb_inst}/doc"
629	readme="${docdir}/Readme.txt"
630	# git doesn't seem to appreciate a CRLF terminated file so build the
631	# DOS version on the fly
632	test -d "${docdir}" || mkdir -p "${docdir}"
633	${AWK} '{printf("%s\r\n", $0)}' Readme.txt > "${readme}"
634
635	sed \
636		-e "s;@pcb_version@;${pcb_version};g" \
637		-e "s;@pcb_prefix@;${pcb_inst_dos};g" \
638		-e "s;@pcb_srcdir@;${top_src_dir};g" \
639		-e "s;@gtk_win32_runtime_dos@;${win32_runtime_dos};g" \
640		${srcdir}/pcb.nsi.in > ${srcdir}/pcb.nsi
641
642	echo "Creating windows installer"
643	"${MAKENSIS}" pcb.nsi
644
645	echo "Windows installer left in ${srcdir}:"
646	ls -l ${srcdir}/*.exe
647
648##########################################################################
649#
650# Create DOS batch file wrapper around the installer
651#
652	bat=run_install.bat
653
654	cat << EOF
655
656Creating DOS batch file wrapper for the installer.
657If you have just built this under cygwin on Vista,
658you will need to either run the installer from
659the Vista start menu, Windows explorer or directly from
660the cygwin shell with
661
662./${bat}
663
664EOF
665
666	cat > ${bat} << EOF
667
668.\pcbinst-${pcb_version}.exe
669
670EOF
671
672	chmod 755 ${bat}
673
674fi
675
676
677##########################################################################
678#
679# Cleanup and exit
680#
681
682if test -d "${tmpdir}" ; then
683	rm -fr "${tmpdir}"
684fi
685