How can you check if AC_PROG_CXX has failed? - autoconf

The AC_PROG_CXX macro checks for possible C++ compilers and in the event of failure, happily just sets CXX to g++ even if it knows g++ doesn't really exist.
My question is, how can you understand if AC_PROG_CXX did actually find a proper compiler?
I am asking because I have a C++ library in my project that could be optionally compiled. I can't seem to figure out how on earth I'm supposed to know whether I can actually compile anything with CXX.
Some of the macros like AC_PROG_CC_C99 give a variable (in this case ac_cv_prog_cc_c99) that can tell me if the feature exists or not. I tried ac_cv_prog_cxx and similar things, but it doesn't seem to exist.

You could try compiling a minimal program, e.g.,
AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[#ifndef __cplusplus
#error "broken C++"
#endif]])],,
[CXX=;])
AC_LANG_POP([C++])
If the compilation fails, we explicitly set CXX to an empty string. So depending on what you want to do:
if test "x$CXX" != x ; then
... we have a working C++ compiler - setup optional stuff ...
fi
Or as part of a conditional build in a Makefile.am file:
AM_CONDITIONAL([ENABLE_CXX_SRC], [test "x$CXX" != x])

Related

Ignoring specific scons warnings

I'm using scons for building. I had encountered the following warning (when compiling some classes that are used in multiple build targets):
scons: warning: Two different environments were specified for target /home/stackuser/src/dsl/build/debug/common/LocalLog.o,
but they appear to have the same action: $CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM $SOURCES
So the accepted way around this warning is to use env.Object in the source list for common cpp files:
client_srcs = [
env.Object("../common/LocalLog.cpp"),
env.Object("../common/LogMsg.cpp"),
"LogWriter.cpp",
"QueueConsumer.cpp",
env.Object("../common/QueueStore.cpp"),
env.Object("../common/TimeFunctions.cpp")
]
However, when using this env.Object function around the common cpp files, some targets don't build (linker error linking to boost):
/usr/include/boost/system/error_code.hpp:208: undefined reference to `boost::system::get_system_category()'
/usr/include/boost/system/error_code.hpp:209: undefined reference to `boost::system::get_generic_category()'
/usr/include/boost/system/error_code.hpp:214: undefined reference to `boost::system::get_generic_category()'
/usr/include/boost/system/error_code.hpp:215: undefined reference to `boost::system::get_generic_category()'
This linker error is described here; to summarize the accepted answer:
When statically linking the linker expects that libraries will come
after the files containing references to them. You need to move your
.o files before your -l flags.
However, if I just remove the env.Object calls in the SConscript, I get these scons warnings, but compilation and linking is successful.
I'd just like to ignore these scons warnings; (how) can I turn them off?
If you take a short look at the MAN page ( http://scons.org/doc/production/HTML/scons-man.html ), you'll find the "warn=no-all" option...amongst a lot of other useful stuff.
Note however, that switching off this warning is a bad idea in general, because it's hinting at flaws in your build description. You're telling SCons to build a file like "debug/common/LocalLog.o" from two (or more) different environments. This may work as long as the command lines used (and the environments, including all shell variable settings) are exactly the same, so that's why SCons continues.
But usually you want to have one single way to build a specific target file.
There are three proper solutions to your dilemma (probably more, but these are the ones that came to my head immediately):
1.) Put the sources/objects that you want to use in multiple places into a separate lib and then link against that.
2.) For each time you compile the same *.CPP file, give a different unique name to the object file (LocalLog_a.o, LocalLog_b.log, ...).
3.) Compile the source one time (env.Object('LocalLog.cpp'), and then add the resulting object file to your list of sources for each program/library in question:
client_srcs = [
"../common/LocalLog.$OBJSUFFIX",
"../common/LogMsg.$OBJSUFFIX",
"LogWriter.cpp",
"QueueConsumer.cpp",
"../common/QueueStore.$OBJSUFFIX",
"../common/TimeFunctions.$OBJSUFFIX")
]

AC_CHECK_LIB does not find library but compilation runs anyway

