Often, it is not enough to only build an executable, it should also be installable. With CMake, we can specify install rules using the install()
command. Supporting local installations for your builds in CMake is often as simple as specifying an install location and the targets and files to be installed
Configure.h.in file
ubuntu@ubuntu:$ vim TutorialConfig.h.in
ubuntu@ubuntu:$ cat TutorialConfig.h.in
// the configured options and settings for Tutorial
// TODO : Define Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH
ubuntu@ubuntu:$
Cxx file
ubuntu@ubuntu:$ vim tutorial.cxx
ubuntu@ubuntu:$ cat tutorial.cxx
// A simple program that computes the square root of a number
#include <cmath>
#include <iostream>
#include <string>
#include "TutorialConfig.h"
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
//report version
std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
<< Tutorial_VERSION_MINOR << std::endl;
std::cout << "Usage: " << argv[0] << " number" << std::endl;
return 1;
}
// convert input to double
// std::stod是C++ 11标准函数
const double inputValue = std::stod(argv[1]);
// calculate square root
const double outputValue = mysqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;
return 0;
}
ubuntu@ubuntu:$
Top CMake file
ubuntu@ubuntu:$ vim CMakeLists.txt
ubuntu@ubuntu:$ cat CMakeLists.txt
# TODO : Set the minimum required version of CMake to be 3.10
cmake_minimum_required(VERSION 3.10)
# TODO : Create a project named Tutorial and project version number 1.0
project(Tutorial VERSION 1.0)
# TODO : Replace the following code by:
# * Creating an interface library called tutorial_compiler_flags
# Hint: use add_library() with the INTERFACE signature
# * Add compiler feature cxx_std_11 to tutorial_compiler_flags
# Hint: Use target_compile_features()
# specify the C++ standard
# set(CMAKE_CXX_STANDARD 11)
# set(CMAKE_CXX_STANDARD_REQUIRED True)
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
# TODO : Create helper variables to determine which compiler we are using:
# * Create a new variable gcc_like_cxx that is true if we are using CXX and
# any of the following compilers: ARMClang, AppleClang, Clang, GNU, LCC
# * Create a new variable msvc_cxx that is true if we are using CXX and MSVC
# Hint: Use set() and COMPILE_LANG_AND_ID
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
# TODO : Add warning flag compile options to the interface library
# tutorial_compiler_flags.
# * For gcc_like_cxx, add flags -Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused
# * For msvc_cxx, add flags -W3
# Hint: Use target_compile_options()
target_compile_options(tutorial_compiler_flags INTERFACE
"$<${gcc_like_cxx}:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>"
"$<${msvc_cxx}:-W3>"
)
# TODO 7: With nested generator expressions, only use the flags for the
# build-tree
# Hint: Use BUILD_INTERFACE
target_compile_options(tutorial_compiler_flags INTERFACE
"$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# TODO : Create a variable MY_MATH using option and set default to ON
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# TODO : Use configure_file to configure and copy TutorialConfig.h.in to
# TutorialConfig.h
configure_file(TutorialConfig.h.in TutorialConfig.h)
# TODO : Use list() and APPEND to create a list of optional libraries
# called EXTRA_LIBS and a list of optional include directories called
# EXTRA_INCLUDES. Add the MathFunctions library and source directory to
# the appropriate lists.
#
# Only call add_subdirectory and only add MathFunctions specific values
# to EXTRA_LIBS and EXTRA_INCLUDES if USE_MYMATH is true.
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
# TODO : Add an executable called Tutorial to the project
# Hint: Be sure to specify the source file as tutorial.cxx
add_executable(Tutorial tutorial.cxx)
# TODO : Use target_link_libraries to link the library to our executable
# Link to tutorial_compiler_flags
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
# TODO : Use target_include_directories to include ${PROJECT_BINARY_DIR}
target_include_directories(Tutorial PUBLIC
${PROJECT_BINARY_DIR}
)
# TODO : Install Tutorial in the bin directory
# Hint: Use the TARGETS and DESTINATION parameters
install(TARGETS Tutorial DESTINATION bin)
# TODO : Install Tutorial.h to the include directory
# Hint: Use the FILES and DESTINATION parameters
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
DESTINATION include
)
ubuntu@ubuntu:$
MathFunctions directory
ubuntu@ubuntu:$ ls -tlr
total 16
-rw-r--r-- 1 ubuntu ubuntu 904 Oct 12 22:26 tutorial.cxx
-rw-r--r-- 1 ubuntu ubuntu 188 Oct 12 22:26 TutorialConfig.h.in
drwxr-xr-x 2 ubuntu ubuntu 4096 Oct 12 22:26 MathFunctions
-rw-r--r-- 1 ubuntu ubuntu 2115 Oct 18 17:30 CMakeLists.txt
ubuntu@ubuntu:$
MathFunctions Cxx file
ubuntu@ubuntu:$ vim mysqrt.cxx
ubuntu@ubuntu:$ cat mysqrt.cxx
#include <iostream>
// a hack square root calculation using simple operations
double mysqrt(double x)
{
if (x <= 0) {
return 0;
}
double result = x;
// do ten iterations
for (int i = 0; i < 10; ++i) {
if (result <= 0) {
result = 0.1;
}
double delta = x - (result * result);
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
return result;
}
ubuntu@ubuntu:$
MathFunctions header file
ubuntu@ubuntu:$ vim MathFunctions.h
ubuntu@ubuntu:$ cat MathFunctions.h
#ifndef __MATHFUNCTION___H__H
#define __MATHFUNCTION___H__H
double mysqrt(double x);
#endif
ubuntu@ubuntu:$
MathFunctions CMake file
ubuntu@ubuntu:$ vim CMakeLists.txt
ubuntu@ubuntu:$ cat CMakeLists.txt
# TODO : Add a library called MathFunctions
# Hint: You will need the add_library command
add_library(MathFunctions mysqrt.cxx)
# TODO : State that anybody linking to MathFunctions needs to include the
# current source directory, while MathFunctions itself doesn't.
# Hint: Use target_include_directories with the INTERFACE keyword
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# TODO : Link to tutorial_compiler_flags
target_link_libraries(MathFunctions)
# TODO : Create a variable called installable_libs that is a list of all
# libraries we want to install (e.g. MathFunctions and tutorial_compiler_flags)
# Then install the installable libraries to the lib folder.
# Hint: Use the TARGETS and DESTINATION parameters
set(installable_libs MathFunctions tutorial_compiler_flags)
install(TARGETS ${installable_libs} DESTINATION lib)
# TODO : Install the library headers to the include folder.
# Hint: Use the FILES and DESTINATION parameters
install(FILES MathFunctions.h DESTINATION include)
构建cmake工程
ubuntu@ubuntu:$ mkdir exercise9_build
ubuntu@ubuntu:$ ls -tlr
total 20
-rw-r--r-- 1 ubuntu ubuntu 904 Oct 12 22:26 tutorial.cxx
-rw-r--r-- 1 ubuntu ubuntu 188 Oct 12 22:26 TutorialConfig.h.in
-rw-r--r-- 1 ubuntu ubuntu 2350 Oct 19 10:41 CMakeLists.txt
drwxrwxr-x 5 ubuntu ubuntu 4096 Oct 19 10:43 exercise9_build
drwxr-xr-x 2 ubuntu ubuntu 4096 Oct 19 11:05 MathFunctions
ubuntu@ubuntu:$ cd exercise9_build
ubuntu@ubuntu:$ cmake -DUSE_MYMATH=ON ..
-- Build files have been written to: /home/ubuntu/study/cmake-learning/cmake-3.25.0-rc1-tutorial-source/Step5/exercise9_build
ubuntu@ubuntu:$ cmake --build .
ubuntu@ubuntu:$ cmake --install . --prefix=.
-- Install configuration: ""
-- Installing: /home/ubuntu/study/cmake-learning/cmake-3.25.0-rc1-tutorial-source/Step5/exercise9_build/./lib/libMathFunctions.a
-- Installing: /home/ubuntu/study/cmake-learning/cmake-3.25.0-rc1-tutorial-source/Step5/exercise9_build/./include/MathFunctions.h
-- Installing: /home/ubuntu/study/cmake-learning/cmake-3.25.0-rc1-tutorial-source/Step5/exercise9_build/./bin/Tutorial
-- Installing: /home/ubuntu/study/cmake-learning/cmake-3.25.0-rc1-tutorial-source/Step5/exercise9_build/./include/TutorialConfig.h
ubuntu@ubuntu:$ ls -tlr
total 72
-rw-r--r-- 1 ubuntu ubuntu 137 Oct 19 11:08 TutorialConfig.h
-rw-rw-r-- 1 ubuntu ubuntu 14733 Oct 19 11:08 CMakeCache.txt
-rw-rw-r-- 1 ubuntu ubuntu 8136 Oct 19 11:08 Makefile
-rw-rw-r-- 1 ubuntu ubuntu 3060 Oct 19 11:08 cmake_install.cmake
drwxrwxr-x 3 ubuntu ubuntu 4096 Oct 19 11:08 MathFunctions
-rwxrwxr-x 1 ubuntu ubuntu 15008 Oct 19 11:08 Tutorial
drwxrwxr-x 6 ubuntu ubuntu 4096 Oct 19 11:08 CMakeFiles
drwxrwxr-x 2 ubuntu ubuntu 4096 Oct 19 11:08 lib
-rw-rw-r-- 1 ubuntu ubuntu 448 Oct 19 11:08 install_manifest.txt
drwxrwxr-x 2 ubuntu ubuntu 4096 Oct 19 11:08 include
drwxrwxr-x 2 ubuntu ubuntu 4096 Oct 19 11:08 bin
ubuntu@ubuntu:$ ls -tlr lib
total 4
-rw-r--r-- 1 ubuntu ubuntu 3364 Oct 19 11:08 libMathFunctions.a
ubuntu@ubuntu:$ ls -tlr include/
total 8
-rw-r--r-- 1 ubuntu ubuntu 25 Oct 12 22:26 MathFunctions.h
-rw-r--r-- 1 ubuntu ubuntu 137 Oct 19 11:08 TutorialConfig.h
ubuntu@ubuntu:$ ls -tlr bin
total 16
-rwxr-xr-x 1 ubuntu ubuntu 15008 Oct 19 11:08 Tutorial
ubuntu@ubuntu:$
运行可执行文件
ubuntu@ubuntu:$ ls -tlr
total 72
-rw-r--r-- 1 ubuntu ubuntu 137 Oct 19 11:08 TutorialConfig.h
-rw-rw-r-- 1 ubuntu ubuntu 14733 Oct 19 11:08 CMakeCache.txt
-rw-rw-r-- 1 ubuntu ubuntu 8136 Oct 19 11:08 Makefile
-rw-rw-r-- 1 ubuntu ubuntu 3060 Oct 19 11:08 cmake_install.cmake
drwxrwxr-x 3 ubuntu ubuntu 4096 Oct 19 11:08 MathFunctions
-rwxrwxr-x 1 ubuntu ubuntu 15008 Oct 19 11:08 Tutorial
drwxrwxr-x 6 ubuntu ubuntu 4096 Oct 19 11:08 CMakeFiles
drwxrwxr-x 2 ubuntu ubuntu 4096 Oct 19 11:08 lib
-rw-rw-r-- 1 ubuntu ubuntu 448 Oct 19 11:08 install_manifest.txt
drwxrwxr-x 2 ubuntu ubuntu 4096 Oct 19 11:08 include
drwxrwxr-x 2 ubuntu ubuntu 4096 Oct 19 11:08 bin
ubuntu@ubuntu:$ cd bin
ubuntu@ubuntu:$ ls -tr
Tutorial
ubuntu@ubuntu:$
ubuntu@ubuntu:$ ./Tutorial 4294967296
Computing sqrt of 4.29497e+09 to be 2.14748e+09
Computing sqrt of 4.29497e+09 to be 1.07374e+09
Computing sqrt of 4.29497e+09 to be 5.36871e+08
Computing sqrt of 4.29497e+09 to be 2.68435e+08
Computing sqrt of 4.29497e+09 to be 1.34218e+08
Computing sqrt of 4.29497e+09 to be 6.71089e+07
Computing sqrt of 4.29497e+09 to be 3.35545e+07
Computing sqrt of 4.29497e+09 to be 1.67773e+07
Computing sqrt of 4.29497e+09 to be 8.38878e+06
Computing sqrt of 4.29497e+09 to be 4.19465e+06
The square root of 4.29497e+09 is 4.19465e+06
ubuntu@ubuntu:$ ./Tutorial 10
Computing sqrt of 10 to be 5.5
Computing sqrt of 10 to be 3.65909
Computing sqrt of 10 to be 3.19601
Computing sqrt of 10 to be 3.16246
Computing sqrt of 10 to be 3.16228
Computing sqrt of 10 to be 3.16228
Computing sqrt of 10 to be 3.16228
Computing sqrt of 10 to be 3.16228
Computing sqrt of 10 to be 3.16228
Computing sqrt of 10 to be 3.16228
The square root of 10 is 3.16228
ubuntu@ubuntu:$ ./Tutorial
./Tutorial Version 1.0
Usage: ./Tutorial number
ubuntu@ubuntu:$