Android ndk 如何获得ndk构建使用的完整编译器和链接器标志集?

Android ndk 如何获得ndk构建使用的完整编译器和链接器标志集?,android-ndk,Android Ndk,有没有一种简单的方法可以获取NDK构建使用的完整的编译和链接器标志集?现在我们通过查看C++在Android工作室项目中添加的CFILE文件来进行黑客攻击。 问题是,绝大多数时候我们都在构建许多现有的第三方项目,每个项目都有自己的构建系统。重写构建系统以使用Android的工具(cmake和ndk构建系统)将是疯狂的;我们需要使用现有的make系统,大多数情况下,这意味着我们需要为配置脚本提供CFLAGS、CXX_标志、cppfagas、LDFLAGS等。这些标志集在我找到的任何地方都没有记录,

有没有一种简单的方法可以获取NDK构建使用的完整的编译和链接器标志集?现在我们通过查看C++在Android工作室项目中添加的CFILE文件来进行黑客攻击。 问题是,绝大多数时候我们都在构建许多现有的第三方项目,每个项目都有自己的构建系统。重写构建系统以使用Android的工具(cmake和ndk构建系统)将是疯狂的;我们需要使用现有的make系统,大多数情况下,这意味着我们需要为配置脚本提供CFLAGS、CXX_标志、cppfagas、LDFLAGS等。这些标志集在我找到的任何地方都没有记录,除了通过查看本地Android ndk构建的输出

更新:我想我不太清楚我到底想要什么

我们有一些讨厌的脚本,它们设法使用cmake从现有构建中吸取正确的标志集。(其中一个项目,你说需要20分钟,但你错得可笑。)。这些脚本与r16 beta 1版背道而驰。我真的不需要编写令人讨厌的不稳定脚本来拉出标志,因为它们可能会在下一个ndk版本中崩溃

(这是我们脚本的最后一个输出,以防您想看到我所说的标志:)

请尝试检查

{SDK_PATH}/ndk-bundle/build/core/toolchains/arm-linux-androideabi-4.9/setup.mk
或者不同的工具链(这取决于你在构建什么)。定义了交叉编译所需的标志

编辑

我做了一些挖掘工作

如果编辑文件:

{SDK_PATH}/ndk-bundle/build/core/definitions.mk
并找到一行
定义ev编译cpp源代码
。或者更好地定义ev构建文件

你可以在那里加上

$(info $_FLAGS is [${_FLAGS}])
$$eval
之前

现在,如果您构建了一些东西,您将看到标志。

请尝试检查

{SDK_PATH}/ndk-bundle/build/core/toolchains/arm-linux-androideabi-4.9/setup.mk
或者不同的工具链(这取决于你在构建什么)。定义了交叉编译所需的标志

编辑

我做了一些挖掘工作

如果编辑文件:

{SDK_PATH}/ndk-bundle/build/core/definitions.mk
并找到一行
定义ev编译cpp源代码
。或者更好地定义ev构建文件

你可以在那里加上

$(info $_FLAGS is [${_FLAGS}])
$$eval
之前


现在,如果您构建了一些东西,您将看到标志。

对于自定义构建系统,您应该使用。这将处理好所有针对Android的基本标志。它不会处理任何最好留给构建系统的决策,例如优化级别、调试标志等

编辑:


不幸的是,您当前的解决方案目前是最好的。最终,工具链配置将被移动到
$NDK/meta
中的JSON文件中,就像一些已经存在的(琐碎的)东西一样,以便我们可以在NDK build和CMake之间共享这些信息,但这不会很快发生。

对于自定义构建系统,您应该使用。这将处理好所有针对Android的基本标志。它不会处理任何最好留给构建系统的决策,例如优化级别、调试标志等

编辑:


不幸的是,您当前的解决方案目前是最好的。最终,工具链配置将被移动到
$NDK/meta
中的JSON文件中,就像一些已经存在的(琐碎的)东西一样,这样我们可以在NDK build和CMake之间共享这些信息,但这不会很快发生。

使用CMake来驱动配置,或者以您需要的任何格式写出值

例如,这里有一个CMakeLists.txt文件,用于配置和编译expat项目。它希望expat的源已经在系统上。可能您需要的大部分内容都在标准的\u configure\u env宏中;您需要的是经过修改的CFLAGS等

