#!/usr/bin/perl -w =head1 NAME dh_illumos_gate - unpack and prepare illumos sources =cut use strict; use Debian::Debhelper::Dh_Lib; use Dpkg::Changelog::Parse; use Cwd; =head1 SYNOPSIS B [S>] [options] [-- [tar options]] [files and/or directories to extract] =head1 DESCRIPTION C is responsible for unpacking illumos sources and adjusting the sources for Debian build environment (paths to programs, command options, linker and compiler flags, etc.). C extracts given files or directories, if any. Otherwise it extracts entire F. In any case B<-X> option can be used to exclude some files or directories, and top directory F is always stripped.. If files interested to C are unpacked they will be configured. See L. After executing C one can use commands like this to configure or build components of illumos gate: ksh93 usr/bldenv.sh usr/env.sh -c "cd usr/src/lib/libzfs && make --sun install" L provides more convenient way to do this. =head1 OPTIONS =over 4 =item B<-B> B<--build> Extract files known to be required for building illumos components. These are F, F, F. If any file under F is requested, F are extracted too. Same for F. This option is provided only for convenience. You are free to extract these files explicitly. =item B<-X>I B<--exclude=>I Do not extract files or directories matching I. This option can be used multiple times. I is passed as is to L via I<--exclude=PATTERN>. =item B<-D>I B<--destdir=>I Copy all extracted files into this directory, and make any changes in there instead of the current directory. =item B<--create-orig> Create I<.orig> tarball. =back =head1 EXAMPLES =over 4 =item Unpack and configure the whole illumos source tree (F) dh_illumos_gate =item Unpack and configure whole illumos source tree, but F dh_illumos_gate -X usr/src/uts =item Unpack and configure whole illumos source tree, but F; then add F dh_illumos_gate -X usr/src/uts dh_illumos_gate usr/src/uts/common/sys =item Unpack all Makefiles under F dh_illumos_gate usr/src/Makefile\* =item Unpack all header files under F dh_illumos_gate -- --wildcards-match-slash usr/src/uts/*.h =item Create source tarball out of F excluding F<*.mf> files dh_illumos_gate --create-orig usr/src/cmd -X*.mf =back =head1 FILES =over 4 =item /usr/src/illumos-gate/illumos-gate-$(VER).tar.xz This file contains complete and unmodified illumos sources. It is provided by package I. Version C<$(VER)> is determined from F: (\d+\.\d+).* => \1, e. g.: 2.10+3 => VER = 2.10 =back =head1 DETAILS Here are things which this helper does after unpacking illumos sources. =over 4 =cut $dh{DESTDIR} = '.'; init( options => { 'build|B' => \$dh{BUILD}, 'destdir|D=s' => \$dh{DESTDIR}, 'create-orig' => \$dh{CREATE_ORIG}, } ); my %options = ( file => 'debian/changelog' ); my $changelog = changelog_parse(%options); my $version = $changelog->{'Version'}; my $cwd = getcwd(); my @tar_X = (); if ( defined( $dh{'EXCLUDE'} ) && $dh{'EXCLUDE'} ) { foreach my $x ( @{ $dh{'EXCLUDE'} } ) { push @tar_X, '--exclude'; push @tar_X, $x; } } if ( $dh{CREATE_ORIG} ) { my $source = $changelog->{'Source'}; my $source_version = $version =~ s!^(.*)-[^-]+$!$1!r; my $tarball = "$cwd/../${source}_${source_version}.orig.tar.xz"; my $base = "$source-$source_version"; doit( 'tar', '-c', '-J', '--owner', '0', '--group', '0', '--mode', 'u=rwX,go=rX', '--transform', "s,^,$base/,", '-f', $tarball, @tar_X, @ARGV ); exit; } else { my $ver; if ( $version =~ /^(\d+(\.\d+)+(\.git\w+)?).*$/ ) { $ver = $1; } else { error( "Could not determine illumos source version from changelog. " . "It should be like 5.10.6.gitXYZ+1, but it is '$version'" ); } my $tarball = "/usr/src/illumos-gate/illumos-gate-$ver.tar.xz"; if ( !-f $tarball ) { error( "$tarball does not exist. You might not have package illumos-source-$ver " . "installed or have a typo in debian/changelog" ); } my @to_extract = (); if (@ARGV) { if ( $dh{'BUILD'} ) { push @to_extract, ( 'usr/src/Makefile*', 'usr/src/common/mapfiles', 'usr/src/tools/scripts/bldenv.sh', ); if ( grep { m|.*usr/src/lib/.*| } @ARGV ) { push @to_extract, 'usr/src/lib/Makefile*'; } if ( grep { m|.*usr/src/cmd/.*| } @ARGV ) { push @to_extract, 'usr/src/cmd/Makefile*'; } } push @to_extract, map { m,(?:illumos-gate/)?(.*),; $1 } @ARGV; } else { push @to_extract, 'usr'; } my @to_extract_real = (); foreach my $p (@to_extract) { if ( $p =~ /^-/ ) { push @to_extract_real, $p; #XXX: tar option } else { push @to_extract_real, 'illumos-gate/' . $p; #XXX: path } } doit( 'mkdir', '-p', $dh{DESTDIR} ); doit( 'tar', '-C', $dh{DESTDIR}, '-x', '-f', $tarball, @tar_X, '--wildcards', '--strip-components=1', @to_extract_real ); } =item Saving original files Any files from illumos sources, changed by this helper, are saved with F<.orig> suffix, so you can investigate changes. For example, you can use C to see all changes. =cut =item Changes to F (if extracted): Remove option C<-s> (strip) from install command for directories and files. This options does not make sense for directories and GNU L is not tolerant here. Also replace option C<-f> with C<-t>. Append C with C<-m32> since native host compiler can produce 64-bit code by default. Explicitly undefine some CPP macros related to amd64 for building 32-bit objects, e. i. options like C<-U__amd64> are appended to C and C. C flags are appended to C command. Delete (set to empty) variable C, cause we are not using shared lex library (F), but static Flex library (libl.a). In variables C and C replace variables C<$(CTFSTABS)> and C<$(CTFCONVERT)> with explicit F and F, because those variables are empty when building without CTF, but creating offsets really requires CTF data. This is used when compiling libc and illumos kernel. =cut my $multiarch = `dpkg-architecture -qDEB_HOST_MULTIARCH`; chomp $multiarch; my $bits = `dpkg-architecture -qDEB_HOST_ARCH_BITS`; chomp $bits; # In illumos source 32-bit binaries are default my ( $libdir32, $libdir64, $usrlibdir32, $usrlibdir64 ); if ( $bits == 64 ) { $libdir32 = "lib32"; $usrlibdir32 = "usr/$libdir32"; $libdir64 = "lib/$multiarch"; $usrlibdir64 = "usr/$libdir64"; } else { $libdir32 = "lib/$multiarch"; $usrlibdir32 = "usr/$libdir32"; $libdir64 = "lib64"; $usrlibdir64 = "usr/$libdir64"; } my $Makefile_master = $dh{DESTDIR} . '/usr/src/Makefile.master'; my $Makefile_master_orig = $Makefile_master . '.orig'; if ( -f $Makefile_master ) { if ( !-e $Makefile_master_orig ) { doit( 'cp', '-f', $Makefile_master, $Makefile_master_orig ); } # Be careful with modern CPP: my $i386_undef = '-Uamd64 -U__amd64 -U__amd64__ -U__x86_64__ -U__x86_64 -U_LP64'; doit( 'sed', '-r', '-i', ' /^INS\.(file|dir)/ s, -s,,; /^INS\.file/ s, -f, -t,; /^i386_XARCH\s*=/s,$, -m32 ' . $i386_undef . ',; /^i386_AS_XARCH\s*=/s,$, ' . $i386_undef . ',; /^COMPILE\.s/s,$, $($(MACH)_AS_XARCH),; /^MAPFILE.LEX/d; /^OFFSETS_CREATE/ s,\$\(CTFSTABS\),ctfstabs,; /^OFFSETS_CREATE/ s,\$\(CTFCONVERT\),ctfconvert,; ', $Makefile_master ); } =item Changes to F (if extracted): Append C to C command, because C by default uses C compiler to create shared library. Set C, C, C and C to match Debian multiarch layout. For example C = F and C = F on I. It cannot be done in environment file F (see below), because in some cases C will be overriden by C within makefiles. =cut my $Makefile_lib = $dh{DESTDIR} . '/usr/src/lib/Makefile.lib'; my $Makefile_lib_orig = $Makefile_lib . '.orig'; if ( -f $Makefile_lib ) { if ( !-e $Makefile_lib_orig ) { doit( 'cp', '-f', $Makefile_lib, $Makefile_lib_orig ); } doit( 'sed', '-r', '-i', ' /^BUILD.SO/ s,\$\(CC\),$(CC) $(CFLAGS),; ', $Makefile_lib ); doit( 'sed', '-r', '-i', " s,^(ROOTFS_LIBDIR)\\s*=.*,\\1=\$(ROOT)/$libdir32,; s,^(ROOTFS_LIBDIR64)\\s*=.*,\\1=\$(ROOT)/$libdir64,; s,^(ROOTLIBDIR)\\s*=.*,\\1=\$(ROOT)/$usrlibdir32,; s,^(ROOTLIBDIR64)\\s*=.*,\\1=\$(ROOT)/$usrlibdir64,; ", $Makefile_lib ); } =item Changes to F (if extracted): Remove trailing spaces in the line C Maybe we should patch GNU make to do it for us in SunOS mode. Remove linker flag for setting ELF interpreter (-Wl,-I/lib/ld.so.1) =cut my $Makefile_cmd = $dh{DESTDIR} . '/usr/src/cmd/Makefile.cmd'; my $Makefile_cmd_orig = $Makefile_cmd . '.orig'; if ( -f $Makefile_cmd ) { if ( !-e $Makefile_cmd_orig ) { doit( 'cp', '-f', $Makefile_cmd, $Makefile_cmd_orig ); } doit( 'sed', '-r', '-i', ' /^TEXT_DOMAIN/ s,\s+$,,g; ', $Makefile_cmd ); doit( 'sed', '-r', '-i', ' /LDFLAGS\s*\+=\s*-Wl,-I\/lib\/ld\.so\.1/d; ', $Makefile_cmd ); } =item Create F (if F exists and F does not) Set C to the current directry. Set C from F<./debian/changelog>. For example it can be C<2.10-3>. Set C=F to call L instead of GNU L. Default system GCC is build to use GNU L, but L is required to build most illumos components. See L. Set proto area to be F<./debian/tmp>. Disable linting libraries by replacing C with ":". So it will do nothing. Successfully. Also define C to empty string to prevent installation of lint libraries (which do not exist). Disable modifying comment section of ELFs by replacing C with ":". Disable stripping by replacing C with ":". Enable GCC and GCC4 mode by defining C<__GNUC> and C<__GNUC4>. Change GCC root to F, so the default system compiler is used. Define C to be C. Export all C variables (using C) to make them available from makefiles. =cut chdir $dh{DESTDIR}; my $codemgr_ws = getcwd(); chdir $cwd; my $env = $dh{DESTDIR} . '/usr/env.sh'; my $mach = `uname -p`; chomp $mach; if ( open( ENV, '>', $env ) ) { print ENV "# This file was generated by dh_illumos_gate(1)\n"; print ENV "export VERSION='$version'\n"; print ENV "export CODEMGR_WS='$codemgr_ws'\n"; print ENV "export ROOT='$cwd/debian/tmp'\n"; print ENV "export SRC='$codemgr_ws/usr/src'\n"; print ENV "export MULTI_PROTO='no'\n"; print ENV "export CW_NO_SHADOW=1\n"; print ENV "export LD_ALTEXEC='/usr/bin/ld-gnu-to-sun'\n"; print ENV "export BUILD_TOOLS='/opt'\n"; print ENV "export MACH='$mach'\n"; print ENV "export LINT=:\n"; print ENV "export LINTLIB=''\n"; print ENV "export __GNUC=''\n"; print ENV "export __GNUC4=''\n"; print ENV "export GCC_ROOT='/usr'\n"; print ENV "export CW_GCC=gcc\n"; print ENV "export SAVEARGS=\n"; print ENV "export LEX='/usr/bin/flex -l'\n"; print ENV "export STRIP=':'\n"; print ENV "export MCS=':'\n"; print ENV "export DEB_LIBDIR_32='/$libdir32'\n"; print ENV "export DEB_USRLIBDIR_32='/$usrlibdir32'\n"; print ENV "export DEB_LIBDIR_64='/$libdir64'\n"; print ENV "export DEB_USRLIBDIR_64='/$usrlibdir64'\n"; print ENV "export LDLIBS32=\"-L\$ROOT/\$DEB_LIBDIR_32 -L\$ROOT/\$DEB_USRLIBDIR_32\"\n"; print ENV "export LDLIBS64=\"-L\$ROOT/\$DEB_LIBDIR_64 -L\$ROOT/\$DEB_USRLIBDIR_64\"\n"; print ENV 'export LDLIBS_NATIVE="', ( $bits == 64 ) ? '$LDLIBS64' : '$LDLIBS32', "\"\n"; print ENV `dpkg-architecture -s`; close(ENV); } else { error("Failed to write `$env': $!"); } =item Create F (if not exists and F extracted) Copy F to F. Fix definition of C variables, so this script will not override them if they are already defined. These variables can be set to ":", when executing L with option C<--without-ctf>. =cut my $bldenv_sh_orig = $dh{DESTDIR} . '/usr/src/tools/scripts/bldenv.sh'; my $bldenv_sh = $dh{DESTDIR} . '/usr/bldenv.sh'; if ( -f $bldenv_sh_orig ) { doit( 'cp', '-f', $bldenv_sh_orig, $bldenv_sh ); doit( 'sed', '-r', '-i', ' s,export +(CTF.+)="(.+)",export \1="${\1:-\2}",; s,^PATH=".+",PATH="${PATH}:/opt/onbld/bin:/opt/onbld/bin/${MACH}:.",; ', $bldenv_sh ); } =back =head1 NOTES To clean package (via C<./debian/rules clean>) you should just remove F directory: rm -rf usr C will fail if extracting files which should be extracted due to option C<--build>. This is a L issue (tar: ...: Not found in archive). For example, this will fail: dh_illumos_gate --build usr/src/cmd usr/src/lib/Makefile.lib Workaround: dh_illumos_gate --build usr/src/cmd dh_illumos_gate usr/src/lib/Makefile.lib =head1 SEE ALSO L, L. =head1 AUTHOR Igor Pashev =cut