I finally figured out a little bit of what I didn’t know about find_X when I integrated with Android Studio

Said in the previous

  1. By default, androidstudio downloads cmake asCmake version 3.10.2My current version of Android Studio is:Android Studio 4.0
  2. You can download the latest version of cmake and configure it for yourselflocal.properties Cmake. Dir \ = D: \ \ softwarefiles \ \ chrome \ \ cmake - 3.10.2 - win64 - x64To add this, we also need to addbuild.gradleadd
    android {
        externalNativeBuild {
            cmake {
                path "src/main/cpp/CMakeLists.txt"
                version "3.10.2"}}}Copy the code

    Of course, we still take our own as the standard. Because there will be other problems. Because Android has cmake configured for us and you have to get the latest one because you have to implement it yourselfandroid.toolchain.cmakeOtherwise, cool

  3. Because each compilation is repeated many times, so in thebuild.gradleTo add the following code
    android {
        defaultConfig {
            ndk{
                abiFilters "arm64-v8a"}}}Copy the code

    This only compiles code for the specified platform

First impression

First, Android has the following options by default:

if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
  set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
endif()

if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
  set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
endif()

if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
  set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()

if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
  set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
endif()
Copy the code

The above options have the following effects

# find_package ()
message(WARNING "CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ${CMAKE_FIND_ROOT_PATH_MODE_PACKAGE}")
# find_program ()
message(WARNING "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ${CMAKE_FIND_ROOT_PATH_MODE_PROGRAM}")
# find_library ()
message(WARNING "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ${CMAKE_FIND_ROOT_PATH_MODE_LIBRARY}")
# affect find_file() and find_path()
message(WARNING "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ${CMAKE_FIND_ROOT_PATH_MODE_INCLUDE}")
Copy the code

The specific value is:

  1. ONLYThe relevantrootOnly in theCMAKE_FIND_ROOT_PATHLook in here
  2. NEVERThe relevantrootOnly in theCMAKE_SYSROOTLook in here
  3. BOTHThe relevantrootWill be inCMAKE_SYSROOT CMAKE_FIND_ROOT_PATHTogether to find

To enter the body

Look at the configuration in Android

Tree /f ├─ CPP │ ├─ cmakelists.txt │ ├─ cmakelists.txt │ ├─ Cmakelists.txt │ ├─ Include │ curl │ ├─include │ curl A ├─ Java │ ├─ com │ ├─ example │ ├─ myApplication │.ktCopy the code

For the purpose of AndroidStudio I want my outer cmakelists. TXT to be able to find curl’s library by means of find_package

The current version of cmake is 3.18, but 3.10.2 does not affect our use. Ha ha.

Findcurl. Cmake has two alternative formats.

According to the official document, here and directly on the correct answer. 【 The college entrance examination is not easy, come on 】

set(libname curl)
find_path(${libname}_INCLUDE_DIR
        curl.h
        HINTS ${CMAKE_SOURCE_DIR}/curl/include
        CMAKE_FIND_ROOT_PATH_BOTH
        )
        
FIND_LIBRARY(${libname}_LIBRARY NAMES curl PATHS curl/lib)

IF(${libname}_INCLUDE_DIR AND ${libname}_LIBRARY)
    SET(${libname}_FOUND TRUE)
ENDIF()
IF(${libname}_FOUND)
    if(NOT ${libname}_FIND_QUIETLY)
        MESSAGE(WARNING "FOUND LIBRARY:${${libname}_LIBRARY}")
    ENDIF()
ELSE(${libname}_FOUND)
    if(${libname}_FIND_REQUIRED)
        MESSAGE(FATAL_ERROR "cant found")
    endif()
endif(${libname}_FOUND)
Copy the code

You can’t find the curl. H header file, for example.

Open the official document, in fact, this is the most correct way to solve the problem ah.

The find_path rule, So if you use find_path (BOOST_STATE_HPP NAMES curl. H PATHS module/curl/include NO_DEFAULT_PATH) sorry you can’t find it.

The document says: There are six priorities to look for.

In a nutshell

The first level can be skipped with NO_CMAKE_PATH, If CMAKE_LIBRARY_ARCHITECTURE is set it will be suffixes and then go to CMAKE_PREFIX_PATH CMAKE_INCLUDE_PATH CMAKE_FRAMEWORK_PATH

The second level can be skipped with NO_CMAKE_ENVIRONMENT_PATH

If I set HINTS here

Level 4 can be skipped by NO_SYSTEM_ENVIRONMENT_PATH

Level 5 can be skipped with NO_CMAKE_SYSTEM_PATH, Then go to CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_INCLUDE_PATH CMAKE_SYSTEM_FRAMEWORK_PATH

If I set PATHS here

The API is listed below

find_path (<VAR> name1 [path1 path2 ...] ) find_path ( <VAR> name | NAMES name1 [name2 ...]  [HINTS path1 [path2 ... ENV var]] [PATHS path1 [path2 ... ENV var]] [PATH_SUFFIXES suffix1 [suffix2 ...]] [DOC"cache documentation string"]
          [NO_DEFAULT_PATH]
          [NO_CMAKE_PATH]
          [NO_CMAKE_ENVIRONMENT_PATH]
          [NO_SYSTEM_ENVIRONMENT_PATH]
          [NO_CMAKE_SYSTEM_PATH]
          [CMAKE_FIND_ROOT_PATH_BOTH |
           ONLY_CMAKE_FIND_ROOT_PATH |
           NO_CMAKE_FIND_ROOT_PATH]
         )
