YaST/开发/常见问题

< YaST‎ | 开发
Jump to: navigation, search

Template:Traslation

About

This article describes problems that could YaST developer run into. Proposes solutions or helps to avoid from them.


Dependencies

A lot of YaST packages are dependent on each other. Installing one YaST package could require five another which could also require another YaST packages or some libraries.

It's because a majority of YaST packages offer some functionality to other packages, mainly by sharing YCP modules or SCR agents. In general, only a small part of YaST package is really needed by another one which leads into wasting space and installing unneeded stuff.

This problem can have more solutions:

  • Moving shared YCP modules or SCR Agents to some other YaST package. Such package is very often yast2.rpm.
  • Call shared modules or agents conditionally.
 {
   import "PackageSystem";
   
   string package_name = "yast2-foo";
   boolean additional_functionality = false;
   
   // Needed package is installed
   if (PackageSystem::Installed(package_name)) {
     additional_functionality = true;
   
   // Installing needed package
   } else if (
     PackageSystem::CheckAndInstallPackagesInteractive ([package_name]) &&
     // user might skip installation and confirm to continue
     PackageSystem::Installed (package_name)
   ) {
     additional_functionality = true;
   
   // Package is not installed and user has denied to install it
   } else {
     additional_functionality = false;
   }
   
   if (additional_functionality) {
     // offer some special functionality
   }
 }
This solution could lead into other problems (described later).


SCR Agents are Read when Starting YaST

All available SCR agents are read when YaST is starting. Installing new YaST package doesn't offer newly-installed SCR agent to the already running YaST application. There are two nasty solutions:

  • Close SCR and open it again. This will read all available SCR agents again.
 integer handle = WFM::SCRGetDefault ();
 WFM::SCRClose (handle);
 WFM::SCROpen ("scr", true);
Honestly, this can make more problems than it solves. Closing SCR before flushing the data stored in can leave data handled by SCR in an undefined state. Developers have to be really sure what they do.
  • Registering new agent on-the-fly. You have to know how this agent is defined and register it manually or read the agent definition from defined location and use that definition during registration. When registering manually, you have to watch changes in the agent itself and change your copy whenever it is modified.
 {
   // manually
   SCR::RegisterAgent(.slp, `ag_slp(`SlpAgent()));
 }

These solutions are proposals for new

  • Creating new YCP function to register a specific agent (.slp for instance) where definition would be looked up on a disk.
  • Creating new YCP function that would force rereading all (or rather reading-only-new) agents on request.
  • Lazy-loading of SCR agents. This would speed-up YaST start-up as well.


Non-Conditional Imports and Includes

All YCP sources are evaluated and checked at once. Developer can't define that some YCP module should be loaded just in a special case.

Example:

 {
   import "Features";
   
   Features::Read();
   
   if (Features::HasPopupSupport()) {
     import "Popup";
     
     Popup::DoSomething();
   }
 }

This example doesn't do what it seems. All imports are executed before script starts so it can break when module Popup is not installed.

Conditional imports can be solved by calling YCP clients that import such module:

 {
   import "Features";
   
   Features::Read();
   
   if (Features::HasPopupSupport()) {
     WFM::call("import_popup_module");
   }
 }

With import_popup_module.ycp:

 {
   import "Popup";
   
   Popup::DoSomething();
 }

This example works but it's slower than common YCP execution because import_popup_module.ycp needs to be checked for syntax and evaluated first. Of course, import_popup_module.ycp must be installed in this example. Some checking, whether the client is installed should be done before WFM::call() to prevent from failure.

There is also another solution when for using functionality offered by YaST packages that are not installed when YaST itself is started. Some package, which must be installed in that time, contains a Perl wrapper module which contains API definition of a YCP module that we would like to install during the runtime.

In case of Perl, only these API definitions are checked.

 #!/usr/bin/perl -w
 
 package PerlAPIPopup;
 use strict;
 use YaPI;
 
 YaST::YCP::Import ("Popup");
 
 our %TYPEINFO;
 
 BEGIN{$TYPEINFO{Message} = ["function", "void", "string"]};
 sub Message {
   my $self = shift;
   my $message = shift;
   Popup->Message($message)
 }
 
 1;

This Perl module could be imported in YCP code, but functions defined in it would need to be called only when the Popup module is installed (also installed on-the-fly).

 {
   import "PerlAPIPopup";
   
   ...
   
   if (installed) {
     PerlAPIPopup (message);
   }
 }

Unstable Development

Shared API of YCP modules or SCR agents can change and a developers find that out just after their YaST packages break in autobuild. This is very often caused by not checking who uses my module and how.