Mb2 shared output directory: allow to disable zypper distribution update

When using shared output directory, the build always starts with zypper dup: https://github.com/sailfishos/sdk-setup/blob/master/sdk-setup/src/mb2#L1035

Now, this can lead to unexpected results on more complicated projects. For example, some packages can be pulled into the target which are incompatible with the actual build requirements pulled into the target one line below.

Such incompatibility came out while working on Sony Tama port which includes multiple devices. During zypper dup, config packages were pulled into the target followed by Android system packages for one of the devices. As a result, building version package for some other device failed as a conflict was detected by zypper.

This would have been avoided if I could disable zypper dup action

Thanks for the idea. We will consider implementing it in some future release.

Turning the --snapshot option on should prevent such an issue.

Why would it prevent it? It will run zypper dup inside the snapshot which can break the build the same way.

I have stumbled into this issues when using the builds with snapshots.

Other build would use other snapshot.

Also note that with snapshots in use, you can do mb2 build-requires reset to reset a snapshot to a clean state when you feel it’s needed.

I failed to reply to that part. The same snapshot is recycled for the same build directory. So either use different build directory or use mb2 build-requires reset when switching device variant.

Indeed, contamination between the builds can be prevented with snapshots. And it is a great feature.

However, the issue experienced here is within a build of a single package. So, in my case, while building droid-hal-version-h8324:

  • zypper dup pulls in droid-config-XXXX and, as a result, droid-system-apollo and droid-system-apollo-h8314. The latter was by chance and, in theory, same could be provided by droid-system-apollo-h8314 (pay attention to the number behind h!)

  • zypper install of dependencies on the line after that in mb2 script finds out that actually droid-system-apollo-h8324 is needed and that conflicts with installed h8314 system-apollo package.

This would all be prevented if zypper dup would be absent. Hence my request.

Ah now I see! The devil is in the details :slight_smile:

Before I dig deeper, let me ask, are you sure the way things are packaged here is optimal? Couldn’t this be possibly fixed by different packaging strategy?

Imagine the output directory was a regular repository. It is absolutely valid to do a zypper dup prior to zypper in from a regular repository. So it makes me think there is likely a more correct solution. I am not saying that it is necessarily an issue with your packaging! This is just the easiest idea to start with :slight_smile:

The packaging follows the same approach as in https://build.merproject.org/project/show/nemo:devel:hw:sony:tama . It allows to support all 6 devices from Sony Tama and, in this respect, is “optimal”. As a bonus, it exposes issues in the build systems when I work on automating the builds using SDK.

I agree that it is valid to make zypper dup from regular repository. However, it is also valid to ask not to do that, which is my request.

Also regular repository can have packages providing the same symbols and in conflict with each other. As long as they are not pulled in as build requirements at the same time, it is fine. In these cases, zypper dup will be of more harm than use.

I could even suggest that use of zypper dup in this context is unexpected and should not be enabled by default. This is as the requirements should be set by zypper in as it is for regular builds.

What I am trying to avoid is:

“This is FooBar. You can build it simply with mb2/sfdk, just do not ever forget to pass these magic options…”

I.e., avoid surprises where possible. That’s why I want to be sure that adding the option is the right solution to the right problem.

I could even suggest that use of zypper dup in this context is unexpected and should not be enabled by default. This is as the requirements should be set by zypper in as it is for regular builds.

This might be actually the right direction. Maybe the zypper dup could be completely removed. But I am afraid it wasn’t added there just for fun. It’s likely there to deal with package versions moving back and forth, where the sole zypper in would fail.

Maybe the (equivalent of) zypper dup could be done some more clever way, so that it does pick randomly where multiple options exist. OBS also deals with similar issues https://en.opensuse.org/openSUSE:Build_Service_prjconf#Prefer. Ideas?

Yes, it makes sense not to overload with options.

Re Prefer: In context of automated builds using tbuilder, the solution that works for range of projects is rather radical:

  1. use clean SDK target and make/force reset snapshot
  2. install packages requested by user into that snapshot. those are installed even if not in BuildRequires
  3. build a single package. This includes installation of BuildRequires
  4. go to 1

Here, step 2 corresponds to OBS Prefer. It is not exactly the same, but seems to be sufficient for the cases I have tested so far. I haven’t implemented “-package”, let’s see if it is needed.

Could you please try whether doing zypper in also prior to zypper dup (ignoring possible failure) prevents the issue?

