美文网首页
CMake系列2 - 编译选项探测系统库信息

CMake系列2 - 编译选项探测系统库信息

作者: FredricZhu | 来源:发表于2022-03-17 09:44 被阅读0次

CMake官方文档如下,
https://cmake.org/cmake/help/latest/guide/tutorial/Adding%20a%20Custom%20Command%20and%20Generated%20File.html
本文主要演示使用CMake CheckSymbolExists函数探查系统是否存在相应的函数,如果不存在,就使用CMake自带的数学库。并定义编译选项,让程序根据编译选项,执行对应分支。

程序结构如下,


image.png

tutorial.cpp

#include "tutorial_config.h"

#ifdef USE_MYMATH
    #include "math_functions.h"
#endif

#include <cmath>
#include <iostream>
#include <string>


int main(int argc, char* argv[]) {
    if(argc < 2) {
        std::cout << argv[0] <<  " Version " << Tutorial_VERSION_MAJOR << "."
            << Tutorial_VERSION_MINOR << std::endl;
        std::cout << "Usage: " << argv[0] << " number" << std::endl;
        return EXIT_FAILURE;
    }

    double const input_val = std::stod(argv[1]);

#ifdef USE_MYMATH
    double const ouput_val = mysqrt(input_val);
#else
    double const ouput_val = sqrt(input_val);
#endif
    
    std::cout << "The sqrt root of " << input_val << " is: " << ouput_val << std::endl;
    return EXIT_SUCCESS;
}

tutorial_config.h.in

// Tutorial的配置选项和设置
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

外层CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

# 设置工程名称和版本
project(Tutorial VERSION 1.0)

# 指定C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED true)

# 是否使用自定义的 math实现
option(USE_MYMATH "Use tutorial provided math implementation" ON)

# 配置生成header文件
configure_file(tutorial_config.h.in tutorial_config.h)

# 添加 math_functions 库
if(USE_MYMATH)
    add_subdirectory(math_functions)
    list(APPEND EXTRA_LIBS math_functions)
endif()

add_executable(Tutorial tutorial.cpp)

target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})

target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")

enable_testing()

# 应用程序能运行吗?
add_test(NAME Runs COMMAND Tutorial 25)
# 使用消息 能工作吗?
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(Usage PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number")

# 定义一个函数来简化添加测试
function(do_test target arg result)
    add_test(NAME Comp${arg} COMMAND ${target} ${arg})
    set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endfunction()

# 做基于输出结果的测试
do_test(Tutorial 4 "The sqrt root of 4 is: 2")
do_test(Tutorial 9 "The sqrt root of 9 is: 3")
do_test(Tutorial 5 "The sqrt root of 5 is: 2.23607")
do_test(Tutorial 7 "The sqrt root of 7 is: 2.64575")
do_test(Tutorial 25 "The sqrt root of 25 is: 5")
do_test(Tutorial -25 "The sqrt root of -25 is: 0")
do_test(Tutorial 0.0001 "The sqrt root of 0.0001 is: 0.01")

install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/tutorial_config.h" DESTINATION include)

math_functions/CMakeLists.txt

add_library(math_functions mysqrt.cpp)

target_include_directories(math_functions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

# 系统是否包含log和exp 函数?
include(CheckSymbolExists)
check_symbol_exists(log "math.h" HAVE_LOG)
check_symbol_exists(exp "math.h" HAVE_EXP)

if(NOT (HAVE_LOG AND HAVE_EXP))
    unset(HAVE_LOG CACHE)
    unset(HAVE_EXP CACHE)
    set(CMAKE_REQUIRED_LIBRARIES "m")
    check_symbol_exists(log "math.h" HAVE_LOG)
    check_symbol_exists(exp "math.h" HAVE_EXP)
    if(HAVE_LOG AND HAVE_EXP)
        target_link_libraries(math_functions PRIVATE m)
    endif()
endif()

# 添加编译选项
if(HAVE_LOG AND HAVE_EXP)
    target_compile_definitions(math_functions PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()

install(TARGETS math_functions DESTINATION lib)
install(FILES math_functions.h DESTINATION include)

math_functions/math_functions.h

#ifndef _FREDRIC_MATH_FUNCTIONS_H_
#define _FREDRIC_MATH_FUNCTIONS_H_

double mysqrt(double x);

#endif

math_functions/my_sqrt.cpp

#include <iostream>
#include <cmath>

#include "math_functions.h"

// a hack square root calculation using simple operations
double mysqrt(double x) {
    if (x <= 0) {
        return 0;
    }

#if defined(HAVE_LOG) && defined(HAVE_EXP)
    double result = exp(log(x) * 0.5);
    std::cout << "Computing sqrt of " << x << " to be " << result
            << " using log and exp" << std::endl;
#else
    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;
    }
#endif
    return result;
}

程序输出如下,


image.png

相关文章

网友评论

      本文标题:CMake系列2 - 编译选项探测系统库信息

      本文链接:https://www.haomeiwen.com/subject/tccvdrtx.html