]> git.saurik.com Git - apt.git/commitdiff
support DEB_BUILD_PROFILES and -P for build profiles
authorDavid Kalnischkies <david@kalnischkies.de>
Tue, 25 Feb 2014 13:26:18 +0000 (14:26 +0100)
committerDavid Kalnischkies <david@kalnischkies.de>
Thu, 13 Mar 2014 12:58:44 +0000 (13:58 +0100)
Inspired by the rest of the patch in 661537, but abstract the
parsing of various ways of setting the build profiles more so it can
potentially be reused and all apt parts have the same behaviour.

Especially config options, cmdline options and environment will not be
combined as proposed as this isn't APTs usual behaviour and dpkg doesn't
do it either, so one overrides the other as it normally does.

apt-pkg/aptconfiguration.cc
apt-pkg/aptconfiguration.h
apt-pkg/deb/deblistparser.cc
apt-private/private-cmndline.cc
cmdline/apt-config.cc
cmdline/apt-get.cc
debian/control
doc/apt-get.8.xml
doc/apt.conf.5.xml
test/integration/framework
test/integration/test-bug-661537-build-profiles-support [new file with mode: 0755]

index f5c758e14524ac7d8a5c34c40d4dba90c2455e5c..3948854c66496c9b683c315a3d87b14f606a0209 100644 (file)
@@ -426,7 +426,7 @@ void Configuration::setDefaultConfigurationForCompressors() {
        }
 }
                                                                        /*}}}*/
-// getCompressors - Return Vector of usbale compressors                        /*{{{*/
+// getCompressors - Return Vector of usealbe compressors               /*{{{*/
 // ---------------------------------------------------------------------
 /* return a vector of compressors used by apt-ftparchive in the
    multicompress functionality or to detect data.tar files */
@@ -508,4 +508,28 @@ Configuration::Compressor::Compressor(char const *name, char const *extension,
                UncompressArgs.push_back(uncompressArg);
 }
                                                                        /*}}}*/
+// getBuildProfiles - return a vector of enabled build profiles                /*{{{*/
+std::vector<std::string> const Configuration::getBuildProfiles() {
+       // order is: override value (~= commandline), environment variable, list (~= config file)
+       std::string profiles_env = getenv("DEB_BUILD_PROFILES") == 0 ? "" : getenv("DEB_BUILD_PROFILES");
+       if (profiles_env.empty() == false) {
+               profiles_env = SubstVar(profiles_env, " ", ",");
+               std::string const bp = _config->Find("APT::Build-Profiles");
+               _config->Clear("APT::Build-Profiles");
+               if (bp.empty() == false)
+                       _config->Set("APT::Build-Profiles", bp);
+       }
+       return _config->FindVector("APT::Build-Profiles", profiles_env);
+}
+std::string const Configuration::getBuildProfilesString() {
+       std::vector<std::string> profiles = getBuildProfiles();
+       if (profiles.empty() == true)
+               return "";
+       std::vector<std::string>::const_iterator p = profiles.begin();
+       std::string list = *p;
+       for (; p != profiles.end(); ++p)
+          list.append(",").append(*p);
+       return list;
+}
+                                                                       /*}}}*/
 }
index bf7deae85698e48cc6aeddcdb0db4209e9a1bcc9..026493c6df40a560c9ab9a67967da72a39960b6b 100644 (file)
@@ -117,6 +117,11 @@ public:                                                                    /*{{{*/
 
        /** \brief Return a vector of extensions supported for data.tar's */
        std::vector<std::string> static const getCompressorExtensions();
+
+       /** \return Return a vector of enabled build profile specifications */
+       std::vector<std::string> static const getBuildProfiles();
+       /** \return Return a comma-separated list of enabled build profile specifications */
+       std::string static const getBuildProfilesString();
                                                                        /*}}}*/
        private:                                                        /*{{{*/
        void static setDefaultConfigurationForCompressors();
index a4795f15d95923ec722185da230a7c35efc38316..89f3514c942c32ff5bb9cc847637737fdf25ed11 100644 (file)
@@ -625,7 +625,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
         if (unlikely(I == Stop))
            return 0;
 
