4

更新

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


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

问题描述

我有一个库项目,我们称之为 Foo,我使用cpack命令打包它。这个包包含FooConfig.cmakeFooTargets.cmake文件(由cmake机制导出的第二个)。问题是,这还不足以让 cmake 使用它。find_package()找到它,但与 链接时fooNo rule to make target foo-NOTFOUND', needed by bar.exe'. Stop.出现错误。

但如果我make install DESTDIR=./out_dirFooTargets-noconfig.cmake. 该文件包含 foo 库文件的路径。

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

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

更多信息,注释:

  • 我的操作系统: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)

富/富.cpp:

#include <iostream>

#include "foo.h"

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

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

酒吧/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})

酒吧/酒吧.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-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/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)
4

1 回答 1

1

使用 export 命令从构建目录创建导出的目标以供使用:

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

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

于 2014-05-15T13:23:29.807 回答