jjzjj

android - CMake共享项目子目录避免重建

coder 2023-12-15 原文

对于一个项目,我正在使用带有 CMake 的 Android gradle 脚本,gradle 插件版本为 3:0:0,CMake 版本为 3.6。 gradle 和 CMake 文件都非常简单且无趣(只需定义使用的文件 - 我仍然可以根据需要复制粘贴它们)。

我有以下项目结构;基本上是一个生成几十个 .so 文件的代码库(Android 包的 native 部分被打包到 apk 中,因此称为“可执行文件”),它们都依赖于相同的共享库代码(静态库,因此称为“库” ').库代码仍然(相对)易变,所以我希望可执行文件对它们具有项目级依赖性,这样无论何时构建可执行文件,每次更改代码时都会按需重建库。 结构如下:

+ LibProjects/
---Bin/ (Originally empty)
---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt)
...
---Lib10/CMakeLists.txt (same)
+ Executables/
---Executable1/CMakeLists.txt (source files here)
--------------/AndroidFiles/build.gradle (and other android project files)(points to the CMakeLists.txt)
...
---Executable40/CMakeLists.txt

图书馆的 CMakeLists 使用

将它们的输出重定向到 Bin 文件夹
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/../Bin/${ANDROID_ABI}/${LibraryName})

可执行文件的项目“正常”添加对库的依赖

add_subdirectory(${PROJECTS_ROOT}/LibProjects/${LibraryName} ${PROJECTS_ROOT}/Framework/Bin/Android/${ANDROID_ABI}/${LibraryName})...

几乎一切正常,因为我可以获得合理的可执行文件并且可执行文件会触发库的构建。

问题是,当按顺序构建可执行文件时,每个都不会重用其他项目的库项目输出:当我构建 Executable1 时,它将构建所有库(正常),然后它会自行构建。之后,当我构建 Executable2 时,它不会重用已经为 Executable1 构建的库,依此类推 - 这有效地将我的构建时间增加了约 10 倍。

我可以按预期在/Bin 文件夹中找到每个库的构建输出,但它们不会在可执行文件中重复使用 - bin 文件夹中没有 CMake“项目文件”(这是正确的术语),所有这些都在可执行构建目录中生成。

我试图解决的问题是构建时间,因为每个库都会为每个可执行文件重新构建。

目前我正在考虑的解决方案是以某种方式指示 CMake 使用 Bin 文件夹(或另一个文件夹)作为每个库在其自己的文件夹中而不是可执行文件的工作文件夹,希望 gradle android 插件能够足够聪明,然后发现 cmakefile 和目标文件都不需要重新生成,并避免重建。

我的限制是我无法重组代码库本身,并且每个可执行文件都必须与其他可执行文件分开构建 - 绝对不可能有顶级 CMake - 每个可执行文件都应该能够被触发它自己的。

最佳答案

CMake 可以通过从当前构建目录读取信息来猜测构建是否是最新的。

当您在 Executables/<x> 中手动运行 CMake 时目录,cmake 从与 Executable/<x> 关联的构建目录中检索信息目录。然后它检查构建文件的时间戳是否对应于在此构建目录中执行的最后一次构建。如果没有,它会重建。发生的事情是:Lib1库文件是在你构建之后构建的 Executable1 ,然后在 Executalbe2 中运行 cmake , 它比较 Lib1 的时间戳target 文件,看看这个文件不是由 cmake build 的这个实例生成的,然后重建 lib。等等。

所以你有两个选择:

1- 构建库并将其目标文件安装在 bin 中目录(例如使用 install cmake 命令和 make install bash 命令)。然后在Executalbe<x>/CMakeLists你用find_library命令而不是 add_subdirectory .

2- 或者您创建一个具有以下结构的 super 项目:

+  supper_project
---CMakeLists.txt #add_subdirectory(LibProjects/lib<x>)... add_subdirectory(Executables/Executalbe<x>)...
  + LibProjects/
  ---Bin/ (Originally empty)
  ---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt)
  ...
  ---Lib10/CMakeLists.txt (same)
  + Executables/
  ---Executable1/CMakeLists.txt (source files here)
  --------------/AndroidFiles/build.gradle (and other android project files)
  (not any more:points to the CMakeLists.txt)
  ...
  ---Executable40/CMakeLists.txt

关于android - CMake共享项目子目录避免重建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47797954/

有关android - CMake共享项目子目录避免重建的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  3. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  4. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  5. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

    我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

  6. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  7. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  8. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

    是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

  9. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  10. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

随机推荐