diff --git a/sdk-setup/src/mb2 b/sdk-setup/src/mb2
index dd793b2..f3ba2ee 100755
--- a/sdk-setup/src/mb2
+++ b/sdk-setup/src/mb2
@@ -1032,6 +1032,7 @@ maybe_verify_target_dependencies() {
             filter_repo "$exclude_source_name" "$OPT_OUTPUTDIR" "$filtered_outputdir"
             local args=(--"$OPT_SEARCH_OUTPUTDIR_VERBOSITY" --non-interactive \
                 --plus-repo "$filtered_outputdir" --no-gpg-checks)
+            sb2 -t "$OPT_TARGET" -m sdk-install -R zypper "${args[@]}" in "${deps[@]}"
             sb2 -t "$OPT_TARGET" -m sdk-install -R zypper "${args[@]}" dup --from '~plus-repo-1'
             sb2 -t "$OPT_TARGET" -m sdk-install -R zypper "${args[@]}" in "${deps[@]}"
         else
1 Like

I will be able to check in few hours.

I think it will work for my case. But then there is a question regarding on why not to allow disabling it? Downgrade is the only reason I can see in using dup with the downgrade of some package installed by default in the base target, but that should be rare. Proper use of snapshots should take care of these downgrades in most of the practical cases.

There is still a possibility to find a solution that works without tweaking.

1 Like

Nice goal. Just from my current troubleshooting, I must say that having zypper dup executed during a build was unexpected. Which made debugging much harder than it would be otherwise. In this respect, I would have dropped dup and let developers run it if needed for their projects.

PS: but it is OK to have different opinions, I will test that solution as well and will report back

The dup happens when the --search-output-dir option is active. The option exists to save developers from the need to maintain their build targets manually - all build time dependencies, including those built locally, are installed automatically. For that to work reliably (=no manual intervention is needed) the dup is needed.

I found a possible source of your issues. https://github.com/rinigus/tbuilder/blob/master/tbuilder#L129 By passing an argument to the --snapshot option you forces it to reuse single snapshot for various packages. I didn’t check further what the scope of self.project is, but with the argument passed to --snapshot it definitely does not use a dedicated snapshot for each build.

Please try again with original mb2 and --snapshot without argument.

In this case it will use single snapshot for single build directory. It will use a pool of snapshots and recycle them but never use a dirty snapshot for different build directories. (Pool size is currently hardcoded as SNAPSHOT_POOL_SIZE in mb2 sources.)

To avoid confusion: When a build directory is removed and created again (or just cleared the .mb2 subdirectory), the effect is the same as using a different build directory. So it is OK to use the same path for different packages. It is only required to clear the build directory before proceeding with different package.

@martyone, thanks for looking into the code! It is a bit hidden, but the snapshot is reset before building each package at https://github.com/rinigus/tbuilder/blob/master/tbuilder#L78

tbuilder creates Makefile to keep track between dependencies. After building one package, a non-zero exit is imposed also for successful build to recheck availability of packages, reset the snapshot and start again.

So, while the same name snapshot is used for the project, it should be clean one without any extras installed.

Should have included into original reply, sorry for splitting into two messages:

Named snapshot allows me to handle package preferences, similar to OBS. Thus, after force reset of the snapshot, the preferred packages are installed (if any) and the build of the next package is started.

See example config at https://github.com/sailfishos-sony-tama/tbuilder-project/blob/hybris-10/config.yaml . These packages are under install keyword. (kernel modules packages will be removed from that list in the next update)

My understanding is you do this just to fight the issue with dup and you want to get rid of this.

I.e. that the issue with dup happens unless you reset the snapshot before building each package.

This is not surprising. When you compare it to OBS, it starts every build with a clean target. And this is what you achieve either with temporary snapshot (--snapshot without argument) or with named snapshot (--snapshot with argument) reset prior to each build as you do.

If you need some fixed deps installed in the snapshot, you can

  1. create a named snapshot by using sdk-manage directly and
  2. run mb2 passing the named snapshot as --target and --snapshot without argument in addition to that
$ sdk-assistant list
sf
├─sfarm
│ └─sfarm.mb2.YRN  (snapshot)
└─sfx86
  ├─sfx86.mb2.EKH  (snapshot)
  ├─sfx86.mb2.U48  (snapshot)
  └─sfx86.mb2.V24  (snapshot)
$ sdk-manage target snapshot sfx86 sfx86.project
$ sdk-assistant package-install sfx86.project packageA packageB ...
...
$ sdk-assistant list
sf
├─sfarm
│ └─sfarm.mb2.YRN  (snapshot)
└─sfx86
  ├─sfx86.project  (snapshot)
  ├─sfx86.mb2.EKH  (snapshot)
  ├─sfx86.mb2.U48  (snapshot)
  └─sfx86.mb2.V24  (snapshot)
$ mb2 -t sfx86.project --snapshot build
Taking snapshot 'sfx86.project.mb2.W8F' of 'sfx86.project' target...
Using /srv/mer/toolings/sf//opt/cross/bin/i486-meego-linux-gnu-gcc to detect target architecture:
Finished writing sb2.gcc.config
gcc configured.
...
$ sdk-assistant list
sf
├─sfarm
│ └─sfarm.mb2.YRN  (snapshot)
└─sfx86
  ├─sfx86.project  (snapshot)
  │ └─sfx86.project.mb2.W8F  (snapshot)
  ├─sfx86.mb2.EKH  (snapshot)
  ├─sfx86.mb2.U48  (snapshot)
  └─sfx86.mb2.V24  (snapshot)