cmake使用03:库链接

  1. 简单的链接一个库

目录如下:
./step3是我们的这个项目工程目录,./step3/MathFuncions/下存在第三方库(静态库libMathFunciotns.a,libMathFunctions.so,提供mysqrt()函数)

step3/--
      |---build
      |---MathFuntion/
            |---libMathFunctions.a
            |---libMathFunctions.so
            |---MathFunctions.h
      |---Tutorial.cxx
      |---TutorialConfig.h.in 
      |---CMakeLists.txt

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) return 1;
 
  std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
              << Tutorial_VERSION_MINOR << std::endl;
    


  // convert input to double
  const double inputValue = std::stod(argv[1]);


#ifdef USE_MYMATH
  const double outputValue = mysqrt(inputValue);
#else
  const double outputValue = sqrt(inputValue);
#endif

  std::cout << "The square root of " << inputValue << " is " << outputValue
            << std::endl;
  return 0;
}

为了实现选择性链接第三方库还是标准库中的开方函数,CMakeLists.txt修改如下:
如果2出链接了第三方库,则对应的3处也应包含该库的头文件

cmake_minimum_required(VERSION 3.10)

project(Tutorial VERSION 1.0)

# 指定使用c++标准.必须位于所有add_**调用之前
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)



option(USE_MYMATH "Use tutorial provided math implementation" ON)

#  基于TutorialConfig.h.in生成 TutorialConfig.h
configure_file(TutorialConfig.h.in TutorialConfig.h)

#1.如果USE_MYMATH=ON,将会对变量EXTRA_LIBS和EXTRA_INCLUDES以分号间隔追加。
if(USE_MYMATH)
  list(APPEND EXTRA_LIBS MathFunctions)
  list(APPEND EXTRA_INCLUDES ${PROJECT_SOURCE_DIR}/MathFunctions )
endif()
# 
add_executable(Tutorial tutorial.cxx)

#2:库链接。
# USE_MYMATH=ON,${EXTRA_LIBS}==MathFunctions,等价 -lMathFunctions ,优先动态库libMathFunctions.so
# USE_MYMATH=OFF,${EXTRA_LIBS}== ,即不链接第三库,使用的标准库中的sqrt函数。
# 如果我们想要链接的是libMathFunctions.a静态库,就指定带路径静态库即可,如下
# set(EXTRA_LIBS,${PROJECT_SOURCE_DIR}/MathFunctions/libMathFunctions.a)
target_link_libraries(Tutorial PUBLIC  ${EXTRA_LIBS})

#3:头文件包含
target_include_directories(Tutorial PUBLIC
                           ${PROJECT_BINARY_DIR}
                           ${EXTRA_INCLUDES}
                           )

在构建目录./step3/build/下执行:
cmake .. -DUSE_MYMath=on
make
这使得CMakeLists.txt中链接第三方库libMathFunctions.a,tutorial.cxx条件编译包含第三方库的头文件和调用mysqrt函数

cmake .. -DUSE_MYMath=on
make
这使得CMakeLists.txt中不链接链接第三方库libMathFunctions.a,tutorial.cxx条件编译不包含第三方库的头文件和调用标准库中sqrt函数

  1. 创建子CMakeList.txt用于生成库
    目录结构如下
step3/--
      |---build
      |---MathFuntion/(子目录)
            |---mysqrt.cxx
            |---MathFunctions.h
            |--CMakeLists.txt(子CMakeLists.txt)
      |---Tutorial.cxx
      |---TutorialConfig.h.in
      |---CMakeLists.txt

首先看下子CMakeLists.txt,它就是生成库:

# 同一CMakeLists.txt内不能同时生成同名静态和动态库,通过手动取消、添加注释实现切换
# 生成动态库(默认就是位置无关的动态库):libMathFunctions.so
#add_library(MathFunctions SHARED mysqrt.cxx)

# 生成静态库:libMathFunctions.a
add_library(MathFunctions  STATIC mysqrt.cxx)


再看主CMakeLists.txt,在1)处调用子目录的CMakeLists.txt。

cmake_minimum_required(VERSION 3.10)

project(Tutorial VERSION 1.0)

# 指定使用c++标准.必须位于所有add_**调用之前
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

option(USE_MYMATH "Use tutorial provided math implementation" ON)

# 基于TutorialConfig.h.in生成 TutorialConfig.h
configure_file(TutorialConfig.h.in TutorialConfig.h)

# 根据USE_MYMATH
if(USE_MYMATH)
  # 1.执行子目录${CMake_CURRENT_SOURCE_DIR}/MathFunctions下的子CMakeLists.txt
  # 将构建结果存放构与之相应的目录:${PROJECT_SOURCE_DIR}/MathFunctions/build
  add_subdirectory(MathFunctions ${PROJECT_SOURCE_DIR}/MathFunctions/build)


  list(APPEND EXTRA_LIBS MathFunctions)
  list(APPEND EXTRA_INCLUDES ${PROJECT_SOURCE_DIR}/MathFunctions )
endif()
message(EXTRA_LIBS=${EXTRA_LIBS},EXTRA_INCLUDES=${EXTRA_INCLUDES},BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS},USE_MYMATH=${USE_MYMATH},  
CMAKE_LIBRARY_PATH=${CMAKE_LIBRARY_PATH})



# 生成可执行文件
add_executable(Tutorial tutorial.cxx)

# 指定target的链接库名。这里为可执行文件Tutorial连接库${EXTRA_LIBS}。target也可为库文件。
# 
target_link_libraries(Tutorial PUBLIC  ${EXTRA_LIBS})

# 指定target的所需头文件的路径
target_include_directories(Tutorial PUBLIC
                           ${PROJECT_BINARY_DIR}
                           ${EXTRA_INCLUDES}
                           )

ps:
CMAKE_SOURCE_DIR:
最顶层CMakeLists.txt所在目录

CMAKE_BIN_DIR:
最顶层CMakeLists.txt的构建目录

project_SOURCE_DIR:
最近调用project()的CMakeLists.txt所在目录

project_BIN_DIR:
最近调用project()的CMakeLists.txt的构建目录

CMAKE_CURRENT_SOURCE_DIR:
当前CMakeLists.txt的所在目录,这是当前CMakeLists.txt中各种文件名的路径

CMAKE_CUREENT_BIN_DIR:
当前CMakeLists.txt的构建目录,这是当前CMakeLists.txt的输出文件(Makefile、add_XX输出的target)存放目录
何为构建目录:CMakeLists.txt执行输出的存放位置。
例如:
上述主CMakeLists.txt是在外部通过CMake ..调用,那执行cmake ..时的工作目录就是该主CMakeList.txt的构建目录。
子CMakeLists.txt是在主CMakeLists.txt内通过add_subdirectory调用
,子CMakeLists.txt的构建目录就是由add_susbdirectory()指定的。

posted @ 2024-07-05 15:49  旅行者2号  阅读(18)  评论(0编辑  收藏  举报