.. _autospec: autospec ######## **autospec** is a tool used to assist with the automated creation and maintenance of RPM packaging in |CL-ATTR|. Where a standard :abbr:`RPM (RPM Package Manager)` build process using :command:`rpmbuild` requires a tarball and :file:`.spec` file to start, autospec requires only a tarball and package name to start. .. contents:: :local: :depth: 1 Description *********** The autospec tool attempts to infer the requirements of the :file:`.spec` file by analyzing the source code and :file:`Makefile` information. It continuously runs updated builds based on new information discovered from build failures until it has a complete and valid :file:`.spec` file. If needed, you can influence the behavior of autospec and customize the build by providing optional `control files`_ to the autospec tool. autospec uses **mock** as a sandbox to run the builds. Visit the `mock wiki`_ for additional information on using mock. For a general understanding of how an RPM works, visit the `rpm website`_ or the `RPM Packaging Guide`_. .. raw:: html How it works ************ Learn the autospec tool set up and process. .. contents:: :local: :depth: 1 Prerequisites ============= The setup for building source in |CL| must be completed before using the autospec tool. Refer to `Setup environment to build source`_ for instructions on completing the setup. Create an RPM ============= The basic autospec process is described in the following steps: #. The :command:`make autospec` command generates a :file:`.spec` file based on the analysis of code and existing control files. Any control files should be located in the same directory as the resulting :file:`.spec` file. View the `autospec README`_ for more information on `control files`_. #. autospec creates a build root with mock config. #. autospec attempts to build an RPM from the generated :file:`.spec`. #. autospec detects any missed declarations in the :file:`.spec`. #. If build errors occur, autospec scans the build log to try to detect the root cause. #. If autospec detects the root cause and knows how to continue, it restarts the build automatically at step 1 with updated build instructions. #. Otherwise, autospec stops the build for user inspection to resolve the errors. Respond to the build process output by fixing source code issues and/or editing control files to resolve issues, which may include dependencies or exclusions. See `autospec README`_ for more information on control files. The user resumes the process at step 1 after errors are resolved. If a binary dependency doesn't exist in |CL|, you must build it before running autospec again. Following these steps, autospec continues to rebuild the package, based on new information discovered from build failures, until it has a valid :file:`.spec`. If no build errors occur, RPM packages are successfully built. Examples ******** Complete `Setup environment to build source`_ before using these examples. .. contents:: :local: :depth: 1 Example 1: Build RPM with an existing spec file =============================================== This example shows how to build a RPM from a pre-packaged upstream package with an existing spec file. The example uses the ``dmidecode`` package. #. Navigate to the autospec workspace and clone the ``dmidecode`` package: .. code-block:: bash cd ~/clearlinux make clone_dmidecode .. note:: You can clone all package repos at once using the following command: .. code-block:: bash make [-j NUM] clone-packages The optional NUM is the number of threads to use. For a list of available packages, view the :file:`~/clearlinux/projects/common/packages` file. #. Navigate to the local copy of the ``dmidecode`` package and build it: .. code-block:: bash cd ~/clearlinux/packages/dmidecode/ make build #. The resulting RPMs are in :file:`./rpms`. Build logs and additional RPMs are in :file:`./results`. Example 2: Build a new RPM ========================== This example shows how to build a new RPM with no spec file. The example will create a simple helloclear RPM. #. Navigate to the autospec workspace and build the helloclear RPM. The :file:`Makefile` provides a :command:`make autospecnew` that can automatically generate an RPM package using the autospec tool. You must pass the URL to the source tarball and the NAME of the RPM you wish to create: .. code-block:: bash cd ~/clearlinux make autospecnew URL="https://github.com/clearlinux/helloclear/archive/helloclear-v1.0.tar.gz" NAME="helloclear" The resulting RPMs are in :file:`./packages/helloclear/rpms`. Build logs and additional RPMs are in :file:`./packages/helloclear/results`. Example 3: Generate a new spec file with a pre-defined package ============================================================== This example shows how to modify an existing package to create a custom RPM. In this example you will make a simple change to the ``dmidecode`` package and rebuild the package. #. Navigate to the autospec workspace and clone the ``dmidecode`` package: .. code-block:: bash cd ~/clearlinux make clone_dmidecode #. Navigate into the *dmidecode* directory: .. code-block:: bash cd packages/dmidecode #. Open the :file:`excludes` file with an editor and add these lines: .. code-block:: console /usr/bin/biosdecode /usr/bin/ownership /usr/bin/vpddecode /usr/share/man/man8/biosdecode.8 /usr/share/man/man8/ownership.8 /usr/share/man/man8/vpddecode.8 .. note:: These files aren't needed by dmidecode, so we can remove them without any issues. #. In the :file:`dmidecode` directory, build the modified ``dmidecode`` package: .. code-block:: bash make autospec #. The resulting RPMs are in :file:`./rpms`. Logs are in :file:`./results`. Example 4: Provide control files to autospec ============================================ This example shows how to modify control files to correct build failures that autospec is unable to resolve. In this example, you will add a missing license and dependencies so autospec can complete a successful build. #. Navigate to the autospec workspace: .. code-block:: bash cd ~/clearlinux #. If you have not already, clone all upstream package repos: .. code-block:: bash make [-j NUM] clone-packages The optional NUM is the number of threads to use. .. note:: In a later step of this example, we will search the cloned package repos for a missing dependency. #. Build the opae-sdk RPM: .. code-block:: bash make autospecnew URL="https://github.com/OPAE/opae-sdk/archive/0.13.0.tar.gz" NAME="opae-sdk" This results in an error for a missing license file: .. code-block:: console [FATAL] Cannot find any license or opae-sdk.license file! #. Navigate to the package with build failures: .. code-block:: bash cd packages/opae-sdk #. Add one or more valid license identifiers from the `SPDX License List `_. In the example below, two different licenses are appropriate based on the opae-sdk project licensing: .. code-block:: bash echo "BSD-3-Clause MIT" > opae-sdk.license #. Run autospec again: .. code-block:: bash make autospec This results in a generic error: .. code-block:: console [FATAL] Build failed, aborting #. Open the build log to view the error details: .. code-block:: bash cat ./results/build.log The build log contains details for the specific failures. In this instance, there are missing dependencies: .. code-block:: console CMake Error: The following variables are used in this project, but they are set to NOTFOUND. Please set them or make sure they are set and tested correctly in the CMake files: CJSON_LIBRARY linked by target "opae-c++-utils" in directory /builddir/build/BUILD/opae-sdk-0.13.0/tools/c++utilslib json-c_LIBRARIES linked by target "opae-c" in directory /builddir/build/BUILD/opae-sdk-0.13.0/libopae libuuid_LIBRARIES linked by target "opae-c" in directory /builddir/build/BUILD/opae-sdk-0.13.0/libopae #. Search the spec files of upstream |CL| packages to see if the json-c library is available. In this case, it does exist and we'll add the json-c 'dev' package into the buildreq_add: .. code-block:: bash grep 'json-c\.so$' ~/clearlinux/packages/*/*.spec echo "json-c-dev" >> buildreq_add .. note:: This search step works only if the user cloned all of the upstream package repos. In this example, upstream package repos were cloned in a previous step. #. Search the spec files of upstream |CL| packages to see if the libuuid library is available. In this case, it exists in the util-linux package, so we'll add util-linux-dev package into the buildreq_add: .. code-block:: bash grep 'libuuid\.so$' ~/clearlinux/packages/*/*.spec echo "util-linux-dev" >> buildreq_add #. Run autospec again and find the successfully-generated RPMs in the :file:`rpms` directory: .. code-block:: bash make autospec .. note:: If you need a dependency that does not exist in the |CL| repo, you must first build it manually (see `Example 2: Build a new RPM`_), then add the repo so that autospec knows the package exists. For example: .. code-block:: bash cd ~/clearlinux/packages/ make repoadd make repostatus You only need to add the dependency to the :file:`buildreq_add` control file if autospec is not able to automatically find the correct dependency on its own. .. TODO: Document how to set up a license server for use with autospec. .. TODO: Demonstrate control file management. Establish specific use cases. Example 5: Update an existing package ===================================== The |CL| team prefers to carry no patches and seeks to make the latest releases work. If we do need patches, we use :command:`autospec` to add, remove, or manage patches. The :command:`autospec` control files are integral to the patch management process. Developers can expect a more streamlined approach to managing a large collection of packages with :command:`autospec`. Adding and submitting patches ----------------------------- * To add patches to |CL| upstream, follow `patching source code`_. * To submit a patch to upstream, follow `contributing to an existing software package`_. If you maintain a downstream derivative of |CL| and you want to integrate new or patched packages into your mix, follow the process in :ref:`mixer`. Assuming you have followed the above process, :command:`autospec` has generated a new spec file. Refresh a package and inspect ----------------------------- In this example, we use autospec to refresh the :command:`m4` package and recreate RPM files. #. Navigate to the top-level directory of the workspace .. code-block:: bash cd clearlinux - where :command:`clearlinux` is the top level of the tooling workspace #. Run the make_clone command and then navigate to the package. .. code-block:: bash make clone_m4 cd packages/m4 #. Make desired changes to the package, its control files, or other files. #. Finally, run: .. code-block:: bash make autospec #. To view spec file changes, run: .. code-block:: bash git show m4.spec The output shows: .. code-block:: console m4: Autospec creation for version 1.4.18 diff --git a/m4.spec b/m4.spec index f76c78d..97b846a 100644 --- a/m4.spec +++ b/m4.spec @@ -6,15 +6,14 @@ # Name : m4 Version : 1.4.18 -Release : 88 +Release : 89 URL : http://mirrors.kernel.org/gnu/m4/m4-1.4.18.tar.xz Source0 : http://mirrors.kernel.org/gnu/m4/m4-1.4.18.tar.xz -Source99 : http://mirrors.kernel.org/gnu/m4/m4-1.4.18.tar.xz.sig +Source1 : http://mirrors.kernel.org/gnu/m4/m4-1.4.18.tar.xz.sig Summary : No detailed summary available Group : Development/Tools ... #. The following commands provide a more complete view of the changes. * :command:`git log -p` * :command:`gitk` Test packaged software ********************** After software has been packaged with autospec, the resulting RPMs can be tested for functionality before being integrated and deployed into a |CL| image with the :ref:`Mixer tool `. The |CL| development tooling offers two ways to quickly test autospec generated RPMs. .. note:: The methods outlined below should only be used for temporary testing on development systems. Test in a |CL| virtual machine ============================== The |CL| development tooling includes a method to install RPMs into a |CL| virtual machine running on the KVM hypervisor. Using a :abbr:`VM (Virtual Machine)` allows testing in a completely isolated environment. To test an autospec-created package inside a VM: #. Download the |CL| KVM image into the :file:`~/clearlinux` directory as :file:`clear.img`. The location and name :file:`clear.img.xz` is important for the tooling to work: .. code-block:: bash cd ~/clearlinux curl -o clear.img.xz https://download.clearlinux.org/image/$(curl https://download.clearlinux.org/image/latest-images | grep '[0-9]'-kvm) #. Extract the downloaded |CL| KVM image: .. code-block:: bash unxz -v clear.img.xz #. Copy the QEMU start script and virtual firmware needed for KVM into the :file:`~/clearlinux` directory: .. code-block:: bash cp ~/clearlinux/projects/common/start_qemu.sh . cp /usr/share/qemu/OVMF.fd . #. Run :command:`make install` from the package's autospec directory. The :command:`make install` command mounts the downloaded |CL| KVM image and installs the autospec-created RPM into it: .. code-block:: bash cd ~/clearlinux/packages/ make install The code that makes this possible can be viewed by searching for the *install:* target in the `Makefile.common`_ file on GitHub. #. Return to the :file:`~/clearlinux` directory and start the |CL| VM: .. code-block:: bash cd ~/clearlinux/ sudo ./start_qemu.sh clear.img #. A new |CL| VM will launch in the console. Log into the VM as *root* and set a new password for the VM. #. Check that the software is installed in the |CL| VM as expected and perform any relevant tests. #. After testing has been completed, the |CL| VM can be powered off and deleted: .. code-block:: bash poweroff rm clear.img Test directly on a development machine ====================================== The |CL| development tooling also includes a method to extract autospec-created RPMs locally onto a |CL| development system for testing. Extracting an RPM directly onto a system offers quicker testing; however conflicts may occur and responsibility to remove the software after testing is up to the developer. To test an autospec created package directly on the |CL| development system: #. Run :command:`make install-local` from the package's autospec directory. The :command:`make install-local` command extracts the RPM directly onto the filesystem of the running |CL| system: .. code-block:: bash cd ~/clearlinux/packages/ make install-local The code that makes this possible can be viewed by searching for the *install-local:* target in the `Makefile.common`_ file on GitHub. #. Check that the software is installed as expected and perform any relevant tests. #. After testing has been completed, the software and any related files must be identified and deleted. The :command:`swupd repair --picky` command can help restore the state of the :file:`/usr` directory (see :ref:`swupd `) however any other files must be cleaned up manually. References ********** Reference the `autospec README`_ for details regarding `autospec` commands and options. Setup environment to build source ================================= .. _install-tooling-after-header: Setup of the workspace and tooling used for building source in |CL| is mostly automated for you with a setup script. It uses tools from the :command:`os-clr-on-clr` bundle. The setup script creates a workspace in the :file:`clearlinux` folder, with the subfolders :file:`Makefile`, :file:`packages`, and :file:`projects`. The :file:`projects` folder contains the main tools used for making packages in |CL| :file:`autospec` and :file:`common`. Follow these steps to setup the workspace and tooling for building source: #. Install the :command:`os-clr-on-clr` bundle: .. code-block:: bash sudo swupd bundle-add os-clr-on-clr #. Download the :file:`user-setup.sh` script: .. code-block:: bash curl -O https://raw.githubusercontent.com/clearlinux/common/master/user-setup.sh #. Make :file:`user-setup.sh` executable: .. code-block:: bash chmod +x user-setup.sh #. Run the script as an unprivileged user: .. code-block:: bash ./user-setup.sh #. After the script completes, log out and log in again to complete the setup process. #. Set your Git user email and username for the repos on your system: .. code-block:: bash git config --global user.email "you@example.com" git config --global user.name "Your Name" This global setting is used by |CL| tools that make use of Git. .. _install-tooling-end: Related topics ************** * :ref:`Mixer tool ` * :ref:`Proxy Configuration ` .. _contributing to an existing software package: https://github.com/clearlinux/distribution/blob/master/contributing.md#contributing-to-an-existing-software-package .. _patching source code: https://github.com/clearlinux/distribution/blob/master/contributing.md#patching-source-code .. _`Makefile.common`: https://github.com/clearlinux/common/blob/master/Makefile.common .. _autospec README: https://github.com/clearlinux/autospec .. _control files: https://github.com/clearlinux/autospec#control-files .. _mock wiki: https://github.com/rpm-software-management/mock/wiki .. _rpm website: http://rpm.org .. _RPM Packaging Guide: https://rpm-packaging-guide.github.io/ .. TODO: Add link to how to submit a new package: https://github.com/clearlinux/distribution/blob/master/contributing.md#contributing-a-new-software-package