アップデート
Windows の cpack バージョンのバグのようです。Linux (Ubuntu) では、cpack コマンドで不足しているファイルが表示されます。時間があるときに、さらに調査を行い、結果を投稿します。
注: この質問を単純化して新しい短い例を作成することができたので、この質問を完全に変更しました。しかし、コアの問題は少しも変わりませんでした。
問題の説明
私はライブラリ プロジェクトを持っています。それを Foo と呼びましょうcpack
。コマンドを使用してパックします。このパッケージにはFooConfig.cmake
、FooTargets.cmake
ファイル (cmake メカニズムによってエクスポートされた 2 番目のファイル) が含まれています。問題は、cmake がそれを使用するのに十分ではないということです。find_package()
で見つけたのですが、でリンクするfoo
とNo rule to make target foo-NOTFOUND', needed by bar.exe'. Stop.
エラーが出ます。
しかし、でインストールするとmake install DESTDIR=./out_dir
、動作し、もう 1 つのファイルが含まれます: FooTargets-noconfig.cmake
. このファイルには、foo ライブラリ ファイルへのパスが含まれています。
それで、これを修正するために私は何をする必要がありますか?この動作を説明するドキュメントはありますか?
おまけの質問:*-noconfig*
ファイルにはライブラリへのパスが含まれていますが、ヘッダー ディレクトリへのパスは含まれていません。この生成されたファイルにも自動的に含まれるようにライブラリ プロジェクトを構成する方法はありますか?
詳細情報、メモ:
- 私の OS: 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.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})
バー/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-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)