Copy the code

Print here the values of the parameters that may be affected

message(WARNING "CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}")
message(WARNING "CMAKE_ANDROID_ARCH_ABI ${CMAKE_ANDROID_ARCH_ABI}")
message(WARNING "CMAKE_LIBRARY_ARCHITECTURE ${CMAKE_LIBRARY_ARCHITECTURE}")
message(WARNING "CMAKE_SYSTEM_INCLUDE_PATH ${CMAKE_SYSTEM_INCLUDE_PATH}")
message(WARNING "CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH}")
message(WARNING "CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH}")
message(WARNING "CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE}")
message(WARNING "CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK}")
message(WARNING "CMAKE_STAGING_PREFIX ${CMAKE_STAGING_PREFIX}")
message(WARNING "CMAKE_SYSROOT ${CMAKE_SYSROOT}")
message(WARNING "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ${CMAKE_FIND_ROOT_PATH_MODE_INCLUDE}")

Copy the code

The output

CMAKE_PREFIX_PATH CMAKE_ANDROID_ARCH_ABI armeabi-v7a CMAKE_LIBRARY_ARCHITECTURE arm-linux-androideabi CMAKE_SYSTEM_INCLUDE_PATH /usr/include/X11 CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_FIND_ROOT_PATH D:\workspace\AndroidStudio\AndroidStudioProjects\app\.cxx\cmake\debug\prefab\armeabi-v7a\prefab; D:/env/android-ndk-r20b CMAKE_FIND_APPBUNDLE CMAKE_FIND_FRAMEWORK CMAKE_STAGING_PREFIX CMAKE_SYSROOT D:/env/android-ndk-r20b/toolchains/llvm/prebuilt/windows-x86_64/sysroot CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLYCopy the code

So let’s write down what doesn’t work, and what does

Error prone point 1: CMAKE_MODULE_PATH

CMAKE_MODULE_PATH and assumes that it only affects the find_package lookup path. So setting it is meaningless for find_path

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/module/curl/include ${CMAKE_MODULE_PATH}")
Copy the code

Error point 2: CMAKE_PREFIX_PATH

Find_path is affected by CMAKE_PREFIX_PATH, so it should be valid. If CMAKE_LIBRARY_ARCHITECTURE is set, the search path will change to /include/

, which is set in Android Studio!!

The NDK will be configured for you by default. Check the NDK installation directory android-ndk-r20b\build\cmake\android.toolchain.cmake to see which variables are set.

Error point three: given the full path or cannot find

In this case, add CMAKE_FIND_ROOT_PATH_BOTH or NO_CMAKE_FIND_ROOT_PATH, Set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE “BOTH”) specifies BOTH

Then findxx.cmake will find it correctly. It can be used in cmakelists.txt

Cmake_minimum_required (VERSION 3.4.1 track)set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/curl)
find_package(curl REQUIRED)
message(WARNING "find it ${curl_LIBRARY}")

add_library(native-lib
        SHARED
        test.c
        )
target_include_directories(native-lib PRIVATE ${curl_INCLUDE_DIR})
target_link_libraries(native-lib
        ${log-lib}
        ${curl_LIBRARY}
        -lz
        )
Copy the code

At this point, you can refer to it in your code

#include "curl.h"
#include <jni.h>
#include <stdio.h>

int main() {printf("hello");
   CURL * curl = curl_easy_init();
}
Copy the code

By the way, if you have a requirement for the imported header file, for example, do not include curl. H and want include/curl

set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "NEVER")
find_path(${libname}_INCLUDE_DIR
        include/curl.h
        HINTS ${CMAKE_SOURCE_DIR}/curl
        #[[CMAKE_FIND_ROOT_PATH_BOTH]]
        NO_DEFAULT_PATH
        )
Copy the code

So you can import it in your own project

#include "include/curl.h"
#include <jni.h>
#include <stdio.h>

int main() {printf("hello");
   CURL * curl = curl_easy_init();
}
Copy the code

The above. This is done using the Android Studio IDE. Cmake compilation. Of course, you can do this yourself by setting env

export NDK_HOME=~/workspace/env/ndk_r20/android-ndk-r20
export NDK_BUILD=${NDK_HOME}/ndk-build

export TOOLROOT=${NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin
export TOOLPREFIX=arm-linux-androideabi

export CC=${TOOLROOT}/armv7a-linux-androideabi16-clang
export CXX=${TOOLROOT}/armv7a-linux-androideabi16-clang++
export CPP="${CC} -E"
export AR=${TOOLROOT}/arm-linux-androideabi-ar
export LD=${TOOLROOT}/arm-linux-androideabi-ld
export NM=${TOOLROOT}/arm-linux-androideabi-nm
export RANLIB=${TOOLROOT}/arm-linux-androideabi-ranlib
export STRIP=${TOOLROOT}/arm-linux-androideabi-strip
export READELF=${TOOLROOT}/arm-linux-androideabi-readelf
export ADDR2LINE=${TOOLROOT}/arm-linux-androideabi-addr2line
export OBJDUMP=${TOOLROOT}/arm-linux-androideabi-objdump

export LDFLAGS="-static-libstdc++"

export PRJ_NAME=android

export ARCH=arm
Copy the code

Then the rest of the business is the same as any other platform development.

source ./env
$CC test.c
Copy the code