Cross compilation support in the Package Builder.
This change contains only builder changes and spec files
for cross tools (binutils and gcc)
This change allows to build aarch64 packages on x86_64.
Command invocation:
make packages CROSS_TARGET=aarch64
Change-Id: I4319c68ae1a69c0b8893f798ddf071c3a339e1c7
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6188
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Anish Swaminathan <anishs@vmware.com>
... | ... |
@@ -79,6 +79,12 @@ else |
79 | 79 |
PACKAGE_BUILD_OPTIONS = |
80 | 80 |
endif |
81 | 81 |
|
82 |
+ifdef CROSS_TARGET |
|
83 |
+CROSS_TARGET_FLAGS = --cross-target $(CROSS_TARGET) |
|
84 |
+else |
|
85 |
+CROSS_TARGET_FLAGS = |
|
86 |
+endif |
|
87 |
+ |
|
82 | 88 |
TOOLS_BIN := $(SRCROOT)/tools/bin |
83 | 89 |
CONTAIN := $(TOOLS_BIN)/contain |
84 | 90 |
ifeq ($(ARCH),x86_64) |
... | ... |
@@ -153,6 +159,7 @@ packages: check-docker-py check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_XRPMS) $( |
153 | 153 |
$(PACKAGE_BUILD_OPTIONS) \ |
154 | 154 |
$(PHOTON_RPMCHECK_FLAGS) \ |
155 | 155 |
$(PHOTON_KAT_BUILD_FLAGS) \ |
156 |
+ $(CROSS_TARGET_FLAGS) \ |
|
156 | 157 |
$(PUBLISH_BUILD_DEPENDENCIES) \ |
157 | 158 |
$(PACKAGE_WEIGHTS) \ |
158 | 159 |
--threads ${THREADS} |
... | ... |
@@ -179,6 +186,7 @@ packages-docker: check-docker-py check-docker-service check-tools $(PHOTON_STAGE |
179 | 179 |
--pkginfo-file $(PHOTON_PKGINFO_FILE) \ |
180 | 180 |
$(PACKAGE_BUILD_OPTIONS) \ |
181 | 181 |
$(PHOTON_RPMCHECK_FLAGS) \ |
182 |
+ $(CROSS_TARGET_FLAGS) \ |
|
182 | 183 |
$(PUBLISH_BUILD_DEPENDENCIES) \ |
183 | 184 |
$(PACKAGE_WEIGHTS) \ |
184 | 185 |
--threads ${THREADS} |
... | ... |
@@ -269,6 +277,7 @@ tool-chain-stage2: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_RPMS) $(PHOTON_S |
269 | 269 |
$(PACKAGE_BUILD_OPTIONS) \ |
270 | 270 |
$(PHOTON_RPMCHECK_FLAGS) \ |
271 | 271 |
$(PHOTON_KAT_BUILD_FLAGS) \ |
272 |
+ $(CROSS_TARGET_FLAGS) \ |
|
272 | 273 |
--log-path $(PHOTON_LOGS_DIR) \ |
273 | 274 |
--threads ${THREADS} |
274 | 275 |
|
275 | 276 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,56 @@ |
0 |
+Name: binutils-aarch64-linux-gnu |
|
1 |
+Summary: Cross Binutils for Aarch64 |
|
2 |
+Version: 2.31.1 |
|
3 |
+Release: 1%{?dist} |
|
4 |
+License: GPLv2+ |
|
5 |
+URL: http://www.gnu.org/software/binutils |
|
6 |
+Group: System Environment/Base |
|
7 |
+Vendor: VMware, Inc. |
|
8 |
+Distribution: Photon |
|
9 |
+Source0: https://ftp.gnu.org/gnu/binutils/binutils-%{version}.tar.xz |
|
10 |
+%define sha1 binutils=3b031410897fe224412f3a6a1b052402d2fbcc6a |
|
11 |
+BuildArch: x86_64 |
|
12 |
+ |
|
13 |
+%define target_arch aarch64-unknown-linux-gnu |
|
14 |
+%define sysroot /target-aarch64 |
|
15 |
+ |
|
16 |
+%description |
|
17 |
+The Binutils package contains a linker, an assembler, |
|
18 |
+and other tools for handling object files. |
|
19 |
+ |
|
20 |
+%prep |
|
21 |
+%setup -q -n binutils-%{version} |
|
22 |
+ |
|
23 |
+%build |
|
24 |
+ |
|
25 |
+sh configure \ |
|
26 |
+ --prefix=%{_prefix} \ |
|
27 |
+ --target=%{target_arch} \ |
|
28 |
+ --with-sysroot=%{sysroot} \ |
|
29 |
+ --disable-multilib && \ |
|
30 |
+make configure-host && \ |
|
31 |
+make %{?_smp_mflags} |
|
32 |
+ |
|
33 |
+%install |
|
34 |
+make DESTDIR=%{buildroot} install |
|
35 |
+rm -rf %{buildroot}%{_infodir} |
|
36 |
+rm -rf %{buildroot}%{_datadir}/locale |
|
37 |
+ |
|
38 |
+%post -p /sbin/ldconfig |
|
39 |
+%postun -p /sbin/ldconfig |
|
40 |
+ |
|
41 |
+%files |
|
42 |
+%defattr(-,root,root) |
|
43 |
+%{_bindir}/* |
|
44 |
+%{_datadir}/* |
|
45 |
+%{_prefix}/%{target_arch}/* |
|
46 |
+ |
|
47 |
+%changelog |
|
48 |
+* Fri Nov 02 2018 Alexey Makhalov <amakhalov@vmware.com> 2.31.1-1 |
|
49 |
+- Cloned from cross-aarch64-tools.spec |
|
50 |
+* Thu Nov 1 2018 Sriram Nambakam <snambakam@vmware.com> 1.0.0-3 |
|
51 |
+- Updated versions of cross toolchain components |
|
52 |
+* Mon Oct 22 2018 Sriram Nambakam <snambakam@vmware.com> 1.0.0-2 |
|
53 |
+- Replace _sysroot definition with sysroot |
|
54 |
+* Fri Oct 19 2018 Sriram Nambakam <snambakam@vmware.com> 1.0.0 |
|
55 |
+- Initial build. First version |
0 | 56 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,223 @@ |
0 |
+%global security_hardening nofortify |
|
1 |
+ |
|
2 |
+# It needs linux sources only to generate linux-api-headers for |
|
3 |
+# local glibc build. glibc bits get dropped and will not be packaged |
|
4 |
+%define linux_kernel_version 4.19.52 |
|
5 |
+%define glibc_version 2.28 |
|
6 |
+ |
|
7 |
+Name: gcc-aarch64-linux-gnu |
|
8 |
+Summary: Cross GCC for Aarch64 |
|
9 |
+Version: 7.3.0 |
|
10 |
+Release: 1%{?dist} |
|
11 |
+Group: Development/Tools |
|
12 |
+Vendor: VMware, Inc. |
|
13 |
+Distribution: Photon |
|
14 |
+License: GPLv2+ |
|
15 |
+URL: http://gcc.gnu.org |
|
16 |
+Source0: https://ftp.gnu.org/gnu/gcc/gcc-%{version}/gcc-%{version}.tar.xz |
|
17 |
+%define sha1 gcc=9689b9cae7b2886fdaa08449a26701f095c04e48 |
|
18 |
+Source1: https://www.kernel.org/pub/linux/kernel/v4.x/linux-%{linux_kernel_version}.tar.xz |
|
19 |
+%define sha1 linux=0fc8eeba8a8a710c95d71f140dfdc4bdff735248 |
|
20 |
+Source2: https://ftp.gnu.org/gnu/glibc/glibc-%{glibc_version}.tar.xz |
|
21 |
+%define sha1 glibc=ccb5dc9e51a9884df8488f86982439d47b283b2a |
|
22 |
+Source3: https://ftp.gnu.org/gnu/mpfr/mpfr-4.0.1.tar.gz |
|
23 |
+%define sha1 mpfr=655e3cf416a0cc9530d9cb3c38dc8839504f0e98 |
|
24 |
+Source4: https://ftp.gnu.org/gnu/gmp/gmp-6.1.2.tar.xz |
|
25 |
+%define sha1 gmp=9dc6981197a7d92f339192eea974f5eca48fcffe |
|
26 |
+Source5: https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz |
|
27 |
+%define sha1 mpc=b019d9e1d27ec5fb99497159d43a3164995de2d0 |
|
28 |
+Patch0: libsanitizer-avoidustat.h-glibc-2.28.patch |
|
29 |
+Patch1: PLUGIN_TYPE_CAST.patch |
|
30 |
+BuildArch: x86_64 |
|
31 |
+Provides: libgcc_s.so.1 |
|
32 |
+Provides: libgcc_s.so.1(GCC_3.0) |
|
33 |
+Provides: libgcc_s.so.1(GCC_3.3) |
|
34 |
+Provides: libgcc_s.so.1(GCC_4.2.0) |
|
35 |
+Provides: libgcc_s.so.1(GLIBC_2.0) |
|
36 |
+BuildRequires: binutils-aarch64-linux-gnu |
|
37 |
+Requires: binutils-aarch64-linux-gnu |
|
38 |
+ |
|
39 |
+%global target_arch aarch64-unknown-linux-gnu |
|
40 |
+%global target_linux_arch arm64 |
|
41 |
+%global sysroot /target-aarch64 |
|
42 |
+ |
|
43 |
+%description |
|
44 |
+The GCC package contains the GNU compiler collection, |
|
45 |
+which includes the C and C++ compilers. |
|
46 |
+ |
|
47 |
+%prep |
|
48 |
+%setup -c -q |
|
49 |
+%setup -T -D -q -a 1 |
|
50 |
+%setup -T -D -q -a 2 |
|
51 |
+%setup -T -D -q -a 3 |
|
52 |
+%setup -T -D -q -a 4 |
|
53 |
+%setup -T -D -q -a 5 |
|
54 |
+ |
|
55 |
+cd gcc-%{version} |
|
56 |
+%patch0 -p1 |
|
57 |
+%patch1 -p1 |
|
58 |
+ln -sf `ls -1d ../mpfr-*/` mpfr |
|
59 |
+ln -sf `ls -1d ../gmp-*/` gmp |
|
60 |
+ln -sf `ls -1d ../mpc-*/` mpc |
|
61 |
+ |
|
62 |
+# disable no-pie for gcc binaries |
|
63 |
+sed -i '/^NO_PIE_CFLAGS = /s/@NO_PIE_CFLAGS@//' gcc/Makefile.in |
|
64 |
+ |
|
65 |
+%build |
|
66 |
+ |
|
67 |
+# Create usrmove symlinks |
|
68 |
+mkdir -p %{sysroot}/usr/lib && ln -s usr/lib %{sysroot}/lib |
|
69 |
+mkdir -p %{sysroot}/usr/bin && ln -s usr/bin %{sysroot}/bin |
|
70 |
+mkdir -p %{sysroot}/usr/sbin && ln -s usr/sbin %{sysroot}/sbin |
|
71 |
+ |
|
72 |
+builddir=$RPM_BUILD_DIR/%{name}-%{version} |
|
73 |
+ |
|
74 |
+### |
|
75 |
+### Step 1 |
|
76 |
+### |
|
77 |
+ |
|
78 |
+echo "Step 1. Building Linux headers" |
|
79 |
+ |
|
80 |
+cd $builddir/linux-%{linux_kernel_version} && \ |
|
81 |
+make mrproper && \ |
|
82 |
+make ARCH=%{target_linux_arch} headers_check && \ |
|
83 |
+make ARCH=%{target_linux_arch} \ |
|
84 |
+ INSTALL_HDR_PATH=%{sysroot}%{_prefix} \ |
|
85 |
+ headers_install |
|
86 |
+ |
|
87 |
+### |
|
88 |
+### Step 2 |
|
89 |
+### |
|
90 |
+ |
|
91 |
+echo "Step 2. Building GCC C compiler" |
|
92 |
+ |
|
93 |
+mkdir -p $builddir/build-gcc-%{target_arch} && \ |
|
94 |
+cd $builddir/build-gcc-%{target_arch} && \ |
|
95 |
+$builddir/gcc-%{version}/configure \ |
|
96 |
+ --prefix=%{_prefix} \ |
|
97 |
+ --target=%{target_arch} \ |
|
98 |
+ --with-sysroot=%{sysroot} \ |
|
99 |
+ --enable-plugins \ |
|
100 |
+ --enable-languages=c \ |
|
101 |
+ --enable-threads=posix \ |
|
102 |
+ --enable-linker-build-id \ |
|
103 |
+ --disable-multilib && \ |
|
104 |
+make %{?_smp_mflags} all-gcc && \ |
|
105 |
+make install-gcc |
|
106 |
+ |
|
107 |
+### |
|
108 |
+### Step 3 |
|
109 |
+### |
|
110 |
+ |
|
111 |
+echo "Step 3. Building GLIBC headers and C runtime" |
|
112 |
+ |
|
113 |
+mkdir -p $builddir/build-glibc-%{target_arch} && \ |
|
114 |
+cd $builddir/build-glibc-%{target_arch} && \ |
|
115 |
+$builddir/glibc-%{glibc_version}/configure \ |
|
116 |
+ --prefix=%{_prefix} \ |
|
117 |
+ --libexecdir=/usr/lib/glibc \ |
|
118 |
+ --build=$MACHTYPE \ |
|
119 |
+ --host=%{target_arch} \ |
|
120 |
+ --target=%{target_arch} \ |
|
121 |
+ --with-headers=%{sysroot}/usr/include \ |
|
122 |
+ --disable-multilib \ |
|
123 |
+ libc_cv_forced_unwind=yes && \ |
|
124 |
+make install-bootstrap-headers=yes install-headers install_root=%{sysroot} && \ |
|
125 |
+make %{?_smp_mflags} csu/subdir_lib && \ |
|
126 |
+mkdir -p %{sysroot}/usr/lib && \ |
|
127 |
+install csu/crt1.o csu/crti.o csu/crtn.o \ |
|
128 |
+ %{sysroot}/usr/lib && \ |
|
129 |
+%{target_arch}-gcc \ |
|
130 |
+ -nostdlib \ |
|
131 |
+ -nostartfiles \ |
|
132 |
+ -shared \ |
|
133 |
+ -x c /dev/null \ |
|
134 |
+ -o %{sysroot}/usr/lib/libc.so && \ |
|
135 |
+mkdir -p %{sysroot}/usr/include/gnu && \ |
|
136 |
+touch %{sysroot}/usr/include/gnu/stubs.h |
|
137 |
+ |
|
138 |
+### |
|
139 |
+### Step 4 |
|
140 |
+### |
|
141 |
+ |
|
142 |
+echo "Stage 4. Building GCC compiler support library" |
|
143 |
+ |
|
144 |
+cd $builddir/build-gcc-%{target_arch} && \ |
|
145 |
+$builddir/gcc-%{version}/configure \ |
|
146 |
+ --prefix=%{_prefix} \ |
|
147 |
+ --target=%{target_arch} \ |
|
148 |
+ --with-sysroot=%{sysroot} \ |
|
149 |
+ --enable-shared \ |
|
150 |
+ --enable-threads=posix \ |
|
151 |
+ --enable-__cxa_atexit \ |
|
152 |
+ --enable-clocale=gnu \ |
|
153 |
+ --enable-languages=c,c++,fortran \ |
|
154 |
+ --disable-multilib \ |
|
155 |
+ --enable-linker-build-id \ |
|
156 |
+ --enable-plugin \ |
|
157 |
+ --with-system-zlib && \ |
|
158 |
+make %{?_smp_mflags} all-target-libgcc && \ |
|
159 |
+make install-target-libgcc |
|
160 |
+make %{?_smp_mflags} DESTDIR=%{buildroot} install-target-libgcc |
|
161 |
+ |
|
162 |
+### |
|
163 |
+### Step 5 |
|
164 |
+### |
|
165 |
+ |
|
166 |
+echo "Step 5. Building full GLIBC" |
|
167 |
+ |
|
168 |
+cd $builddir/build-glibc-%{target_arch} && \ |
|
169 |
+make %{?_smp_mflags} && \ |
|
170 |
+make install install_root=%{sysroot} |
|
171 |
+ |
|
172 |
+### |
|
173 |
+### Step 6 |
|
174 |
+### |
|
175 |
+ |
|
176 |
+echo "Step 6. Building full GCC" |
|
177 |
+ |
|
178 |
+cd $builddir/build-gcc-%{target_arch} && \ |
|
179 |
+make %{?_smp_mflags} all && \ |
|
180 |
+make %{?_smp_mflags} DESTDIR=%{buildroot} install |
|
181 |
+ |
|
182 |
+ |
|
183 |
+%install |
|
184 |
+ |
|
185 |
+CROSS_TOOLCHAIN_PKG_CONFIG=%{buildroot}%{_bindir}/%{target_arch}-pkg-config |
|
186 |
+ |
|
187 |
+cat > $CROSS_TOOLCHAIN_PKG_CONFIG << EOF |
|
188 |
+#! /bin/sh |
|
189 |
+ |
|
190 |
+SYSROOT=%{sysroot} |
|
191 |
+ |
|
192 |
+export PKG_CONFIG_DIR= |
|
193 |
+export PKG_CONFIG_LIBDIR=\${SYSROOT}/usr/lib/pkgconfig:\${SYSROOT}/usr/share/pkgconfig |
|
194 |
+export PKG_CONFIG_SYSROOT_DIR=\${SYSROOT} |
|
195 |
+ |
|
196 |
+exec pkg-config "\$@" |
|
197 |
+EOF |
|
198 |
+chmod +x $CROSS_TOOLCHAIN_PKG_CONFIG |
|
199 |
+ |
|
200 |
+%post -p /sbin/ldconfig |
|
201 |
+%postun -p /sbin/ldconfig |
|
202 |
+ |
|
203 |
+%files |
|
204 |
+%defattr(-,root,root) |
|
205 |
+%{_bindir}/* |
|
206 |
+%{_libdir}/* |
|
207 |
+%exclude %{_libdir}/debug |
|
208 |
+%{_lib64dir}/* |
|
209 |
+%{_libexecdir}/* |
|
210 |
+%{_datadir}/* |
|
211 |
+%exclude %{_datadir}/info/dir |
|
212 |
+%{_prefix}/%{target_arch}/* |
|
213 |
+ |
|
214 |
+%changelog |
|
215 |
+* Fri Nov 02 2018 Alexey Makhalov <amakhalov@vmware.com> 7.3.0-1 |
|
216 |
+- Cloned from cross-aarch64-tools.spec |
|
217 |
+* Thu Nov 1 2018 Sriram Nambakam <snambakam@vmware.com> 1.0.0-3 |
|
218 |
+- Updated versions of cross toolchain components |
|
219 |
+* Mon Oct 22 2018 Sriram Nambakam <snambakam@vmware.com> 1.0.0-2 |
|
220 |
+- Replace _sysroot definition with sysroot |
|
221 |
+* Fri Oct 19 2018 Sriram Nambakam <snambakam@vmware.com> 1.0.0 |
|
222 |
+- Initial build. First version |
... | ... |
@@ -53,29 +53,11 @@ class PackageBuilder(object): |
53 | 53 |
else: |
54 | 54 |
tUtils.installToolchainRPMS(self.sandbox, self.package, self.version, availablePackages=self.doneList) |
55 | 55 |
|
56 |
- listDependentPackages, listTestPackages, listInstalledPackages, listInstalledRPMs = ( |
|
57 |
- self._findDependentPackagesAndInstalledRPM(self.sandbox)) |
|
56 |
+ self._installDependencies(constants.buildArch) |
|
57 |
+ if constants.crossCompiling: |
|
58 |
+ self._installDependencies(constants.targetArch) |
|
58 | 59 |
|
59 | 60 |
pkgUtils = PackageUtils(self.logName, self.logPath) |
60 |
- |
|
61 |
- if listDependentPackages: |
|
62 |
- self.logger.debug("Installing the build time dependent packages......") |
|
63 |
- for pkg in listDependentPackages: |
|
64 |
- packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) |
|
65 |
- self._installPackage(pkgUtils, packageName, packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs) |
|
66 |
- for pkg in listTestPackages: |
|
67 |
- flag = False |
|
68 |
- packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) |
|
69 |
- for depPkg in listDependentPackages: |
|
70 |
- depPackageName, depPackageVersion = StringUtils.splitPackageNameAndVersion(depPkg) |
|
71 |
- if depPackageName == packageName: |
|
72 |
- flag = True |
|
73 |
- break; |
|
74 |
- if flag == False: |
|
75 |
- self._installPackage(pkgUtils, packageName,packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs) |
|
76 |
- pkgUtils.installRPMSInOneShot(self.sandbox) |
|
77 |
- self.logger.debug("Finished installing the build time dependent packages....") |
|
78 |
- |
|
79 | 61 |
pkgUtils.adjustGCCSpecs(self.sandbox, self.package, self.version) |
80 | 62 |
pkgUtils.buildRPMSForGivenPackage(self.sandbox, self.package, self.version, |
81 | 63 |
self.logPath) |
... | ... |
@@ -91,11 +73,37 @@ class PackageBuilder(object): |
91 | 91 |
if self.sandbox: |
92 | 92 |
self.sandbox.destroy() |
93 | 93 |
|
94 |
+ def _installDependencies(self, arch, deps=[]): |
|
95 |
+ listDependentPackages, listTestPackages, listInstalledPackages, listInstalledRPMs = ( |
|
96 |
+ self._findDependentPackagesAndInstalledRPM(self.sandbox, arch)) |
|
97 |
+ |
|
98 |
+ # PackageUtils should be initialized here - as per arch basis |
|
99 |
+ # Do not move it to __init__ |
|
100 |
+ pkgUtils = PackageUtils(self.logName, self.logPath) |
|
101 |
+ |
|
102 |
+ if listDependentPackages: |
|
103 |
+ self.logger.debug("Installing the build time dependent packages for " + arch) |
|
104 |
+ for pkg in listDependentPackages: |
|
105 |
+ packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) |
|
106 |
+ self._installPackage(pkgUtils, packageName, packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs, arch) |
|
107 |
+ for pkg in listTestPackages: |
|
108 |
+ flag = False |
|
109 |
+ packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) |
|
110 |
+ for depPkg in listDependentPackages: |
|
111 |
+ depPackageName, depPackageVersion = StringUtils.splitPackageNameAndVersion(depPkg) |
|
112 |
+ if depPackageName == packageName: |
|
113 |
+ flag = True |
|
114 |
+ break; |
|
115 |
+ if flag == False: |
|
116 |
+ self._installPackage(pkgUtils, packageName,packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs, arch) |
|
117 |
+ pkgUtils.installRPMSInOneShot(self.sandbox,arch) |
|
118 |
+ self.logger.debug("Finished installing the build time dependent packages for " + arch) |
|
119 |
+ |
|
94 | 120 |
def _buildPackagePrepareFunction(self, package, version, doneList): |
95 | 121 |
self.package = package |
96 | 122 |
self.version = version |
97 | 123 |
self.logName = "build-" + package + "-" + version |
98 |
- self.logPath = constants.logPath + "/" + package + "-" + version |
|
124 |
+ self.logPath = constants.logPath + "/" + package + "-" + version + "." + constants.currentArch |
|
99 | 125 |
if not os.path.isdir(self.logPath): |
100 | 126 |
cmdUtils = CommandUtils() |
101 | 127 |
cmdUtils.runCommandInShell("mkdir -p " + self.logPath) |
... | ... |
@@ -120,9 +128,9 @@ class PackageBuilder(object): |
120 | 120 |
pkg = rpmfile[0:releaseindex] |
121 | 121 |
return pkg |
122 | 122 |
|
123 |
- def _findInstalledPackages(self, sandbox): |
|
123 |
+ def _findInstalledPackages(self, sandbox, arch): |
|
124 | 124 |
pkgUtils = PackageUtils(self.logName, self.logPath) |
125 |
- listInstalledRPMs = pkgUtils.findInstalledRPMPackages(sandbox) |
|
125 |
+ listInstalledRPMs = pkgUtils.findInstalledRPMPackages(sandbox, arch) |
|
126 | 126 |
listInstalledPackages = [] |
127 | 127 |
for installedRPM in listInstalledRPMs: |
128 | 128 |
pkg = self._findPackageNameAndVersionFromRPMFile(installedRPM) |
... | ... |
@@ -135,18 +143,24 @@ class PackageBuilder(object): |
135 | 135 |
return basePkg in doneList |
136 | 136 |
|
137 | 137 |
|
138 |
- def _findRunTimeRequiredRPMPackages(self, rpmPackage, version): |
|
139 |
- return SPECS.getData().getRequiresForPackage(rpmPackage, version) |
|
138 |
+ def _findRunTimeRequiredRPMPackages(self, rpmPackage, version, arch): |
|
139 |
+ return SPECS.getData(arch).getRequiresForPackage(rpmPackage, version) |
|
140 |
+ |
|
141 |
+ def _findBuildTimeRequiredPackages(self, arch): |
|
142 |
+ deps = SPECS.getData(arch).getBuildRequiresForPackage(self.package, self.version) |
|
140 | 143 |
|
141 |
- def _findBuildTimeRequiredPackages(self): |
|
142 |
- return SPECS.getData().getBuildRequiresForPackage(self.package, self.version) |
|
144 |
+ # Add BuildRequiresNative list |
|
145 |
+ if constants.crossCompiling and arch == constants.buildArch: |
|
146 |
+ deps.extend(SPECS.getData(arch).getBuildRequiresNativeForPackage(self.package, self.version)) |
|
147 |
+ |
|
148 |
+ return deps |
|
143 | 149 |
|
144 | 150 |
def _findBuildTimeCheckRequiredPackages(self): |
145 | 151 |
return SPECS.getData().getCheckBuildRequiresForPackage(self.package, self.version) |
146 | 152 |
|
147 | 153 |
def _installPackage(self, pkgUtils, package, packageVersion, sandbox, destLogPath, |
148 |
- listInstalledPackages, listInstalledRPMs): |
|
149 |
- rpmfile = pkgUtils.findRPMFile(package,packageVersion); |
|
154 |
+ listInstalledPackages, listInstalledRPMs, arch): |
|
155 |
+ rpmfile = pkgUtils.findRPMFile(package,packageVersion,arch); |
|
150 | 156 |
if rpmfile is None: |
151 | 157 |
self.logger.error("No rpm file found for package: " + package + "-" + packageVersion) |
152 | 158 |
raise Exception("Missing rpm file") |
... | ... |
@@ -158,42 +172,46 @@ class PackageBuilder(object): |
158 | 158 |
listInstalledPackages.append(pkg) |
159 | 159 |
listInstalledRPMs.append(specificRPM) |
160 | 160 |
self._installDependentRunTimePackages(pkgUtils, package, packageVersion, sandbox, destLogPath, |
161 |
- listInstalledPackages, listInstalledRPMs) |
|
161 |
+ listInstalledPackages, listInstalledRPMs, arch) |
|
162 | 162 |
noDeps = False |
163 | 163 |
if (package in self.mapPackageToCycles or |
164 | 164 |
package in self.listNodepsPackages or |
165 | 165 |
package in constants.noDepsPackageList): |
166 | 166 |
noDeps = True |
167 |
- pkgUtils.prepRPMforInstall(package,packageVersion, noDeps, destLogPath) |
|
167 |
+ pkgUtils.prepRPMforInstall(package,packageVersion, noDeps, destLogPath, arch) |
|
168 | 168 |
|
169 | 169 |
def _installDependentRunTimePackages(self, pkgUtils, package, packageVersion, sandbox, destLogPath, |
170 |
- listInstalledPackages, listInstalledRPMs): |
|
171 |
- listRunTimeDependentPackages = self._findRunTimeRequiredRPMPackages(package, packageVersion) |
|
170 |
+ listInstalledPackages, listInstalledRPMs, arch): |
|
171 |
+ listRunTimeDependentPackages = self._findRunTimeRequiredRPMPackages(package, packageVersion, arch) |
|
172 | 172 |
if listRunTimeDependentPackages: |
173 | 173 |
for pkg in listRunTimeDependentPackages: |
174 | 174 |
if pkg in self.mapPackageToCycles: |
175 | 175 |
continue |
176 | 176 |
packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg) |
177 |
- rpmfile = pkgUtils.findRPMFile(packageName, packageVersion) |
|
177 |
+ rpmfile = pkgUtils.findRPMFile(packageName, packageVersion, arch, True) |
|
178 | 178 |
if rpmfile is None: |
179 | 179 |
self.logger.error("No rpm file found for package: " + packageName + "-" + packageVersion) |
180 | 180 |
raise Exception("Missing rpm file") |
181 | 181 |
latestPkgRPM = os.path.basename(rpmfile).replace(".rpm", "") |
182 | 182 |
if pkg in listInstalledPackages and latestPkgRPM in listInstalledRPMs: |
183 | 183 |
continue |
184 |
- self._installPackage(pkgUtils, packageName,packageVersion, sandbox, destLogPath,listInstalledPackages, listInstalledRPMs) |
|
184 |
+ self._installPackage(pkgUtils, packageName,packageVersion, sandbox, destLogPath,listInstalledPackages, listInstalledRPMs, arch) |
|
185 | 185 |
|
186 |
- def _findDependentPackagesAndInstalledRPM(self, sandbox): |
|
187 |
- listInstalledPackages, listInstalledRPMs = self._findInstalledPackages(sandbox) |
|
186 |
+ def _findDependentPackagesAndInstalledRPM(self, sandbox, arch): |
|
187 |
+ listInstalledPackages, listInstalledRPMs = self._findInstalledPackages(sandbox, arch) |
|
188 | 188 |
self.logger.debug(listInstalledPackages) |
189 |
- listDependentPackages = self._findBuildTimeRequiredPackages() |
|
189 |
+ if constants.crossCompiling and arch == constants.buildArch: |
|
190 |
+ listDependentPackages = self._findBuildTimeRequiredPackages(constants.targetArch) |
|
191 |
+ # TODO remove unsupported by buildArch packages from this list |
|
192 |
+ else: |
|
193 |
+ listDependentPackages = self._findBuildTimeRequiredPackages(arch) |
|
190 | 194 |
listTestPackages=[] |
191 | 195 |
if constants.rpmCheck and self.package in constants.testForceRPMS: |
192 | 196 |
# One time optimization |
193 | 197 |
if constants.listMakeCheckRPMPkgWithVersionstoInstall is None: |
194 | 198 |
constants.listMakeCheckRPMPkgWithVersionstoInstall=[] |
195 | 199 |
for package in constants.listMakeCheckRPMPkgtoInstall: |
196 |
- version = SPECS.getData().getHighestVersion(package) |
|
200 |
+ version = SPECS.getData(arch).getHighestVersion(package) |
|
197 | 201 |
constants.listMakeCheckRPMPkgWithVersionstoInstall.append(package+"-"+version) |
198 | 202 |
|
199 | 203 |
listDependentPackages.extend(self._findBuildTimeCheckRequiredPackages()) |
... | ... |
@@ -46,18 +46,20 @@ class PackageManager(object): |
46 | 46 |
|
47 | 47 |
def buildToolChainPackages(self, buildThreads): |
48 | 48 |
pkgCount = self.buildToolChain() |
49 |
- if self.pkgBuildType == "container": |
|
50 |
- # Stage 1 build container |
|
51 |
- #TODO image name constants.buildContainerImageName |
|
52 |
- if pkgCount > 0 or not self.dockerClient.images.list(constants.buildContainerImage): |
|
53 |
- self._createBuildContainer(True) |
|
54 |
- self.logger.info("Step 2 : Building stage 2 of the toolchain...") |
|
55 |
- self.logger.info(constants.listToolChainPackages) |
|
56 |
- self.logger.info("") |
|
57 |
- self._buildGivenPackages(constants.listToolChainPackages, buildThreads) |
|
58 |
- self.logger.info("The entire toolchain is now available") |
|
59 |
- self.logger.info(45 * '-') |
|
60 |
- self.logger.info("") |
|
49 |
+ # Stage 2 makes sence only for native tools |
|
50 |
+ if not constants.crossCompiling: |
|
51 |
+ if self.pkgBuildType == "container": |
|
52 |
+ # Stage 1 build container |
|
53 |
+ #TODO image name constants.buildContainerImageName |
|
54 |
+ if pkgCount > 0 or not self.dockerClient.images.list(constants.buildContainerImage): |
|
55 |
+ self._createBuildContainer(True) |
|
56 |
+ self.logger.info("Step 2 : Building stage 2 of the toolchain...") |
|
57 |
+ self.logger.info(constants.listToolChainPackages) |
|
58 |
+ self.logger.info("") |
|
59 |
+ self._buildGivenPackages(constants.listToolChainPackages, buildThreads) |
|
60 |
+ self.logger.info("The entire toolchain is now available") |
|
61 |
+ self.logger.info(45 * '-') |
|
62 |
+ self.logger.info("") |
|
61 | 63 |
if self.pkgBuildType == "container": |
62 | 64 |
# Stage 2 build container |
63 | 65 |
#TODO: rebuild container only if anything in listToolChainPackages was built |
... | ... |
@@ -1,5 +1,4 @@ |
1 | 1 |
import os |
2 |
-import platform |
|
3 | 2 |
import shutil |
4 | 3 |
import re |
5 | 4 |
import random |
... | ... |
@@ -39,8 +38,10 @@ class PackageUtils(object): |
39 | 39 |
self.noDepsPackagesToInstallInAOneShot = "" |
40 | 40 |
self.logfnvalue = None |
41 | 41 |
|
42 |
- def prepRPMforInstall(self, package, version, noDeps=False, destLogPath=None): |
|
43 |
- rpmfile = self.findRPMFile(package, version) |
|
42 |
+ def prepRPMforInstall(self, package, version, noDeps=False, destLogPath=None, arch=None): |
|
43 |
+ if not arch: |
|
44 |
+ arch=constants.currentArch |
|
45 |
+ rpmfile = self.findRPMFile(package, version, arch) |
|
44 | 46 |
if rpmfile is None: |
45 | 47 |
self.logger.error("No rpm file found for package: " + package) |
46 | 48 |
raise Exception("Missing rpm file") |
... | ... |
@@ -59,7 +60,7 @@ class PackageUtils(object): |
59 | 59 |
if "noarch" in rpmfile: |
60 | 60 |
rpmDestFile += "noarch/" |
61 | 61 |
else: |
62 |
- rpmDestFile += platform.machine()+"/" |
|
62 |
+ rpmDestFile += arch+"/" |
|
63 | 63 |
rpmDestFile += rpmName |
64 | 64 |
|
65 | 65 |
if noDeps: |
... | ... |
@@ -69,8 +70,11 @@ class PackageUtils(object): |
69 | 69 |
self.rpmFilesToInstallInAOneShot += " " + rpmDestFile |
70 | 70 |
self.packagesToInstallInAOneShot += " " + package |
71 | 71 |
|
72 |
- def installRPMSInOneShot(self, sandbox): |
|
72 |
+ def installRPMSInOneShot(self, sandbox, arch): |
|
73 | 73 |
rpmInstallcmd = self.rpmBinary + " " + self.installRPMPackageOptions |
74 |
+ if constants.crossCompiling and arch == constants.targetArch: |
|
75 |
+ rpmInstallcmd += " --ignorearch --noscripts --root /target-" + constants.targetArch |
|
76 |
+ |
|
74 | 77 |
# TODO: Container sandbox might need + self.forceRpmPackageOptions |
75 | 78 |
if self.noDepsRPMFilesToInstallInAOneShot != "": |
76 | 79 |
self.logger.debug("Installing nodeps rpms: " + |
... | ... |
@@ -142,12 +146,15 @@ class PackageUtils(object): |
142 | 142 |
CommandUtils().runCommandInShell(cmd, logfn=self.logger.debug) |
143 | 143 |
self.logger.debug("RPM build is successful") |
144 | 144 |
|
145 |
- def findRPMFile(self, package,version="*"): |
|
145 |
+ def findRPMFile(self, package,version="*",arch=None, throw=False): |
|
146 |
+ if not arch: |
|
147 |
+ arch=constants.currentArch |
|
148 |
+ |
|
146 | 149 |
cmdUtils = CommandUtils() |
147 | 150 |
if version == "*": |
148 |
- version = SPECS.getData().getHighestVersion(package) |
|
149 |
- release = SPECS.getData().getRelease(package, version) |
|
150 |
- buildarch=SPECS.getData().getBuildArch(package, version) |
|
151 |
+ version = SPECS.getData(arch).getHighestVersion(package) |
|
152 |
+ release = SPECS.getData(arch).getRelease(package, version) |
|
153 |
+ buildarch=SPECS.getData(arch).getBuildArch(package, version) |
|
151 | 154 |
filename= package + "-" + version + "-" + release + "." + buildarch+".rpm" |
152 | 155 |
|
153 | 156 |
fullpath = constants.rpmPath + "/" + buildarch + "/" + filename |
... | ... |
@@ -159,18 +166,23 @@ class PackageUtils(object): |
159 | 159 |
if os.path.isfile(fullpath): |
160 | 160 |
return fullpath |
161 | 161 |
|
162 |
+ if throw: |
|
163 |
+ raise Exception("RPM %s not found" % (filename)) |
|
162 | 164 |
return None |
163 | 165 |
|
164 |
- def findInstalledRPMPackages(self, sandbox): |
|
166 |
+ def findInstalledRPMPackages(self, sandbox, arch): |
|
165 | 167 |
rpms = None |
166 | 168 |
def setOutValue(data): |
167 | 169 |
nonlocal rpms |
168 | 170 |
rpms = data |
169 | 171 |
cmd = self.rpmBinary + " " + self.queryRpmPackageOptions |
172 |
+ if constants.crossCompiling and arch == constants.targetArch: |
|
173 |
+ cmd += " --root /target-" + constants.targetArch |
|
170 | 174 |
sandbox.run(cmd, logfn=setOutValue) |
171 | 175 |
return rpms.split() |
172 | 176 |
|
173 | 177 |
def adjustGCCSpecs(self, sandbox, package, version): |
178 |
+ # TODO: need to harden cross compiller also |
|
174 | 179 |
opt = " " + SPECS.getData().getSecurityHardeningOption(package, version) |
175 | 180 |
sandbox.put(self.adjustGCCSpecScript, "/tmp") |
176 | 181 |
cmd = "/tmp/" + self.adjustGCCSpecScript + opt |
... | ... |
@@ -257,6 +269,12 @@ class PackageUtils(object): |
257 | 257 |
|
258 | 258 |
for macro in macros: |
259 | 259 |
rpmBuildcmd += ' --define \"%s\"' % macro |
260 |
+ |
|
261 |
+ if constants.crossCompiling: |
|
262 |
+ rpmBuildcmd += ' --define \"_build %s-unknown-linux-gnu\"' % constants.buildArch |
|
263 |
+ rpmBuildcmd += ' --define \"_host %s-unknown-linux-gnu\"' % constants.targetArch |
|
264 |
+ rpmBuildcmd += ' --target='+constants.targetArch+'-unknown-linux-gnu' |
|
265 |
+ |
|
260 | 266 |
rpmBuildcmd += " " + specFile |
261 | 267 |
|
262 | 268 |
self.logger.debug("Building rpm....") |
... | ... |
@@ -1,5 +1,4 @@ |
1 | 1 |
import os |
2 |
-import platform |
|
3 | 2 |
import queue |
4 | 3 |
import json |
5 | 4 |
import operator |
... | ... |
@@ -13,8 +12,8 @@ from SpecParser import SpecParser |
13 | 13 |
|
14 | 14 |
class SpecData(object): |
15 | 15 |
|
16 |
- def __init__(self, logPath, specFilesPath): |
|
17 |
- |
|
16 |
+ def __init__(self, arch, logPath, specFilesPath): |
|
17 |
+ self.arch = arch |
|
18 | 18 |
self.logger = Logger.getLogger("SpecData", logPath, constants.logLevel) |
19 | 19 |
|
20 | 20 |
# map default package name to list of SpecObjects. Usually it is just |
... | ... |
@@ -36,12 +35,12 @@ class SpecData(object): |
36 | 36 |
# creates corresponding SpecObjects and put them in internal mappings. |
37 | 37 |
def _readSpecs(self, specFilesPath): |
38 | 38 |
for specFile in self._getListSpecFiles(specFilesPath): |
39 |
- spec = SpecParser(specFile) |
|
39 |
+ spec = SpecParser(specFile, self.arch) |
|
40 | 40 |
|
41 | 41 |
# skip the specfile if buildarch differs |
42 | 42 |
buildarch = spec.packages.get('default').buildarch |
43 | 43 |
if (buildarch != "noarch" and |
44 |
- platform.machine() != buildarch): |
|
44 |
+ buildarch != self.arch): |
|
45 | 45 |
self.logger.info("skipping spec file: "+str(specFile)) |
46 | 46 |
continue |
47 | 47 |
|
... | ... |
@@ -136,6 +135,13 @@ class SpecData(object): |
136 | 136 |
packages.append(pkg.package) |
137 | 137 |
return packages |
138 | 138 |
|
139 |
+ def getBuildRequiresNativeForPackage(self, package, version): |
|
140 |
+ packages=[] |
|
141 |
+ for pkg in self._getSpecObjField(package, version, field=lambda x : x.buildRequiresNative): |
|
142 |
+ properVersion = self._getProperVersion(pkg) |
|
143 |
+ packages.append(pkg.package+"-"+properVersion) |
|
144 |
+ return packages |
|
145 |
+ |
|
139 | 146 |
def getBuildRequiresForPkg(self, pkg): |
140 | 147 |
package, version = StringUtils.splitPackageNameAndVersion(pkg) |
141 | 148 |
return self.getBuildRequiresForPackage(package, version) |
... | ... |
@@ -293,19 +299,23 @@ class SpecData(object): |
293 | 293 |
self.logger.debug(self.getPkgNamesFromObj(specObj.installRequires)) |
294 | 294 |
self.logger.debug(specObj.installRequiresPackages) |
295 | 295 |
self.logger.debug("security_hardening: " + specObj.securityHardening) |
296 |
+ self.logger.debug("BuildArch: " + str(specObj.buildarch)) |
|
296 | 297 |
self.logger.debug("------------------------------------------------") |
297 | 298 |
|
298 | 299 |
|
299 | 300 |
class SPECS(object): |
300 | 301 |
__instance = None |
301 |
- specData = None |
|
302 |
+ specData = {} |
|
302 | 303 |
|
303 | 304 |
@staticmethod |
304 |
- def getData(): |
|
305 |
+ def getData(arch=None): |
|
306 |
+ if not arch: |
|
307 |
+ arch=constants.currentArch |
|
308 |
+ |
|
305 | 309 |
""" Static access method. """ |
306 | 310 |
if SPECS.__instance is None: |
307 | 311 |
SPECS() |
308 |
- return SPECS.__instance.specData |
|
312 |
+ return SPECS.__instance.specData[arch] |
|
309 | 313 |
|
310 | 314 |
def __init__(self): |
311 | 315 |
""" Virtually private constructor. """ |
... | ... |
@@ -319,7 +329,7 @@ class SPECS(object): |
319 | 319 |
# Preparse some files |
320 | 320 |
|
321 | 321 |
# adding kernelversion rpm macro |
322 |
- spec = SpecParser(constants.specPath + "/linux/linux.spec") |
|
322 |
+ spec = SpecParser(constants.specPath + "/linux/linux.spec", constants.buildArch) |
|
323 | 323 |
defPkg = spec.packages.get('default') |
324 | 324 |
kernelversion = defPkg.version |
325 | 325 |
constants.addMacro("KERNEL_VERSION", kernelversion) |
... | ... |
@@ -338,5 +348,11 @@ class SPECS(object): |
338 | 338 |
constants.addMacro("kernelsubrelease", kernelsubrelease) |
339 | 339 |
|
340 | 340 |
# Full parsing |
341 |
- self.specData = SpecData(constants.logPath, constants.specPath) |
|
342 |
- |
|
341 |
+ self.specData[constants.buildArch] = SpecData(constants.buildArch, |
|
342 |
+ constants.logPath, |
|
343 |
+ constants.specPath) |
|
344 |
+ |
|
345 |
+ if constants.buildArch != constants.targetArch: |
|
346 |
+ self.specData[constants.targetArch] = SpecData(constants.targetArch, |
|
347 |
+ constants.logPath, |
|
348 |
+ constants.specPath) |
... | ... |
@@ -1,6 +1,5 @@ |
1 | 1 |
# pylint: disable=invalid-name,missing-docstring |
2 | 2 |
import re |
3 |
-import platform |
|
4 | 3 |
from StringUtils import StringUtils |
5 | 4 |
from SpecStructures import dependentPackageData, Package, SpecObject |
6 | 5 |
from constants import constants |
... | ... |
@@ -15,7 +14,8 @@ class SpecParser(object): |
15 | 15 |
self.position = -1 |
16 | 16 |
self.endposition = -1 |
17 | 17 |
|
18 |
- def __init__(self, specfile): |
|
18 |
+ def __init__(self, specfile, arch): |
|
19 |
+ self.arch = arch |
|
19 | 20 |
self.cleanMacro = None |
20 | 21 |
self.prepMacro = None |
21 | 22 |
self.buildMacro = None |
... | ... |
@@ -26,6 +26,7 @@ class SpecParser(object): |
26 | 26 |
self.specAdditionalContent = "" |
27 | 27 |
self.globalSecurityHardening = "" |
28 | 28 |
self.defs = {} |
29 |
+ self.defs["_arch"] = arch |
|
29 | 30 |
self.conditionalCheckMacroEnabled = False |
30 | 31 |
self.macro_pattern = re.compile(r'%{(\S+?)\}') |
31 | 32 |
self.specfile = specfile |
... | ... |
@@ -33,7 +34,7 @@ class SpecParser(object): |
33 | 33 |
self._parseSpecFile() |
34 | 34 |
|
35 | 35 |
def _parseSpecFile(self): |
36 |
- self.packages["default"] = Package() |
|
36 |
+ self.packages["default"] = Package(self.arch) |
|
37 | 37 |
currentPkg = "default" |
38 | 38 |
with open(self.specfile) as specFile: |
39 | 39 |
lines = specFile.readlines() |
... | ... |
@@ -42,7 +43,7 @@ class SpecParser(object): |
42 | 42 |
while i < totalLines: |
43 | 43 |
line = lines[i].strip() |
44 | 44 |
if self._isConditionalArch(line): |
45 |
- if platform.machine() != self._readConditionalArch(line): |
|
45 |
+ if self.arch != self._readConditionalArch(line): |
|
46 | 46 |
# skip conditional body |
47 | 47 |
deep = 1 |
48 | 48 |
while i < totalLines and deep != 0: |
... | ... |
@@ -74,7 +75,7 @@ class SpecParser(object): |
74 | 74 |
if not returnVal: |
75 | 75 |
return False |
76 | 76 |
if line.startswith('%package'): |
77 |
- pkg = Package(defaultpkg) |
|
77 |
+ pkg = Package(self.arch, defaultpkg) |
|
78 | 78 |
pkg.name = packageName |
79 | 79 |
currentPkg = packageName |
80 | 80 |
self.packages[pkg.name] = pkg |
... | ... |
@@ -94,6 +95,8 @@ class SpecParser(object): |
94 | 94 |
self._readChecksum(line, self.packages[currentPkg]) |
95 | 95 |
elif self._isExtraBuildRequires(line): |
96 | 96 |
self._readExtraBuildRequires(line, self.packages[currentPkg]) |
97 |
+ elif self._isBuildRequiresNative(line): |
|
98 |
+ self._readBuildRequiresNative(line, self.packages[currentPkg]) |
|
97 | 99 |
elif self._isDefinition(line): |
98 | 100 |
self._readDefinition(line) |
99 | 101 |
elif self._isConditionalCheckMacro(line): |
... | ... |
@@ -272,6 +275,11 @@ class SpecParser(object): |
272 | 272 |
return True |
273 | 273 |
return False |
274 | 274 |
|
275 |
+ def _isBuildRequiresNative(self, line): |
|
276 |
+ if re.search('^%define *buildrequiresnative', line, flags=re.IGNORECASE): |
|
277 |
+ return True |
|
278 |
+ return False |
|
279 |
+ |
|
275 | 280 |
def _isChecksum(self, line): |
276 | 281 |
if re.search('^%define *sha1', line, flags=re.IGNORECASE): |
277 | 282 |
return True |
... | ... |
@@ -439,6 +447,18 @@ class SpecParser(object): |
439 | 439 |
pkg.extrabuildrequires.extend(dpkg) |
440 | 440 |
return True |
441 | 441 |
|
442 |
+ def _readBuildRequiresNative(self, line, pkg): |
|
443 |
+ data = line.strip() |
|
444 |
+ words = data.split(" ", 2) |
|
445 |
+ if len(words) != 3: |
|
446 |
+ print("Error: Unable to parse line: " + line) |
|
447 |
+ return False |
|
448 |
+ dpkg = self._readDependentPackageData(words[2]) |
|
449 |
+ if dpkg is None: |
|
450 |
+ return False |
|
451 |
+ pkg.buildrequiresnative.extend(dpkg) |
|
452 |
+ return True |
|
453 |
+ |
|
442 | 454 |
def _readChecksum(self, line, pkg): |
443 | 455 |
strUtils = StringUtils() |
444 | 456 |
line = self._replaceMacros(line) |
... | ... |
@@ -532,6 +552,12 @@ class SpecParser(object): |
532 | 532 |
dependentPackages.extend(pkg.extrabuildrequires) |
533 | 533 |
return dependentPackages |
534 | 534 |
|
535 |
+ def _getBuildRequiresNative(self): |
|
536 |
+ dependentPackages = [] |
|
537 |
+ for pkg in self.packages.values(): |
|
538 |
+ dependentPackages.extend(pkg.buildrequiresnative) |
|
539 |
+ return dependentPackages |
|
540 |
+ |
|
535 | 541 |
def _getPackageNames(self): |
536 | 542 |
packageNames = [] |
537 | 543 |
for pkg in self.packages.values(): |
... | ... |
@@ -589,6 +615,7 @@ class SpecParser(object): |
589 | 589 |
specObj.installRequires = self._getRequiresTypeAllPackages("install") |
590 | 590 |
specObj.checkBuildRequires = self._getCheckBuildRequiresAllPackages() |
591 | 591 |
specObj.extraBuildRequires = self._getExtraBuildRequires() |
592 |
+ specObj.buildRequiresNative = self._getBuildRequiresNative() |
|
592 | 593 |
specObj.listPackages = self._getPackageNames() |
593 | 594 |
specObj.listSources = self._getSourceNames() |
594 | 595 |
specObj.listPatches = self._getPatchNames() |
... | ... |
@@ -1,4 +1,3 @@ |
1 |
-import platform |
|
2 | 1 |
|
3 | 2 |
class dependentPackageData(object): |
4 | 3 |
|
... | ... |
@@ -8,14 +7,14 @@ class dependentPackageData(object): |
8 | 8 |
self.compare = "" |
9 | 9 |
|
10 | 10 |
class Package(object): |
11 |
- def __init__(self, basePkg=None): |
|
11 |
+ def __init__(self, buildarch, basePkg=None): |
|
12 | 12 |
self.summary = "" |
13 | 13 |
self.name = "" |
14 | 14 |
self.group = "" |
15 | 15 |
self.license = "" |
16 | 16 |
self.version = "" |
17 | 17 |
self.release = "" |
18 |
- self.buildarch = platform.machine() |
|
18 |
+ self.buildarch = buildarch |
|
19 | 19 |
self.distribution = "Photon" |
20 | 20 |
self.basePkgName = "" |
21 | 21 |
self.URL = "" |
... | ... |
@@ -27,6 +26,7 @@ class Package(object): |
27 | 27 |
self.buildprovides = [] |
28 | 28 |
self.checkbuildrequires = [] |
29 | 29 |
self.extrabuildrequires = [] |
30 |
+ self.buildrequiresnative = [] |
|
30 | 31 |
|
31 | 32 |
self.requires = [] |
32 | 33 |
self.provides = [] |
... | ... |
@@ -70,11 +70,12 @@ class SpecObject(object): |
70 | 70 |
# list of subpackage names that have %files section |
71 | 71 |
self.listRPMPackages = [] |
72 | 72 |
|
73 |
- # Next four lists store dependentPackageData objects |
|
73 |
+ # Next five lists store dependentPackageData objects |
|
74 | 74 |
self.buildRequires = [] |
75 | 75 |
self.installRequires = [] |
76 | 76 |
self.checkBuildRequires = [] |
77 | 77 |
self.extraBuildRequires = [] |
78 |
+ self.buildRequiresNative = [] |
|
78 | 79 |
# map subpackage name to list of install requires |
79 | 80 |
# dependentPackageData objects |
80 | 81 |
self.installRequiresPackages = {} |
... | ... |
@@ -1,5 +1,4 @@ |
1 | 1 |
import os.path |
2 |
-import platform |
|
3 | 2 |
import traceback |
4 | 3 |
import re |
5 | 4 |
from CommandUtils import CommandUtils |
... | ... |
@@ -44,7 +43,7 @@ class ToolChainUtils(object): |
44 | 44 |
return None |
45 | 45 |
|
46 | 46 |
def buildCoreToolChainPackages(self): |
47 |
- self.logger.info("Step 1 : Building the core toolchain packages.....") |
|
47 |
+ self.logger.info("Step 1 : Building the core toolchain packages for " + constants.currentArch) |
|
48 | 48 |
self.logger.info(constants.listCoreToolChainPackages) |
49 | 49 |
self.logger.info("") |
50 | 50 |
chroot = None |
... | ... |
@@ -70,7 +69,7 @@ class ToolChainUtils(object): |
70 | 70 |
for package in coreToolChainYetToBuild: |
71 | 71 |
self.logger.debug("Building core toolchain package : " + package) |
72 | 72 |
version = SPECS.getData().getHighestVersion(package) |
73 |
- destLogPath = constants.logPath + "/" + package + "-" + version |
|
73 |
+ destLogPath = constants.logPath + "/" + package + "-" + version + "." + constants.currentArch |
|
74 | 74 |
if not os.path.isdir(destLogPath): |
75 | 75 |
CommandUtils.runCommandInShell("mkdir -p " + destLogPath) |
76 | 76 |
chroot = Chroot(self.logger) |
... | ... |
@@ -91,8 +90,8 @@ class ToolChainUtils(object): |
91 | 91 |
return pkgCount |
92 | 92 |
|
93 | 93 |
def getListDependentPackages(self, package, version): |
94 |
- listBuildRequiresPkg=SPECS.getData().getBuildRequiresForPackage(package, version) |
|
95 |
- listBuildRequiresPkg.extend(SPECS.getData().getCheckBuildRequiresForPackage(package, version)) |
|
94 |
+ listBuildRequiresPkg=SPECS.getData(constants.buildArch).getBuildRequiresForPackage(package, version) |
|
95 |
+ listBuildRequiresPkg.extend(SPECS.getData(constants.buildArch).getCheckBuildRequiresForPackage(package, version)) |
|
96 | 96 |
return listBuildRequiresPkg |
97 | 97 |
|
98 | 98 |
def installToolchainRPMS(self, chroot, packageName=None, packageVersion=None, usePublishedRPMS=True, availablePackages=None): |
... | ... |
@@ -100,9 +99,17 @@ class ToolChainUtils(object): |
100 | 100 |
rpmFiles = "" |
101 | 101 |
packages = "" |
102 | 102 |
listBuildRequiresPackages = [] |
103 |
+ |
|
104 |
+ listRPMsToInstall=list(constants.listToolChainRPMsToInstall) |
|
105 |
+ if constants.crossCompiling: |
|
106 |
+ targetPackageName = packageName |
|
107 |
+ packageName = None |
|
108 |
+ packageVersion = None |
|
109 |
+ listRPMsToInstall.extend(['binutils-'+constants.targetArch+'-linux-gnu', |
|
110 |
+ 'gcc-'+constants.targetArch+'-linux-gnu']) |
|
103 | 111 |
if packageName: |
104 | 112 |
listBuildRequiresPackages = self.getListDependentPackages(packageName, packageVersion) |
105 |
- for package in constants.listToolChainRPMsToInstall: |
|
113 |
+ for package in listRPMsToInstall: |
|
106 | 114 |
pkgUtils = PackageUtils(self.logName, self.logPath) |
107 | 115 |
rpmFile = None |
108 | 116 |
version = None |
... | ... |
@@ -113,11 +120,12 @@ class ToolChainUtils(object): |
113 | 113 |
if depPkgName == package: |
114 | 114 |
version=depPkgVersion |
115 | 115 |
break |
116 |
+ |
|
116 | 117 |
if not version: |
117 |
- version = SPECS.getData().getHighestVersion(package) |
|
118 |
+ version = SPECS.getData(constants.buildArch).getHighestVersion(package) |
|
118 | 119 |
|
119 | 120 |
if availablePackages is not None: |
120 |
- basePkg = SPECS.getData().getSpecName(package)+"-"+version |
|
121 |
+ basePkg = SPECS.getData(constants.buildArch).getSpecName(package)+"-"+version |
|
121 | 122 |
isAvailable = basePkg in availablePackages |
122 | 123 |
else: |
123 | 124 |
# if availablePackages is not provided (rear case) it is safe |
... | ... |
@@ -125,7 +133,7 @@ class ToolChainUtils(object): |
125 | 125 |
isAvailable = True |
126 | 126 |
|
127 | 127 |
if constants.rpmCheck: |
128 |
- rpmFile = pkgUtils.findRPMFile(package, version) |
|
128 |
+ rpmFile = pkgUtils.findRPMFile(package, version, constants.buildArch) |
|
129 | 129 |
|
130 | 130 |
if rpmFile is None: |
131 | 131 |
# Honor the toolchain list order. |
... | ... |
@@ -134,19 +142,21 @@ class ToolChainUtils(object): |
134 | 134 |
# building ('packageName'), then we _must_ use published |
135 | 135 |
# `package` rpm. |
136 | 136 |
if (packageName and |
137 |
- packageName in constants.listToolChainRPMsToInstall and |
|
138 |
- constants.listToolChainRPMsToInstall.index(packageName) < |
|
139 |
- constants.listToolChainRPMsToInstall.index(package)): |
|
137 |
+ packageName in listRPMsToInstall and |
|
138 |
+ listRPMsToInstall.index(packageName) < |
|
139 |
+ listRPMsToInstall.index(package)): |
|
140 | 140 |
isAvailable = False |
141 | 141 |
if isAvailable: |
142 |
- rpmFile = pkgUtils.findRPMFile(package, version) |
|
142 |
+ rpmFile = pkgUtils.findRPMFile(package, version, constants.buildArch) |
|
143 | 143 |
|
144 | 144 |
if rpmFile is None: |
145 |
- if not usePublishedRPMS or isAvailable: |
|
146 |
- raise Exception("%s-%s not found in available packages" % (package, version)) |
|
145 |
+ if not usePublishedRPMS or isAvailable or constants.crossCompiling: |
|
146 |
+ raise Exception("%s-%s.%s not found in available packages" % (package, version, constants.buildArch)) |
|
147 |
+ |
|
148 |
+ # Safe to use published RPM |
|
147 | 149 |
|
148 | 150 |
# sqlite-autoconf package was renamed, but it still published as sqlite-autoconf |
149 |
- if (package == "sqlite") and (platform.machine() == "x86_64"): |
|
151 |
+ if (package == "sqlite") and (constants.buildArch == "x86_64"): |
|
150 | 152 |
package = "sqlite-autoconf" |
151 | 153 |
rpmFile = self._findPublishedRPM(package, constants.prevPublishRPMRepo) |
152 | 154 |
if rpmFile is None: |
... | ... |
@@ -159,6 +169,7 @@ class ToolChainUtils(object): |
159 | 159 |
rpmFiles += " " + rpmFile |
160 | 160 |
packages += " " + package+"-"+version |
161 | 161 |
|
162 |
+ self.logger.debug(rpmFiles) |
|
162 | 163 |
self.logger.debug(packages) |
163 | 164 |
cmd = (self.rpmCommand + " -i -v --nodeps --noorder --force --root " + |
164 | 165 |
chroot.getID() +" --define \'_dbpath /var/lib/rpm\' "+ rpmFiles) |
... | ... |
@@ -168,14 +179,18 @@ class ToolChainUtils(object): |
168 | 168 |
self.logger.error("Installing toolchain RPMS failed") |
169 | 169 |
raise Exception("RPM installation failed") |
170 | 170 |
self.logger.debug("Successfully installed default toolchain RPMS in Chroot:" + chroot.getID()) |
171 |
+ |
|
171 | 172 |
if packageName: |
172 | 173 |
self.installExtraToolchainRPMS(chroot, packageName, packageVersion) |
173 | 174 |
|
175 |
+ if constants.crossCompiling: |
|
176 |
+ self.installTargetToolchain(chroot, targetPackageName) |
|
177 |
+ |
|
174 | 178 |
def installExtraToolchainRPMS(self, sandbox, packageName, packageVersion): |
175 |
- listOfToolChainPkgs = SPECS.getData().getExtraBuildRequiresForPackage(packageName, packageVersion) |
|
179 |
+ listOfToolChainPkgs = SPECS.getData(constants.buildArch).getExtraBuildRequiresForPackage(packageName, packageVersion) |
|
176 | 180 |
if not listOfToolChainPkgs: |
177 | 181 |
return |
178 |
- self.logger.debug("Installing package specific toolchain RPMS for " + packageName + |
|
182 |
+ self.logger.debug("Installing package specific toolchain RPMs for " + packageName + |
|
179 | 183 |
": " + str(listOfToolChainPkgs)) |
180 | 184 |
rpmFiles = "" |
181 | 185 |
packages = "" |
... | ... |
@@ -202,3 +217,39 @@ class ToolChainUtils(object): |
202 | 202 |
self.logger.debug("Command Executed:" + cmd) |
203 | 203 |
self.logger.error("Installing custom toolchains failed") |
204 | 204 |
raise Exception("RPM installation failed") |
205 |
+ |
|
206 |
+ # Install target's core toolchain packages up to 'stopAtPackage' package |
|
207 |
+ def installTargetToolchain(self, chroot, stopAtPackage=None): |
|
208 |
+ self.logger.debug("Installing target toolchain RPMS.......") |
|
209 |
+ pkgUtils = PackageUtils(self.logName, self.logPath) |
|
210 |
+ rpmFiles = "" |
|
211 |
+ packages = "" |
|
212 |
+ for package in constants.listCoreToolChainPackages: |
|
213 |
+ if stopAtPackage and package == stopAtPackage: |
|
214 |
+ break |
|
215 |
+ version = SPECS.getData().getHighestVersion(package) |
|
216 |
+ basePkg = SPECS.getData().getSpecName(package) |
|
217 |
+ # install all subpackages of given package |
|
218 |
+ # for instance: for 'glibc' we want glibc-devel, glibc-tools, |
|
219 |
+ # glibc-i18n, etc also to be installed |
|
220 |
+ subpackages = SPECS.getData().getRPMPackages(basePkg, version) |
|
221 |
+ for p in subpackages: |
|
222 |
+ rpmFile = pkgUtils.findRPMFile(p, version, constants.targetArch) |
|
223 |
+ rpmFiles += " " + rpmFile |
|
224 |
+ packages += " " + package+"-"+version |
|
225 |
+ |
|
226 |
+ self.logger.debug(packages) |
|
227 |
+ |
|
228 |
+ cmd = "mkdir -p " + chroot.getID() +"/target-"+ constants.targetArch+"/var/lib/rpm" |
|
229 |
+ CommandUtils.runCommandInShell(cmd, logfn=self.logger.debug) |
|
230 |
+ |
|
231 |
+ if rpmFiles != "": |
|
232 |
+ cmd = (self.rpmCommand+" -Uvh --nodeps --ignorearch --noscripts --root "+ |
|
233 |
+ chroot.getID() +"/target-"+ constants.targetArch+ |
|
234 |
+ " --define \'_dbpath /var/lib/rpm\' "+rpmFiles) |
|
235 |
+ retVal = CommandUtils.runCommandInShell(cmd, logfn=self.logger.debug) |
|
236 |
+ if retVal != 0: |
|
237 |
+ self.logger.debug("Command Executed:" + cmd) |
|
238 |
+ self.logger.error("Installing toolchain failed") |
|
239 |
+ raise Exception("RPM installation failed") |
|
240 |
+ self.logger.debug("Successfully installed target toolchain RPMS in chroot:" + chroot.getID()) |
... | ... |
@@ -2,7 +2,6 @@ |
2 | 2 |
|
3 | 3 |
from argparse import ArgumentParser |
4 | 4 |
import os.path |
5 |
-import platform |
|
6 | 5 |
import collections |
7 | 6 |
import traceback |
8 | 7 |
import sys |
... | ... |
@@ -57,6 +56,7 @@ def main(): |
57 | 57 |
default="../../common/data/packageWeights.json") |
58 | 58 |
parser.add_argument("-bt", "--build-type", dest="pkgBuildType", choices=['chroot', 'container'], default="chroot") |
59 | 59 |
parser.add_argument("-F", "--kat-build", dest="katBuild", default=None) |
60 |
+ parser.add_argument("-ct", "--cross-target", dest="targetArch", choices=['x86_64', 'aarch64'], default=None) |
|
60 | 61 |
parser.add_argument("-pj", "--packages-json-input", dest="pkgJsonInput", default=None) |
61 | 62 |
parser.add_argument("PackageName", nargs='?') |
62 | 63 |
options = parser.parse_args() |
... | ... |
@@ -80,12 +80,12 @@ def main(): |
80 | 80 |
if not os.path.isdir(options.publishXRPMSPath): |
81 | 81 |
logger.error("Given X RPMS Path is not a directory:" + options.publishXRPMSPath) |
82 | 82 |
errorFlag = True |
83 |
- if not os.path.isdir(options.publishRPMSPath + "/" + platform.machine()): |
|
84 |
- logger.error("Given RPMS Path is missing " + platform.machine()+ |
|
83 |
+ if not os.path.isdir(options.publishRPMSPath + "/" + constants.buildArch): |
|
84 |
+ logger.error("Given RPMS Path is missing " + constants.buildArch + |
|
85 | 85 |
" sub-directory:"+options.publishRPMSPath) |
86 | 86 |
errorFlag = True |
87 |
- if not os.path.isdir(options.publishXRPMSPath+"/" + platform.machine()): |
|
88 |
- logger.error("Given X RPMS Path is missing "+platform.machine()+ |
|
87 |
+ if not os.path.isdir(options.publishXRPMSPath+"/" + constants.buildArch): |
|
88 |
+ logger.error("Given X RPMS Path is missing "+ constants.buildArch + |
|
89 | 89 |
" sub-directory:"+options.publishXRPMSPath) |
90 | 90 |
errorFlag = True |
91 | 91 |
if not os.path.isdir(options.publishRPMSPath+"/noarch"): |
... | ... |
@@ -121,8 +121,14 @@ def main(): |
121 | 121 |
logger.error("Found some errors. Please fix input options and re-run it.") |
122 | 122 |
return False |
123 | 123 |
|
124 |
- cmdUtils.runCommandInShell("mkdir -p "+options.rpmPath+"/"+platform.machine()) |
|
124 |
+ if options.targetArch: |
|
125 |
+ constants.targetArch = options.targetArch |
|
126 |
+ |
|
127 |
+ cmdUtils.runCommandInShell("mkdir -p "+options.rpmPath+"/"+constants.buildArch) |
|
125 | 128 |
cmdUtils.runCommandInShell("mkdir -p "+options.rpmPath+"/noarch") |
129 |
+ if constants.buildArch != constants.targetArch: |
|
130 |
+ cmdUtils.runCommandInShell("mkdir -p "+options.rpmPath+"/"+constants.targetArch) |
|
131 |
+ |
|
126 | 132 |
|
127 | 133 |
if not os.path.isdir(options.sourceRpmPath): |
128 | 134 |
cmdUtils.runCommandInShell("mkdir -p "+options.sourceRpmPath) |
... | ... |
@@ -176,14 +182,25 @@ def main(): |
176 | 176 |
elif options.toolChainStage == "stage2": |
177 | 177 |
pkgManager = PackageManager() |
178 | 178 |
pkgManager.buildToolChainPackages(options.buildThreads) |
179 |
- elif options.installPackage: |
|
180 |
- buildSpecifiedPackages([package], options.buildThreads, options.pkgBuildType) |
|
181 |
- elif options.pkgJsonInput: |
|
182 |
- buildPackagesInJson(options.pkgJsonInput, options.buildThreads, |
|
183 |
- options.pkgBuildType, pkgInfoJsonFile, logger) |
|
184 | 179 |
else: |
185 |
- buildPackagesForAllSpecs(options.buildThreads, options.pkgBuildType, |
|
186 |
- pkgInfoJsonFile, logger) |
|
180 |
+ if constants.buildArch != constants.targetArch: |
|
181 |
+ # It is cross compilation. |
|
182 |
+ # first build all native packages |
|
183 |
+ buildPackagesForAllSpecs(options.buildThreads, |
|
184 |
+ options.pkgBuildType, |
|
185 |
+ pkgInfoJsonFile, logger) |
|
186 |
+ # Then do the build to the target |
|
187 |
+ constants.currentArch = constants.targetArch |
|
188 |
+ constants.crossCompiling = True |
|
189 |
+ |
|
190 |
+ if options.installPackage: |
|
191 |
+ buildSpecifiedPackages([package], options.buildThreads, options.pkgBuildType) |
|
192 |
+ elif options.pkgJsonInput: |
|
193 |
+ buildPackagesInJson(options.pkgJsonInput, options.buildThreads, |
|
194 |
+ options.pkgBuildType, pkgInfoJsonFile, logger) |
|
195 |
+ else: |
|
196 |
+ buildPackagesForAllSpecs(options.buildThreads, options.pkgBuildType, |
|
197 |
+ pkgInfoJsonFile, logger) |
|
187 | 198 |
except Exception as e: |
188 | 199 |
logger.error("Caught an exception") |
189 | 200 |
logger.error(str(e)) |
... | ... |
@@ -1,3 +1,4 @@ |
1 |
+import platform |
|
1 | 2 |
from Logger import Logger |
2 | 3 |
|
3 | 4 |
class constants(object): |
... | ... |
@@ -30,6 +31,10 @@ class constants(object): |
30 | 30 |
buildOptions = {} |
31 | 31 |
# will be extended later from listMakeCheckRPMPkgtoInstall |
32 | 32 |
listMakeCheckRPMPkgWithVersionstoInstall = None |
33 |
+ buildArch = platform.machine() |
|
34 |
+ targetArch = platform.machine() |
|
35 |
+ crossCompiling = False |
|
36 |
+ currentArch = buildArch |
|
33 | 37 |
|
34 | 38 |
noDepsPackageList = [ |
35 | 39 |
"texinfo", |