RPM spec file condition based on availability of a dependency - rpmbuild

I want to create a cross-distribution RPM spec file for an application that bundles a certain library. The application uses this bundled library by default, but also provides a build-time option for using the version of the library installed in the system instead. I want the RPM to link the application to the system library if it is available (since this will make the package smaller, and because the system library gets security patches more frequently than the version bundled with the application) and if not, to fall back to the (default) bundled version. Is there any way of writing a conditional in the spec file that accomplishes this?
For example, I want to do something like
%if available(libfoo-devel >= 1.0)
BuildRequires: libfoo-devel >= 1.0
%endif
%prep
cat << EOF > build_config_file
%if available(libfoo-devel >= 1.0)
ac_add_options --with-system-foo
%endif
EOF
Right now I'm using conditionals that check for macros defined by particular versions of OSes that I already know package the correct library, but this is rather brittle and convoluted. (That is, I need to manually check each target distribution to see if it packages the correct version of the library, and then write a condition in the spec file for that distribution; moreover, I need to repeat this process periodically in case the correct version of the library becomes available for a distribution that didn't package it previously.) It would be simpler if I could just test for the availability of the dependency directly.

You must decide before creating the rpm how you will create it. Compilation happens before the target rpm is created, not upon installation.
As I see it you might consider creating two rpms:
one compiled with libfoo-devel
one without
I would then suggest a spec file along these lines:
Name: package
...
%package libfoo
Summary: %{name} build with libfoo
BuildRequires: libfoo-devel >= 1.0
Requires: libfoo >= 1.0
%build
build --without-libfoo --target "${RPM_BUILD_ROOT}/usr/bin/without-libfoo"
build --with-libfoo --target "${RPM_BUILD_ROOT}/usr/bin/with-libfoo"
%install
/usr/bin/without-libfoo
%install libfoo
/usr/bin/with-libfoo
Notes:
yes this means compiling twice: once with and once without libfoo
building this spec file will create two packages: "package.rpm" and "package-libfoo.rpm"

Related

How do I effectively utilize the "build" step in Julia?

Per the Julia Docs:
The build step is executed the first time a package is installed or when explicitly invoked with build. A package is built by executing the file deps/build.jl.
Why would I want to make a build.jl file and how do I effectively utilize the benefits it allows for?
Typically (historically) the build step and the build.jl file is used for downloading/installing binary dependencies with e.g. BinaryProvider (or its predecessor BinDeps)1. The build step can also be used to install configuration files. For example, IJulia uses build.jl in order to install a Julia kernel for Jupyter.
If your package is pure Julia code you typically don't have a build.jl file since there is no need for it.
1 With Julia 1.3 we have Artifacts which is meant to replace the BinaryProvider workflow and make build.jl obsolete for the purpose of downloading and installing prebuilt binaries.

RPM Spec file conditional Requires per distribution AFTER build

I want to build RPM files and I want them to be commonly used and beeing not depending on which distribution is installed.
Now I found a requirement which name is different on RHEL and SLES.
I found this as possible solution:
%if 0%{?suse_version}
Requires: jdk >= 2000:1.8.0_00-fcs, netcat, telnet, at
%else
Requires: jdk >= 2000:1.8.0_00-fcs, nc, telnet, at
%endif
But my problem with is, that it's an if query for the Build process, what I wish to have is depending on the distribution I install, the already build rpm file would solve this.
Because with this solution, I would need to build RPM files for every kind of centos and rhel and sles distribution on all these different OSes while only the name of nc and netcat differ as Required packages.
Any idea how I can do that?
Thanks
rpm-4.13 will solve my issue: http://www.rpm.org/wiki/PackagerDocs/BooleanDependencies
or - requires one of the operands to be fulfilled
Requires: (pkgA >= 3.2 or pkgB)
You cannot do what you are asking at install-time. However, you can require the executable itself, e.g. /bin/netcat and it should work... unless it was part of the great UsrMove...

Compiling haskell module Network on win32/cygwin

