Android Studio使用Gcc编译时,如何将其更改为G ++? 使用CMake

问题描述

我有一个Android Studio项目,该项目使用带有JNI的Native C ++代码,但是当我尝试构建我的项目时,它会抛出error: undefined reference to 'std::basic_ostream<char... 错误。

我正在使用ubuntu,我相信问题是由使用gcc编译器的IDE引起的,并尝试将其编译为C代码。当我尝试通过在终端中运行gcc -o foo foo.cpp来运行简单的hello world程序时,它给出了相同的错误。当我将gcc更改为g ++时,一切正常。

但是如何在IDE中更改编译器?我对使用CMake有点陌生,我认为我需要使用cmake的enable_language函数,但是即使我在我的CMakeLists.txt文件中添加enable_language(CPP)行,也会出现相同的错误。

这是我的CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)
include_directories("/usr/include/x86_64-linux-gnu/c++/9")
include_directories("/usr/include/c++/9")
include_directories("/usr/include/x86_64-linux-gnu")
include_directories("/usr/include")
file(GLOB srcs *.cpp *.c)
file(GLOB hdrs *.hpp *.h)



include_directories(${OpenCV_DIR}/jni/include)
include_directories(${TESSERACT_INCLUDE_DIRS})
include_directories(${LEPTONICA_INCLUDE_DIRS})
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs/${ANDROID_ABI}/libopencv_java4.so)

add_library( 
             native-lib

             
             SHARED

             #
             native-lib.cpp )



find_library( 
              log-lib

              
              log )


target_link_libraries( 
                    native-lib
                    lib_opencv
                    ${log-lib}
                    ${TESSERACT_LIBRARIES}
                    ${LEPTONICA_LIBRARIES})

谢谢!

ps:我的G ++和Gcc版本是9.3.0,已经安装了构建必备软件。

解决方法

您的CMakeLists.txt非常混乱。让我们一个接一个地解决一些潜在的问题,看看它是否开始起作用。

解决方案可能在第7点,但是我已经写了所有内容,因此我将其留在这里。让我知道我的回答是否对您有帮助。


1。 Android Studio是否真的使用此CMakeLists.txt文件进行构建?

NDK有两种常用的构建系统-较旧的ndk-build和较新的CMake。检查您的Gradle构建文件,以查看此CMakeLists.txt是否真正被使用。以下是有关其工作方式的文档:https://developer.android.com/studio/projects/gradle-external-native-builds

当然,您可以在CMakeLists.txt文件中故意犯下语法错误,以查看构建系统是否开始抱怨它。

并且请注意,在为Android构建时,不应单独调用CMake。应该从Android Studio用于构建整个项目的Gradle脚本中调用它。


2。所有使用C ++库的源文件都具有.cpp扩展名吗?

CMake根据文件的扩展名确定使用哪种编译器(C或C ++)。如果它是.c文件,则使用C编译器。如果是.cpp文件,则使用C ++编译器。

还要注意,Android NDK现在使用Clang(来自LLVM项目)而不是GCC,因此GCC版本或自定义GCC调用可能无关紧要。

您还可以使CMake变得冗长-打印所有构建命令,以查看正确执行了哪些命令。将set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON")添加到您的CMakeLists.txt文件中,使其变得冗长。


3。是否使用了正确的C ++库?

您缺少的符号(来自std :: basic_ostream的符号)在C ++库(我认为)中定义,需要链接到您的库。默认情况下,应该链接libc ++,这是正确的选择。但是有一个选项可以解决这个问题。因此,请在gradle构建文件中检查ANDROID_STL变量,并删除对该变量的所有分配。 NDK中的C ++库问题在这里说明:https://developer.android.com/ndk/guides/cpp-support#cmake


4。缺少源文件。

调用add_library时,您仅添加一个源文件- native-lib.cpp 。因此,只有一个文件会在库中编译(链接到的lib_opencv除外)。第file(GLOB srcs *.cpp *.c)行将所有cpp和c文件分配给 $ {srcs} 变量,但是该变量未被使用。您可以将 add_library 更改为使用该变量:add_library( native-lib SHARED ${srcs} )

如果您还希望包含子目录中的文件,请在file(GLOB srcs *.cpp *.c)命令中使用 GLOB_RECURSE 代替 GLOB

据我所知,file(GLOB hdrs *.hpp *.h)行是完全没有用的。我看不到所有头文件的列表在CMake脚本中如何有用。


5。使用新的基于目标的CMake配置。

较旧的CMake使用基于文件的配置,现在鼓励基于目标的配置。基于文件的命令例如是 link_libraries include_directories ,它们基​​于目标的替代方法是 target_link_libraries target_include_directories 。您正在混合这两种样式。基本上,当命令具有其 target _ 变体时,您总是想使用它。

您首先需要使用add_library( native-lib SHARED ${srcs} )创建目标,目标名称为 native-lib 。然后添加所有包含目录,并使用基于目标的命令将所有库链接到该目录。

添加lib_opencv的方式也缺少 find_package 命令。使用find_package(OpenCV REQUIRED),然后使用target_link_libraries( native-lib PUBLIC ${OpenCV_LIBS} )进行链接。

添加日志记录库的方式是可以的,因为log-lib库是本机API(https://developer.android.com/ndk/guides/stable_apis#logging)的一部分,因此更简单。

使用CMake时,您需要搜索Internet或文档以找出将每个库添加到目标所需的命令(除非您从源代码编译库)。尽管几乎总是 find_package target_link_libraries 的某种组合。


6。缺少项目信息。 我不确定这有多重要,但是通常您会使用以下内容启动主CMakeLists.txt:

cmake_minimum_required( VERSION 3.4.1 )
project( my_special_project )
set( CMAKE_CXX_STANDARD 14 )
set( CMAKE_CXX_STANDARD_REQUIRED True )

7。不要手动添加系统目录。

考虑一下,这可能是问题所在。扔掉所有这些行:

include_directories("/usr/include/x86_64-linux-gnu/c++/9")
include_directories("/usr/include/c++/9")
include_directories("/usr/include/x86_64-linux-gnu")
include_directories("/usr/include")

Ndk使用自己的工具链,因此切勿手动将路径从系统工具链添加到NDK项目。

我不鼓励在其他任何项目上也这样做。它不是可移植的,类似的事情应该由CMake自己间接解决。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...