]> gitweb.factorcode.org Git - factor.git/blob - build-support/factor.sh
Merge branch 'master' into experimental
[factor.git] / build-support / factor.sh
1 #!/usr/bin/env bash
2
3 # Programs returning != 0 will not cause script to exit
4 set +e
5
6 # Case insensitive string comparison
7 shopt -s nocaseglob
8 #shopt -s nocasematch
9
10 ECHO=echo
11 OS=
12 ARCH=
13 WORD=
14 NO_UI=
15 GIT_PROTOCOL=${GIT_PROTOCOL:="git"}
16 GIT_URL=${GIT_URL:=$GIT_PROTOCOL"://factorcode.org/git/factor.git"}
17
18 test_program_installed() {
19     if ! [[ -n `type -p $1` ]] ; then
20         return 0;
21     fi
22     return 1;
23 }
24
25 ensure_program_installed() {
26     installed=0;
27     for i in $* ;
28     do
29         $ECHO -n "Checking for $i..."
30         test_program_installed $i
31         if [[ $? -eq 0 ]]; then
32             echo -n "not "
33         else    
34             installed=$(( $installed + 1 ))
35         fi
36         $ECHO "found!"
37     done
38     if [[ $installed -eq 0 ]] ; then
39         $ECHO -n "Install "
40         if [[ $# -eq 1 ]] ; then
41             $ECHO -n $1
42         else
43             $ECHO -n "any of [ $* ]"
44         fi
45         $ECHO " and try again."
46         exit 1
47     fi
48 }
49
50 check_ret() {
51     RET=$?
52     if [[ $RET -ne 0 ]] ; then
53        $ECHO $1 failed
54        exit 2
55     fi
56 }
57
58 check_gcc_version() {
59     $ECHO -n "Checking gcc version..."
60     GCC_VERSION=`$CC --version`
61     check_ret gcc
62     if [[ $GCC_VERSION == *3.3.* ]] ; then
63         $ECHO "You have a known buggy version of gcc (3.3)"
64         $ECHO "Install gcc 3.4 or higher and try again."
65         exit 3
66     elif [[ $GCC_VERSION == *4.3.* ]] ; then
67        MAKE_OPTS="$MAKE_OPTS SITE_CFLAGS=-fno-forward-propagate"
68     fi
69     $ECHO "ok."
70 }
71
72 set_downloader() {
73     test_program_installed wget curl
74     if [[ $? -ne 0 ]] ; then
75         DOWNLOADER=wget
76     else
77         DOWNLOADER="curl -O"
78     fi
79 }
80
81 set_md5sum() {
82     test_program_installed md5sum
83     if [[ $? -ne 0 ]] ; then
84         MD5SUM=md5sum
85     else
86         MD5SUM="md5 -r"
87     fi
88 }
89
90 set_gcc() {
91     case $OS in
92         openbsd) ensure_program_installed egcc; CC=egcc;;
93         *) CC=gcc;;
94     esac
95 }
96
97 set_make() {
98     case $OS in
99         netbsd) MAKE='gmake';;
100         freebsd) MAKE='gmake';;
101         openbsd) MAKE='gmake';;
102         dragonflybsd) MAKE='gmake';;
103         *) MAKE='make';;
104     esac
105     if ! [[ $MAKE -eq 'gmake' ]] ; then
106         ensure_program_installed gmake
107     fi
108 }
109
110 check_installed_programs() {
111     ensure_program_installed chmod
112     ensure_program_installed uname
113     ensure_program_installed git
114     ensure_program_installed wget curl
115     ensure_program_installed gcc
116     ensure_program_installed make gmake
117     ensure_program_installed md5sum md5
118     ensure_program_installed cut
119     check_gcc_version
120 }
121
122 check_library_exists() {
123     GCC_TEST=factor-library-test.c
124     GCC_OUT=factor-library-test.out
125     $ECHO -n "Checking for library $1..."
126     $ECHO "int main(){return 0;}" > $GCC_TEST
127     $CC $GCC_TEST -o $GCC_OUT -l $1
128     if [[ $? -ne 0 ]] ; then
129         $ECHO "not found!"
130         $ECHO "Warning: library $1 not found."
131         $ECHO "***Factor will compile NO_UI=1"
132         NO_UI=1
133     fi
134     $DELETE -f $GCC_TEST
135     check_ret $DELETE
136     $DELETE -f $GCC_OUT
137     check_ret $DELETE
138     $ECHO "found."
139 }
140
141 check_X11_libraries() {
142     check_library_exists freetype
143     check_library_exists GLU
144     check_library_exists GL
145     check_library_exists X11
146 }
147
148 check_libraries() {
149     case $OS in
150             linux) check_X11_libraries;;
151     esac
152 }
153
154 check_factor_exists() {
155     if [[ -d "factor" ]] ; then
156         $ECHO "A directory called 'factor' already exists."
157         $ECHO "Rename or delete it and try again."
158         exit 4
159     fi
160 }
161
162 find_os() {
163     if [[ -n $OS ]] ; then return; fi
164     $ECHO "Finding OS..."
165     uname_s=`uname -s`
166     check_ret uname
167     case $uname_s in
168         CYGWIN_NT-5.2-WOW64) OS=winnt;;
169         *CYGWIN_NT*) OS=winnt;;
170         *CYGWIN*) OS=winnt;;
171         *darwin*) OS=macosx;;
172         *Darwin*) OS=macosx;;
173         *linux*) OS=linux;;
174         *Linux*) OS=linux;;
175         *NetBSD*) OS=netbsd;;
176         *FreeBSD*) OS=freebsd;;
177         *OpenBSD*) OS=openbsd;;
178         *DragonFly*) OS=dragonflybsd;;
179         SunOS) OS=solaris;;
180     esac
181 }
182
183 find_architecture() {
184     if [[ -n $ARCH ]] ; then return; fi
185     $ECHO "Finding ARCH..."
186     uname_m=`uname -m`
187     check_ret uname
188     case $uname_m in
189        i386) ARCH=x86;;
190        i686) ARCH=x86;;
191        i86pc) ARCH=x86;;
192        amd64) ARCH=x86;;
193        ppc64) ARCH=ppc;;
194        *86) ARCH=x86;;
195        *86_64) ARCH=x86;;
196        "Power Macintosh") ARCH=ppc;;
197     esac
198 }
199
200 write_test_program() {
201     echo "#include <stdio.h>" > $C_WORD.c
202     echo "int main(){printf(\"%d\", 8*sizeof(void*)); return 0; }" >> $C_WORD.c
203 }
204
205 c_find_word_size() {
206     $ECHO "Finding WORD..."
207     C_WORD=factor-word-size
208     write_test_program
209     gcc -o $C_WORD $C_WORD.c
210     WORD=$(./$C_WORD)
211     check_ret $C_WORD
212     $DELETE -f $C_WORD*
213 }
214
215 intel_macosx_word_size() {
216     ensure_program_installed sysctl
217     $ECHO -n "Testing if your Intel Mac supports 64bit binaries..."
218     sysctl machdep.cpu.extfeatures | grep EM64T >/dev/null
219     if [[ $? -eq 0 ]] ; then
220         WORD=64
221         $ECHO "yes!"
222     else
223         WORD=32
224         $ECHO "no."
225     fi
226 }
227
228 find_word_size() {
229     if [[ -n $WORD ]] ; then return; fi
230     if [[ $OS == macosx && $ARCH == x86 ]] ; then
231         intel_macosx_word_size
232     else
233         c_find_word_size
234     fi
235 }
236
237 set_factor_binary() {
238     case $OS in
239         winnt) FACTOR_BINARY=factor-console.exe;;
240         *) FACTOR_BINARY=factor;;
241     esac
242 }
243
244 set_factor_library() {
245     case $OS in
246         winnt) FACTOR_LIBRARY=factor.dll;;
247         macosx) FACTOR_LIBRARY=libfactor.dylib;;
248         *) FACTOR_LIBRARY=libfactor.a;;
249     esac
250 }
251
252 set_factor_image() {
253     FACTOR_IMAGE=factor.image
254 }
255
256 echo_build_info() {
257     $ECHO OS=$OS
258     $ECHO ARCH=$ARCH
259     $ECHO WORD=$WORD
260     $ECHO FACTOR_BINARY=$FACTOR_BINARY
261     $ECHO FACTOR_LIBRARY=$FACTOR_LIBRARY
262     $ECHO FACTOR_IMAGE=$FACTOR_IMAGE
263     $ECHO MAKE_TARGET=$MAKE_TARGET
264     $ECHO BOOT_IMAGE=$BOOT_IMAGE
265     $ECHO MAKE_IMAGE_TARGET=$MAKE_IMAGE_TARGET
266     $ECHO GIT_PROTOCOL=$GIT_PROTOCOL
267     $ECHO GIT_URL=$GIT_URL
268     $ECHO DOWNLOADER=$DOWNLOADER
269     $ECHO CC=$CC
270     $ECHO MAKE=$MAKE
271     $ECHO COPY=$COPY
272     $ECHO DELETE=$DELETE
273 }
274
275 check_os_arch_word() {
276     if ! [[ -n $OS && -n $ARCH && -n $WORD ]] ; then
277         $ECHO "OS: $OS"
278         $ECHO "ARCH: $ARCH"
279         $ECHO "WORD: $WORD"
280         $ECHO "OS, ARCH, or WORD is empty.  Please report this."
281
282         echo $MAKE_TARGET
283         exit 5
284     fi
285 }
286
287 set_build_info() {
288     check_os_arch_word
289     if [[ $OS == macosx && $ARCH == ppc ]] ; then
290         MAKE_IMAGE_TARGET=macosx-ppc
291         MAKE_TARGET=macosx-ppc
292     elif [[ $OS == linux && $ARCH == ppc ]] ; then
293         MAKE_IMAGE_TARGET=linux-ppc
294         MAKE_TARGET=linux-ppc
295     elif [[ $OS == winnt && $ARCH == x86 && $WORD == 64 ]] ; then
296         MAKE_IMAGE_TARGET=winnt-x86.64
297         MAKE_TARGET=winnt-x86-64
298     elif [[ $ARCH == x86 && $WORD == 64 ]] ; then
299         MAKE_IMAGE_TARGET=unix-x86.64
300         MAKE_TARGET=$OS-x86-64
301     else
302         MAKE_IMAGE_TARGET=$ARCH.$WORD
303         MAKE_TARGET=$OS-$ARCH-$WORD
304     fi
305     BOOT_IMAGE=boot.$MAKE_IMAGE_TARGET.image
306 }
307
308 parse_build_info() {
309     ensure_program_installed cut
310     $ECHO "Parsing make target from command line: $1"
311     OS=`echo $1 | cut -d '-' -f 1`
312     ARCH=`echo $1 | cut -d '-' -f 2`
313     WORD=`echo $1 | cut -d '-' -f 3`
314     
315     if [[ $OS == linux && $ARCH == ppc ]] ; then WORD=32; fi
316     if [[ $OS == linux && $ARCH == arm ]] ; then WORD=32; fi
317     if [[ $OS == macosx && $ARCH == ppc ]] ; then WORD=32; fi
318     if [[ $OS == wince && $ARCH == arm ]] ; then WORD=32; fi
319     
320     $ECHO "OS=$OS"
321     $ECHO "ARCH=$ARCH"
322     $ECHO "WORD=$WORD"
323 }
324
325 find_build_info() {
326     find_os
327     find_architecture
328     find_word_size
329     set_factor_binary
330     set_factor_library
331     set_factor_image
332     set_build_info
333     set_downloader
334     set_gcc
335     set_make
336     echo_build_info
337 }
338
339 invoke_git() {
340     git $*
341     check_ret git
342 }
343
344 git_clone() {
345     echo "Downloading the git repository from factorcode.org..."
346     invoke_git clone $GIT_URL
347 }
348
349 git_pull_factorcode() {
350     echo "Updating the git repository from factorcode.org..."
351     invoke_git pull $GIT_URL master
352 }
353
354 cd_factor() {
355     cd factor
356     check_ret cd
357 }
358
359 set_copy() {
360     case $OS in
361         winnt) COPY=cp;;
362         *) COPY=cp;;
363     esac
364 }
365
366 set_delete() {
367     case $OS in
368         winnt) DELETE=rm;;
369         *) DELETE=rm;;
370     esac
371 }
372
373 backup_factor() {
374     $ECHO "Backing up factor..."
375     $COPY $FACTOR_BINARY $FACTOR_BINARY.bak
376     $COPY $FACTOR_LIBRARY $FACTOR_LIBRARY.bak
377     $COPY $BOOT_IMAGE $BOOT_IMAGE.bak
378     $COPY $FACTOR_IMAGE $FACTOR_IMAGE.bak
379     $ECHO "Done with backup."
380 }
381
382 check_makefile_exists() {
383     if [[ ! -e "Makefile" ]] ; then
384         echo ""
385         echo "***Makefile not found***"
386         echo "You are likely in the wrong directory."
387         echo "Run this script from your factor directory:"
388         echo "     ./build-support/factor.sh"
389         exit 6
390     fi
391 }
392
393 invoke_make() {
394     check_makefile_exists
395     $MAKE $MAKE_OPTS $*
396     check_ret $MAKE
397 }
398
399 make_clean() {
400     invoke_make clean
401 }
402
403 make_factor() {
404     invoke_make NO_UI=$NO_UI $MAKE_TARGET -j5
405 }
406
407 update_boot_images() {
408     echo "Deleting old images..."
409     $DELETE checksums.txt* > /dev/null 2>&1
410         # delete boot images with one or two characters after the dot
411     $DELETE $BOOT_IMAGE.{?,??} > /dev/null 2>&1
412     $DELETE temp/staging.*.image > /dev/null 2>&1
413     if [[ -f $BOOT_IMAGE ]] ; then
414         get_url http://factorcode.org/images/latest/checksums.txt
415         factorcode_md5=`cat checksums.txt|grep $BOOT_IMAGE|cut -f2 -d' '`;
416         set_md5sum
417         case $OS in
418              netbsd) disk_md5=`md5 $BOOT_IMAGE | cut -f4 -d' '`;;
419              *) disk_md5=`$MD5SUM $BOOT_IMAGE|cut -f1 -d' '` ;;
420         esac
421         echo "Factorcode md5: $factorcode_md5";
422         echo "Disk md5: $disk_md5";
423         if [[ "$factorcode_md5" == "$disk_md5" ]] ; then
424             echo "Your disk boot image matches the one on factorcode.org."
425         else
426             $DELETE $BOOT_IMAGE > /dev/null 2>&1
427             get_boot_image;
428         fi
429     else
430         get_boot_image
431     fi
432 }
433
434 get_boot_image() {
435     echo "Downloading boot image $BOOT_IMAGE."
436     get_url http://factorcode.org/images/latest/$BOOT_IMAGE
437 }
438
439 get_url() {
440     if [[ $DOWNLOADER -eq "" ]] ; then
441         set_downloader;
442     fi
443     echo $DOWNLOADER $1 ;
444     $DOWNLOADER $1
445     check_ret $DOWNLOADER
446 }
447
448 maybe_download_dlls() {
449     if [[ $OS == winnt ]] ; then
450         get_url http://factorcode.org/dlls/freetype6.dll
451         get_url http://factorcode.org/dlls/zlib1.dll
452         get_url http://factorcode.org/dlls/OpenAL32.dll
453         get_url http://factorcode.org/dlls/alut.dll
454         get_url http://factorcode.org/dlls/comerr32.dll
455         get_url http://factorcode.org/dlls/gssapi32.dll
456         get_url http://factorcode.org/dlls/iconv.dll
457         get_url http://factorcode.org/dlls/k5sprt32.dll
458         get_url http://factorcode.org/dlls/krb5_32.dll
459         get_url http://factorcode.org/dlls/libcairo-2.dll
460         get_url http://factorcode.org/dlls/libeay32.dll
461         get_url http://factorcode.org/dlls/libiconv2.dll
462         get_url http://factorcode.org/dlls/libintl3.dll
463         get_url http://factorcode.org/dlls/libpq.dll
464         get_url http://factorcode.org/dlls/libxml2.dll
465         get_url http://factorcode.org/dlls/libxslt.dll
466         get_url http://factorcode.org/dlls/msvcr71.dll
467         get_url http://factorcode.org/dlls/ogg.dll
468         get_url http://factorcode.org/dlls/pgaevent.dll
469         get_url http://factorcode.org/dlls/sqlite3.dll
470         get_url http://factorcode.org/dlls/ssleay32.dll
471         get_url http://factorcode.org/dlls/theora.dll
472         get_url http://factorcode.org/dlls/vorbis.dll
473         chmod 777 *.dll
474         check_ret chmod
475     fi
476 }
477
478 get_config_info() {
479     find_build_info
480     check_installed_programs
481     check_libraries
482 }
483
484 bootstrap() {
485     ./$FACTOR_BINARY -i=$BOOT_IMAGE
486 }
487
488 install() {
489     check_factor_exists
490     get_config_info
491     git_clone
492     cd_factor
493     make_factor
494     get_boot_image
495     maybe_download_dlls
496     bootstrap
497 }
498
499
500 update() {
501     get_config_info
502     git_pull_factorcode
503     backup_factor
504     make_clean
505     make_factor
506 }
507
508 update_bootstrap() {
509     update_boot_images
510     bootstrap
511 }
512
513 refresh_image() {
514     ./$FACTOR_BINARY -script -e="USE: vocabs.loader USE: system refresh-all USE: memory save 0 exit"
515     check_ret factor
516 }
517
518 make_boot_image() {
519     ./$FACTOR_BINARY -script -e="\"$MAKE_IMAGE_TARGET\" USE: system USE: bootstrap.image make-image save 0 exit"
520     check_ret factor
521
522 }
523
524 install_build_system_apt() {
525     sudo apt-get --yes install libc6-dev libfreetype6-dev libx11-dev xorg-dev glutg3-dev wget git-core git-doc rlwrap gcc make
526     check_ret sudo
527 }
528
529 install_build_system_port() {
530     test_program_installed git
531     if [[ $? -ne 1 ]] ; then
532         ensure_program_installed yes
533         echo "git not found."
534         echo "This script requires either git-core or port."
535         echo "If it fails, install git-core or port and try again."
536         ensure_program_installed port
537         echo "Installing git-core with port...this will take awhile."
538         yes | sudo port install git-core
539     fi
540 }
541
542 usage() {
543     echo "usage: $0 install|install-x11|install-macosx|self-update|quick-update|update|bootstrap|dlls|net-bootstrap|make-target|report [optional-target]"
544     echo "If you are behind a firewall, invoke as:"
545     echo "env GIT_PROTOCOL=http $0 <command>"
546     echo ""
547     echo "Example for overriding the default target:"
548     echo "    $0 update macosx-x86-32"
549 }
550
551 MAKE_TARGET=unknown
552
553 # -n is nonzero length, -z is zero length
554 if [[ -n "$2" ]] ; then
555     parse_build_info $2
556 fi
557
558 set_copy
559 set_delete
560
561 case "$1" in
562     install) install ;;
563     install-x11) install_build_system_apt; install ;;
564     install-macosx) install_build_system_port; install ;;
565     self-update) update; make_boot_image; bootstrap;;
566     quick-update) update; refresh_image ;;
567     update) update; update_bootstrap ;;
568     bootstrap) get_config_info; bootstrap ;;
569     report) find_build_info ;;
570     dlls) get_config_info; maybe_download_dlls;;
571     net-bootstrap) get_config_info; update_boot_images; bootstrap ;;
572     make-target) ECHO=false; find_build_info; echo $MAKE_TARGET ;;
573     *) usage ;;
574 esac