CPack:如何使用导出创建库包?缺少*Targets-noconfig.cmake文件

CPack:如何使用导出创建库包?缺少*Targets-noconfig.cmake文件,cmake,cpack,Cmake,Cpack,更新 这看起来像是Windows cpack版本的错误——在Linux(Ubuntu)下,cpack命令会删除丢失的文件。当我有更多的时间时,我会做更多的研究并发布结果 注意:我完全改变了这个问题,因为我能够简化它并创建新的、更短的示例。然而,核心问题丝毫没有改变 问题描述 我有一个库项目,我们称之为Foo,我使用cpack命令打包它。此包包含FooConfig.cmake和FooTargets.cmake文件(第二个由cmake机制导出)。问题是,这不足以让cmake使用它find_pack

更新

这看起来像是Windows cpack版本的错误——在Linux(Ubuntu)下,cpack命令会删除丢失的文件。当我有更多的时间时,我会做更多的研究并发布结果


注意:我完全改变了这个问题,因为我能够简化它并创建新的、更短的示例。然而,核心问题丝毫没有改变

问题描述

我有一个库项目,我们称之为Foo,我使用
cpack
命令打包它。此包包含
FooConfig.cmake
FooTargets.cmake
文件(第二个由cmake机制导出)。问题是,这不足以让cmake使用它
find_package()
找到它,但是当链接到
foo
时,
没有规则使目标foo未找到',bar.exe需要它。停止。
出现错误

但是如果我用
make install DESTDIR=./out\u dir
安装它,它会工作,并且它还包含一个文件:
FooTargets noconfig.cmake
。此文件包含foo库文件的路径

那么,我需要做什么来解决这个问题?是否有描述此行为的文档?

附加问题:我看到
*-noconfig*
文件包含库的路径,但不包含头目录的路径。有没有办法配置库项目,使生成的文件也自动包含它

更多信息,请注意:

- Foo/                          (Experimental library)
  - CMakeLists.txt              (XyzLib configuration)
  - foo.cpp                     (Function implementation - just prints something)
  - foo.h                       (Contains just single function)
  - FooConfig.cmake             (Configuration so the find_package find the
                                 library)
- Bar/                          (Testing executable)
  - CMakeLists.txt              (Executable configuration)
  - bar.cpp                     (Main function printing something and
                                 calling the Foo library function)
  • 我的操作系统:Windows7,64位
  • 编译器:mingw4.4.0(32位)。(注意:是,我使用
    mingw32 make
    命令代替
    make
  • CMake版本:CMake 2.8.12.2
  • 我尝试使用
    makeinstall
    的结果和
    No规则使Index.exe需要的目标xyznotfound'。停止。
    错误消失,编译的所有内容和结果exe都按预期工作。看起来noconfig文件就是所需的全部内容
工作流/复制步骤:

- Foo/                          (Experimental library)
  - CMakeLists.txt              (XyzLib configuration)
  - foo.cpp                     (Function implementation - just prints something)
  - foo.h                       (Contains just single function)
  - FooConfig.cmake             (Configuration so the find_package find the
                                 library)
- Bar/                          (Testing executable)
  - CMakeLists.txt              (Executable configuration)
  - bar.cpp                     (Main function printing something and
                                 calling the Foo library function)
  • 创建代码后(见下文):
  • cmakegui
    创建生成目录(库项目)(配置,然后生成)
  • mingw32 make
    在生成目录中
  • 变体a)
    mingw32使install DESTDIR=./out\u dir
    安装库
  • 变量b)
    cpack-C CpackConfig.cmake-G ZIP
    获取库中的包
  • 使用上一步中的文件,并将其移动到环境变量
    CMAKE\u PREFIX\u PATH中的特殊目录,以便CMAKE可以找到它(注意“移动”,而不是“复制”,以便删除原始文件)
  • cmakegui
    用于可执行项目(再次配置,然后生成)
  • mingw32 make
    在生成目录中
变体a)和b)的最后一步不同。对于a),构建完成和可执行文件正常工作,如预期的那样。在b)的情况下,错误
没有规则使Index.exe需要的目标xyz“未找到”。停止。
显示,没有更多信息

我的示例代码:

- Foo/                          (Experimental library)
  - CMakeLists.txt              (XyzLib configuration)
  - foo.cpp                     (Function implementation - just prints something)
  - foo.h                       (Contains just single function)
  - FooConfig.cmake             (Configuration so the find_package find the
                                 library)
- Bar/                          (Testing executable)
  - CMakeLists.txt              (Executable configuration)
  - bar.cpp                     (Main function printing something and
                                 calling the Foo library function)
Foo/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6.3)
project("Foo")

add_library(foo STATIC foo.h foo.cpp)

set_target_properties(foo PROPERTIES PUBLIC_HEADER foo.h)

install(TARGETS foo EXPORT fooTargets
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib
        PUBLIC_HEADER DESTINATION include
        INCLUDES DESTINATION include)

install(FILES FooConfig.cmake DESTINATION lib/foo)

install(EXPORT fooTargets FILE "FooTargets.cmake" DESTINATION lib/foo)

include(CPack)
cmake_minimum_required(VERSION 2.6.3)
project("Bar")

add_executable(bar bar.cpp)

find_package(Foo REQUIRED)
include_directories(${Foo_INCLUDE_DIRS})
target_link_libraries(bar ${Foo_LIBRARIES})
Foo/Foo.cpp:

#include <iostream>

#include "foo.h"

void FooCall()
{
    ::std::cout << "Hello from Foo!" << ::std::endl;
}
Foo/FooConfig.cmake:

# - Config file for the Foo library package
# This module defines the following variables:
#  Foo_FOUND         - true if this module was found, false otherwise
#  Foo_INCLUDE_DIRS  - include directories
#  Foo_LIBRARIES     - libraries to link against