-        std::vector<string> const profiles = _config->FindVector("APT::Build-Profiles");
+        std::vector<string> const profiles = APT::Configuration::getBuildProfiles();
 
         const char *End = I;
         bool Found = false;
index ef7d65f3c59de7fec88efe2943fa94ccd873e417..b99443210d313b7957b34a7a901c0ca7a0dfe350 100644 (file)
@@ -141,6 +141,7 @@ bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const * const
    {
       addArg('b', "compile", "APT::Get::Compile", 0);
       addArg('b', "build", "APT::Get::Compile", 0);
+      addArg('P', "build-profiles", "APT::Build-Profiles", CommandLine::HasArg);
       addArg(0, "diff-only", "APT::Get::Diff-Only", 0);
       addArg(0, "debian-only", "APT::Get::Diff-Only", 0);
       addArg(0, "tar-only", "APT::Get::Tar-Only", 0);
@@ -149,6 +150,7 @@ bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const * const
    else if (CmdMatches("build-dep"))
    {
       addArg('a', "host-architecture", "APT::Get::Host-Architecture", CommandLine::HasArg);
+      addArg('P', "build-profiles", "APT::Build-Profiles", CommandLine::HasArg);
       addArg(0, "purge", "APT::Get::Purge", 0);
       addArg(0, "solver", "APT::Solver", CommandLine::HasArg);
       // this has no effect *but* sbuild is using it (see LP: #1255806)
index 30c2a22d578089bf1e530f3ae37fc4646e51a067..9f20b3c1b40097b9c1c2f03cadfb7a6699968629 100644 (file)
@@ -155,6 +155,11 @@ int main(int argc,const char *argv[])                                      /*{{{*/
         _config->Set(comp + "UncompressArg::", *a);
    }
 
+   std::vector<std::string> const profiles = APT::Configuration::getBuildProfiles();
+   _config->Clear("APT::Build-Profiles");
+   for (std::vector<std::string>::const_iterator p = profiles.begin(); p != profiles.end(); ++p)
+      _config->Set("APT::Build-Profiles::", *p);
+
    // Match the operation
    CmdL.DispatchArg(Cmds);
    
index 12e385b69557d8f3e371dab7b6b2484fd0ba9ab4..f8de80a91c40a75f40b471705a66633ff44f3d56 100644 (file)
@@ -970,6 +970,12 @@ bool DoSource(CommandLine &CmdL)
            string buildopts = _config->Find("APT::Get::Host-Architecture");
            if (buildopts.empty() == false)
               buildopts = "-a" + buildopts + " ";
+
+           // get all active build profiles
+           std::string const profiles = APT::Configuration::getBuildProfilesString();
+           if (profiles.empty() == false)
+              buildopts.append(" -P").append(profiles).append(" ");
+
            buildopts.append(_config->Find("DPkg::Build-Options","-b -uc"));
 
            // Call dpkg-buildpackage
index 2d58d0711918fd9d2ae519e9488a31b2a2d87810..5ce68414e63bc80ce9c5582670761e1cc29d2c01 100644 (file)
@@ -21,7 +21,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${apt:keyring}, gnupg
 Replaces: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~)
 Breaks: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~)
 Conflicts: python-apt (<< 0.7.93.2~)
-Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, python-apt
+Suggests: aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), apt-doc, python-apt
 Description: commandline package manager
  This package provides commandline tools for searching and
  managing as well as querying information about packages
index 595ea875d05f15219e17fde9593c3de35aff8ad7..1ed08904e9ad60078c680ae45758190f8dfc7d62 100644 (file)
      by <command>apt-get source --compile</command> and how cross-builddependencies
      are satisfied. By default is it not set which means that the host architecture
      is the same as the build architecture (which is defined by <literal>APT::Architecture</literal>).
-     Configuration Item: <literal>APT::Get::Host-Architecture</literal>
+     Configuration Item: <literal>APT::Get::Host-Architecture</literal>.
+     </para></listitem>
+     </varlistentry>
+
+     <varlistentry><term><option>-P</option></term>
+                   <term><option>--build-profiles</option></term>
+     <listitem><para>This option controls the activated build profiles for which
+     a source package is built by <command>apt-get source --compile</command> and
+     how build dependencies are satisfied. By default no build profile is active.
+     More than one build profile can be activated at a time by concatenating them
+     with a comma.
+     Configuration Item: <literal>APT::Build-Profiles</literal>.
      </para></listitem>
      </varlistentry>
 
