1#!/bin/sh -e
2
3##########################################################################
4#   Script description:
5#       Bootstrap a FreeBSD ports tree under any prefix
6#
7#   History:
8#   Date        Name        Modification
9#   2016-10-11  Jason Bacon Begin
10##########################################################################
11
12##########################################################################
13#   FIXME:
14#       perl5-5.24.1_1 installed as perl5.24-5.24.1_1 on first attempt.
15#           Why did it work properly the second time?
16#       ruby-2.3.4,1 couldn't find it's own shared lib
17#           Added ${PREFIX}/lib to LD_LIBRARY_PATH in module
18#           Using $PREFIX/sbin/ldconfig does not work
19#       Some ports assume root priveleges
20#           Try USES+=uidfix
21#           May also need USES+=fakeroot
22##########################################################################
23
24usage()
25{
26    printf "Usage: $0\n"
27    exit 1
28}
29
30
31##########################################################################
32#   Main
33##########################################################################
34
35if [ $# != 0 ]; then
36    usage
37fi
38
39export PATH=${PATH}:/usr/local/sbin:/usr/local/bin
40
41case $(auto-ostype) in
42FreeBSD)
43    if [ `whoami` = root ]; then
44	default_prefix=/sharedapps
45	printf "auto-ports-setup is not well-tested.  Running as root may harm your system.\n"
46	printf "Continue? y/[n] "
47	read cont
48	if [ 0$cont != 0y ]; then
49	    exit
50	fi
51    else
52	default_prefix=$HOME/Ports
53    fi
54
55    # PATH will be scrubbed during setup
56    auto_append_line=`which auto-append-line`
57
58    # Make sure things are readable when they should be
59    umask 022
60
61    # Determine paths
62    printf "Installation prefix? [$default_prefix] "
63    read prefix
64    if [ 0$prefix = 0 ]; then
65	prefix=$default_prefix
66    fi
67
68    snapshot=''
69    while [ 0$snapshot != 01 ] && [ 0$snapshot != 02 ]; do
70	cat << EOM
71
721.. Install quarterly snapshot
732.. Install latest ports (head)
74
75EOM
76	printf "Selection? "
77	read snapshot
78	case $snapshot in
79	1)
80	    printf "Year? "
81	    read year
82	    printf "Quarter? "
83	    read quarter
84	    snapshot_suffix=${year}Q$quarter
85	    ;;
86
87	2)
88	    snapshot_suffix=`date +%Y-%m-%d`
89	    ;;
90	esac
91    done
92
93    printf "\nAdd -$snapshot_suffix to installation directories? [y]/n "
94    read add_suffix
95    if [ 0$add_suffix = 0n ]; then
96	ports_dir="$prefix/ports"
97	install_dir="$prefix/local"
98    else
99	ports_dir="$prefix/ports-$snapshot_suffix"
100	install_dir="$prefix/local-$snapshot_suffix"
101    fi
102
103    if [ -e $install_dir ]; then
104	printf "$install_dir already exists.  Overwrite? y/[n] "
105	read overwrite
106	if [ 0$overwrite != 0y ]; then
107	    exit
108	fi
109    fi
110
111    cat << EOM
112
113============================================================================
114Packages will be installed under
115
116    $install_dir
117    
118Frameworks for building and installing will be under
119
120    $ports_dir
121
122System files will be under
123
124    $install_dir/var
125
126============================================================================
127EOM
128
129    printf "Add -march=native to all builds? y/[n] "
130    read native
131
132    printf "Proceed? [y]/n "
133    read proceed
134    if [ 0$proceed = 0n ]; then
135	exit
136    fi
137
138    mkdir -p $install_dir/etc $install_dir/var/run
139
140    # Start clean
141    unset CC CFLAGS CPP CPPFLAGS CXX CXXFLAGS FC FFLAGS LD LDFLAGS LD_LIBRARY_PATH
142    PATH=/usr/bin:/usr/sbin:/bin:/sbin
143    export PATH
144    git=/usr/local/bin/git
145
146    # Download ports snapshot
147    if [ ! -e $ports_dir/Makefile ]; then
148	if [ 0$year != 0 ]; then
149	    $git clone https://git.FreeBSD.org/ports.git \
150		-b ${year}Q$quarter $ports_dir
151	else
152	    checkout=''
153	    while [ 0$checkout != 01 ] && [ 0$checkout != 02 ]; do
154		cat << EOM
155
1561.. Use portsnap
1572.. Use subversion
158
159EOM
160		printf "Selection? "
161		read checkout
162	    done
163	    case $checkout in
164	    1)
165		# Generate portsnap.conf
166		mkdir -p $install_dir/var/db/portsnap
167		printf "Generating $install_dir/etc/portsnap.conf...\n"
168		sed -e "s|# PORTSDIR=.*|PORTSDIR=$ports_dir|" \
169		    -e "s|# WORKDIR=.*|WORKDIR=$install_dir/var/db/portsnap|" \
170		    /etc/portsnap.conf > $install_dir/etc/portsnap.conf
171		portsnap -f $install_dir/etc/portsnap.conf fetch extract
172		;;
173	    2)
174		$git clone https://git.FreeBSD.org/ports.git $ports_dir
175		;;
176	    esac
177	fi
178    else
179	cat << EOM
180
181$ports_dir already populated.
182
183Remove $ports_dir/Makefile and run again to override.
184
185EOM
186    fi
187
188    etcdir=$install_dir/etc
189    mkdir -p $etcdir
190    if [ 0$native = 0y ]; then
191	for flags in CFLAGS CXXFLAGS FFLAGS; do
192	    $auto_append_line $flags "$flags+=-march=native" $install_dir/etc/make.conf $0
193	done
194    fi
195
196    ##########################################################################
197    #   Generate sh rc scripts
198    ##########################################################################
199
200    printf "Generating $etcdir/ports.sh...\n"
201    cat << EOM > $etcdir/ports.sh
202
203unset CC CFLAGS CPP CPPFLAGS CXX CXXFLAGS FC FFLAGS LD LDFLAGS LD_LIBRARY_PATH
204
205PORTS=$install_dir
206PORTS_INCLUDE=$install_dir/include
207PORTS_LIB=$install_dir/lib
208
209# Redirect port builds
210PORTSDIR=$ports_dir
211LOCALBASE=$install_dir
212PORT_DBDIR=$install_dir/var/db/ports
213PKG_DBDIR=$install_dir/var/db/pkg
214PKG_CACHEDIR=$install_dir/var/cache/pkg
215PKG_PLUGINS_DIR=$install_dir/lib/pkg
216PLUGINS_CONF_DIR=$install_dir/etc/pkg
217REPOS_DIR=$install_dir/etc/pkg/repos
218INSTALL_AS_USER=yes
219LDCONFIG=$install_dir/sbin/ldconfig
220
221# FIXME: Needed for ruby.  Why?
222LD_LIBRARY_PATH=$install_dir/lib:/usr/lib:/lib
223
224# Remove /usr/local from PATH for dependencies that use "which"
225PATH=$install_dir/bin:$install_dir/sbin:/bin:/sbin:/usr/bin:/usr/sbin
226MANPATH=$install_dir/man:/usr/share/man
227
228export PORTS PORTS_INCLUDE PORTS_LIB PORTSDIR LOCALBASE PORT_DBDIR PKG_DBDIR \
229    PKG_CACHEDIR PKG_PLUGINS_DIR PLUGINS_CONF_DIR REPOS_DIR INSTALL_AS_USER \
230    LDCONFIG LD_LIBRARY_PATH PATH MANPATH
231EOM
232
233    printf "Generating $etcdir/ports-non-exclusive.sh...\n"
234    cat << EOM > $etcdir/ports-non-exclusive.sh
235    
236    unset CC CFLAGS CPP CPPFLAGS CXX CXXFLAGS FC FFLAGS LD LDFLAGS LD_LIBRARY_PATH
237    
238    PORTS=$install_dir
239    PORTS_INCLUDE=$install_dir/include
240    PORTS_LIB=$install_dir/lib
241    
242    # Redirect port builds
243    PORTSDIR=$ports_dir
244    LOCALBASE=$install_dir
245    PORT_DBDIR=$install_dir/var/db/ports
246    PKG_DBDIR=$install_dir/var/db/pkg
247    PKG_CACHEDIR=$install_dir/var/cache/pkg
248    PKG_PLUGINS_DIR=$install_dir/lib/pkg
249    PLUGINS_CONF_DIR=$install_dir/etc/pkg
250    REPOS_DIR=$install_dir/etc/pkg/repos
251    INSTALL_AS_USER=yes
252    LDCONFIG=$install_dir/sbin/ldconfig
253    
254    # FIXME: Needed for ruby.  Why?
255    LD_LIBRARY_PATH=$install_dir/lib:/usr/lib:/lib
256    
257    # Remove /usr/local from PATH for dependencies that use "which"
258    PATH=$install_dir/bin:$install_dir/sbin:\$PATH
259    MANPATH=$install_dir/man:/usr/local/man:/usr/share/man
260    
261    export PORTS PORTS_INCLUDE PORTS_LIB PORTSDIR LOCALBASE PORT_DBDIR PKG_DBDIR \
262	PKG_CACHEDIR PKG_PLUGINS_DIR PLUGINS_CONF_DIR REPOS_DIR INSTALL_AS_USER \
263	LDCONFIG LD_LIBRARY_PATH PATH MANPATH
264    
265    cat << EOW
266
267==============================================================================
268WARNING:
269
270ports-non-exclusive.sh allows programs and libraries that are not part of
271this ports tree or the base system to remain in PATH and LD_LIBRARY_PATH.
272This may cause some programs to malfunction.
273
274DO NOT USE ports-non-exclusive.sh while building ports!!!
275
276Use with caution when running programs from $install_dir.
277==============================================================================
278
279EOW
280EOM
281
282    ##########################################################################
283    #   Generate csh rc scripts
284    ##########################################################################
285
286    printf "Generating $etcdir/ports.csh...\n"
287    cat << EOM > $etcdir/ports.csh
288
289unsetenv CC CFLAGS CPP CPPFLAGS CXX CXXFLAGS FC FFLAGS LD LDFLAGS LD_LIBRARY_PATH
290
291setenv          PORTS               $install_dir
292setenv          PORTS_INCLUDE       $install_dir/include
293setenv          PORTS_LIB           $install_dir/lib
294
295# Redirect port builds
296setenv          PORTSDIR            $ports_dir
297setenv          LOCALBASE           $install_dir
298setenv          PORT_DBDIR          $install_dir/var/db/ports
299setenv          PKG_DBDIR           $install_dir/var/db/pkg
300setenv          PKG_CACHEDIR        $install_dir/var/cache/pkg
301setenv          PKG_PLUGINS_DIR     $install_dir/lib/pkg
302setenv          PLUGINS_CONF_DIR    $install_dir/etc/pkg
303setenv          REPOS_DIR           $install_dir/etc/pkg/repos
304setenv          INSTALL_AS_USER     yes
305setenv          LDCONFIG            $install_dir/sbin/ldconfig
306
307# FIXME: Needed for ruby.  Why?
308setenv          LD_LIBRARY_PATH     $install_dir/lib:/usr/lib:/lib
309
310# Remove /usr/local from PATH for dependencies that use "which"
311setenv          PATH                $install_dir/bin:$install_dir/sbin:/bin:/sbin:/usr/bin:/usr/sbin
312setenv          MANPATH             $install_dir/man:/usr/share/man
313EOM
314
315    printf "Generating $etcdir/ports-non-exclusive.csh...\n"
316    cat << EOM > $etcdir/ports-non-exclusive.csh
317
318unsetenv CC CFLAGS CPP CPPFLAGS CXX CXXFLAGS FC FFLAGS LD LDFLAGS LD_LIBRARY_PATH
319
320setenv          PORTS               $install_dir
321setenv          PORTS_INCLUDE       $install_dir/include
322setenv          PORTS_LIB           $install_dir/lib
323
324# Redirect port builds
325setenv          PORTSDIR            $ports_dir
326setenv          LOCALBASE           $install_dir
327setenv          PORT_DBDIR          $install_dir/var/db/ports
328setenv          PKG_DBDIR           $install_dir/var/db/pkg
329setenv          PKG_CACHEDIR        $install_dir/var/cache/pkg
330setenv          PKG_PLUGINS_DIR     $install_dir/lib/pkg
331setenv          PLUGINS_CONF_DIR    $install_dir/etc/pkg
332setenv          REPOS_DIR           $install_dir/etc/pkg/repos
333setenv          INSTALL_AS_USER     yes
334setenv          LDCONFIG            $install_dir/sbin/ldconfig
335
336# FIXME: Needed for ruby.  Why?
337setenv          LD_LIBRARY_PATH     $install_dir/lib:/usr/lib:/lib
338
339# Remove /usr/local from PATH for dependencies that use "which"
340setenv          PATH                $install_dir/bin:$install_dir/sbin:\$PATH
341setenv          MANPATH             $install_dir/man:/usr/local/man:/usr/share/man
342
343cat << EOW
344
345==============================================================================
346WARNING:
347
348ports-non-exclusive.csh allows programs and libraries that are not part of
349this ports tree or the base system to remain in PATH and LD_LIBRARY_PATH.
350This may cause some programs to malfunction.
351
352DO NOT USE ports-non-exclusive.csh while building ports!!!
353
354Use with caution when running programs from $install_dir.
355==============================================================================
356
357EOW
358EOM
359
360    ##########################################################################
361    #   Generate module files
362    ##########################################################################
363
364    modules_dir=$install_dir/etc/modulefiles/ports
365    mkdir -p $modules_dir
366
367    printf "Generating $modules_dir/$snapshot_suffix...\n"
368    cat << EOM > $modules_dir/$snapshot_suffix
369#%Module1.0#####################################################################
370proc ModulesHelp { } {
371    puts stdout "\n\tAll software installed via the FreeBSD ports in"
372    puts stdout "\t$ports_dir"
373    puts stdout "\tThis module prepends the ports directories to"
374    puts stdout "\tappropriate environment variable(s)."
375}
376
377module-whatis   "All software installed via FreeBSD ports in $ports_dir"
378
379set     version         $snapshot_suffix
380set     ports_dir       $ports_dir
381set     install_dir     $install_dir
382
383prepend-path    MODULEPATH          \$install_dir/etc/modulefiles
384
385unsetenv        CC
386unsetenv        CFLAGS
387unsetenv        CPP
388unsetenv        CPPFLAGS
389unsetenv        CXX
390unsetenv        CXXFLAGS
391unsetenv        FC
392unsetenv        FFLAGS
393unsetenv        LD
394unsetenv        LDFLAGS
395unsetenv        LD_LIBRARY_PATH
396
397setenv          PORTS               \$install_dir
398setenv          PORTS_INCLUDE       \$install_dir/include
399setenv          PORTS_LIB           \$install_dir/lib
400
401# Redirect port builds
402setenv          PORTSDIR            \$ports_dir
403setenv          LOCALBASE           \$install_dir
404setenv          PORT_DBDIR          \$install_dir/var/db/ports
405setenv          PKG_DBDIR           \$install_dir/var/db/pkg
406setenv          PKG_CACHEDIR        \$install_dir/var/cache/pkg
407setenv          PKG_PLUGINS_DIR     \$install_dir/lib/pkg
408setenv          PLUGINS_CONF_DIR    \$install_dir/etc/pkg
409setenv          REPOS_DIR           \$install_dir/etc/pkg/repos
410setenv          INSTALL_AS_USER     yes
411setenv          LDCONFIG            \$install_dir/sbin/ldconfig
412
413# FIXME: Needed for ruby.  Why?
414setenv          LD_LIBRARY_PATH     \$install_dir/lib:/usr/lib:/lib
415
416# Remove /usr/local from PATH for dependencies that use "which"
417setenv          PATH                \$install_dir/bin:\$install_dir/sbin:/bin:/sbin:/usr/bin:/usr/sbin
418setenv          MANPATH             \$install_dir/man:/usr/share/man
419EOM
420
421    printf "Generating $modules_dir/$snapshot_suffix-non-exclusive...\n"
422    cat << EOM > $modules_dir/$snapshot_suffix-non-exclusive
423#%Module1.0#####################################################################
424proc ModulesHelp { } {
425    puts stdout "\n\tAll software installed via the FreeBSD ports in"
426    puts stdout "\t$ports_dir"
427    puts stdout "\tThis module prepends the ports directories to"
428    puts stdout "\tappropriate environment variable(s)."
429}
430
431module-whatis   "All software installed via FreeBSD ports in $ports_dir"
432
433puts stderr "\n======================================================================"
434puts stderr "WARNING:\n"
435puts stderr "ports/${snapshot_suffix#-}-non-exclusive allows programs and libraries"
436puts stderr "that are not part of this pkgsrc tree or the base system to remain in"
437puts stderr "PATH and LD_LIBRARY_PATH.  This may cause some programs to malfunction."
438puts stderr "======================================================================\n"
439
440set     version         $snapshot_suffix
441set     ports_dir       $ports_dir
442set     install_dir     $install_dir
443
444prepend-path    MODULEPATH          \$install_dir/etc/modulefiles
445
446unsetenv        CC
447unsetenv        CFLAGS
448unsetenv        CPP
449unsetenv        CPPFLAGS
450unsetenv        CXX
451unsetenv        CXXFLAGS
452unsetenv        FC
453unsetenv        FFLAGS
454unsetenv        LD
455unsetenv        LDFLAGS
456unsetenv        LD_LIBRARY_PATH
457
458setenv          PORTS               \$install_dir
459setenv          PORTS_INCLUDE       \$install_dir/include
460setenv          PORTS_LIB           \$install_dir/lib
461
462# Redirect port builds
463setenv          PORTSDIR            \$ports_dir
464setenv          LOCALBASE           \$install_dir
465setenv          PORT_DBDIR          \$install_dir/var/db/ports
466setenv          PKG_DBDIR           \$install_dir/var/db/pkg
467setenv          PKG_CACHEDIR        \$install_dir/var/cache/pkg
468setenv          PKG_PLUGINS_DIR     \$install_dir/lib/pkg
469setenv          PLUGINS_CONF_DIR    \$install_dir/etc/pkg
470setenv          REPOS_DIR           \$install_dir/etc/pkg/repos
471setenv          INSTALL_AS_USER     yes
472setenv          LDCONFIG            \$install_dir/sbin/ldconfig
473
474# FIXME: Needed for ruby.  Why?
475setenv          LD_LIBRARY_PATH     \$install_dir/lib:/usr/lib:/lib
476
477# Remove /usr/local from PATH for dependencies that use "which"
478prepend-path    PATH                \$install_dir/bin:\$install_dir/sbin
479setenv          MANPATH             \$install_dir/man:/usr/local/man:/usr/share/man
480EOM
481
482# May need something like this to avoid picking up /usr/local/lib
483# Wrapping ldconfig below seems to take care of ports that use ldconfig,
484# but what about the rest?
485# setenv          LD_LIBRARY_PATH     \$install_dir/lib:/usr/lib:/lib
486
487# Wrap ldconfig to allow non-root owned directories
488mkdir -p $install_dir/sbin
489    printf "Generating $install_dir/sbin/ldconfig...\n"
490    cat << EOM > $install_dir/sbin/ldconfig
491
492/sbin/ldconfig -i -f $install_dir/var/run/ld-elf.so.hints \$@
493EOM
494    chmod 755 $install_dir/sbin/ldconfig
495
496    # Set default LDCONFIG in port make fragments
497    sed -i '' "s|LDCONFIG?=.*/sbin/ldconfig|LDCONFIG?= $install_dir/sbin/ldconfig|g" \
498	$ports_dir/Mk/bsd.commands.mk
499
500    # FIXME: Patch other critical variables into .mk files to protect against
501    # env corruption.  PKG_DBDIR, ...
502
503    # Preload standard lib directories into hints file
504    $install_dir/sbin/ldconfig -m /lib /usr/lib
505
506    . $install_dir/etc/ports.sh
507    printenv
508    cd $ports_dir/ports-mgmt/pkg
509    make deinstall || true
510    make -DBATCH reinstall
511
512    # Test for sqlite issue with NFS.  If lock file left behind after install,
513    # remove it and adjust pkg.conf to use an NFS-safe locking mechanism.
514    if [ -d $install_dir/var/db/pkg/local.sqlite.lock ]; then
515	rmdir $install_dir/var/db/pkg/local.sqlite.lock
516	printf "NFS_WITH_PROPER_LOCKING=yes\n" >> $install_dir/etc/pkg.conf
517    fi
518    ;;
519
520*)
521    auto-unsupported-os $0
522    exit 1
523    ;;
524
525esac
526