The Include(CheckIPOSupported)
command checks if the compiler supports interprocedural optimization (IPO), a compiler technique that optimizes multiple source files and function boundaries to enhance performance.
The include(CheckIPOSupported)
command includes a CMake module, which provides functions and macros for checking IPO support in the current compiler. Here's an example of how to use it in a CMakeLists.txt
file:
cmake_minimum_required(VERSION 3.25.1)project(MyProject)# including CheckIPOSupported libararyinclude(CheckIPOSupported)# check if IPO is supportedcheck_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_OUTPUT)if(IPO_SUPPORTED)message(STATUS "IPO is supported: ${IPO_OUTPUT}")set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)else()message(STATUS "IPO is not supported: ${IPO_OUTPUT}")endif()# including directoriesinclude_directories(include)set(SOURCESsrc/main.cppsrc/foo.cppsrc/bar.cpp)# enabling private compiler optionsadd_executable(MyExecutable ${SOURCES})target_compile_options(MyExecutable PRIVATE -Wall -Wextra)
Lines 1–2: Set the minimum required version of CMake to 3.25.1
and declare a CMake project named MyProject
.
Line 5: Includes a module named CheckIPOSupported
, which is used in a CMake script to determine if the compiler supports IPO to allow enhanced program optimization across multiple translation units during compilation.
Line 8: Calls the check_ipo_supported
function with four arguments: RESULT
, IPO_SUPPORTED
, OUTPUT
, and IPO_OUTPUT
, which checks for IPO support and stores the result and associated output in the specified variables.
Lines 9–14: Check if IPO is supported. If it is, then enable it and display a related message. Otherwise, display a message indicating that IPO is not supported.
Lines 17–22: Include header files from the include
directory and define the main.cpp
, foo.cpp
, and bar.cpp
source files located in the src
directory.
Line 25: CMake script compiles source files defined by ${SOURCES}
into an executable named MyExecutable.
Line 26: Enables private compiler options for it to enforce stricter warnings using -Wall
and -Wextra
.
Here's an implementation of the main.cpp
file:
#include <iostream>#include "foo.h"#include "bar.h"// main functionint main() {Foo foo;Bar bar;foo.doSomething();bar.doSomethingElse();std::cout << "Program executed successfully!" << std::endl;return 0;}
Lines 1–3: Include necessary header files, namely iostream
, foo.h
, and bar.h.
Allow access to input/output streams and declarations from foo.h
and bar.h
for further code implementation.
Lines 6–16: Define a main
function that creates instances of the Foo
and Bar
classes. Call the doSomething
method on the foo
object and the doSomethingElse
method on the bar
object. Then, output "Program executed successfully!"
to the console to indicate a successful program execution.
Here's an example implementation of the foo.h
header files:
#ifndef FOO_H#define FOO_H// declaring classclass Foo {public:void doSomething();};#endif
Lines 1–10: Define the foo.h
header file that guards against multiple inclusion and declares the Foo
class with a doSomething()
public member function.
Here's an example implementation of the bar.h
header files:
#ifndef BAR_H#define BAR_H// declaring classclass Bar {public:void doSomethingElse();};#endif
Lines 1–10: Define the bar.h
header file that guards against multiple inclusion and declares the Bar
class with a doSomethingElse()
public member function.
Here's an implementation of the foo.cpp
file:
#include <iostream>#include "foo.h"// function bodyvoid Foo::doSomething() {std::cout << "Doing something in Foo." << std::endl;}
Lines 1–2: Include the standard input/output stream header and a custom header, foo.h
, for potential further code dependencies.
Lines 4–6: Define the doSomething
member function within the Foo
class, which outputs the text “Doing something in Foo”
to the standard output stream, followed by a new line.
Here's an example implementation of the bar.cpp
file:
#include <iostream>#include "bar.h"// function bodyvoid Bar::doSomethingElse() {std::cout << "Doing something else in Bar." << std::endl;}
Lines 1–2: Include the standard input/output stream header and the bar.h
custom header for potential further code dependencies.
Lines 4–6: Define the doSomethingElse
member function within the Foo
class, which outputs the text, “Doing something else in Bar”
, to the standard output stream, followed by a new line.
In this example, foo.h
defines the Foo
class with a single-member function, doSomething()
. Similarly, bar.h
defines the Bar
class with a single-member function, doSomethingElse()
. Both header files are protected with the included guards (#ifndef
and #define
directives) to prevent multiple inclusion and potential symbol redefinition issues. These header files can also be included in the corresponding source files (main.cpp
, foo.cpp
, bar.cpp
) to provide the necessary declarations and definitions for the classes and their member functions.
We need to run the following commands to run the CMake program.
Here is the command to compile and link the program:
cmake -B buildtree
Here is the command to build the program:
cmake --build buildtree/
Here is the command to execute the program:
./buildtree/MyExecutable
Now, let's practice the above commands and see the CMake output by clicking the “Run” button.
#ifndef BAR_H #define BAR_H class Bar { public: void doSomethingElse(); }; #endif // BAR_H
Free Resources