I am adding autotool support to a library project. It relies on another self-written library which is not necessarily in a default library path. So I will set LDFLAGS when configuring.
Nevertheless, I want to check for the library in order to warn the user to set LDFLAGS correctly. Therefore I put in this line:
AC_CHECK_LIB([foo], [foo_func],
[AC_DEFINE([HAVE_FOO, [1],
[Define if you have libfoo])],
[AC_MSG_WARN([libfoo not found.])])
Now, if I do not set LDFLAGS, the check fails as expected and the warning is printed. BUT: When I run make, the code compiles nevertheless, because I have the library path set in the environment variable LD_LIBRARY_PATH. I find this confusing... I would want either the check to fail and the code not to compile or the check does not fail and the code compiles.
Am I misunderstanding what AC_CHECK_LIB means or what am I doing wrong?
AC_CHECK_LIB does not care what conclusions you attach to the presence or absence of the library. It just determines whether the library is there and executes its third argument if so, and its fourth argument if not.
So getting the logic you want is up to you. If you replace AC_MSG_WARN by AC_MSG_ERROR in the fourth argument, as ldav1s suggests in the comment, then the configure script will abort if the check fails, and the code will not compile.

autoconf/automake: conditional compilation based on presence of library?

I need to conditionally compile some code based on the presence of a library. Seems like this should be easy with autoconf/automake but I can't figure it out.
For example, if there is a PNG library present, I want to include code to use it. My configure.ac has:
AC_CHECK_LIB([png], [png_create_write_struct_2])
and my Makefile.am has:
if USE_LIBPNG
libdev_la_SOURCES += png.c
endif
(which adds png.c to the list of sources for libdev so it gets compiled).
An automake conditional like USE_LIBPNG requires the conditional be defined in configure.ac, so i need:
AM_CONDITIONAL([USE_LIBPNG], [test SOMETHINGOROTHER])
The question is, what can test SOMETHINGOROTHER be? What does AC_CHECK_LIB define that I can test for?
AC_CHECK_LIB's default behavior is to define a symbol (in config.h) which can be used in source code, but that doesn't help the Makefile since the AM_CONDITIONAL needs a shell test
I tried overriding the default AC_CHECK_LIB behavior like so:
AC_CHECK_LIB([png], [png_create_write_struct_2], [HAS_LIBPNG=1])
after which I could test for it:
AM_CONDITIONAL([USE_LIBPNG], [test "x$HAS_LIBPNG" = "x1"])
This is ugly, but works for the Makefile... but creates a new problem: since it discards the original AC_CHECK_LIB behavior, and I no longer get a symbol added to config.h, which I need.
I must be missing something basic, or possible Doing It Wrong. Have been digging around for hours and found no answer.
Anyone?
If the library you're checking for supplies a .pc file for use with pkg-config, then you're much better off using PKG_CHECK_MODULES to get the correct flags. libpng does:
(in configure.ac)
PKG_CHECK_MODULES([libpng], [libpng12])
This gives you access to the variables $(libpng_CFLAGS) and $(libpng_LIBS) which you will want to add to Makefile.am (probably in AM_CFLAGS/AM_CXXFLAGS and LDADD, or target-specific versions thereof).
It will also cause configure to fail with an error if libpng12.pc isn't found. If you want configure to continue, you'll need to supply the third and fourth arguments to PKG_CHECK_MODULES, which are ACTION-IF-FOUND and ACTION-IF-NOT-FOUND:
(in configure.ac)
PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])
Now, if you need an automake conditional, you can do something like:
(in configure.ac)
AM_CONDITIONAL([USE_LIBPNG], [test "$HAVE_LIBPNG" -eq 1])
If you also need the preprocessor definition, you could use AC_DEFINE like so:
(in configure.ac)
AS_IF([test "$USE_LIBPNG" -eq 1], [AC_DEFINE([USE_LIBPNG], [1], [Define if using libpng.])])
Possibly nicer is to set the definition in Makefile.am:
(in Makefile.am)
AM_CPPFLAGS =
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
endif
This will clutter your command line, though, whereas AC_DEFINE can put the definition in a header if you use AC_CONFIG_HEADERS. I guess this doesn't really matter if you use AM_SILENT_RULES([yes]) or don't care about your command line being neat (and let's be honest, automake generates some pretty gnarly command lines anyway).
A note on good autoconf style
It is considered poor form to build optional support based on whether or not a check succeeded (see this gentoo doc for details). Here's how I'd code optional support for libpng:
(in configure.ac)
# This is because the first PKG_CHECK_MODULES call is inside a conditional.
PKG_PROG_PKG_CONFIG
AC_ARG_WITH([libpng],
[AS_HELP_STRING([--with-libpng],
[support handling png files #<:#default=check#:>#])],
[],
[with_libpng=check])
AS_CASE(["$with_libpng"],
[yes], [PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1])],
[no], [],
[PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])])
AM_CONDITIONAL([USE_LIBPNG], [test "$with_libpng" != no -a "$HAVE_LIBPNG" -eq 1])
(in Makefile.am)
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
AM_CFLAGS += $(libpng_CFLAGS)
LDADD += $(libpng_LIBS)
libdev_la_SOURCES += png.c
endif
If your library doesn't have a .pc file
For completeness, here's how I'd check for a library that didn't have a .pc file. I'll skip over the details of following good autoconf style. AC_CHECK_LIB sets a cache variable, so you can test that instead of replacing the ACTION-IF-FOUND of AC_CHECK_LIB:
(in configure.ac)
AC_CHECK_LIB([png], [png_create_write_struct_2])
# Then test:
AS_IF([test "$ac_cv_lib_png_png_create_write_struct_2" = yes], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])
# Or set conditional:
AM_CONDITIONAL([USE_LIBPNG], [test "$ac_cv_lib_png_png_create_write_struct_2" = yes])
IMHO, you should only do it this way if you have no other option.
I will disagree mildly with Jack on his recommendation to use PKG_CHECK_MODULES. It is probably best to avoid using that. But I will agree with Jack on avoiding assigning to LIBS in the 3rd argument to AC_CHECK_LIB. Life is easier if you let AC_CHECK_LIB use the default settings.
Although AC_CHECK_LIB does not define a shell variable indicating whether or not the library was found, you can do this in configure.ac:
AM_CONDITIONAL([USE_LIBPNG],[grep HAVE_LIBPNG confdefs.h > /dev/null])
Arguably, this is relying on internal autoconf details, but in practice will work reliably.
Thanks for the replies.
Jack: I'm trying for maximum portability, so can't assume the libraries were installed as part of a package (they're not on my own box!), which means the no-other-option solution you suggested is what I already tried-- setting a shell variable manually-- but also manually performs the extra steps that would have been done by AC_CHECK_LIB: prepending the library to LIBS and defining HAVE_LIBxxx.
There was a catch though: autoheader complains about the bare AC_DEFINE:
autoheader: warning: missing template: HAVE_LIBPNG
autoheader: Use AC_DEFINE([HAVE_LIBPNG], [], [Description])
I'd be nice if autoheader worked in the future, so I had to change AC_DEFINE to the full monty:
AC_CHECK_LIB([png], [png_create_write_struct_2],
[HAS_LIBPNG=1
LIBS="-lpng $LIBS"
AC_DEFINE([HAVE_LIBPNG], 1, [Define to 1 if you have the `png' library (-lpng)])])
This works, but I don't much like having to duplicate the default behavior of AC_CHECK_LIB.
William: Yes I could grep for the symbol definition in confdefs.h, that also works.
Both solutions have their pros and cons (what doesn't?). Not sure which way I'll go, but it's nice to have options.
Thanks again.

unistd.h related difficulty when compiling bison & flex program under vc++

I'm using bison & flex (downloaded via cygwin) with vc++. When I compile the program I got an error:
...: fatal error C1083: Cannot open include file: 'unistd.h': No such file or directory
The corresponding code in the flex-generated file is:
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
* down here because we want the user's section 1 to have been scanned first.
* The user has a chance to override it with an option.
*/
/* %if-c-only */
#include <unistd.h>
/* %endif */
/* %if-c++-only */
/* %endif */
#endif
If I define YY_NO_UNISTD_H in the flex file(.l) this error will disappear, but I get several other errors:
...: error C2447: '{' : missing function header (old-style formal list?)
...: warning C4018: '<' : signed/unsigned mismatch
...: error C3861: 'isatty': identifier not found
How can I fix this problem?
All these errors occur in the flex-generated scanner.
I know it's because unistd.h doesn't exist in windows. Do I have to write my own unistd.h? If so how to write it in order to eliminate those errors?
isatty is used by the lexer to determine if the input stream is a terminal or a pipe/file. The lexer uses this information to change its caching behavior (the lexer reads large chunks of the input when it is not a terminal). If you know that your program will never be used in an interactive kind, you can add %option never-interactive to you lexer. When the program is run with user input, use %option interactive. When both uses are desired, you can either generate an interactive lexer, which gives a performance loss when used in batch mode, or provide your own isatty function.
Use %option nounistd in your .l file to remove the dependence on unistd.h.
just in case somebody's still this problem, Flex comes with unistd.h within its devel files. I found this here:
http://sourceforge.net/tracker/index.php?func=detail&aid=931222&group_id=23617&atid=379173
to put it short, just make sure your compiler can reach it. in my case it's just adding "C:\GnuWin32\include" to the additional inclusion directories
use win_flex.exe with option --wincompat and you dont need to hack your lex file
unistd.h is a UNIX header, so it's not present in VC++; your best bet is probably to compile it using g++ in Cygwin (or mingw/msys). You could also look at this question for other suggestions.
I'm using flex 2.5.4 that comes from the GnuWin32 project, which doesn't check for YY_NO_UNISTD_H.
In my version, Flex looks for unistd.h only when being compiled as C++, so you can save yourself all this trouble if your yylval doesn't use any C++ constructs.
I had to use the STL in yylval (using a pointer to make it a POD type), so in order to make flex compile in C++ I created this simple unistd.h:
#include <io.h>
That's all it takes (actually, I could copy the unistd.h file that comes with GnuWin32, like flyontheweb suggests).
P.S. To wrap things up: in Bison I put yylval's required STL header files in %code requires {} and added the current directory to the INCLUDE paths in my makefile.
I am too late but anyway I will share my findings to save someone still looking for answer.
In my case having an empty unistd.h file in the location where compiler looks for headers works for me.
Well this post is old but I face the same problem and here is something that should work.
WinFlexBison
I ran into this problem recently after upgrading to Angular 14.
npm install -g latest-version
resolved my issue.

Building Visual C++ app that doesn't use CRT functions still references some

This is part of a series of at least two closely related, but distinct questions. I hope I'm doing the right thing by asking them separately.
I'm trying to get my Visual C++ 2008 app to work without the C Runtime Library. It's a Win32 GUI app without MFC or other fancy stuff, just plain Windows API.
So I set Project Properties -> Configuration -> C/C++ -> Advanced -> Omit Default Library Names to Yes (compiler flag /Zl) and rebuilt. Let's pretend I have written a suitable entry point function, which is the subject of my other question.
I get two linker errors; they are probably related. The linker complains about unresolved external symbols __fltused and _memcpy in foobar.obj. Needless to say, I use neither explicitly in my program, but I do use memcpy somewhere in foobar.cpp. (I would have used CopyMemory but that turns out to be #defined to be identical to memcpy...)
(I thought I could get rid of the memcpy problem by using a compiler intrinsic, like #pragma intrinsic(memcpy), but this makes no difference.)
If I look at the preprocessor output (adding /P to the compiler command line), I see no references to either __fltused or _memcpy in foobar.i.
So, my question is: Where do these linker errors come from, and how do I resolve them?
__fltused implies you are using or have at least declared some floats or doubles. The compiler injects this 'useless' symbol to cause a floating support .obj to get loaded from the crt. You can get around this by simply declaring a symbol with the name
#ifdef __cplusplus
extern "C" {
#endif
int _fltused=0; // it should be a single underscore since the double one is the mangled name
#ifdef __cplusplus
}
#endif
WRT _memcpy - memcpy is a __cdecl function, and all cdecl functions get an automatic _ as part of their decoration. so, when you say "__cdecl memcpy" - the compiler & linker go looking for a symbol called '_memcpy'. Intrinsic functions - even explicitly requested - can still be imported if the build settings have debug settings that contra-indicate intrinsics. So you are going to need to implement your own memcpy and related functions at some point anyway.
I recommend setting the "generate assembly listing" (or some such) compiler option for foobar.cpp once, and then inspecting the assembler code. This should really tell you where these symbols are used.

Resources