这一次,我们会给我们的工程添加一个库。这个库包含我们自定义的计算实数平方根的函数。之后工程编译出的可执行文件会使用这个库的平方根计算函数,而不是在Toturial.cxx文件中include一个函数。这次我们将生成这个库的代码放到一个叫MathFunctions的子目录。CMakeLists.txt需要包含如下行:

add_library(MathFunctions mysqrt.cxx)



名为“sqrt.cxx”的文件包含一个叫做mysqrt的函数,这个函数提供与默认sqrt函数相似的功能。为了使用新编译出的库,我们需要在CMakeLists.txt文件靠前的位置使用add_subdirectory函数告诉cmake 在使用这个库之前编译这个库。同时,我们也要使用include_directories来告诉cmake 在哪里

找MathFunctions/mysqrt.h。添加库的代码大致如下:

include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions) 
 
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial MathFunctions)



接下来,我们让使用这个库变为可选的。当然在这个教程中这一操作意义不大,但是在之后开发人员使用的时候,例如决定是否使用某个第三方库,这一功会变得很必要。要实现这一功能,第一步是在CMakeLists.txt文件中添加一个选项,代码大致如下:

# should we use our own math functions?
option (USE_MYMATH 
        "Use tutorial provided math implementation" ON)



这些代码会cmake gui界面中显示一个默认为ON的选项,用户可以根据需要选择是否启用它。这一选项会被保存在缓存文件中,这样用户就不必须在每次启动这个cmake项目时都重新设置。接下来要做的就是根据选项决定是否编译和链接MathFunctions库,体现在代码上就是在CMakeLists.txt靠前位置添加如下代码:

# add the MathFunctions library?
#
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
  add_subdirectory (MathFunctions)
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
 
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial  ${EXTRA_LIBS})


变量”USE_MYMATH”就是用来确定是否编译和链接MathFunctions库。需要注意通常会有一个变量(这个例子中是EXTRA_LIBS)收集可选的之后要被编译到可执行文件的库。这是一个常用来保持较大且有很多可选库的项目清洁的方法。对应新的选项,代码也会有相应的变化:

// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
#ifdef USE_MYMATH   // 这一宏的使用还要和cmake文件配合详见后文
#include "MathFunctions.h"
#endif
 
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"%s Version %d.%d\n", argv[0],
            Tutorial_VERSION_MAJOR,
            Tutorial_VERSION_MINOR);
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
 
  double inputValue = atof(argv[1]);
 
#ifdef USE_MYMATH   // 使用定义的宏
  double outputValue = mysqrt(inputValue);
#else
  double outputValue = sqrt(inputValue);
#endif
 
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}



在代码中,我们使用了宏USE_MYMATH。这一宏是由CMake通过TutorialConfig.h.in配置文件提供给代码文件的,要实现它需要在TutorialConfig.h.in添加如下代码:

#cmakedefine USE_MYMATH