From 33d7924d64a86833701627dc82da383460fbf1db Mon Sep 17 00:00:00 2001 From: Daniel P. Berrangé Date: Apr 25 2023 09:13:22 +0000 Subject: [PATCH 1/2] mingw: use RPM source syntax highlighting Signed-off-by: Daniel P. Berrangé --- diff --git a/guidelines/modules/ROOT/pages/MinGW.adoc b/guidelines/modules/ROOT/pages/MinGW.adoc index 10e25fc..bfcebf6 100644 --- a/guidelines/modules/ROOT/pages/MinGW.adoc +++ b/guidelines/modules/ROOT/pages/MinGW.adoc @@ -105,23 +105,25 @@ replaced by `+%mingw_find_lang+`. This causes all translation filelists to be split in per-target filelists. For example: when a spec file contains something like this: -.... +[source, rpm-spec] +---- %install %mingw_find_lang foo -.... +---- then one file per mingw target will get created named `+mingw32-foo.lang+`, `+mingw64-foo.lang+`, and `+ucrt64-foo.lang+`. These file lists can be included in the %files section for the targets: -.... +[source, rpm-spec] +---- %files -n mingw32-foo -f mingw32-foo.lang %files -n mingw64-foo -f mingw64-foo.lang %files -n ucrt64-foo -f ucrt64-foo.lang -.... +---- == Filesystem layout @@ -209,27 +211,29 @@ guidelines. The MinGW cross-compilers and binutils which generate i686 binaries for Windows with the MSVCRT runtime are named: -.... +[source, rpm-spec] +---- %{_bindir}/i686-w64-mingw32-gcc %{_bindir}/i686-w64-mingw32-g++ %{_bindir}/i686-w64-mingw32-ld %{_bindir}/i686-w64-mingw32-as %{_bindir}/i686-w64-mingw32-strip etc. -.... +---- The same binaries are present in `+%{_prefix}/i686-w64-mingw32/bin+` without any prefix in the name, i.e., -.... +[source, rpm-spec] +---- %{_prefix}/i686-w64-mingw32/bin/gcc %{_prefix}/i686-w64-mingw32/bin/g++ %{_prefix}/i686-w64-mingw32/bin/ld %{_prefix}/i686-w64-mingw32/bin/as %{_prefix}/i686-w64-mingw32/bin/strip etc. -.... +---- The same also applies for the x86_64 target with both MSVCRT and UCRT runtimes. The target with MSVCRT uses 'x86_64-w64-mingw32' @@ -245,21 +249,24 @@ because MinGW requires a root filesystem location. The location for Win32 target with MSVCRT runtime is provided by the macro: -.... +[source, rpm-spec] +---- %{mingw32_sysroot} %{_prefix}/i686-w64-mingw32/sys-root -.... +---- The Win64 target with MSVCRT runtime is provided by the macro: -.... +[source, rpm-spec] +---- %{mingw64_sysroot} %{_prefix}/x86_64-w64-mingw32/sys-root -.... +---- The Win64 target with UCRT runtime is provided by the macro: -.... +[source, rpm-spec] +---- %{ucrt64_sysroot} %{_prefix}/x86_64-w64-mingw32ucrt/sys-root -.... +---- @@ -450,7 +457,8 @@ are packages which have to be built once for a static version and once for a shared version. Such packages can add a custom suffix to the build directory used. Say you've got something like below: -.... +[source, rpm-spec] +---- mkdir build_shared pushd build_shared %{mingw32_configure} --enable-shared @@ -459,14 +467,15 @@ used. Say you've got something like below: pushd build_static %{mingw32_configure} --enable-static popd -.... +---- This can be rewritten to something like this: -.... +[source, rpm-spec] +---- MINGW_BUILDDIR_SUFFIX=shared %mingw_configure --enable-shared MINGW_BUILDDIR_SUFFIX=static %mingw_configure --enable-static -.... +---- Most packages used the command `+make %{?_smp_mflags}+` to build the package. In the MinGW cross compiler framework you have to use @@ -502,9 +511,10 @@ form 'mingw32(foo.dll)' should be used for Win32 binaries and the form Correct dependency generation is done automatically. Packagers should start their spec files with this line: -.... +[source, rpm-spec] +---- %{?mingw_package_header} -.... +---- All binary packages should depend on `+mingw32-filesystem+` or `+mingw64-filesystem+` (depending on the files in the package). @@ -512,8 +522,11 @@ All binary packages should depend on `+mingw32-filesystem+` or All specfiles should BuildRequire at least one of these (depending on the targets for which you want to build): -`+BuildRequires:  mingw32-filesystem+` + -`+BuildRequires:  mingw64-filesystem+` +[source, rpm-spec] +---- + BuildRequires:  mingw32-filesystem + BuildRequires:  mingw64-filesystem +---- and any other BuildRequires that they need. @@ -525,7 +538,10 @@ dependancy on the `+mingw-XX-filesystem+` packages should be used. All packages should have: -`+BuildArch: noarch+` +[source, rpm-spec] +---- + BuildArch: noarch +---- unless they contain Fedora native executables. @@ -538,10 +554,11 @@ Because of the peculiarity of Windows, DLLs are stored in the `+%{mingw32_libdir}+` directory. For example, for a library called `+foo+` there would be: -.... +[source, rpm-spec] +---- %{mingw32_bindir}/foo.dll %{mingw32_libdir}/foo.dll.a -.... +---- The `+foo.dll+` file is the main library, `+foo.dll.a+` is a stub linked to applications so they can find the library at runtime. All of these files are @@ -562,9 +579,10 @@ explicitly in the `+%files+` section in order to catch this during RPM builds. Libraries and executables should be stripped. This is done correctly and automatically if the spec file starts with this line: -.... +[source, rpm-spec] +---- %{?mingw_package_header} -.... +---- === Debuginfo subpackage @@ -572,11 +590,12 @@ Most binaries contain debugging symbols when the package gets built. To split the debugging symbols to a separate debuginfo package (as is done with native Fedora packages) the spec file must include these lines: -.... +[source, rpm-spec] +---- %{?mingw_package_header} [...] %{?mingw_debug_package} -.... +---- The `+%{?mingw_debug_package}+` line must be placed after the `+%description tag+`. Otherwise spectool and other RPM tools may fail to @@ -625,7 +644,8 @@ to bundle it with their Windows installers. == Example Specfile -.... +[source, rpm-spec] +---- %{?mingw_package_header} Name: mingw-example @@ -740,4 +760,4 @@ find %{buildroot} -name "*.la" -delete %changelog * Sun Apr 15 2012 Erik van Pienbroek - 1.0.0-1 - Initial release -.... +---- From cf7a8d2758ccb4dd8dee2b000acecfb500574693 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrangé Date: Apr 27 2023 09:34:28 +0000 Subject: [PATCH 2/2] mingw: document approach for integrating mingw with native packages Historically the mingw packages were introduced as completely separate components in Fedora, with their own spec files, separate maintainers, etc. This was driven primarily from a reasonable concern that the maintenence of MinGW builds would be an unacceptable burden on the existing native package maintainers. In the many years since MinGW was introduced to Fedora, however, it has become clear that this concern was mostly unfounded. While some packages may be more difficult, the majority of MinGW packages are not difficult to keep building successfully in Fedora. Furthermore the existance of MinGW support in Fedora, has enabled upstream projects to actively test Windows support in their CI systems prior to release. There biggest problem for MinGW packages in Fedora has turned out to be caused by the very decision to package them as completely separated components. Specifically it is difficult to ensure that MinGW builds are being kept in sync with changes to the native package builds, even when both share the same maintainer. This is particularly apparent when looking at reports of unaddressed CVEs in Fedora packages. With this all in mind, it is the view of the MinGW SIG that Fedora is best served by having MinGW support integrated into the native packages in general. While the specific maintainer of the native package will have slightly more work, history has demonstrated this is not likely to be significant in most cases. For Fedora maintainers in aggregate, the amount of effort spent on MinGW will decrease, benefiting the project as a whole. This proposal thus strongly promotes the integrated MinGW packaging approach to be the default, though existing native package maintainers retain the ability to decline such proposals. The concept of integrating MinGW support into the native packages has already been put into practice on many packages where the same Fedora contributor maintained both the MinGW and native packages. Specifically examples implemented by Sandro Mani are: mingw-eigen3 mingw-enchant2 mingw-freeimage mingw-gdal mingw-GeographicLib mingw-geos mingw-giflib mingw-gtkspell3 mingw-gtkspellmm30 mingw-jxrlib mingw-leptonica mingw-libgeotiff mingw-libimagequant mingw-libkml mingw-librttopo mingw-libspatialite mingw-libwebp mingw-openjpeg2 mingw-OpenSceneGraph mingw-osgearth mingw-podofo mingw-proj mingw-python-pillow mingw-qtspell mingw-shapelib mingw-svg2svgt mingw-tesseract mingw-uriparser and examples by Daniel Berrange are mingw-libvirt mingw-gtk-vnc mingw-libvirt-glib mingw-libosinfo mingw-osinfo-db-tools Signed-off-by: Daniel P. Berrangé --- diff --git a/guidelines/modules/ROOT/pages/MinGW.adoc b/guidelines/modules/ROOT/pages/MinGW.adoc index bfcebf6..6c09a84 100644 --- a/guidelines/modules/ROOT/pages/MinGW.adoc +++ b/guidelines/modules/ROOT/pages/MinGW.adoc @@ -1,5 +1,5 @@ = Packaging Guidelines for MinGW Cross Compilers - + == Introduction The Fedora MinGW project's mission is to provide an excellent development @@ -18,6 +18,108 @@ Win64 with the UCRT runtime is also supported, however, only for the base toolchain. Builds for UCRT are not enabled for packages above the toolchain at this time. +== Separate vs integrated MinGW source packages + +There are two permitted ways to provide MinGW builds of software in Fedora: + +* **Separate source packages**: There are distinct RPM spec files for the + native and MinGW builds, maintained as independent components of Fedora. + This is the traditional approach to MinGW packaging in Fedora + +* **Integrated source packages**: There is a single RPM spec file for the + native and MinGW builds, as a single component of Fedora. The MinGW builds + are emitted as binary sub-RPMs. This is the modern, preferred, approach to + MinGW packaging in Fedora. + +The traditional approach of completely separated source packages was adopted +initially because of concerns that instability in the MinGW toolchain or +Windows builds may prevent timely updates to the native package. Experience +in Fedora since then has shown that is not generally a problem that impacts +most packages, especially where Windows support is an explicitly tested +deliverable of the upstream project. + +Using the separate packaging approach has a significantly higher overhead: + +* The addition of MinGW support must go through the full Fedora review + process for new packages, largely duplicating review already performed + on the native package. + +* There is an ongoing burden for the maintainer to ensure the MinGW source + package tracks changes to the corresponding native source package as it + rebases to new releases. + +* There is additional work in handling patches/updates in response to bug + reports. Bug reports are often only reported against one of the two + components not both, but with security vulnerabilities there are twice + the number of bug reports created. There are then also multiple koji + builds and updates to handle. + +With the integrated packaging approach there is a small extra overhead on the +native package maintainer to ensure MinGW builds keep working and a small +additional load of MinGW specific bug reports. This is usually negligible +compared to the overhead of maintaining separated packages. + +With this in mind, the recommendation of the MinGW SIG is thus: + +* Where the same Fedora contributor intends to maintain both the native + and MinGW builds of a package, they **MUST** use the integrated packaging + approach. + +* Where the upstream project explicitly supports the Windows platform as + a build target and has automated CI, contributors **SHOULD** prefer the + integrated MinGW packaging approach. Native package maintainers **SHOULD** + ordinarily accept addition of integrated MinGW support. If declining the + request the native maintainer should give a rationale for their decision. + +* Where the upstream project does not have automated testing of Windows + builds, the MinGW package support **MAY** use either packaging approach. + The native maintainer may decline the request for integrated packaging + at their discretion. + +* Where the upstream project only supports Windows builds, the separate + packaging approach **MUST** be used. There will be no corresponding + native package in Fedora expected. This situation is very rare. + +* When a contributor proposes a new native package to Fedora that provides + libraries that are known to support Windows, the reviewer **SHOULD** + inquire whether the contributor would like to add MinGW builds at the + same time. The contributor may decline this request at their discretion. + +== Adding MinGW support alongside a new native package + +When a corresponding native package does not already exist, it will always +be required to go through the standard Fedora new package review process. +The proposed MinGW support **MUST** follow the integrated packaging approach +to provide both the MinGW and native builds, where technically possible. +As noted in the previous section, in some rare situations there will be no +corresponding native package, thus requiring the separate pacakaging approach +to be taken. + +== Adding MinGW support to an existing native package + +When a corresponding native package is already present in Fedora, the +preference is to add MinGW support to the native source package. + +Where the source package changes are simple, the contributor **SHOULD**: + + * Make the required spec file additions in their fork of the package + * Submit a koji scratch-build to prove the changes have the expected + effect + * Open a merge request against the native package with the spec changes, + adding a link to the koji scratch-build results as a comment. + +The existing native package maintainer thus gets clear view of the impact of +the MinGW additions to their package, to evaluate the viability of following +the integrated packaging approach. + +Where there is doubt about the viability of following the integrated package +approach, a bug **MAY** be opened against the package ahead of starting work +to discuss the two packaging options with the native package maintainer. + +If the native maintainer declines the proposal to add MinGW support to the +existing package, the regular Fedora new package process MUST be followed +to introduce MinGW support following the separate packaging approach. + == Track Fedora native package versions In general terms, cross-compiled MinGW versions of packages which are already @@ -26,6 +128,9 @@ as possible. This means they should stay at the same version, include all the same patches as the native Fedora package, and be built with the same configuration options. +The preferred way to achieve this goal is for the MinGW support to use the +integrated packaging approach. + == Follow Fedora policy Cross compiled MinGW packages must follow Fedora policy, except where noted in @@ -43,7 +148,7 @@ packages are created by sections with `+%files -n mingw32-foo+`, [cols=",",] |======================================================= -|`+mingw-+` |Used for source package and RPM spec name +|`+mingw-+` |Used for source package and RPM spec name (only where the separate packaging approach is chosen) |`+mingw32-+` |Used for packages which are built for Win32 with the MSVCRT runtime |`+mingw64-+` |Used for packages which are built for Win64 with the MSVCRT runtime |`+ucrt64-+` |Used for packages which are built for Win64 with the UCRT runtime @@ -74,7 +179,7 @@ To aid developers in this several RPM macros have been developed which are part of the mingw-filesystem package. These RPM macros will be explained later on in these guidelines. -By default a MinGW package will be built for both the Win32 and Win64 targets +By default MinGW support will be built for both the Win32 and Win64 targets with the MSVCRT runtime. Building of the Win64 target with the UCRT64 runtime is not yet enabled by default. @@ -92,18 +197,22 @@ indicated by setting one or more of these: Each cross compiled MinGW package which builds binaries for a specific target should put the binaries for that target in a separate subpackage. So if a -package `+foo+` builds binaries for the Win32 and Win64 targets with the MSVCRT -runtime, then the source RPM should provide two subpackages named `+mingw32-foo+` -and `+mingw64-foo+`. If a package builds for the UCRT runtime, it will also -have a `+ucrt64-foo+` subpackage. +package `+mingw-foo+` or `+foo+` builds binaries for the Win32 and Win64 targets +with the MSVCRT runtime, then the source RPM should provide two subpackages +named `+mingw32-foo+` and `+mingw64-foo+`. If a package builds for the UCRT +runtime, it will also have a `+ucrt64-foo+` subpackage. This means that a spec file must contains %package and %files sections for all the targets. -If a package contains translations then all calls to the `+%find_lang+` must be -replaced by `+%mingw_find_lang+`. This causes all translation filelists to be -split in per-target filelists. For example: when a spec file contains something -like this: +When using the separate packaging approach, packages containing translations +must use `+%mingw_find_lang+` instead of `+%find_lang+`. + +When using the integrated packaging approach, packages containing translations +must use `+%find_lang` followed by `+%mingw_find_lang+`. + +This causes all translation filelists to be split in per-target filelists. For +example: when a spec file contains something like this: [source, rpm-spec] ---- @@ -543,7 +652,11 @@ All packages should have: BuildArch: noarch ---- -unless they contain Fedora native executables. +unless they contain Fedora native executables. Where using the separate +packaging approach, the `+BuildArch+` tag must be present in the common +spec file header. Where using the integrated packaging approach, the +`+BuildArch+` tag must be present under the %package header for each MinGW +sub-RPM that is present. == Libraries (DLLs) @@ -601,6 +714,17 @@ The `+%{?mingw_debug_package}+` line must be placed after the `+%description tag+`. Otherwise spectool and other RPM tools may fail to function. +When using the integrated packaging approach the `+%install+` section must +also contain a call to the `+%{mingw_debug_install_post}+` macro after any +binary files have been installed to the virtual root: + +[source, rpm-spec] +---- + %install + [...] + %{?mingw_debug_install_post} +---- + == File listing The MinGW packages are intended to allow developers to compile and test the @@ -642,7 +766,236 @@ Note, generic Documentation aimed at end users, as opposed to developers, should be included where it is likely that application developers will want to bundle it with their Windows installers. -== Example Specfile +== Converting between separate and integrated packaging + +In general it it possible to convert in either direction between the separate +and integrated packaging approaches. Both approaches result in the exact same +binary RPMs for MinGW content, only differing in their source RPM specfile. + +To convert from separate to integrated packaging + +* Ensure the existing native software package has either the same (or newer) + version number as the existing MinGW package. +* Add MinGW support to the existing native package spec file +* If both the native and existing MinGW packages were at the same version, + ensure the release number of the native package is newer than any previous + build of the MinGW package. +* Build the new native package with MinGW support +* Retire the separate MinGW package + +To convert from integrated to separate packaging + +* Go through the new package review process for the separate MinGW package, + ensuring it is the same version number as the existing integrated package +* Import the separate MinGW package to dist-git but don't build it. +* Drop MinGW support from the existing native package spec file +* Build the native package without MinGW support +* Ensure the separate MinGW package has a newer release number than any existing + MinGW binary sub-RPMs built from the native package +* Build the separate MinGW package + +In both cases the upgrade experience should be transparent to users installing +and updating Fedora deployments. + +It is recommended that such conversions only be performed in Rawhide. If there +is need to do a conversion from integrated to separate packaging in a stable +release stream, a single Bohdi update must include both the native and mingw +package builds. + +== Disabling MinGW packages + +When using the integrated packaging approach it **MUST** be possible to disable +the build of MinGW sub-RPMs, and the build **MUST** be disabled by default +except for the Fedora distribution target. This ensures that the native package +can still be built in derivative distros, such as RHEL, where the MinGW +toolchains not included. This is achieved by including a conditional near +the top of the specfile: + +[source, rpm-spec] +---- +%if 0%{?fedora} +%bcond_without mingw +%else +%bcond_with mingw +%endif +---- + +and then wrapping all MinGW related `+%package+` / `+%files` definitions and +relevant `+%build+` or `+%install+` commands in a conditional check: + +[source, rpm-spec] +---- +%if %{with mingw} +%package -n mingw32-example +Summary: %{summary} +BuildArch: noarch +[...] +%endif +---- + +== Example Integrated Package Specfile + +[source, rpm-spec] +---- +%if 0%{?fedora} +%bcond_without mingw +%else +%bcond_with mingw +%endif + +Name: example +Version: 1.0.0 +Release: 1%{?dist} +Summary: Example library + +License: LGPL-2.1-or-later +URL: https://fedoraproject.org +Source: https://fedoraproject.org/example-%{version}.tar.bz2 + +BuildRequires: gcc +BuildRequires: binutils +BuildRequires: gettext +BuildRequires: zlib + +%if %{with mingw} +BuildRequires: mingw32-filesystem +BuildRequires: mingw32-gcc +BuildRequires: mingw32-binutils +BuildRequires: mingw32-gettext +BuildRequires: mingw32-win-iconv +BuildRequires: mingw32-zlib + +BuildRequires: mingw64-filesystem +BuildRequires: mingw64-gcc +BuildRequires: mingw64-binutils +BuildRequires: mingw64-gettext +BuildRequires: mingw64-win-iconv +BuildRequires: mingw64-zlib +%endif + +%description +Example library. + +%package devel +Summary: Example library development package +... + +%description devel +Example library development headers and library. + +%if %{with mingw} +# If a package maintainer wishes to bundle static libraries then they +# can be placed in -static subpackages. Otherwise, the -static subpackages +# can be dropped + +# Win32 +%package -n mingw32-example +Summary: MinGW compiled example library for the Win32 target +BuildArch: noarch + +%description -n mingw32-example +MinGW compiled example library for the Win32 target. + +%package -n mingw32-example-static +Summary: Static version of the MinGW Win32 compiled example library +Requires: mingw32-example = %{version}-%{release} + +%description -n mingw32-example-static +Static version of the MinGW Win32 compiled example library. + +# Win64 +%package -n mingw64-example +Summary: MinGW compiled example library for the Win64 target + +%description -n mingw64-example +MinGW compiled example library for the Win64 target. +BuildArch: noarch + +%package -n mingw64-example-static +Summary: Static version of the MinGW Win64 compiled example library +Requires: mingw64-example = %{version}-%{release} + +%description -n mingw64-example-static +Static version of the MinGW Win64 compiled example library. + +%{?mingw_debug_package} +%endif + + +%prep +%autosetup -p1 -n example-%{version} + + +%build + +%define _configure ../../configure + +mkdir -p build/native +cd build/native +%configure ... +%make_build +cd ../.. + +%if %{with mingw} +%mingw_configure --enable-static --enable-shared --enable-foo +%mingw_make_build +%endif + +%install +cd build/native +%make_install + +%find_lang example +cd ../.. + +%if %{with mingw} +%mingw_make_install + +%mingw_find_lang example +%endif + +%files +%{_libdir}/libexample.so.* + +%files devel +%{_libdir}/libexample.so +%{_libdir}/pkgconfig/example.pc +%{_includedir}/example/ + +# Static subpackages are optional (as mentioned earlier) + +%if %{with mingw} +# Win32 +%files -n mingw32-example -f mingw32-example.lang +%{mingw32_bindir}/libexample-0.dll +%{mingw32_includedir}/example/ +%{mingw32_libdir}/libexample.dll.a +%{mingw32_libdir}/pkgconfig/example.pc + +%files -n mingw32-example-static +%{mingw32_libdir}/libexample.a + +# Win64 +%files -n mingw64-example -f mingw64-example.lang +%{mingw64_bindir}/libexample-0.dll +%{mingw64_includedir}/example/ +%{mingw64_libdir}/libexample.dll.a +%{mingw64_libdir}/pkgconfig/example.pc + +%files -n mingw64-example-static +%{mingw64_libdir}/libexample-0.a +%endif + +%changelog +* Sun Apr 15 2012 Erik van Pienbroek - 1.0.0-1 +- Initial release +---- + +== Example Separate Package Specfile + +The separate package specfile essentially extracts all the content within the +`+%{with mingw}+` conditionals from the previous example, and puts it into a +standalone specfile. [source, rpm-spec] ----