index bfc43ba29fa4c240b26b81a0e50e95301352e5f3..78f6a27a26823efe5d2f0447e126cb5b3b8fa509 100644 (file)
@@ -177,6 +177,15 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      </para></listitem>
      </varlistentry>
 
+     <varlistentry><term><option>Build-Profiles</option></term>
+     <listitem><para>
+     List of all build profiles enabled for build-dependency resolution,
+     without the "<literal>profile.</literal>" namespace prefix.
+     By default this list is empty. The <envar>DEB_BUILD_PROFILES</envar>
+     as used by &dpkg-buildpackage; overrides the list notation.
+     </para></listitem>
+     </varlistentry>
+
      <varlistentry><term><option>Default-Release</option></term>
      <listitem><para>Default release to install packages from if more than one
      version is available. Contains release name, codename or release version. Examples: 'stable', 'testing',
index 911a4d7429292763fbd3fc6ed577932ff06f82c9..9c4ac87d3ec007355492a8c4dab546369b6245a5 100644 (file)
@@ -120,6 +120,9 @@ aptwebserver() {
 dpkg() {
        command dpkg --root=${TMPWORKINGDIRECTORY}/rootdir --force-not-root --force-bad-path --log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log "$@"
 }
+dpkgcheckbuilddeps() {
+       command dpkg-checkbuilddeps --admindir=${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg "$@"
+}
 aptitude() {
        if [ -f ./aptconfig.conf ]; then
                APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY}  command aptitude "$@"
@@ -240,6 +243,9 @@ setupenvironment() {
        # newer gpg versions are fine without it, but play it safe for now
        gpg --quiet --check-trustdb --secret-keyring $SECRETKEYRING --keyring $SECRETKEYRING >/dev/null 2>&1
 
+       # cleanup the environment a bit
+       unset GREP_OPTIONS DEB_BUILD_PROFILES
+
        msgdone "info"
 }
 
diff --git a/test/integration/test-bug-661537-build-profiles-support b/test/integration/test-bug-661537-build-profiles-support
new file mode 100755 (executable)
index 0000000..ae1403f
--- /dev/null
@@ -0,0 +1,147 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64' 'i386' 'armel'
+
+insertinstalledpackage 'build-essential' 'all' '0' 'Multi-Arch: foreign'
+
+insertpackage 'unstable' 'foo' 'all' '1.0'
+insertpackage 'unstable' 'bar' 'all' '1.0'
+
+insertsource 'unstable' 'buildprofiles' 'any' '1' 'Build-Depends: foo (>= 1.0) [i386 arm] <!profile.stage1 !profile.cross>, bar'
+
+# table from https://wiki.debian.org/BuildProfileSpec
+insertsource 'unstable' 'spec-1' 'any' '1' 'Build-Depends: foo <!profile.stage1>'
+insertsource 'unstable' 'spec-2' 'any' '1' 'Build-Depends: foo <profile.stage1>'
+insertsource 'unstable' 'spec-3' 'any' '1' 'Build-Depends: foo <!profile.stage1 !profile.notest>'
+insertsource 'unstable' 'spec-4' 'any' '1' 'Build-Depends: foo <profile.stage1 profile.notest>'
+insertsource 'unstable' 'spec-5' 'any' '1' 'Build-Depends: foo <!profile.stage1 profile.notest>'
+insertsource 'unstable' 'spec-6' 'any' '1' 'Build-Depends: foo <profile.stage1 !profile.notest>'
+# multiple stanzas not supported: error out
+insertsource 'unstable' 'spec-7' 'any' '1' 'Build-Depends: foo <profile.stage1><!profile.notest>'
+insertsource 'unstable' 'spec-8' 'any' '1' 'Build-Depends: foo <profile.stage1> <!profile.notest>'
+
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  bar
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst bar (1.0 unstable [all])
+Conf bar (1.0 unstable [all])' aptget build-dep buildprofiles -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  bar foo
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst bar (1.0 unstable [all])
+Inst foo (1.0 unstable [all])
+Conf bar (1.0 unstable [all])
+Conf foo (1.0 unstable [all])' aptget build-dep buildprofiles -s -o APT::Architecture=i386
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  bar
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst bar (1.0 unstable [all])
+Conf bar (1.0 unstable [all])' aptget build-dep buildprofiles -s -o APT::Architecture=armel
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  bar
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst bar (1.0 unstable [all])
+Conf bar (1.0 unstable [all])' aptget build-dep buildprofiles -s -o APT::Architecture=i386 -P stage1
+
+KEEP='Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  foo
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst foo (1.0 unstable [all])
+Conf foo (1.0 unstable [all])'
+DROP='Reading package lists...
+Building dependency tree...
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.'
+
+msgtest 'Check if version of installed dpkg is high enough for' 'build profiles support'
+if dpkg --compare-versions "$(command dpkg-query --showformat='${Version}' --show dpkg)" 'ge' '1.17.2'; then
+       msgpass
+       testwithdpkg() {
+               msgtest "Test with" "dpkg-checkbuilddeps -d '$1' -P '$2'"
+               local OUTPUT="${TMPWORKINGDIRECTORY}/rootdir/tmp/testwithdpkg.output"
+               if dpkgcheckbuilddeps -d "$1" -P "$2" /dev/null >$OUTPUT 2>&1; then
+                       if [ "$3" = "$DROP" ]; then
+                               msgpass
+                       else
+                               cat $OUTPUT
+                               msgfail
+                       fi
+               else
+                       if [ "$3" = "$KEEP" ]; then
+                               msgpass
+                       else
+                               cat $OUTPUT
+                               msgfail
+                       fi
+               fi
+       }
+else
+       msgskip
+       testwithdpkg() {
+               msgtest "Test with" "dpkg-checkbuilddeps -d '$1' -P '$2'"
+               msgskip
+       }
+fi
+
+testprofile() {
+       if [ -n "$3" ]; then
+               testequal "$4" aptget build-dep "$1" -s -P "$3"
+               export DEB_BUILD_PROFILES="$(echo "$3" | tr ',' ' ')"
+               testequal "$4" aptget build-dep "$1" -s -o with::environment=1
+               unset DEB_BUILD_PROFILES
+       else
+               testequal "$4" aptget build-dep "$1" -s
+       fi
+       testwithdpkg "$2" "$3" "$4"
+}
+
+testprofile 'spec-1' 'foo <!profile.stage1>' '' "$KEEP"
+testprofile 'spec-1' 'foo <!profile.stage1>' 'stage1' "$DROP"
+testprofile 'spec-1' 'foo <!profile.stage1>' 'notest' "$KEEP"
+testprofile 'spec-1' 'foo <!profile.stage1>' 'stage1,notest' "$DROP"
+
+testprofile 'spec-2' 'foo <profile.stage1>' '' "$DROP"
+testprofile 'spec-2' 'foo <profile.stage1>' 'stage1' "$KEEP"
+testprofile 'spec-2' 'foo <profile.stage1>' 'notest' "$DROP"
+testprofile 'spec-2' 'foo <profile.stage1>' 'stage1,notest' "$KEEP"
+
+testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' '' "$KEEP"
+testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' 'stage1' "$DROP"
+testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' 'notest' "$DROP"
+testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' 'stage1,notest' "$DROP"
+
+testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' '' "$DROP"
+testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' 'stage1' "$KEEP"
+testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' 'notest' "$KEEP"
+testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' 'stage1,notest' "$KEEP"
+
+testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' '' "$KEEP"
+testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' 'stage1' "$DROP"
+testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' 'notest' "$KEEP"
+testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' 'stage1,notest' "$DROP"
+
+testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' '' "$KEEP"
+testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' 'stage1' "$KEEP"
+testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' 'notest' "$DROP"
+testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' 'stage1,notest' "$KEEP"
+
+testfailure aptget build-dep spec-7 -s
+testfailure aptget build-dep spec-8 -s