gnu make - assert specific command line tools are available - gnu-make

In a makefile, how would I make sure that certain tools like gcov, lcov, g++ are available before executing any other targets?
I want to gracefully fail with
gcov/lcov/g++ not available
.

You could try something like:
TOOLS := gcov lcov g++
$(foreach TOOL,$(TOOLS),\
$(if $(shell command -v $(TOOL)),,\
$(error Cannot locate $(TOOL) on PATH)))
This assumes you're using a POSIX shell obviously.

Related

How to print to commandline in nmake?

Is there a command/function in nmake to print to the commandline similar to what is available in GNU make with $(info ...)?
I cannot use echo.

How to put command with doxygen into makefile

I use linux and filter doxygen output as follows:
doxygen 2> >(grep "Arguments.h") 1> /dev/null
which is just to concentrate on failures within Arguments.h.
Now i want to put all that in a minimal makefile for GNU Make 4.3
doc:
doxygen 2> >(grep "Arguments.h") 1> /dev/null
of course later to replace Arguments.h by some other file.
But this does not work: reply is
doxygen 2> >(grep "Arguments.h") 1> /dev/null
/bin/sh: -c: line 0: syntax error near unexpected token `>'
/bin/sh: -c: line 0: `doxygen 2> >(grep "Arguments.h") 1> /dev/null'
make: *** [makefile:2: doc] Error 1
as far as i know make... one has to escape sth, but no idea what...
Any specialists which can help?
This is not related to escaping etc. This is related to which shell is being used.
GNU make (as with all versions of make) always invokes /bin/sh to run recipes, and that is a POSIX standard shell (or some proximity to it). The command you're using is definitely not supported by the POSIX standard, it appears to be using many features available only as enhancements in the bash shell.
If you want to write your recipes using bash features you have to tell make that it should be using bash as the shell, not /bin/sh. You can add this to your makefile:
SHELL = /bin/bash

How to change compiler version to build an Rcpp-based package?

I'm authoring a package that uses an external .so library and a header file. I notice that it works with g++-4.9 but not g++5.0 or above after I compiled the demo code in pure C++ for testing. My system default is g++ 5.4.0.
I tried adding CXX=g++-4.9 to ./configure and src/Makevars but the compiler still turns out to be system default g++. I don't want to modify global configuration (e.g. in ~/.R/Makevars) because it will influence other package builds.
Is there a local way to specify the compiler version Rcpp uses to compile cpp files when I build this package?
Step 1: Set CXX for all varieties in src/Makevars this comes about because you might be using CXX_STD = CXX11 so CXX11 is used instead of CXX...
CXX=g++-4.9
CXX1X=g++-4.9
CXX11=g++-4.9
CXX14=g++-4.9
Note: This assumes you are only compiling C++ code.
Step 2: Test for gcc 4.9 in configure.ac with:
AC_PREREQ(2.61)
AC_INIT(your_package_name_here, m4_esyscmd_s([awk -e '/^Version:/ {print $2}' DESCRIPTION]))
AC_COPYRIGHT(Copyright (C) 2017 your name?)
## Determine Install Location of R
: ${R_HOME=$(R RHOME)}
if test -z "${R_HOME}"; then
AC_MSG_ERROR([Could not determine R_HOME.])
fi
## Setup RBin
RBIN="${R_HOME}/bin/R"
CXX=`"${RBIN}" CMD config CXX`
CPPFLAGS=`"${RBIN}" CMD config CPPFLAGS`
CXXFLAGS=`"${RBIN}" CMD config CXXFLAGS`
## We are using C++
AC_LANG(C++)
AC_REQUIRE_CPP
## Check the C++ compiler using the CXX value set
AC_PROG_CXX
## If the compiler is g++, then GXX is set so version information can be exaimed
if test "${GXX}" = yes; then
AC_MSG_CHECKING([whether g++ version is sufficient])
gxx_version=$(${CXX} -v 2>&1 | awk '/^.*g.. version/ {print $3}')
case ${gxx_version} in
4.9.*)
AC_MSG_RESULT([(${gxx_version}) yes])
;;
1.*|2.*|3.*|4.0.*|4.1.*|4.2.*|4.3.*|4.4.*|4.5.*|4.6.*|4.7.*|4.8.*|5.*|6.*|7.*)
AC_MSG_RESULT([no])
AC_MSG_WARN([Only g++ version 4.9.* be used to compile this package.])
AC_MSG_ERROR([Please set the default compiler to gcc++-4.9.])
;;
esac
else
AC_MSG_WARN([The package uses an external shared library that only compiles with gcc++-4.9])
AC_MSG_ERROR([Please set the default compiler to gcc++-4.9.])
fi
AC_OUTPUT

Force run MakeFile rule to run shell command

I have the following rule in my make file which runs only a shell command
install:
$(shell insmod kdisk.ko)
but when I do > make install, it always says that make: 'install' is up to date.
How can I force it to run the shell command?
You probably want to declare the target as
.PHONY: install
install: kdisk.ko
insmod kdisk.ko
This tells the make program that:
the install target requires kdisk.ko before it can be started
the install target is a phony target and will not try to produce a install file, just to do something useful.
the recipe bound to install is insmod kdisk.ko.
With your declaration, the command insmod kdisk.ko will be processed as make reads the file and its output will be used as a recipe for the install target. Quite not what you want.

make sees different PATH than account's .bashrc-configured PATH

I want to call ShellCheck, a Haskell program for linting shell scripts, from a Makefile.
When I install ShellCheck via cabal install, it is installed as ~/.cabal/bin/shellcheck. So, I have configured Bash accordingly:
$ cat ~/.bashrc
export PATH="$PATH:~/.cabal/bin"
$ source ~/.bashrc
$ shellcheck -V
ShellCheck - shell script analysis tool
version: 0.3.4
license: GNU Affero General Public License, version 3
website: http://www.shellcheck.net
This enables me to run shellcheck from any directory in Bash. However, when I try to call it from a Makefile, make cannot find shellcheck.
$ cat Makefile
shlint:
-shlint lib/
shellcheck:
-shellcheck lib/**
lint: shlint shellcheck
$ make shellcheck
shellcheck lib/**
/bin/sh: 1: shellcheck: not found
make: [shellcheck] Error 127 (ignored)
I think that make is not receiving the same PATH as my normal Bash shell. How can I fix this?
Try using $HOME, not ~:
export PATH="$PATH:$HOME/.cabal/bin"
The ~-means-home-directory feature is not supported in pathnames everywhere in all shells. When make runs a recipe it doesn't use the user's shell (that would be a disaster!) it uses /bin/sh always.
On some systems (particularly Debian/Ubuntu-based GNU/Linux distributions) the default /bin/sh is not bash, but rather dash. Dash doesn't support ~ being expanded in the PATH variable.
In general, you should reserve ~ for use on the command line as a shorthand. But in scripting, etc. you should always prefer to write out $HOME.
ETA:
Also, the double-star syntax lib/** is a non-standard feature of shells like bash and zsh and will not do anything special in make recipes. It is identical to writing lib/*.
You can force make to use a different shell than /bin/sh by adding:
SHELL := /bin/bash
to your makefile, for example, but this makes it less portable (if that's an issue).

Resources