cmake_minimum_required(VERSION 3.6)

project (expat)

macro(standard_configure_env output)
set(${output}
    CC=${ANDROID_C_COMPILER}
    CXX=${ANDROID_CXX_COMPILER}
    CFLAGS=--target=${CMAKE_C_COMPILER_TARGET}\ --sysroot=${ANDROID_SYSROOT}\ \ --gcc-toolchain=${ANDROID_TOOLCHAIN_ROOT}\ ${ANDROID_COMPILER_FLAGS}
    CXXFLAGS=${ANDROID_COMPILER_FLAGS_CXX}
    AR=${ANDROID_AR} 
    RANLIB=${ANDROID_RANLIB}  
    LD=${CMAKE_LINKER}  
    LDFLAGS=${ANDROID_LINKER_FLAGS}
)
endmacro()

include(ProcessorCount)
ProcessorCount(nCpus)

set(expat_output_dir ${CMAKE_CURRENT_BINARY_DIR}/expat)
set(expat_build_dir ${expat_output_dir}/expat_bin)
set(expat_install_dir ${expat_output_dir}/install)
set(expat_src_dir /Users/james/yourpathgoeshere/cmake/expat/src/expat-2.1.0)

set(markers_dir ${expat_output_dir}/markers)
file(MAKE_DIRECTORY ${markers_dir})

set(expat_copied ${markers_dir}/copied)
set(expat_configured ${markers_dir}/configured)

set(expat_final_lib ${expat_install_dir}/lib/libexpat.a)

file(MAKE_DIRECTORY ${expat_install_dir}/include)

standard_configure_env(configure_env)

set(configure_host ${ANDROID_HEADER_TRIPLE})
# expat doesn't understand these Android architectures, so set them by hand to what expat can
# use
if(${configure_host} STREQUAL aarch64-linux-android)
set(configure_host arm-linux-android64v8a)
elseif(${configure_host} STREQUAL armv7-linux-androideabi)
set(configure_host arm-linux-androideabiv7a)
endif()

set(configure_args
    --host=${configure_host}
    --disable-shared
    --prefix=${expat_output_dir}/install
    --exec-prefix=${expat_output_dir}/install
    )

add_custom_command(
    OUTPUT ${expat_configured}
    COMMAND ${configure_env} ./configure ${configure_args} && touch ${expat_configured}
    DEPENDS ${expat_copied}
    WORKING_DIRECTORY ${expat_build_dir}
    )

add_custom_command(
    OUTPUT ${expat_copied}
    COMMAND ${CMAKE_COMMAND} -E copy_directory ${expat_src_dir} ${expat_build_dir}
    COMMAND touch ${expat_copied}
    )

add_custom_command(
    OUTPUT ${expat_final_lib}
    COMMAND make -j${nCpus} installlib && touch ${expat_final_lib}
    WORKING_DIRECTORY ${expat_build_dir}
    DEPENDS ${expat_configured}
    )

add_custom_target(expat_build DEPENDS ${expat_final_lib})
add_library(expat STATIC IMPORTED GLOBAL)
add_dependencies(expat expat_build)

set_target_properties(expat
  PROPERTIES
  LINKER_LANGUAGE CXX
  IMPORTED_LOCATION ${expat_install_dir}/lib/libexpat.a
  INTERFACE_INCLUDE_DIRECTORIES ${expat_install_dir}/include)

感谢@DanAlbert和@Jakubiskorz指出我真的很想从cmake那里得到这一点。

使用cmake来驱动配置,或者以您需要的任何格式写出值

例如,这里有一个CMakeLists.txt文件,用于配置和编译expat项目。它希望expat的源已经在系统上。可能您需要的大部分内容都在标准的\u configure\u env宏中;您需要的是经过修改的CFLAGS等

cmake_minimum_required(VERSION 3.6)

project (expat)

macro(standard_configure_env output)
set(${output}
    CC=${ANDROID_C_COMPILER}
    CXX=${ANDROID_CXX_COMPILER}
    CFLAGS=--target=${CMAKE_C_COMPILER_TARGET}\ --sysroot=${ANDROID_SYSROOT}\ \ --gcc-toolchain=${ANDROID_TOOLCHAIN_ROOT}\ ${ANDROID_COMPILER_FLAGS}
    CXXFLAGS=${ANDROID_COMPILER_FLAGS_CXX}
    AR=${ANDROID_AR} 
    RANLIB=${ANDROID_RANLIB}  
    LD=${CMAKE_LINKER}  
    LDFLAGS=${ANDROID_LINKER_FLAGS}
)
endmacro()

