Build

Warning!!

ALL THE FOLLOWING INSTRUCTIONS ASSUMES THAT ARE IN YOUR CONTAINER UNDER THE DEVEL USER !!! refer to this section to enter in your container.

Build environment

Your home directory comes with some pre-created directories. Here are their purpose:

  • gitsources: directory where is your git clone repositories of your project, applications sources
  • gitpkgs: directory where is your git clone repositories of your package project, where is the spec file
  • build: this directory will hold all your RPM package build results, after rpmbuild command

The container comes with an aarch64 ready build environment. To be in a cross-compiling environment you have to source a file which will finish to setup your environment to correctly point to cross-compiler and libraries paths. Execute the following:

[devel@redpesk-builder build]$ . /usr/aarch64-linux-gnu/bin/cross-profile-setup-sdk-aarch64.sh

Crossbuild your project

Here is an example of how to crossbuild an AGL binding:

cd gitsources
git clone https://github.com/redpesk-samples/helloworld-binding.git
cd helloworld-binding
mkdir build
cd build
. /usr/aarch64-linux-gnu/bin/cross-profile-setup-sdk-aarch64.sh
cmake ..
# if there is "no version found" error, specify version, example:
cmake .. -DVERSION=8.99.6

If everything goes as planned, you will have an output like that:

Distribution detected (separated by ';' choose one of them) redpesk
Include: /usr/share/cmake/Modules/CMakeAfbTemplates/cmake/cmake.d/01-build_options.cmake
Include: /usr/share/cmake/Modules/CMakeAfbTemplates/cmake/cmake.d/02-variables.cmake
-- Check gcc_minimal_version (found gcc version 8.1.1) 	(found g++ version 8.1.1)
Include: /usr/share/cmake/Modules/CMakeAfbTemplates/cmake/cmake.d/03-macros.cmake
Include: /usr/share/cmake/Modules/CMakeAfbTemplates/cmake/cmake.d/04-extra_targets.cmake
.. Warning: RSYNC_TARGET RSYNC_PREFIX not defined 'make remote-target-populate' not instanciated
.. Warning: RSYNC_TARGET not defined 'make widget-target-install' not instanciated
-- Configuring done
-- Generating done
-- Build files have been written to: /home/devel/gitsources/helloworld-binding/build

Then you can continue with a make:

make -j
Scanning dependencies of target test-files
Scanning dependencies of target prepare_package
Scanning dependencies of target helloworld-skeleton
Scanning dependencies of target htdocs
Scanning dependencies of target prepare_package_test
Scanning dependencies of target helloworld-subscribe-event
Scanning dependencies of target fixture-files
Scanning dependencies of target helloworld-config
[  7%] Generating package
[  7%] Building C object helloworld-skeleton/CMakeFiles/helloworld-skeleton.dir/helloworld-service-binding.c.o
[ 11%] Generating htdocs
[ 14%] Generating package-test
Scanning dependencies of target autobuild
[ 18%] Generating test-files
[ 22%] Generating fixture-files
[ 25%] Generating package-test/htdocs
[ 29%] Generating helloworld-config
[ 33%] Building C object helloworld-subscribe-event/CMakeFiles/helloworld-subscribe-event.dir/helloworld-event-service-binding.c.o
[...]
[ 96%] Generating package/lib/afb-helloworld-skeleton.so
[ 96%] Built target project_populate_helloworld-skeleton
[ 96%] Built target helloworld-subscribe-event
Scanning dependencies of target project_populate_helloworld-subscribe-event
[100%] Generating package/lib/afb-helloworld-subscribe-event.so
[100%] Built target project_populate_helloworld-subscribe-event
Scanning dependencies of target populate
[100%] Built target populate
Scanning dependencies of target helloworld-binding_build_done
++ Debug from afb-binder --port=1234  --ldpaths=package --workdir=. --roothttp=../htdocs --token= --verbose
[100%] Built target helloworld-binding_build_done

(Cross)Build the RPM packages

Warning!!

