C++20 source_location

使用source_location类可以减少代码中出现__FILE__ , __FUNCTION__ , __LINE__宏的次数。
https://zh.cppreference.com/w/cpp/utility/source_location

01 source_location头文件

source_location是表示关于源码的信息,例如文件名、行号以及函数名的类。
在头文件<source_location>中。1

namespace std {
  struct source_location {
    // 源位置构造
    static consteval source_location current() noexcept;
    constexpr source_location() noexcept;
 
    // 源位置域访问
    constexpr uint_least32_t line() const noexcept;
    constexpr uint_least32_t column() const noexcept;
    constexpr const char* file_name() const noexcept;
    constexpr const char* function_name() const noexcept;
 
  private:
    uint_least32_t line_;               // 仅为阐释
    uint_least32_t column_;             // 仅为阐释
    const char* file_name_;             // 仅为阐释
    const char* function_name_;         // 仅为阐释
  };
}

02 source_location用法

source_location 类表示关于源码的具体信息,例如文件名、行号以及函数名。以前,希望获得关于调用位置的信息(用于记录、测试或调试目的)的函数必须使用宏,以令如 __LINE____FILE__ 的预定义宏于调用方的环境展开。 source_location 类提供更好的替代。2

source_location类方法说明
current构造对应调用点位置的新 source_location(公开静态成员函数)
line返回此对象所表示的行号
column返回此对象所表示的列号
file_name返回此对象所表示的文件名
function_name返回此对象表示的函数名,若它存在
#include <iostream>
#include <string_view>
#include <source_location>
 
void log(std::string_view message,
         const std::source_location& location = std::source_location::current())
{
    std::cout << "info:"
              << location.file_name() << ":"
              << location.line() << " "
              << message << '\n';
}
 
int main()
{
    log("Hello world!");
}
// info:main.cpp:15 Hello world!

03 github上一个source_location实现

一个github上面的关于gcc与clang支持的source_location。3
https://github.com/paweldac/source_location

https://github.com/5455945/cpp_demo/blob/master/C%2B%2B20/source_location/source_location.cpp

#include <iostream>
#include <string_view>
// https://github.com/paweldac/source_location
#include "source_location.hpp"

// https://zh.cppreference.com/w/cpp/header/source_location
// https://zh.cppreference.com/w/cpp/utility/source_location
void log(const std::string_view& message, const std::source_location& location = std::source_location::current())
{
    std::cout << "info: "
        << location.file_name() << " "
        << location.function_name() << " "
        << location.line() << " "
        << location.column() << " "
        << message << '\n';
}

int main()
{
    auto location = std::source_location::current();
    std::cout << "info: " << location.file_name() << ":" << location.line() << ":"
        << location.column() << ":" << location.function_name() << ": "
        << "01 Hello World!" << std::endl;

    log("02 Hello world!");

    auto location2 = std::source_location::current(__FILE__, __FUNCTION__, __LINE__, 0);
    std::cout << location2.file_name() << ":" << location2.line() << ":"
        << location2.column() << ":" << location2.function_name() << ": "
        << "03 Hello World!" << std::endl;

    log("04 Hello world!", std::source_location::current(__FILE__, __FUNCTION__, __LINE__, 0));

    return 0;
}

https://github.com/paweldac/source_location/blob/master/include/source_location/source_location.hpp

#ifndef NOSTD_SOURCE_LOCATION_HPP
#define NOSTD_SOURCE_LOCATION_HPP

#pragma once

#include <cstdint>

namespace std {
struct source_location {
public:
#if not defined(__apple_build_version__) and defined(__clang__) and (__clang_major__ >= 9)
    static constexpr source_location current(const char* fileName = __builtin_FILE(),
        const char* functionName = __builtin_FUNCTION(),
        const uint_least32_t lineNumber = __builtin_LINE(),
        const uint_least32_t columnOffset = __builtin_COLUMN()) noexcept
#elif defined(__GNUC__) and (__GNUC__ > 4 or (__GNUC__ == 4 and __GNUC_MINOR__ >= 8))
    static constexpr source_location current(const char* fileName = __builtin_FILE(),
        const char* functionName = __builtin_FUNCTION(),
        const uint_least32_t lineNumber = __builtin_LINE(),
        const uint_least32_t columnOffset = 0) noexcept
#else
    static constexpr source_location current(const char* fileName = "unsupported",
        const char* functionName = "unsupported",
        const uint_least32_t lineNumber = 0,
        const uint_least32_t columnOffset = 0) noexcept
#endif
    {
        return source_location(fileName, functionName, lineNumber, columnOffset);
    }

