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

时间:2014-05-15 08:12:32

标签: cmake cpack

更新

看起来它是Windows cpack版本的bug - 在Linux(Ubuntu)下cpack命令丢失文件。当我有更多时间时,我会做更多研究并发布结果。


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

问题描述

我有一个库项目,让我们称之为Foo,我使用cpack命令打包它。此程序包包含FooConfig.cmakeFooTargets.cmake个文件(第二个由cmake机制导出)。问题是,这是不够让cmake使用它。 find_package()找到了它,但在与foo关联时,会出现No rule to make target foo-NOTFOUND', needed by bar.exe'. Stop.错误。

但是,如果我使用make install DESTDIR=./out_dir安装它,它可以工作,它还包含一个文件:FooTargets-noconfig.cmake。该文件包含foo库文件的路径。

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

奖金问题:我看到*-noconfig*文件包含库的路径,但不包含headers目录。有没有办法如何配置库项目,所以这个生成的文件也会自动包含它?

更多信息,备注:

  • 我的操作系统:Windows 7,64位。
  • 编译器:MinGW 4.4.0(32位)。 (注意:是的,而不是make我使用mingw32-make命令。)
  • CMake版本:cmake 2.8.12.2。
  • 我尝试使用make install的结果并且No rule to make target xyz-NOTFOUND', needed by Index.exe'. Stop.错误消失了,编译的所有内容和结果exe都按预期工作。看起来noconfig文件就是所需要的。

工作流程/重现步骤:

  • 创建代码后(见下文):
  • cmake-gui创建构建目录(库项目)(配置,然后生成)
  • 构建目录中的
  • mingw32-make
  • 变体a)mingw32-make install DESTDIR=./out_dir来安装库
  • 变体b)cpack -C CpackConfig.cmake -G ZIP以获取包含库
  • 使用上一步中的文件并将其移动到CMAKE_PREFIX_PATH环境变量中的特殊目录,以便cmake可以找到它(注意“移动”,而不是“复制”,以便删除原始文件)。
  • cmake-gui用于可执行项目(再次,配置,然后生成)
  • 构建目录中的
  • mingw32-make

变体a)和b)的最后一步是不同的。对于a),正常构建完成和可执行文件正常工作。如果是b),则会显示错误No rule to make target xyz-NOTFOUND', needed by Index.exe'. Stop.,但没有更多信息。

我的示例代码:

- 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)

Foo / foo.cpp:

#include <iostream>

#include "foo.h"

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

Foo / foo.h:

#ifndef FOO_H
#define FOO_H

void FooCall();

#endif // FOO_H

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("Bar")

add_executable(bar bar.cpp)

find_package(Foo REQUIRED)
include_directories(${Foo_INCLUDE_DIRS})
target_link_libraries(bar ${Foo_LIBRARIES})

酒吧/ bar.cpp

#include <iostream>

#include "foo.h"

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

一些生成的文件:

如果你感兴趣的话,生成的文件很少:

LIB /富/ FooTargets-noconfig.cmake

#----------------------------------------------------------------
# Generated CMake target import file for configuration "".
#----------------------------------------------------------------

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

# Import target "foo" for configuration ""
set_property(TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(foo PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "CXX"
  IMPORTED_LOCATION_NOCONFIG "${_IMPORT_PREFIX}/lib/libfoo.a"
  )

list(APPEND _IMPORT_CHECK_TARGETS foo )
list(APPEND _IMPORT_CHECK_FILES_FOR_foo "${_IMPORT_PREFIX}/lib/libfoo.a" )

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

LIB /富/ 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)

1 个答案:

答案 0 :(得分:0)

使用export命令创建要在构建目录中使用的导出目标:

http://www.cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html#creating-packages

CMake 2.8.12不支持导出(EXPORT),但支持导出(TARGETS)。