ALL THE FOLLOWING INSTRUCTIONS ASSUMES THAT ARE IN YOUR CONTAINER UNDER THE DEVEL USER !!! refer to this section to enter in your container.

# prerequisite: install needing library
sudo dnf install redpesk-utils

In this section, you can see how to crossbuild RPM packages. It’s possible to use the previous example agl-service-helloworld but we choose an other exemple, Mustache. We are gonna use an intermediate git repository meant for packaging, we will named it gitpkg.

Inside the gitpkg, there are 3 types of files: the spec file, one or several patches (if needed) and sources archives tarball.

First step: populate package sources repository (gitpkg)

# create your project gitpkg and go inside
mkdir ~/gitpkgs/mustach && cd ~/gitpkgs/mustach
# add the specfile in the mustach gitpkg
cat << EOF > mustach.spec
%global _privatelibs libmustach[.]so\(\).*
%global __requires_exclude ^(%{_privatelibs})$

Name:           mustach
Version:        0.0.1
Release:        0%{?dist}
Summary:        mustach is a C implementation of the mustache template specification

License:        APL2.0
URL:            https://gitlab.com/jobol/mustach.git
Source0:        %{name}-%{version}.tar.gz

BuildRequires:  valgrind

%global debug_package %{nil}

%description
C implementation of mustache templating

%prep
%autosetup -p1

%build
make PREFIX=%{_prefix} LIBDIR=%{_libdir}

%install
%make_install PREFIX=%{_prefix} LIBDIR=%{_libdir}

%check
%if "x%{?_crossroot}" == "x"
make test
%endif

%files
%doc
%{_bindir}/%{name}
%{_includedir}/%{name}/mustach-json-c.h
%{_includedir}/%{name}/mustach.h
%{_libdir}/libmustach.so
%{_libdir}/libmustach.so.0
%{_libdir}/libmustach.so.0.99

%license

%changelog
EOF
# init the git repository
git init
# stage spec file changes
git add *.spec

NB: You can referate to the rpm packaging guide to know more about how to create a spec file.

Second step: apply your modifications

You have typically 2 cases that you want to support, an internal OR an existing upstream project.

This second step is different depending on the case. So normally you have to choose between the two cases. We are gonna see that, with our example Mustache.

1st case : Internal project

In this case, you have the access to modify directly sources by cloning them, and create the archive from the path where you cloned the sources.

cd ~/gitsources/
# clone sources
git clone https://gitlab.com/jobol/mustach.git
cd mustach
# modify sources (in this example, we add a library)
sed -i 's/LDLIBS += -ljson-c/LDLIBS += -ljson-c -lm/' Makefile
# this line let to modify automatically the Makefile
# but files can be modified with vim for example

git commit Makefile -sm "Fix add missing lib at link"

cd ~/gitpkgs/mustach
# create the archive from sources
iotpkg archive --path-source ~/gitsources/mustach/ --commit master

# move sources in the good directory
cp *.tar.gz ~/build/SOURCES/
2nd case : Existing upstream project

In this case, you can’t modify sources directly. So you have to create the archive from an URL, and instead of modify directly your sources, you have to create a patch to apply your modifications.

cd ~/gitpkgs/mustach

# retrieve archive from an URL
iotpkg archive --path-source https://gitlab.com/jobol/mustach.git --commit master

# create the patch
cat << EOF > 0001-Fix-add-missing-lib-at-link.patch
diff --git a/Makefile b/Makefile
index 3e0fd17..e58d589 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ SOVER = .0
 SOVEREV = .0.99

 CFLAGS += -fPIC -Wall -Wextra
-LDLIBS += -ljson-c
+LDLIBS += -ljson-c -lm

 lib_OBJ  = mustach.o mustach-json-c.o
 tool_OBJ = mustach.o mustach-json-c.o mustach-tool.o
EOF

