更新
看起来它是Windows cpack版本的bug - 在Linux(Ubuntu)下cpack命令丢失文件。当我有更多时间时,我会做更多研究并发布结果。
注意:我完全改变了这个问题,因为我能够简化它并创建新的更短的例子。核心问题,但丝毫没有改变。
问题描述
我有一个库项目,让我们称之为Foo,我使用cpack
命令打包它。此程序包包含FooConfig.cmake
和FooTargets.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目录。有没有办法如何配置库项目,所以这个生成的文件也会自动包含它?
更多信息,备注:
make
我使用mingw32-make
命令。)make install
的结果并且No rule to make target xyz-NOTFOUND', needed by Index.exe'. Stop.
错误消失了,编译的所有内容和结果exe都按预期工作。看起来noconfig文件就是所需要的。工作流程/重现步骤:
cmake-gui
创建构建目录(库项目)(配置,然后生成)mingw32-make
mingw32-make install DESTDIR=./out_dir
来安装库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)
答案 0 :(得分:0)
使用export命令创建要在构建目录中使用的导出目标:
http://www.cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html#creating-packages
CMake 2.8.12不支持导出(EXPORT),但支持导出(TARGETS)。