    source_location(const source_location&) = default;
    source_location(source_location&&) = default;

    constexpr const char* file_name() const noexcept
    {
        return fileName;
    }

    constexpr const char* function_name() const noexcept
    {
        return functionName;
    }

    constexpr uint_least32_t line() const noexcept
    {
        return lineNumber;
    }

    constexpr std::uint_least32_t column() const noexcept
    {
        return columnOffset;
    }

private:
    constexpr source_location(const char* fileName, const char* functionName, const uint_least32_t lineNumber,
        const uint_least32_t columnOffset) noexcept
        : fileName(fileName)
        , functionName(functionName)
        , lineNumber(lineNumber)
        , columnOffset(columnOffset)
    {
    }

    const char* fileName;
    const char* functionName;
    const std::uint_least32_t lineNumber;
    const std::uint_least32_t columnOffset;
};
} // namespace nostd

#endif

  1. <source_location> ↩︎

  2. std::source_location ↩︎

  3. paweldac/source_location ↩︎

cmake_minimum_required(VERSION 3.14) project(SmartEQ_Android_SO LANGUAGES CXX C) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 99) set(CMAKE_SYSTEM_NAME Android) set(CMAKE_SYSTEM_VERSION 31) # 或者您需要的 Android API 级别 set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) # 设置为 arm64-v8a find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) # 添加头文件路径 include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/FFTW2/HeadFile/fftw ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/block ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/gsl ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/interpolation ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/linalg ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/view ${CMAKE_CURRENT_SOURCE_DIR}/EigenLib ${CMAKE_CURRENT_SOURCE_DIR}/ ) file(GLOB FFTW2_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/FFTW2/SourceFile/fftw/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.c ) file(GLOB GSL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/GSL/SourceFile/interpolation/*.c ${CMAKE_CURRENT_SOURCE_DIR}/GSL/SourceFile/linalg/*.c ${CMAKE_CURRENT_SOURCE_DIR}/GSL/SourceFile/view/*.c ) ## 声明并链接自定义库 libFFTW_GSL_SO.so ## -------------------------------------------- #if(ANDROID) # # Android 平台:动态处理 ABI 和多架构 # set(ANDROID_ABIS arm64-v8a) # foreach(abi ${ANDROID_ABIS}) # if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/FFTWGSL/${abi}/libFFTW_GSL_SO.so) # # 声明 IMPORTED 库目标 # add_library(FFTW_GSL_SO_${abi} SHARED IMPORTED) # set_target_properties(FFTW_GSL_SO_${abi} PROPERTIES # IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/FFTWGSL/${abi}/libFFTW_GSL_SO.so # ) # endif() # endforeach() #else() # # 非 Android 平台(如 Linux) # add_library(FFTW_GSL_SO SHARED IMPORTED) # set_target_properties(FFTW_GSL_SO PROPERTIES # IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/FFTWGSL/arm64-v8a/libFFTW_GSL_SO.so # ) #endif() add_library(SmartEQ_Android_SO SHARED smarteq_android_so.cpp smarteq_android_so.h ${FFTW2_SOURCES} ${GSL_SOURCES} fftw_gsl_so.h fftw_gsl_so.cpp ) target_include_directories(SmartEQ_Android_SO PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/FFTW2/HeadFile/fftw ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/block ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/gsl ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/interpolation ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/linalg ${CMAKE_CURRENT_SOURCE_DIR}/GSL/HeadFile/view ${CMAKE_CURRENT_SOURCE_DIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/EigenLib # ${CMAKE_CURRENT_SOURCE_DIR}/GSL/SourceFile/interpolation # ${CMAKE_CURRENT_SOURCE_DIR}/GSL/SourceFile/linalg # ${CMAKE_CURRENT_SOURCE_DIR}/GSL/SourceFile/view ) ## 链接依赖库 #target_link_libraries(SmartEQ_Android_SO PRIVATE # Qt${QT_VERSION_MAJOR}::Core # FFTW_GSL_SO_${ANDROID_ABI} # Android 平台按 ABI 链接 #) #target_include_directories(SmartEQ_Android_SO PRIVATE # ${CMAKE_CURRENT_SOURCE_DIR}/FFTWGSL/arm64-v8a #) target_link_libraries(SmartEQ_Android_SO PRIVATE Qt${QT_VERSION_MAJOR}::Core) target_compile_definitions(SmartEQ_Android_SO PRIVATE SMARTEQ_ANDROID_SO_LIBRARY) 为什么会爆以上的错误
最新发布
04-03
<think>嗯,用户给了一个CMakeLists.txt文件,然后问为什么会报错。首先,我需要仔细看一下这个CMake配置的内容,找出可能的问题点。不过用户提供的错误信息没有具体说明错误是什么,所以可能需要根据常见的错误情况来分析。 首先,CMake的版本设置为3.14,这可能没问题,但需要注意某些命令是否在旧版本中存在。然后项目名称和语言设置正确。接下来是设置一些自动处理UIC、MOC、RCC,这些是Qt相关的,可能没问题,但需要检查Qt的版本是否正确。 设置Android相关变量,比如SYSTEM_NAME为Android,SYSTEM_VERSION为31,ARCH_ABI为arm64-v8a,这部分应该是配置交叉编译到Android。不过需要注意是否安装了正确的NDK和工具链。 接下来查找Qt包,这里用了find_package两次,第一次是找Qt6或Qt5,然后第二次是找对应版本的Core组件。可能重复了,不过通常应该没问题,但需要确保Qt安装正确,并且CMake能找到它。 添加头文件路径时用了include_directories,不过后面在target_include_directories中又添加了一次,可能会有重复,不过通常不会导致错误,只是不够现代,建议用target_include_directories代替include_directories。 然后通过file(GLOB)收集源文件,这种方式在CMake中不被推荐,因为新增文件时可能不会自动重新生成构建系统,但不会直接导致编译错误,更多是维护问题。 接下来是添加库的部分,用户注释掉了一段关于导入预编译库的代码,可能原本是想链接外部库,但现在被注释掉了。如果代码中依赖这个库,那么链接时就会找不到符号,导致链接错误。比如在target_link_libraries中没有链接FFTW_GSL_SO相关的库,而代码中可能使用了这些库的函数,这会导致未定义的引用错误。 另外,检查target_link_libraries部分,用户目前只链接了Qt的Core模块,但如果有其他依赖库,比如FFTW或GSL的库,可能需要显式链接。特别是用户使用了GSL和FFTW的源代码,是否编译成静态库或动态库?或者是否应该将这些源文件编译到主库中? 还有,EigenLib是一个头文件库,不需要编译,所以包含路径正确即可。但GSL和FFTW的源文件是否正确包含?比如GSL_SOURCES可能包含了.c文件,而项目语言设置为C++和C,所以需要确保C文件被正确编译,并且C和C++的兼容性没有问题,比如是否使用了extern "C"来包含C头文件。 另外,检查编译器标志,C标准是99,C++是11,是否与源代码中的语法兼容?比如C11和C++11的特性是否被正确使用。 还有,在Android环境下,可能需要指定NDK的路径,或者工具链文件是否正确加载。如果CMake没有正确配置Android NDK,可能导致找不到编译器或链接器错误。用户是否在调用CMake时指定了-DANDROID_ABI=arm64-v8a,或者使用了正确的工具链文件? 另外,注释掉的部分原本是处理不同ABI的预编译库,但现在被注释,可能导致在链接时缺少必要的库。如果代码中调用了libFFTW_GSL_SO.so中的函数,而该库未被正确链接,就会出现未定义的符号错误。 可能用户遇到的错误是链接阶段找不到某些函数或符号,比如undefined reference to ...,这可能是因为没有链接必要的库,或者库的路径不正确。需要检查GSL和FFTW的源文件是否被正确编译并链接到目标库中,或者是否应该先编译成静态库再链接。 还有,Qt的Core模块是否被正确找到并链接?如果find_package失败,会导致找不到Qt相关的头文件或链接错误。 总结可能的错误点: 1. 缺少链接FFTW和GSL的库,或者这些库未正确编译到项目中。 2. 预编译的libFFTW_GSL_SO.so未被正确导入和链接,尤其是注释掉相关代码后。 3. Android NDK配置不正确,导致编译器或链接器路径错误。 4. C和C++混合编译时,头文件未正确使用extern "C"导致符号找不到。 5. 源文件中的函数定义缺失或实现不正确。 需要用户提供具体的错误信息,但根据常见情况,重点检查链接库的部分,尤其是被注释掉的FFTW_GSL_SO的导入部分,以及是否所有必要的源文件都被正确包含和编译。</think>以下是针对您提供的 CMakeLists.txt 文件可能存在的错误原因及解决方案的逐步分析: --- ### **一、基础配置分析** #### 1. `cmake_minimum_required(VERSION 3.14)` - **作用**:声明 CMake 最低版本要求(此处为 3.14)。 - **潜在问题**:若本地 CMake 版本低于 3.14,会导致配置失败。 #### 2. Android 平台配置 ```cmake set(CMAKE_SYSTEM_NAME Android) set(CMAKE_SYSTEM_VERSION 31) set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) ``` - **问题**:缺少 Android NDK 工具链配置。 - **解决方案**:需通过 `-DCMAKE_TOOLCHAIN_FILE` 指定 NDK 的 CMake 工具链文件,例如: ```bash cmake .. -DCMAKE_TOOLCHAIN_FILE=${NDK_PATH}/build/cmake/android.toolchain.cmake ``` --- ### **二、Qt 依赖配置** #### 1. 查找 Qt 包 ```cmake find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) ``` - **潜在问题**: - 若系统中未安装 Qt 或路径未正确配置,会导致 `find_package` 失败。 - 重复调用 `find_package` 可能冗余,建议合并为: ```cmake find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) ``` #### 2. 链接 Qt 库 ```cmake target_link_libraries(SmartEQ_Android_SO PRIVATE Qt${QT_VERSION_MAJOR}::Core) ``` - **验证**:确保 `Qt${QT_VERSION_MAJOR}::Core` 目标存在且路径正确。 --- ### **三、源代码与头文件配置** #### 1. 使用 `file(GLOB)` 收集源文件 ```cmake file(GLOB FFTW2_SOURCES ...) file(GLOB GSL_SOURCES ...) ``` - **潜在问题**: - `GLOB` 可能导致新增文件时 CMake 缓存未更新。 - 若路径错误或文件不存在,会导致编译时缺少源文件。 - **建议**:显式列出关键源文件,或确保路径正确。 #### 2. 头文件路径配置 ```cmake include_directories(...) target_include_directories(...) ``` - **问题**:重复包含路径(例如 `${CMAKE_CURRENT_SOURCE_DIR}/`)。 - **建议**:优先使用 `target_include_directories` 替代 `include_directories`。 --- ### **四、预编译库链接问题(关键错误来源)** #### 1. 注释掉的预编译库配置 ```cmake # if(ANDROID) # ... # endif() ``` - **问题**:代码中依赖 `libFFTW_GSL_SO.so`,但相关链接配置被注释,导致链接错误(如 `undefined reference`)。 - **解决方案**: - **方案 1**:取消注释并修复路径,确保 `libFFTW_GSL_SO.so` 存在。 - **方案 2**:直接编译 FFTW/GSL 源代码(需确认代码完整性)。 #### 2. 动态库路径验证 - 确保 `${CMAKE_CURRENT_SOURCE_DIR}/FFTWGSL/arm64-v8a/libFFTW_GSL_SO.so` 存在。 - 若为多 ABI 构建,需遍历所有支持的 ABI。 --- ### **五、C/C++ 标准配置** ```cmake set(CMAKE_CXX_STANDARD 11) set(CMAKE_C_STANDARD 99) ``` - **潜在问题**:若源代码使用 C11/C++17 等更高标准特性,需调整版本。 --- ### **六、Android 特定问题** #### 1. 缺少 NDK 配置 - **验证**:确保已通过 `-DANDROID_ABI=arm64-v8a` 指定 ABI。 - **完整配置示例**: ```bash cmake .. -DCMAKE_TOOLCHAIN_FILE=${NDK_PATH}/build/cmake/android.toolchain.cmake \ -DANDROID_ABI=arm64-v8a \ -DANDROID_PLATFORM=31 ``` #### 2. 符号冲突 - **问题**:C 与 C++ 混合编译时,未使用 `extern "C"` 包裹 C 函数。 - **解决方案**:在 C++ 头文件中添加: ```cpp #ifdef __cplusplus extern "C" { #endif // C 函数声明 #ifdef __cplusplus } #endif ``` --- ### **七、建议的修正步骤** 1. **取消注释预编译库配置**:确保 `libFFTW_GSL_SO.so` 存在并正确链接。 2. **配置 Android NDK**:通过命令行或 CMake 预设指定工具链。 3. **显式列出关键源文件**:避免 `GLOB` 潜在问题。 4. **验证 Qt 安装**:确保 `find_package` 能找到 Qt Core 模块。 5. **检查符号冲突**:使用 `extern "C"` 处理 C/C++ 混合代码。 --- 若提供具体的编译错误信息,可进一步精准定位问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值