# modify the spec file to take into account the patch
sed -i '/Source0/a Patch0:         0001-Fix-add-missing-lib-at-link.patch' mustach.spec
# this line let to add the line "Patch0:         0001-Fix-add-missing-lib-at-link.patch"
# in the spec file after the line with Source0, but normally
# modify yourself the spec file with vim *.spec for example...

# copy sources and patches in the good directory
cp *.tar.gz *patch ~/build/SOURCES/

Third step: build rpm

cd ~/gitpkgs/mustach
# install requires packages before building (valgrind for this example)
dnf builddep mustach.spec
# Source the environment to crossbuild
. /usr/aarch64-linux-gnu/cross-profile-setup-sdk-aarch64.sh
# build rmp with the following command
rpmbuild -bb --nodeps --target aarch64 *.spec
# output of rpmbuild command (Second case here)
Building target platforms: aarch64
Building for target aarch64
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.JGBdm5
+ umask 022
+ cd /home/devel/build/BUILD
+ cd /home/devel/build/BUILD
+ rm -rf mustach-0.0.0+20200406+0+gdc2a8a4f
+ /usr/bin/gzip -dc /home/devel/build/SOURCES/mustach-0.0.0+20200406+0+gdc2a8a4f.tar.gz
+ /usr/bin/tar -xof -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd mustach-0.0.0+20200406+0+gdc2a8a4f
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ /usr/bin/cat /home/devel/build/SOURCES/0001-Fix-add-missing-lib-at-link.patch
+ /usr/bin/patch -p1 -s --fuzz=0 --no-backup-if-mismatch
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.O0PGnQ
+ umask 022
+ cd /home/devel/build/BUILD
+ cd mustach-0.0.0+20200406+0+gdc2a8a4f
+ make
[...]
Processing files: mustach-0.0.0+20200406+0+gdc2a8a4f-0.rpd28.aarch64
Provides: libmustach.so.0.99()(64bit) mustach = 0.0.0+20200406+0+gdc2a8a4f-0.rpd28 mustach(aarch-64) = 0.0.0+20200406+0+gdc2a8a4f-0.rpd28
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: libc.so.6()(64bit) libc.so.6(GLIBC_2.17)(64bit) libjson-c.so.4()(64bit) libmustach.so()(64bit) rtld(GNU_HASH)
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/devel/build/BUILDROOT/mustach-0.0.0+20200406+0+gdc2a8a4f-0.rpd28.aarch64
Wrote: /home/devel/build/RPMS/mustach-0.0.0+20200406+0+gdc2a8a4f-0.rpd28.aarch64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.YwggY9
+ umask 022
+ cd /home/devel/build/BUILD
+ cd mustach-0.0.0+20200406+0+gdc2a8a4f
+ /usr/bin/rm -rf /home/devel/build/BUILDROOT/mustach-0.0.0+20200406+0+gdc2a8a4f-0.rpd28.aarch64
+ exit 0

You can see rpm created in the corresponding directory

ls ~/build/RPMS/
# list of rpm files for this example (Second case here)
mustach-0.0.0+20200406+0+gdc2a8a4f-0.rpd28.aarch64.rpm

Fourth step: commit your modifications

The sources archive (file xxx-version.tar.gz) must be part of gitpkg. It’s a bad idea to versioned this archive directly into git repo of gitpkg. That’s why we will use an extension of git, named Git LFS (for Large File Storage) to managed sources archive. For more information of git lfs, please refer to https://git-lfs.github.com

Here are the command to add your sources archive into gitpkg :

# Setup Git LFS (only one time)
git lfs install

# Select the file types you'd like Git LFS to manage (only one time)
git lfs track *.tar.gz

# Now make sure .gitattributes is tracked (only one time)
git add .gitattributes

# Now, just commit and push to gitpkg as you normally would with normal git.

# Add specfile
git add *spec
# Add patch file(s)
git add *patch
# Add archive
git add *tar.gz

# Commit
git commit -sam "Initial commit"

# If you have a running operational redpesk stack
git remote add origin http://<your_gitlab_url>
# Push changes into gitpkg repo
git push