include(ProcessorCount)
ProcessorCount(nCpus)

set(expat_output_dir ${CMAKE_CURRENT_BINARY_DIR}/expat)
set(expat_build_dir ${expat_output_dir}/expat_bin)
set(expat_install_dir ${expat_output_dir}/install)
set(expat_src_dir /Users/james/yourpathgoeshere/cmake/expat/src/expat-2.1.0)

set(markers_dir ${expat_output_dir}/markers)
file(MAKE_DIRECTORY ${markers_dir})

set(expat_copied ${markers_dir}/copied)
set(expat_configured ${markers_dir}/configured)

set(expat_final_lib ${expat_install_dir}/lib/libexpat.a)

file(MAKE_DIRECTORY ${expat_install_dir}/include)

standard_configure_env(configure_env)

set(configure_host ${ANDROID_HEADER_TRIPLE})
# expat doesn't understand these Android architectures, so set them by hand to what expat can
# use
if(${configure_host} STREQUAL aarch64-linux-android)
set(configure_host arm-linux-android64v8a)
elseif(${configure_host} STREQUAL armv7-linux-androideabi)
set(configure_host arm-linux-androideabiv7a)
endif()

set(configure_args
    --host=${configure_host}
    --disable-shared
    --prefix=${expat_output_dir}/install
    --exec-prefix=${expat_output_dir}/install
    )

add_custom_command(
    OUTPUT ${expat_configured}
    COMMAND ${configure_env} ./configure ${configure_args} && touch ${expat_configured}
    DEPENDS ${expat_copied}
    WORKING_DIRECTORY ${expat_build_dir}
    )

add_custom_command(
    OUTPUT ${expat_copied}
    COMMAND ${CMAKE_COMMAND} -E copy_directory ${expat_src_dir} ${expat_build_dir}
    COMMAND touch ${expat_copied}
    )

add_custom_command(
    OUTPUT ${expat_final_lib}
    COMMAND make -j${nCpus} installlib && touch ${expat_final_lib}
    WORKING_DIRECTORY ${expat_build_dir}
    DEPENDS ${expat_configured}
    )

add_custom_target(expat_build DEPENDS ${expat_final_lib})
add_library(expat STATIC IMPORTED GLOBAL)
add_dependencies(expat expat_build)

set_target_properties(expat
  PROPERTIES
  LINKER_LANGUAGE CXX
  IMPORTED_LOCATION ${expat_install_dir}/lib/libexpat.a
  INTERFACE_INCLUDE_DIRECTORIES ${expat_install_dir}/include)

感谢@DanAlbert和@Jakubiskorz指出,我真的很想从cmake那里得到这一点。

从那些setup.mk文件到传递给链接器和编译器的完整标志集一点也不简单,但这就是问题所在。例如,没有setup.mk文件设置-mstackrealling标志,您将在cmake构建(对于x86)中看到这一点。但是,从这些setup.mk文件获取传递给链接器和编译器的完整标志集并不容易,这就是问题所在。例如,没有setup.mk文件设置-mstackreallign标志,您将在cmake构建(对于x86)中看到这一点。不过,这只是重新表述了问题。当您构建和使用所有这些工具链时,将自动获得哪些标志?(是的,我知道我可以通读代码,我只是想知道是否有一种方法可以做到这一点,从而在ndk的更改中幸存下来。)。好吧,仅仅使用那些预先构建的工具链并不能得到正确的参数集;甚至在会议上的文档也谈到了需要添加的更多标志。“当您构建和使用所有这些工具链时,您会自动获得哪些标志?”您是否在询问为Android构建二进制文件需要哪些标志,或者ndk build可能选择使用的全套标志?更新了问题。我希望NDK构建的所有精确的标志集,对于每一个(体系结构*调试版本)组合,对于C,C++,以及链接共享库和静态库。我不想在每次ndk更新时都用脚本来搞定它。当我在这里,我希望C和C++标志正确地分割(一些项目将它们结合到C++ FLA)