使用Conan构建时无法生成libarrow_bundled_dependencies.a的问题
问题
我们的项目使用Arrow 10.0.0,此前自行构建时可通过arrow.cmake指定组件采用Bundled方式,生成并链接libarrow_bundled_dependencies.a;改用Conan加速构建后,无法生成该库文件。执行conan install . --build=missing后,运行find ~/.conan -name "*bundle*"也未找到相关内容。附上当前Conan配置代码,请问问题出在哪里?
import os from conan import ConanFile from conan.errors import ConanInvalidConfiguration from conan.tools.build import check_min_cppstd, cross_building from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, rmdir from conan.tools.microsoft import is_msvc, is_msvc_static_runtime from conan.tools.scm import Version class ConanUTest(ConanFile): exports = 'VERSION', 'LICENSE', 'README.md' exports_sources = 'CMakeLists.txt', 'src/*', 'include/*', 'cmake/*', 'VERSION' name = 'mypackage' version = '0.1.1' # Take just the first line license = open('LICENSE').read().split('\n', 1)[0] description = open('README.md').read() settings = { 'os': ['Linux'], 'compiler': [ 'gcc', 'clang', 'intel', ], 'build_type': ['Release'], 'arch': ['x86', 'x86_64', 'armv8', 'armv8_32', 'armv8.3'], } generators = 'CMakeDeps', 'deploy' options = {'with_arrow': [True, False]} default_options = { 'with_arrow': False, } def layout(self): cmake_layout(self) def generate(self): tc = CMakeToolchain(self) if cross_building(self): cmake_system_processor = { "armv8": "aarch64", "armv8.3": "aarch64", }.get(str(self.settings.arch), str(self.settings.arch)) if cmake_system_processor == "aarch64": tc.variables["ARROW_CPU_FLAG"] = "armv8" tc.variables["ARROW_DEPENDENCY_SOURCE"] = "AUTO" tc.variables['ARROW_BUILD_STATIC'] = True tc.variables['ARROW_BUILD_SHARED'] = False tc.variables['ARROW_SIMD_LEVEL'] = "AVX2" tc.variables["ARROW_DEPENDENCY_USE_SHARED"] = False tc.variables["ARROW_OPENSSL_USE_SHARED"] = True tc.variables["ARROW_BUILD_TESTS"] = False tc.variables["ARROW_ENABLE_TIMING_TESTS"] = False tc.variables["ARROW_BUILD_EXAMPLES"] = False tc.variables["ARROW_BUILD_BENCHMARKS"] = False tc.variables["ARROW_BUILD_INTEGRATION"] = False tc.variables["ARROW_EXTRA_ERROR_CONTEXT"] = False tc.variables['ARROW_DATASET'] = True tc.variables['ARROW_PARQUET'] = True tc.variables['ARROW_WITH_RE2'] = True tc.variables['ARROW_COMPUTE'] = True tc.variables['ARROW_FLIGHT'] = True tc.variables['ARROW_WITH_UTF8PROC'] = True tc.variables["PARQUET_REQUIRE_ENCRYPTION"] = bool( self.options['arrow:encryption']) # False tc.variables["ARROW_CUDA"] = False tc.variables["ARROW_JEMALLOC"] = False tc.variables["ARROW_IPC"] = False tc.variables["ARROW_JSON"] = False tc.variables["ARROW_CSV"] = True tc.variables["ARROW_FLIGHT_SQL"] = False tc.variables["ARROW_WITH_UCX"] = False tc.variables["ARROW_WITH_SNAPPY"] = True tc.variables["ARROW_BUILD_UTILITIES"] = bool( self.options['arrow:cli']) # False tc.variables["ARROW_GANDIVA"] = False tc.variables["ARROW_S3"] = False tc.variables["ABS_VENDORED"] = True tc.variables["ARROW_DEPENDENCY_SOURCE"] = "BUNDLED" tc.variables["c-ares_SOURCE"] = "BUNDLED" tc.variables["re2_SOURCE"] = "BUNDLED" tc.variables["absl_SOURCE"] = "BUNDLED" tc.variables["Protobuf_SOURCE"] = "BUNDLED" tc.variables["Snappy_SOURCE"] = "BUNDLED" tc.variables["gRPC_SOURCE"] = "BUNDLED" tc.variables["ZLIB_SOURCE"] = "BUNDLED" tc.variables["Thrift_SOURCE"] = "BUNDLED" tc.variables["utf8proc_SOURCE"] = "BUNDLED" tc.variables["ARROW_INCLUDE_DIR"] = True tc.variables["ARROW_WITH_THRIFT"] = self._with_thrift() tc.variables["ARROW_UTF8PROC_USE_SHARED"] = False tc.variables["Thrift_SOURCE"] = "BUNDLED" if self._with_thrift(): # a recent thrift does not require boost tc.variables["THRIFT_VERSION"] = bool( self.dependencies["thrift"].ref.version) tc.variables["ARROW_THRIFT_USE_SHARED"] = bool( self.dependencies["thrift"].options.shared) tc.cache_variables["ENABLE_STATIC"] = "ON" tc.cache_variables["ENABLE_BSON"] = "ON" tc.cache_variables["ENABLE_TESTS"] = "OFF" tc.cache_variables["ENABLE_EXAMPLES"] = "OFF" tc.cache_variables["ENABLE_TRACING"] = "OFF" tc.cache_variables["ENABLE_COVERAGE"] = "OFF" tc.cache_variables["ENABLE_SHM_COUNTERS"] = "OFF" tc.cache_variables["ENABLE_MONGOC"] = "OFF" tc.cache_variables["ENABLE_MAN_PAGES"] = "OFF" tc.cache_variables["ENABLE_HTML_DOCS"] = "OFF" tc.generate() def configure(self): self.options["openssl"].shared = False self.options["pcre2"].fPIC = True self.options["pcre2"].support_jit = True self.options["pcre2"].build_pcre2grep = True self.options["arrow"].shared = True self.options["arrow"].with_orc = False self.options["arrow"].parquet = True self.options["arrow"].dataset_modules = True self.options["arrow"].with_re2 = True self.options["arrow"].compute = True self.options["arrow"].with_flight_rpc = True self.options["arrow"].with_utf8proc = True self.options["arrow"].with_openssl = True self.options["arrow"].encryption = False self.options["arrow"].with_cuda = False self.options["arrow"].with_jemalloc = False self.options["arrow"].with_json = False self.options["arrow"].with_csv = True self.options["arrow"].simd_level = 'avx2' self.options["arrow"].with_flight_sql = False self.options["arrow"].with_snappy = True self.options["arrow"].cli = True self.options["arrow"].gandiva = False self.options["arrow"].with_s3 = False self.options["mongo-c-driver"].with_ssl = False self.options["mongo-c-driver"].with_sasl = False self.options["mongo-c-driver"].srv = False self.options["mongo-c-driver"].with_snappy = False self.options["mongo-c-driver"].with_zlib = False self.options["mongo-c-driver"].with_zstd = False # self.options["gtest"].shared = False def requirements(self): self.requires('arrow/10.0.0') self.requires('openssl/1.1.1t') self.requires('pcre2/10.42') self.requires('fmt/9.1.0') self.requires('mongo-c-driver/1.23.2') self.requires('nlohmann_json/3.11.2') self.requires('yyjson/0.6.0') self.requires('simdjson/3.1.7') self.requires('jemalloc/5.3.0') self.requires('clipp/1.2.3') # self.requires('gtest/1.13.0') self.requires('benchmark/1.7.1') self.requires('argparse/2.9') self.requires('re2/20220601') self.requires('xsimd/9.0.1') # https://conan.io/center/openssl # def build(self): # cmake = CMake(self) # cmake.configure() # cmake.build() def system_requirements(self): pass def package_info(self): self.cpp_info.components["libarrow_flight.a"].set_property( "pkg_config_name", "flight_rpc") self.cpp_info.components["libarrow_flight.a"].libs = [ f"arrow_flight.a"] def package(self): if self.options['arrow'].shared: self.copy(pattern="*.dll", dst="bin", keep_path=False) self.copy(pattern="*.dylib", dst="lib", keep_path=False) self.copy(pattern="*.a", dst="lib", keep_path=False) self.copy(pattern="*.h", dst="lib", keep_path=False) self.copy(pattern="*.hpp", dst="lib", keep_path=False) def _with_thrift(self, required=False): # No self.options.with_thift exists return bool(required or self._parquet()) def _parquet(self, required=False): if required or self.options['arrow'].parquet == "auto": return bool(self.options.get_safe("substrait", False)) else: return bool(self.options['arrow'].parquet)
问题分析与解决方案
核心问题:Conan依赖包的构建逻辑与本地自行编译完全独立
你在项目CMakeToolchain中设置的ARROW_DEPENDENCY_SOURCE、re2_SOURCE等Bundled相关变量完全无效,原因如下:
- Arrow包的构建不受项目CMake变量控制:Conan安装的
arrow/10.0.0是独立的预编译包(或按Conan官方recipe构建的包),其构建参数由Arrow的Conan recipe定义,而非你项目中的CMake变量。你在generate函数里设置的这些ARROW_*变量只会作用于自身项目,无法影响Arrow依赖包的构建过程。 - 依赖管理逻辑冲突:你的
requirements中单独声明了re2/20220601、openssl/1.1.1t等依赖,但又试图让Arrow使用Bundled版本的这些库。Conan的Arrow包默认优先使用Conan中心提供的独立依赖包,而非Arrow源码中Bundled的子模块,因此不会生成libarrow_bundled_dependencies.a。 - 配置参数矛盾:你在
configure中设置self.options["arrow"].shared = True,但在generate里又设置ARROW_BUILD_STATIC=True,两者完全冲突。Arrow的静态/动态库模式由其Conan包的shared选项控制,而非你项目中的CMake变量。
解决办法
方案1:自定义Arrow Conan包,强制使用Bundled依赖
如果必须生成libarrow_bundled_dependencies.a,需要自行构建Arrow的Conan包:
- 编写自定义的Arrow Conan recipe,在recipe的
build阶段设置ARROW_DEPENDENCY_SOURCE="BUNDLED"、re2_SOURCE="BUNDLED"等CMake变量,强制Arrow使用源码中Bundled的依赖。 - 执行
conan create将自定义包上传到本地或私有仓库,然后在项目中依赖这个自定义包。
方案2:通过Conan参数强制构建Arrow并传递Bundled配置
如果不想编写自定义recipe,可在安装时强制构建Arrow,并通过cmake_args传递构建参数:
conan install . --build=arrow \ -o arrow:shared=False \ -c tools.build:cmake_args="-DARROW_DEPENDENCY_SOURCE=BUNDLED -Dre2_SOURCE=BUNDLED -Dabsl_SOURCE=BUNDLED -DProtobuf_SOURCE=BUNDLED -DSnappy_SOURCE=BUNDLED"
注意:需根据Arrow 10.0.0的CMake参数,补充所有需要设置为Bundled的依赖项。
方案3:放弃Bundled模式,统一使用Conan依赖
如果不需要强制使用Bundled依赖,可简化配置:
- 删除
generate函数中所有ARROW_*相关的变量设置,这些变量对Conan安装的Arrow包无意义。 - 确保项目的依赖与Arrow的依赖版本兼容,直接通过Conan管理所有依赖,无需手动链接
libarrow_bundled_dependencies.a(Conan会自动处理依赖链接)。
额外优化点
- 移除
package函数中不合理的拷贝逻辑:你当前的package函数会拷贝所有.a、.h文件到包目录,但这是Arrow包的工作,你的项目包不需要拷贝Arrow的头文件和库文件。 - 修正
package_info中的组件定义:libarrow_flight.a是Arrow包提供的组件,你的项目不需要重新定义,Conan会自动导入Arrow的组件信息。
内容的提问来源于stack exchange,提问作者Gurgen Yegoryan
相关产品推荐
相关产品推荐