get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)

# Import targets
include("${SELF_DIR}/FooTargets.cmake")

# Foo_INCLUDE_DIRS
get_filename_component(Foo_INCLUDE_DIRS "${SELF_DIR}/../../include" ABSOLUTE)

# Foo_LIBRARIES
set(Foo_LIBRARIES foo)
Bar/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6.3)
project("Foo")

add_library(foo STATIC foo.h foo.cpp)

set_target_properties(foo PROPERTIES PUBLIC_HEADER foo.h)

install(TARGETS foo EXPORT fooTargets
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib
        PUBLIC_HEADER DESTINATION include
        INCLUDES DESTINATION include)

install(FILES FooConfig.cmake DESTINATION lib/foo)

install(EXPORT fooTargets FILE "FooTargets.cmake" DESTINATION lib/foo)

include(CPack)
cmake_minimum_required(VERSION 2.6.3)
project("Bar")

add_executable(bar bar.cpp)

find_package(Foo REQUIRED)
include_directories(${Foo_INCLUDE_DIRS})
target_link_libraries(bar ${Foo_LIBRARIES})
Bar/Bar.cpp

#include <iostream>

#include "foo.h"

int main(int argc, char *argv[])
{
    ::std::cout << "Hello from bar!" << ::std::endl;
    FooCall();
    return 0;
}
lib/foo/FooTargets.cmake

# Generated by CMake 2.8.12.2

if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5)
   message(FATAL_ERROR "CMake >= 2.6.0 required")
endif()
cmake_policy(PUSH)
cmake_policy(VERSION 2.6)
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------

# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)

# Protect against multiple inclusion, which would fail when already imported targets are added once more.
set(_targetsDefined)
set(_targetsNotDefined)
set(_expectedTargets)
foreach(_expectedTarget foo)
  list(APPEND _expectedTargets ${_expectedTarget})
  if(NOT TARGET ${_expectedTarget})
    list(APPEND _targetsNotDefined ${_expectedTarget})
  endif()
  if(TARGET ${_expectedTarget})
    list(APPEND _targetsDefined ${_expectedTarget})
  endif()
endforeach()
if("${_targetsDefined}" STREQUAL "${_expectedTargets}")
  set(CMAKE_IMPORT_FILE_VERSION)
  cmake_policy(POP)
  return()
endif()
if(NOT "${_targetsDefined}" STREQUAL "")
  message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n")
endif()
unset(_targetsDefined)
unset(_targetsNotDefined)
unset(_expectedTargets)


# Compute the installation prefix relative to this file.
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)

# Create imported target foo
add_library(foo STATIC IMPORTED)

set_target_properties(foo PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
)

# Load information for each installed configuration.
get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
file(GLOB CONFIG_FILES "${_DIR}/FooTargets-*.cmake")
foreach(f ${CONFIG_FILES})
  include(${f})
endforeach()

# Cleanup temporary variables.
set(_IMPORT_PREFIX)

# Loop over all imported files and verify that they actually exist
foreach(target ${_IMPORT_CHECK_TARGETS} )
  foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )
    if(NOT EXISTS "${file}" )
      message(FATAL_ERROR "The imported target \"${target}\" references the file
   \"${file}\"
but this file does not exist.  Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
   \"${CMAKE_CURRENT_LIST_FILE}\"
but not all the files it references.
")
    endif()
  endforeach()
  unset(_IMPORT_CHECK_FILES_FOR_${target})
endforeach()
unset(_IMPORT_CHECK_TARGETS)

# This file does not depend on other imported targets which have
# been exported from the same project but in a separate export set.

# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)

使用export命令从生成目录创建要使用的导出目标:


CMake 2.8.12不支持导出(导出),但支持导出(目标)。

谢谢您的回答,但我不知道,您的意思是我应该如何使用它。我添加了
导出(目标foo文件“${CMAKE\u CURRENT\u BINARY\u DIR}/foo/FooTargets.CMAKE”)
(从您提供的链接复制和更新),没有任何更改-没有帮助。AFAK,这将为构建树创建
*Targets.cmake
文件,如果我将构建目录添加到前缀变量,或者如果我将添加
export(PACKAGE Foo)
行,它将工作-但仅在本地工作。我应该如何使用它为便携式软件包创建文件?如何使用它以使目标文件不包含硬编码的绝对路径?export()的结果故意不可移植。CMake生成目录不可移植。如果您想要便携,可以使用install(EXPORT)和install。如果您想避免安装,您可能可以这样做,但这是您自己的事情。您可能因为不喜欢答案而对其投了反对票,但这并不是错误的:)。如果我投了反对票而冒犯了您,那么很抱歉-我投了反对票,因为弹出文本是“此答案不有用”,而您的答案并没有完全回答我的问题(您的答案是“如何使我的构建目录能够在
find_package()中使用”)
在“本地项目”中,这与实际项目有所不同)。但如果我要求的是不可能的,只需编辑你的答案,在开头加上“不可能,但你可以这样做”,我将取消否决票——因为这将是我问题的答案,尽管我不喜欢。无论如何,关于您的最后一个答案-如果我的问题中的文字听起来像是我想使
export()
的生成目录或结果可移植,那么我很抱歉,这是误解。我不。我想让
cpack-gzip的结果可以移植到自动生成的配置文件(不是手写的)中,我目前正试图通过
install(导出fooTargets文件“fooTargets.cmake”DESTINATION lib/foo)
(但我对其他解决方案持开放态度),但这些配置文件不起作用(有关详细信息,请参阅我的主要问题),对不起,我想我当时不明白这个问题,我也不知道答案,所以我将保留我的答案。