为何CMake的install(TARGETS)未指定PUBLIC_HEADER仍安装libjxl头文件?
问题描述
我使用CMake 3.31.6执行以下命令:
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "$<TARGET_FILE_DIR:${PROJECT_NAME}>")
发现该命令自动安装了依赖库libjxl的include目录及其中的C++头文件(示例:-- Installing: C:/code/texture-streaming/decoder/bin/x64/release/include/jxl/decode_cxx.h)。我原本认为必须使用PUBLIC_HEADER参数才会安装头文件,但当前仅指定了RUNTIME目标,对此现象存在疑问。
以下是我的CMake配置文件:
根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.21) project(jpegxl-decoder VERSION 0.0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) if(MSVC) add_compile_options( /permissive- /Zc:preprocessor ) endif() add_subdirectory(extern) add_subdirectory(app)
app/CMakeLists.txt
project(app) add_executable(${PROJECT_NAME} app.cpp) target_link_libraries(${PROJECT_NAME} PUBLIC jxl) install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "$<TARGET_FILE_DIR:${PROJECT_NAME}>")
extern/CMakeLists.txt
include(FetchContent) set(BUILD_TESTING OFF CACHE BOOL "") set(JPEGXL_ENABLE_TOOLS OFF CACHE BOOL "") FetchContent_Declare( Libjxl GIT_REPOSITORY https://github.com/libjxl/libjxl.git GIT_TAG v0.11.1 ) FetchContent_MakeAvailable(Libjxl)
原因解析
这事儿和你写的install命令无关,核心原因是libjxl自身的CMake配置里已经定义了完整的安装规则。
你通过FetchContent_MakeAvailable把libjxl作为子项目引入构建,而libjxl的CMakeLists.txt中已经写好了针对自身库目标的install逻辑,其中就包含头文件的安装步骤——这和你是否在自己的install命令里指定PUBLIC_HEADER完全没关系。
当你执行cmake --install时,CMake会默认执行所有加入项目的install规则,包括子项目libjxl里预定义的规则。哪怕你只在自己的命令里指定了RUNTIME目标,libjxl的头文件安装步骤照样会被触发执行。
如果想避免安装libjxl的头文件,可以试试这些办法:
- 拉取libjxl时,设置对应的CMake开关禁用它的安装规则(可以查libjxl的CMake文档,看是否有类似
JPEGXL_SKIP_INSTALL这类选项); - 开启
CMAKE_SKIP_INSTALL_ALL_DEPENDENCY变量,让CMake跳过依赖项的安装操作; - 不用FetchContent拉源码构建,改用
find_package引入预编译好的libjxl库。
内容的提问来源于stack exchange,提问作者kaba
相关产品推荐
相关产品推荐