I am trying to compile Network.HTTP (http://hackage.haskell.org/package/network) on win32/cygwin. However, it does fail with following message:
Setup.hs: Missing dependency on a foreign library:
* Missing (or bad) header file: HsNet.h
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
If the header file does exist, it may contain errors that are caught by the C
compiler at the preprocessing stage. In this case you can re-run configure
with the verbosity flag -v3 to see the error messages.
Unfortuntely it does not give more clues. The HsNet.h includes sys/uio.h which, actually should not be included, and should be configurered correctly.
Don't use cygwin, instead follow Johan Tibells way
Installing MSYS
Install the latest Haskell Platform. Use the default settings.
Download version 1.0.11 of MSYS. You'll need the following files:
MSYS-1.0.11.exe
msysDTK-1.0.1.exe
msysCORE-1.0.11-bin.tar.gz
The files are all hosted on haskell.org as they're quite hard to find in the official MinGW/MSYS repo.
Run MSYS-1.0.11.exe followed by msysDTK-1.0.1.exe. The former asks you if you want to run a normalization step. You can skip that.
Unpack msysCORE-1.0.11-bin.tar.gz into C:\msys\1.0. Note that you can't do that using an MSYS shell, because you can't overwrite the files in use, so make a copy of C:\msys\1.0, unpack it there, and then rename the copy back to C:\msys\1.0.
Add C:\Program Files\Haskell Platform\VERSION\mingw\bin to your PATH. This is neccesary if you ever want to build packages that use a configure script, like network, as configure scripts need access to a C compiler.
These steps are what Tibell uses to compile the Network package for win and I have used this myself successfully several times on most of the haskell platform releases.
It is possible to build network on win32/cygwin. And the above steps, though useful (by Jonke) may not be necessary.
While doing the configuration step, specify
runghc Setup.hs configure --configure-option="--build=mingw32"
So that the library is configured for mingw32, else you will get link or "undefined references" if you try to link or use network library.
This combined with #Yogesh Sajanikar's answer made it work for me (on win64/cygwin):
Make sure the gcc on your path is NOT the Mingw/Cygwin one, but the
C:\ghc\ghc-6.12.1\mingw\bin\gcc.exe
(Run
export PATH="/cygdrive/.../ghc-7.8.2/mingw/bin:$PATH"
before running cabal install network in the Cygwin shell)

Loading Network.HTTP module in Haskell on GHC7.4.1

I am trying to load a file in GHCi (Windows 7 / Haskell Platform 2012.2.0.0 ) which starts with:
import Network.HTTP
import System.IO
...
But I get an error:
Could not find module `Network.HTTP'
This module is in HTTP package, right? So when I run >cabal list HTTP it finds the following:
* HTTP
Synopsis: A library for client-side HTTP
Default available version: 4000.2.3
Installed version: 4000.2.3
Homepage: https://github.com/haskell/HTTP
License: BSD3
Which means the package is installed right? What do I do wrong?
Thank you!
Having the package installed by cabal doesn't make it automatically available to your code. (For example, you could have installed 2 versions of some package, so it's not possible to determine automatically what to make available and what to hide).
Probably the simplest solution is to manage, build and run your project using cabal as well. See How to write a Haskell program, Section 2 describes (among other things) how to set up the files required by Cabal. In particular, your cabal file will contain a line similar to this:
build-depends: base, HTTP
See also Cabal User Guide.
Edit: You can try the following:
Create file test.cabal containing:
Name: test
Version: 0.0
Description: My network program
Build-Type: Simple
Cabal-Version: >=1.2
Executable test
Main-is: Test.hs
Build-Depends: base >= 4 && < 5, HTTP
(Replace Test.hs with your source file.) Then Run
cabal install --only-dependencies
this installs all required dependencies. If it all goes well, you can configure and build the project:
cabal configure
cabal build
Maybe to work interactively with your project, you could use cabal-ghci. I haven't tried it, but looks like it could be just what you need.

Building and installing an R package library with a jnilib extension

I'm building an R package and need to build a jni library for OSX (called myPackage.jnilib) as part of my build process and then have R's automatic installation mechanisms put it inside the libs directory of my package.
The problem is that R's default is to try and build an object called myPackage.so. I'd like to be able to customize this but can't see how.
I can get part of the way by subverting R's mechanisms using a phony "all" target in Makevars (described here) and then copying the file to the inst directory of my package. This is OK for my own local uses but generates headaches when trying to build universal binaries and isn't very portable. I'm currently preparing the package for CRAN so this method isn't likely to work.
I can see two potential solutions but haven't got either to work yet
Copy my library manually to the libs directory of my package during installation. Since this directory is created on the fly, how would I find out what it is from within Makevars or a configure script
The best solution: Tell R CMD SHLIB the name of my output file so I can use R's normal package mechanisms and let it copy the file to the right directory.
In case anyone else encounters this problem I'm posting my own workaround here.
I define targets in my Makevars and copy the libraries directly (ie answer 1). The variable R_LIBRARY_DIR provides the temporary location where the package is being built.
My Makevars now looks something like this
OBJECTS =
LIBSINSTDIR=$(R_LIBRARY_DIR)/myPackage/libs/
#ARCHFLAG is set in the configure script to i386 or ppc as appropriate
JNIINSTDIR=$(LIBSINSTDIR)/#ARCHFLAG#/
.PHONY: all
all: $(SHLIB) jnilib
jnilib: object1.o object2.o
$(CXX) -bundle $(JAVA_LIBS) $(JAVA_CPPFLAGS) -o libmyPackage.jnilib object1.o object2.o
mkdir -p $(JNIINSTDIR)
cp libmyPackage.jnilib $(JNIINSTDIR)

Resources