本文介绍了CPack:如何使用导出创建库包?缺少* Targets-noconfig.cmake文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新



它看起来像是Windows cpack版本错误 - 在Linux(Ubuntu)下,cpack命令丢失的文件。






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



>我有一个库项目,我们称之为Foo,我使用 cpack 命令打包。此包包含 FooConfig.cmake FooTargets.cmake 文件(第二个由cmake机制导出)。问题是,这是不够 cmake使用它。 find_package()找到它,但是当链接到 foo -NOTFOUND',需要由bar.exe'。



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



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

奖金问题:我看到 * - noconfig * 文件包含库的路径,但不包含头文件目录。



更多信息,注意:

>


  • 我的操作系统:Windows 7 64位。

  • 编译器:MinGW 4.4.0(32位)。 (注意:是,而不是 make 我使用 mingw32-make 命令。)

  • CMake版本:cmake 2.8.12.2。

  • 我尝试使用 make install 的结果和没有规则使目标xyz-NOTFOUND',Index.exe'需要。停止。错误消失,一切编译和结果exe正在按预期工作。



工作流程/重现步骤:




  • 创建代码后(见下文):

  • cmake-gui 在构建目录中创建构建目录(库项目)(配置,然后生成)

  • mingw32-make / li>
  • variant a) mingw32-make install DESTDIR =。/ out_dir 可安装库

  • 变量b) cpack -C CpackConfig.cmake -G ZIP 使用库获取包

  • 使用上一步中的文件,到 CMAKE_PREFIX_PATH 环境变量的特殊目录,以便cmake可以找到它(注意移动,而不是复制,所以原始文件被删除)。

  • cmake-gui 用于可执行项目(再次设定,然后产生)




变体a)和b)的最后一步是不同的。对于a),构建完成和可执行工作正常,如预期。在b)的情况下,错误没有规则使目标xyz-NOTFOUND',Index.exe'需要。







$ b b $ b

   -  Foo /(实验库)
- CMakeLists.txt(XyzLib配置)
- foo.cpp(函数实现 -
- foo.h(只包含单个函数)
- FooConfig.cmake(配置所以find_package找到
库)
- Bar /(测试可执行文件)
- CMakeLists.txt(可执行配置)
- bar.cpp(主函数打印东西,
调用Foo库函数)

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 FILEFooTargets.cmakeDESTINATION lib / foo)

include(CPack)

Foo / foo.cpp:

  #include< iostream> 

#includefoo.h

void FooCall()
{
:: std :: cout< 你好,Foo! << :: std :: endl;
}

Foo / foo.h:

  #ifndef FOO_H 
#define FOO_H

void FooCall();

#endif // FOO_H

Foo / FooConfig.cmake:

 # -  Foo库包的配置文件
#此模块定义以下变量:
#Foo_FOUND - 如果找到这个模块,返回true,否则返回false
#Foo_INCLUDE_DIRS - 包含目录
#Foo_LIBRARIES - 链接到$ b的库
$ b get_filename_component(SELF_DIR$ {CMAKE_CURRENT_LIST_FILE}PATH)

#导入目标
include($ {SELF_DIR} /FooTargets.cmake)

#Foo_INCLUDE_DIRS
get_filename_component(Foo_INCLUDE_DIRS$ {SELF_DIR} /。 ./../includeABSOLUTE)

#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 $ {Foo_LIBRARIES})

Bar / bar.cpp

  #include< iostream> 

#includefoo.h

int main(int argc,char * argv [])
{
:: std :: cout << 你好吧! << :: std :: endl;
FooCall();
return 0;
}

一些生成的文件



对于感兴趣的情况,有几个生成的文件:



lib / foo / FooTargets-noconfig.cmake

 #---------------------------- ------------------------------------ 
#生成配置CMake目标导入文件 。
#--------------------------------------------- -------------------

#命令可能需要知道格式版本。
set(CMAKE_IMPORT_FILE_VERSION 1)

#为配置导入目标foo
set_property(TARGET foo APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(foo PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIGCXX
IMPORTED_LOCATION_NOCONFIG$ {_ IMPORT_PREFIX} /lib/libfoo.a


清单(APPEND _IMPORT_CHECK_TARGETS foo)
清单(APPEND _IMPORT_CHECK_FILES_FOR_foo $ {_ IMPORT_PREFIX} /lib/libfoo.a)

#超出这一点的命令不需要知道版本。
set(CMAKE_IMPORT_FILE_VERSION)

lib / foo / FooTargets.cmake


$ b #由CMake生成2.8.12.2

if($ {CMAKE_MAJOR_VERSION}。$ {CMAKE_MINOR_VERSION}LESS 2.5)
消息(FATAL_ERRORCMake> = 2.6.0 required)
endif()
cmake_policy(PUSH)
cmake_policy(VERSION 2.6)
# -------------------------------------------------- ----------
#生成CMake目标导入文件。
#--------------------------------------------- -------------------

#命令可能需要知道格式版本。
set(CMAKE_IMPORT_FILE_VERSION 1)

#防止多次包含,如果再次添加已导入的目标,则会失败。
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 {_expectedTarget})
endif()
endforeach()
if($ {_ targetsDefined}STREQUAL$ {_ expectedTargets})
set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)
return()
endif()
if(NOT$ {_ targetsDefined}STREQUAL)
message(FATAL_ERRORSome(but not all)targets在此导出集中已定义。\\\
Targets定义:$ {_ targetsDefined} \\\
Targets尚未定义:$ {_ targetsNotDefined} \\\

endif()
unset(_targetsDefined)
unset(_targetsNotDefined)
unset(_expectedTargets)


#计算相对于此文件的安装前缀。
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)

