ensure config.h is included once - linux

I have a library project that I'm working on porting to using the autotools suite in Linux. I'm quite new to autotools (this week). I've learned the basics of its operation. I have a question about how to keep the contents of config.h from being redefined.
I'm surprised to find that the generated config.h file doesn't either, 1) wrap each macro in a #ifndef or, 2) that the entire file isn't wrapped in the standard #ifndef CONFIG_H.
As I've alluded, this code is built on Windows and Linux. Thus there are several uses of a macro, _linux (I'm not saying that's the best name, but it's in use everywhere) to bring in elements to classes which exist in Linux only. Thus, this will happen
header.h
#ifndef HEADER1_H
#define HEADER1_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#endif
source.cxx
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "header.h" // oops, preprocessor gets excited because of redefs
One simple solution is I do that standard unique wrap in config.h.in after the file is generated. However, I was wondering, is there a better way of handling this? I can't be the first to encounter this and there might even be a means of handling it in configure.ac but being a complete neophyte in this, I don't know what to even search for.

The way I do this is indeed creating a wrapper file (which I usually call global.h) that reads like this.
#ifndef MY_PROJECT_GLOBAL_H
#define MY_PROJECT_GLOBAL_H
#include <config.h>
/* Maybe other global definitions… */
#endif
Note that the recommended way to #include the config.h file is via <config.h> not "config.h" so it works better with VPATH builds.
Then, all the source files in my project #include this global.h header as their very first #include and don't care about config.h. A header file should never #include config.h since this would lead to bad name conflicts. Actually, if you stick to this guideline, your code should also work without #include guards in the configuration header.
Update regarding OP's comment
Or: How to use configuration results in headers?
If your headers need to declare different things depending on the results of the configure script, you have a number of options, none of which is perfect.
For internal headers, there is no problem. They simply rely on the macros being #defined without #includeing anything. This works if – as is recommended – all source files #include (maybe indirectly as shown above) config.h before any other header.
If the headers are to be installed publicly, this is not such a great solution. For those of your users that use Autoconf, it wouldn't be that bad, although even those would have to remember what checks to place in their configure.ac files. For users who don't use Autoconf, it will be pretty bad. If you only have a few switches (such as Glibc's fature test macros), it is okay to ask your users to #define them before #includeing your headers but if you need many, this is not a real option. Not to mention that you'll expose a lot of implementation details to your users that way.
If all you need to do is branch depending on the platform you are building for, you could probe some of the pre-defined macros like __linux or _WIN32. There is the Boost.Predef library that aims to make these check a little more convenient by providing a higher-level abstraction. The library works with C and C++ alike but, of course, it adds an additional dependency to your project.
Finally, you could make a version of your config.h that uses a macro prefix specific to your project. There is a contribution in the Autoconf macro archive that does exactly that for you. A minimal example could look like this.
AC_PREREQ([2.69])
AC_INIT([example-project], [1.0], [bugs#example.org])
AC_CONFIG_SRCDIR([example.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AX_PREFIX_CONFIG_H([public_config.h], [EXAMPLE_PROJECT], [config.h])
AC_PROG_CC
AC_OUTPUT
Save this as configure.ac, download ax_prefix_config_h.m4 from the Autoconf macro archive and place it in the sub-directory m4 and then run autoreconf && ./configure. It will create the normal config.h and in addition public_config.h where in the latter file, all macros are prefixed with EXAMPLE_PROJECT_. The file public_config.h (which also has #include guards by the way) can be installed and #included in your project's public header files if need be.

With autoheader, you can add header and trailer boiler plate code to config.h
https://www.gnu.org/software/autoconf/manual/autoconf-2.60/html_node/Autoheader-Macros.html
For example, add the following to your configure.ac
#
# Add include guards to config.h
#
AH_TOP([
#ifndef __CONFIG_H_INCLUDE_GUARD
#define __CONFIG_H_INCLUDE_GUARD
])
AH_BOTTOM([
#endif
])

Related

AC_CHECK_HEADERS: define a macro before testing for header presence

A particular C++ logging library called spdlog that I use in my project has a broken package on CentOS (the platform I'm trying to compile on) where the header file will only compile if SPDLOG_FMT_EXTERNAL is defined before any of its files are included. [And this will not be fixed.]
I am trying to find a way to use autoconf directives to test for the presence of this header file - previously I used a homegrown macro that compiles a program which uses that, but its speed latency is unacceptably slow so I am trying to replace it.
Here is the relevant snippet of my configure.ac:
dnl check for libfmt is done earlier...
AC_CHECK_HEADERS([spdlog/spdlog.h], [have_spdlog="yes"], [have_spdlog="no"])
if test x$have_spdlog = xyes; then
LDFLAGS="$LDFLAGS -lspdlog -lfmt";
else
AC_MSG_ERROR([spdlog is required for logging support but is missing.])
fi
The header file spdlog/spdlog.h exists, but Autoconf deems it as not usable because it won't compile by itself.
AC_CHECK_HEADERS has a parameter I can specify include files required to include that particular header file. I can use that to specify the #define macro before the file is included.
Is there an easier way to just directly specify a macro without creating a new header file?
After some experimenting, I learned that the fourth parameter to AC_CHECK_HEADERS accepts macros as well - anything that can be used in a C/C++ preprocessor works as well, such as #ifdef, #endif and so on. It is not restricted to only #include directives.
AC_CHECK_HEADERS([spdlog/spdlog.h], [have_spdlog="yes"], [have_spdlog="no"], [
#define SPDLOG_FMT_EXTERNAL
])

To know precompiled header is used

I have a.cpp that is used in several projects. Some of them are using precompiled headers, others - not. Depending on this I must add or remove line :
#include <stdafx.h>
Is it possible somehow play with #define to make this in automatic way?
UPD.
I can't use empty stdafx.h file in case when precompiled headers are not used because I got strange behaviour in my situation when a.cpp is placed in project sub directory libA. In this case projects that use precompiled header must have line:
#include <stdafx.h>
and projects that are not using PCH must have line:
#include "..\stdafx.h"
Wice versa is not working. Actually I still can't understand this behavior. I would like to have a.cpp file identical for all projects.
You can include a preprocessor define in the project settings for those projects which use precompiled headers, and then base the inclusion of stdafx.h based on its existence. Using your example, libA's C++ settings should include /D USE_PCH, and then in a.cpp:
#ifdef USE_PCH
#include <stdafx.h>
#else
#include "../stdafx.h"
#endif
To ensure that the define and precompiled header settings remain in sync, you could create a property sheet with both settings, and link it to your project. However, if it were me, I would just disable precompiled headers for the files which are shared between libraries. Unless the PCH is very large, and the number of shared sources also very large, the compilation time savings likely won't outweigh the maintenance of this approach.

Is there a way to detect whether #pragma unmanaged is in effect in C++/CLI?

I have a project that includes some performance sensitive native C++ headers making heavy use of templates. For this project we also wrap the headers and add some glue code to expose the functionality to c# and other .NET languages. We'll call this header "layout.h", and we'll assume it's a third party header that I can't change.
In a mixed mode C++/CLI assembly it is relatively easy to make a mistake and #include from a place in the code where #pragma unmanaged (or #pramga managed(push,off) ) . When that happens the templates generate IL, and I get extra managed/unmanaged transitions when running the code and performance goes down the drain.
My question is whether there is a way I can do a compile-time check just before the #include so that compilation fails if I am accidently #including from the wrong context.
// File1.cpp, compiled in a mixed mode C++/CLI assembly with /clr
ASSERT_UNMANAGED()
#include <layout.h>
My naive 1st attempt checked #ifdef _MANAGED, but that is always defined whether I'm in a #pragma unmanaged block of code or not.
The pragma directives must be inserted directly in the include file. In this way, everywhere you include the file an unmanaged section is declared.
Sorry that you have to modify your include file.
You may write ASSERT_MANAGED or ASSERT_UNMANAGED code that would use construct that is available ONLY while compiling managed or unmanaged. A ref class declaration is an example which is avaiable only when using managed.
This is somewhat a dirty solution, but it would work.
Here's a possible solution, making use of the fact that intrinsics are always compiled as native (unmanaged) code:
#include <intrin.h>
#define ASSERT_UNMANAGED() \
int TestFunc(void) { \
__pragma(warning(push)) \
__pragma(warning(error:4793)) \
auto aumt = [] () { return _bextr_u64(65537, 0, 8); }; \
__pragma(warning(pop)) \
return int(aumt()); }
#pragma unmanaged // Comment out this line and the assertion fails!
ASSERT_UNMANAGED()
#pragma managed
EDIT: Of course, if you just want warnings rather than compilation failure, you can remove the 3 __pragma(warning()) lines.

Where to get iostream.h

I'm trying to make something in Linux, but it complains that it can't find iostream.h. What do I need to install to get this file?
The correct name of this standard header is just iostream without an extension.
If your compiler still cannot find it, try the following:
find /usr/include -name iostream -type f -print
...and add it to your include path, following your compiler's documentation.
The header <iostream.h> is an antiquated header from before C++ became standardized as ISO C++ 1998 (it is from the C++ Annotated Reference Manual). The standard C++ header is <iostream>. There are some minor differences between the two, with the biggest difference being that <iostream> puts the included contents in namespace std, so you have to qualify cin, cout, endl, istream, etc. with "std::". As somewhat of a hack (it is a hack because header files should never contain "using" directives as they completely defeat the purpose of namespaces), you could define "iostream.h" as follows:
#ifndef HEADER_IOSTREAM_H
#define HEADER_IOSTREAM_H
#include <iostream>
using namespace std; // Beware, this completely defeats the whole point of
// having namespaces and could lead to name clashes; on the
// other hand, code that still includes <iostream.h> was
// probably created before namespaces, anyway.
#endif
While this is not exactly identical to the original antiquated header, this should be close enough for most purposes (i.e. there should be either nothing or very few things that you will have to fix).
I needed to compile partport on Debian and had problems (CentOS 4.5 worked fine). I did this without any success:
ln -s /usr/include/c++/4.5/iostream /usr/include/c++/4.5/iostream.h
I discovered that iostream.h was provided from C++, and I found it on CentOS 4.5.
So I copied the file iostream.h from CentOS 4.5 to Ubuntu 11.04 (Natty Narwhal), and it worked:
scp root#ip.centos-4.5:/usr/include/c++/3.3.4/backward/iostream.h /usr/include/c++/4.5/iostream.h

Standard Template Library using g++

While migrating a program from windows in linux I encountered a problem using the c++ standard template library. I am trying to typedef a template and I am getting the error 'expected initializer before '<' token on this line
typedef std::list< std::pair< int,double> > PairList;
Any ideas why this would work using mvc++ and not using g++ and how I can fix it?
I think this is about #includes.
The following really minimal piece of code compiles perfectly here with g++ on Linux
#include <utility>
#include <list>
typedef std::list< std::pair< int,double> > PairList;
PairList x;
One thing to remember about standard include files is that they are allowed but not required to call each other. (It's not like they're potentially polluting the namespace by this, since they all use namespace std, which you aren't supposed to mess with.)
It is possible that, in MSVC++, includes , or vice versa, but this is not the case in the g++ headers. Therefore, a program might compile in MSVC++ and not in g++, with a required header missing in the source.
Make sure all of your required headers are actually included, and you should be fine.
Did you #include <utility> for pair?
I have had no problems with the code in G++, and generally found its STL support to be superb. Do you have all the #include directives there? Sometimes those differ from platform to platform (even when they shouldn't).

Resources