Setting Per-File Flags with Automake

Setting per-file flags with automake

Automake only supports per-target flags, while you want per-object flags. One way around is to create a small library that contains your object:

CXXFLAGS = -Wall ...
bin_PROGRAMS = test
test_SOURCES = main.cpp
test_LDADD = libutility.a
noinst_LIBRARIES = libutility.a
libutility_a_SOURCES = utility.cpp
libutility_a_CXXFLAGS = $(CXXFLAGS) -Wno-unused-value

Setting per-file flags with automake

Automake only supports per-target flags, while you want per-object flags. One way around is to create a small library that contains your object:

CXXFLAGS = -Wall ...
bin_PROGRAMS = test
test_SOURCES = main.cpp
test_LDADD = libutility.a
noinst_LIBRARIES = libutility.a
libutility_a_SOURCES = utility.cpp
libutility_a_CXXFLAGS = $(CXXFLAGS) -Wno-unused-value

Specific compilation flags with autotools and static library

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wsuggest-override"
#include <pugixml/pugixml.hpp>
#pragma clang diagnostic pop

...

Is what I usually would do in these instances with clang.

I don't see how this is an automake problem. You're compiling the convenience library without elevated warnings, and the code that uses the dependency header with elevated warnings. You'd have the same problem if you built them using just make, or cmake, or the command line.

Is it possible to set specific _CFLAGS, _LDADD etc. variables for all programs in a _PROGRAMS variable?

Is it possible to just declare these variables for all targets in TESTS?

Not as such. Automake provides for flag-bearing variables expressing default flags and for variables expressing target-specific flags, but there is no built in way to specify flags that apply to a designated subset of targets. Nevertheless, there are ways to exercise the available features to get at least close to what you want.

One way is to set up for recursive building via SUBDIRS and multiple Makefile.am files. With such a setup, you should be able to have separate default flags of each category for each Makefile.am.

But from the wording and the details of the code snippet in the question, I take it that you are using Automake's include directive to build a single makefile, and within that makefile you want to express flags that apply to all the test targets, but not any other targets. Here are some ways to approach that:

  1. define all the wanted flags in an ordinary make variable, and interpolate them into test-specific variables. Example:

    tests_cflags = -O0 -g --coverage
    # ...
    tests_foo_CFLAGS = $(tests_cflags)
    tests_bar_CFLAGS = $(tests_cflags)
    tests_baz_CFLAGS = $(tests_cflags)

    Although that does not overcome the need for target-specific variables for each test target, it does allow you to manage the actual flags all in one place instead of separately for each test.

  2. Flip the script. Supposing that you have a much higher number of tests than you have other compiled targets, set up the default flags to serve the tests, and, where necessary, override them with target-specific flags for the other targets. Most of the Automake defaults are conveyed via variables with the AM_ prefix (LDADD is an exception), so that might look something like this:

    LDADD = $(top_builddir)/src/libmylib.la
    AM_CFLAGS = -O0 -g --coverage
    # ...
    # no tests_foo_CFLAGS, etc.
    # ...
    libmylib_la_CFLAGS = ...

    Note that the value of the target-specific variables (libmylib_la_CFLAGS in this case) can be empty if you just want to suppress the default flags instead of replacing them with different ones.

Either way, you probably want to be familiar with Automake's flag-variable ordering rules.

Where to add a CFLAG, such as -std=gnu99, into an autotools project

autoconf has a macro for this:

Just put:

AC_PROG_CC_STDC

after your AC_PROG_CC and everything will be right.

Especially when you use other compilers that do not have -std=gnu99 but operate in C99 mode by default (or have a different option hpcc's -AC99 springs to mind).

I would NOT use CFLAGS for that kind of thing.

From the docs:

-- Macro: AC_PROG_CC_STDC
If the C compiler cannot compile ISO Standard C (currently C99),
try to add an option to output variable `CC' to make it work. If
the compiler does not support C99, fall back to supporting ANSI
C89 (ISO C90).

After calling this macro you can check whether the C compiler has
been set to accept Standard C; if not, the shell variable
`ac_cv_prog_cc_stdc' is set to `no'.

Automake conditional append or variable assignment for sources/flags/libs

The differences you observe are largely a matter of style, which is subjective and thus largely off-topic here. But your actual question is pretty objective:

Does one of them have a technical downside or nasty side-effect?

No, none of which I am aware. Either approach will work fine, at least in isolation. A larger context might provides reasons to prefer variations on the second approach, such as re-use of the variables in conjunction with more than one target. That would be more likely the case for preprocessor or link options than for choice of source files, however.


Personally, I would structure the particular case you've presented a bit differently:

if OS1
os_src = os1.c
else
if OS2
os_src = os2.c
endif
endif

bin_PROGRAMS = mypkg
mypkg_SOURCES = mypkg.c $(os_src)

To be sure, this is a matter of style, so take it for whatever it's worth to you. Here, the usage of the variable matches the structure of the condition: OS1 and OS2 are alternatives, so between them they control the value of just one variable. The meaning of that variable is therefore clearer, both at the point where its value is set and at the point it is used.

Multiple variables make more sense for multiple distinct, unrelated conditions.

How to set compiler-specific flags with autotools

AM_CXXFLAGS isn't something you should AC_SUBST. It is reserved for use by automake. If you look at the Makefile generated for a C++ target, you will find definitions for CXXCOMPILE and LTCXXCOMPILE, which always include the AM_CXXFLAGS variable.

You want to add the (conditional) compiler flag to AM_CXXFLAGS or to libfoo_la_CXXFLAGS. The former will affect all C++ compilations, and the latter just the per-library compilations. So it's just a matter of getting SPECIFIC_CXXFLAGS right in configure.ac.

AC_PROG_CXX
...
FOO_SPECIFIC_CXXFLAGS=;
if `$CXX -v 2>&1 | grep 'gcc version' >/dev/null 2>&1` ; then
FOO_SPECIFIC_CXXFLAGS="--param max-vartrack-size=100000000"
fi

AC_SUBST(FOO_SPECIFIC_CXXFLAGS, $FOO_SPECIFIC_CXXFLAGS)

The GXX test is insufficient as autoconf just tests for the __GNUC__ macro (AFAIK), so clang++ will set: GXX=yes

The problem is, there isn't a portable way of detecting command line options that are unknown. Intel's icc -v will even reproduce the gcc version string. So you might have to add another filter, like: | grep -v 'icc'

You could optionally check that the flag works as advertised before AC_SUBST, but this doesn't really help if the compiler only generates a warning:

saved_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $FOO_SPECIFIC_CXXFLAGS"

AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],,[FOO_SPECIFIC_CXXFLAGS=;])
AC_LANG_POP([C++])
CXXFLAGS="$saved_CXXFLAGS"

Then in Makefile.am:

AM_CXXFLAGS = $(FOO_SPECIFIC_CXXFLAGS)

or:

libfoo_la_CXXFLAGS = $(FOO_SPECIFIC_CXXFLAGS)


Related Topics



Leave a reply



Submit