You want to define the preprocessor
symbol name
, assigning it either an unspecified
value or the value value
.
The compiler options for defining a macro from the command line are shown in Table 1-16. Instructions for defining a
macro from your IDE are given in Table
1-17. To define a macro using Boost.Build, simply add a property of the form
<define>
name
[=
value
]
to your target’s requirements, as shown in Table 1-15 and Example 1-12.
Table 1-17. Defining a macro from your IDE
Preprocessor symbols are used frequently in C++ source code to allow a single collection of source files to be used with several build configurations or operating systems. For example, suppose you want to write a function that checks whether a file is a directory. Currently, the C++ standard library does not provide the functionality necessary to perform this task; consequently, your function will need to make use of platform specific features. If you want your code to work both on Windows and on Unix, you’ll have to make sure that the code that makes use of Windows-specific features is not visible to the compiler when compiling on Unix, and vice versa. The usual way to achieve this is through conditional compilation , as illustrated in Example 1-25.
Example 1-25. Conditional compilation using predefined macros
#ifdef _WIN32 # include <windows.h> #else // Not Windows - assume we're on Unix # include <sys/stat.h> #endif bool is_directory(const char* path) { #ifdef _WIN32 // Windows implementation #else // Unix implementation #endif }
On Windows, all the toolsets except the Cygwin port of GCC define the macro _WIN32
; macros defined automatically in this way are known as
predefined macros
. Example 1-25 uses the
predefined macro WIN32
to determine which operating
system it is being compiled under and to enable the appropriate platform-specific
code.
Often, however, the configuration information necessary to perform this kind of
conditional compilation is not available as predefined macros. In such cases, it’s
necessary to introduce your own macros and to give them appropriate values using the
methods shown in Table 1-15, Table 1-16, and Table 1-17. A good example is Example 1-2. On Windows, you want the function
georgeringo()
to be declared with the attribute
_ _declspec(dllexport)
when the DLL georgeringo.dll is being built, but with the attribute
_ _declspec(dllimport)
otherwise. As described in
Recipe 1.4, you can achieve this
effect by defining the preprocessor symbol GEORGERINGO_DLL
from the command line when building the DLL, but not when
compiling
code that uses the DLL.
Tip
When you fail to specify a value for a macro, most compilers assign it the value
1
, but others assign it an empty value. When macros
are used to enable conditional compilation as in Example 1-25, this difference is not
important; if you really need a macro to expand to a particular value, however, you
should specify that value explicitly using the syntax
-D<name>=<value>.
Get C++ Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.