#创建导入目标foo
add_library(foo STATIC IMPORTED)

set_target_properties(foo PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES$ {_ IMPORT_PREFIX} / include


#加载每个已安装配置的信息。
get_filename_component(_DIR$ {CMAKE_CURRENT_LIST_FILE}PATH)
文件(GLOB CONFIG_FILES$ {_ DIR} / FooTargets - *。cmake)
foreach(f $ {CONFIG_FILES})
include($ {f})
endforeach()

#清除临时变量。
set(_IMPORT_PREFIX)

#循环所有导入的文件并验证它们实际存在
foreach(target $ {_ IMPORT_CHECK_TARGETS})
foreach(file $ {_ IMPORT_CHECK_FILES_FOR_ $ {target}})
if(NOT EXISTS$ {file})
消息(FATAL_ERROR导入的目标\$ {target} \引用文件
\\ \\$ {file} \
,但此文件不存在可能的原因包括:
*文件已删除,重命名或移动到另一个位置
*安装或卸载过程没有成功完成
*安装包出错,包含
\$ {CMAKE_CURRENT_LIST_FILE} \
但不是所有引用的文件

endif()
endforeach()
unset(_IMPORT_CHECK_FILES_FOR _ $ {target})
endforeach()
unset(_IMPORT_CHECK_TARGETS)

#此文件不依赖于已从同一项目导出
#,但在单独的导出集中导入的其他导入目标。

#超出这一点的命令不需要知道版本。
set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)


解决方案

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





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


Update

It looks like it's Windows cpack version bug - under Linux (Ubuntu) the cpack command the missing file. I'll do more research and post results when I have more time.


Note: I completely changed this question because I was able to simplify it and create new, shorter example. Core problem, however didn't change in the slightest.

Problem description

I have a library project, let's call it Foo, which I pack using cpack command. This package contains FooConfig.cmake and FooTargets.cmake files (the second one exported by cmake mechanisms). Problem is, that this is not enough for cmake to use it. find_package() finds it, but when linking with foo, No rule to make target foo-NOTFOUND', needed by bar.exe'. Stop. error appears.

But if I install it with make install DESTDIR=./out_dir, it works and it contains one more file: FooTargets-noconfig.cmake. This file contains path to the foo library file.

So, what I need to do to fix this? Is there a document describing this behavior?

Bonus question: I see that the *-noconfig* file contains path to the library, but not to headers directory. Is there a way how to configure library project so this generated file will contain it automatically, too?

More info, notes:

  • My OS: Windows 7, 64 bit.
  • Compiler: MinGW 4.4.0 (32 bit). (Note: yes, instead of make I use mingw32-make command.)
  • CMake version: cmake 2.8.12.2.
  • I tried to use result of the make install and the No rule to make target xyz-NOTFOUND', needed by Index.exe'. Stop. error disappeared, everything compiled and result exe was working as expected. It looks like the noconfig file is all what is needed.

Workflow / reproduce steps:

  • After created the code (see bellow):
  • cmake-gui to create build directory (library project) (Configure, then Generate)
  • mingw32-make in build directory
  • variant a) mingw32-make install DESTDIR=./out_dir to install the library
  • variant b) cpack -C CpackConfig.cmake -G ZIP to get package with the library
  • use files from previous step and move it to special directory which is in CMAKE_PREFIX_PATH environment variable so the cmake can find it (note "move", not "copy" so the original files are removed).
  • cmake-gui for executable project (again, Configure, then Generate)
  • mingw32-make in build directory

Last step is different for variant a) and b). For a), build finishes and executable works normally, as expected. In case of b), error No rule to make target xyz-NOTFOUND', needed by Index.exe'. Stop. appears with no more information.

My example code:

- 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/bar.cpp

#include <iostream>

#include "foo.h"

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

Some generated files:

For case you're interested, there are few generated files:

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)
解决方案

Use the export command to create exported targets for use from the build directory:

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

CMake 2.8.12 does not support export(EXPORT), but does support export(TARGETS).

这篇关于CPack:如何使用导出创建库包?缺少* Targets-noconfig.cmake文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 17:54