我使用的是arm-linux-androideabi-g++编译器。当我尝试编译一个简单的“Hello, World!”程序时,它编译得很好。当我通过在代码中添加一个简单的异常处理来测试它时,它也能工作(在添加-fexceptions ..我猜它默认是禁用的)。
这是一个Android设备,我只想使用CMake,而不是ndk-build。
例如- first.cpp
#include <iostream>
using namespace std;
int main()
{
try
{
}
catch (...)
{
}
return 0;
}
./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions
它工作起来没有问题……
问题是……我正在尝试用CMake文件编译该文件。
我想添加-fexceptions作为标志。我试过
set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )
and
set ( CMAKE_C_FLAGS "fexceptions")
它仍然显示一个错误。
注意:考虑到CMake自2012年以来的发展,这里的大多数建议现在已经过时/过时,有更好的替代方案。
假设你想添加这些标志(最好在一个常量中声明它们):
SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS "-lgcov")
有几种方法可以添加它们:
The easiest one (not clean, but easy and convenient, and works only for compile flags, C & C++ at once):
add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
Appending to corresponding CMake variables:
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
Using target properties, cf. doc CMake compile flag target property and need to know the target name.
get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
if(TEMP STREQUAL "TEMP-NOTFOUND")
SET(TEMP "") # Set to empty string
else()
SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
endif()
# Append our values
SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )
现在我使用方法二。
注意:考虑到CMake自2012年以来的发展,这里的大多数建议现在已经过时/过时,有更好的替代方案。
假设你想添加这些标志(最好在一个常量中声明它们):
SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS "-lgcov")
有几种方法可以添加它们:
The easiest one (not clean, but easy and convenient, and works only for compile flags, C & C++ at once):
add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
Appending to corresponding CMake variables:
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
Using target properties, cf. doc CMake compile flag target property and need to know the target name.
get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
if(TEMP STREQUAL "TEMP-NOTFOUND")
SET(TEMP "") # Set to empty string
else()
SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
endif()
# Append our values
SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )
现在我使用方法二。
指定特定于工具链的选项的首选方法是使用CMake的工具链工具。这确保在以下方面有一个清晰的划分:
关于如何将源文件组织成目标文件的指令——在CMakeLists.txt文件中表示,完全与工具链无关;而且
特定工具链应该如何配置的细节——分离到CMake脚本文件中,可由项目的未来用户扩展,可扩展。
理想情况下,在你的CMakeLists.txt文件中应该没有编译器/链接器标志——即使在if/endif块中。您的程序应该使用默认的工具链(例如,GNU/Linux上的GCC或Windows上的MSVC)为本机平台构建,而不需要任何附加标志。
添加工具链的步骤:
Create a file, e.g. arm-linux-androideadi-gcc.cmake with global toolchain settings:
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_CXX_FLAGS_INIT "-fexceptions")
(You can find an example Linux cross-compiling toolchain file here.)
When you want to generate a build system with this toolchain, specify the CMAKE_TOOLCHAIN_FILE parameter on the command line:
mkdir android-arm-build && cd android-arm-build
cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc.cmake ..
(Note: you cannot use a relative path.)
Build as normal:
cmake --build .
工具链文件使交叉编译更容易,但它们还有其他用途:
单元测试的强化诊断。
set(CMAKE_CXX_FLAGS_INIT "-Werror -Wall -Wextra -Wpedantic")
难以配置的开发工具。
#工具链文件用于gcov
set(CMAKE_CXX_FLAGS_INIT "——coverage -fno-exceptions -g")
加强安全检查。
#工具链文件用于GDB
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-fsanitize=address,undefined -fsanitize-undefined-trap-on-error")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fsanitize=address,undefined -static-libasan")