创建柯南 test_package 食谱
Creating conan test_package recipe
我正在玩柯南。所以我创建了两个小项目:
第一个项目是一个小图书馆"fcdk":https://github.com/lmarzull/fcdk/tree/devel
第二个是一个包含柯南和 circle-ci 东西的项目(我还不知道我是否应该将 library/conan/circle-ci 分组到一个项目中,但是这个还不是重点)。
第二个项目叫做"fcdk-conan"
我decide将库的单元测试放在"test_package"目录下的fcdk-conan项目里面。我这样做是为了避免在我的 "fcdk" 库中对 google 测试产生依赖性 cies 并且在 fcdk-conan 项目中有这种依赖性(不知道这是否是个好主意)
我创建了一个非常小的测试程序:
#include <iostream>
int
main()
{
std::cout << "Hello, world!" << std::endl;
}
一切都很好。
但是现在,我想为我的库添加一些单元测试。所以我需要 find/compile/link "fcdk" 库。所以我将 main.cc 文件更改为这个文件:
#include <iostream>
#include <fcdk/CommandLineOptionFlag.h>
int
main()
{
FCDK::CommandLineOptionFlag show_help('h', "help", "show this help message");
std::cout << "Hello, world!" << std::endl;
}
这里是test_package目录的CMakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(FcdkTest CXX)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_executable(
test-fcdk
main.cc
)
target_include_directories(test-fcdk PUBLIC ${CONAN_INCLUDE_DIRS_FCDK})
target_link_libraries(test-fcdk PUBLIC ${CONAN_LIBS_FCDK})
target_link_libraries(test-fcdk PUBLIC CONAN_PKG::fcdk)
enable_testing()
add_test(NAME test-fcdk
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
COMMAND test-fcdk)
而柯南 recipe:
import os
from conans import ConanFile, CMake, tools
class FcdkTestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
requires = "fcdk/1.0.0"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
if not tools.cross_building(self.settings):
os.chdir("bin")
self.run(".%stest-fcdk" % os.sep)
我无法正确实现 test_package 到 link。
CMakeFiles/test-fcdk.dir/main.cc.o: In function `FCDK::CommandLineOptionFlag::accept(FCDK::VisitorBase&)':
main.cc:(.text._ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE[_ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE]+0xa1): undefined reference to `FCDK::demangleTypename(char const*)'
main.cc:(.text._ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE[_ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE]+0xdd): undefined reference to `FCDK::demangleTypename(char const*)'
CMakeFiles/test-fcdk.dir/main.cc.o: In function `main':
main.cc:(.text.startup+0x5e): undefined reference to `FCDK::CommandLineOptionFlag::CommandLineOptionFlag(char, std::string, std::string)'
所有上一步:
conan source
conan install
conan build
conan package
conan export-pkg
很好,对我来说似乎是正确的。我把conan包命令的内容放在这里:
package/
package/conaninfo.txt
package/include
package/include/fcdk
package/include/fcdk/Exception.h
package/include/fcdk/CommandLineOption.h
package/include/fcdk/CommandLineOptionWithValue.h
package/include/fcdk/Visitor.h
package/include/fcdk/ABI.h
package/include/fcdk/CommandLineParser.h
package/include/fcdk/CommandLineOptionFlag.h
package/conanmanifest.txt
package/lib
package/lib/libfcdk.a
package/share
package/share/cmake
package/share/cmake/fcdk
package/share/cmake/fcdk/fcdkTargets.cmake
package/share/cmake/fcdk/fcdkTargets-release.cmake
我还查看了 libfcdk.a 中缺少的符号
例如:
U FCDK::demangleTypename[abi:cxx11](char const*)
U FCDK::demangleTypename[abi:cxx11](char const*)
0000000000000000 t _GLOBAL__sub_I__ZN4FCDK16demangleTypenameB5cxx11EPKc
0000000000000000 T FCDK::demangleTypename[abi:cxx11](char const*)
当我 运行 使用 VERBOSE=1 进行 make 时,我在 link 命令上看不到 fcdk 库信息
/usr/bin/cmake -E cmake_link_script CMakeFiles/test-fcdk.dir/link.txt --verbose=1
/usr/bin/c++ -m64 -O3 -DNDEBUG -rdynamic CMakeFiles/test-fcdk.dir/main.cc.o -o bin/test-fcdk
CMakeFiles/test-fcdk.dir/main.cc.o: In function `FCDK::CommandLineOptionFlag::accept(FCDK::VisitorBase&)':
有人可以帮我弄清楚为什么 test_pacakge recipe 不会 link 再次出现在我的 fcdk/1.0.0 包中吗?
非常感谢
编辑:更新了 test_pacakge 的柯南存储库
https://github.com/lmarzull/fcdk-conan/tree/devel
首先,非常感谢@ymochurad
他指示我用给定库的名称填充 self.cpp_info.libs。
但事已至此,故事还要继续。我需要修改
test_package/CMakeLists.txt
test_package/conanfile.py
# conanfile.py
def package_info(self):
self.cpp_info.libs = [ "fcdk" ]
和
# test_package/CMakeLists.txt
FIND_PACKAGE(fcdk REQUIRED)
# remove conan_basic_setup(TARGETS)
# and replace with:
conan_basic_setup()
# Add ${CONAN_INCLUDE_DIRS}
target_include_directories(test-fcdk
PRIVATE ${CONAN_INCLUDE_DIRS})
# and also fcdk_LIBRARIES in link directive
target_link_libraries(test-fcdk ${fcdk_LIBRARIES})
和
# test_package/conanfile.py
def config_options(self):
self.settings.compiler.libcxx = "libstdc++11"
所有这些修改都解决了最初的问题。
test_package
文件夹的要点在于,如果它包含一个conanfile.py
带有test()
功能,一旦包完全创建,柯南会自动处理它。
注意:为简单起见,省略了Windows细节。
从以下基本项目结构开始:
.
├── CMakeLists.txt
├── conanfile.py
├── src
│ ├── mylib.cpp
│ └── mylib.hpp
└── test_package
├── CMakeLists.txt
├── conanfile.py
└── main.cpp
Top-level CMakeLists.txt
:
cmake_minimum_required(VERSION 3.13)
project(mylib)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_library(${PROJECT_NAME} src/mylib.cpp src/mylib.hpp)
conan_target_link_libraries(${PROJECT_NAME}) // Note the conan_ prefix here
// This will automatically install at the right place depending on the platform
// e.g. a .DLL file goes to bin while .SO/.A/.LIB files go to lib
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME})
install(DIRECTORY src/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
FILES_MATCHING PATTERN "*.hpp")
Top-level conanfile.py
:
from conans import ConanFile, CMake
class MylibConan(ConanFile):
name = "mylib"
version = "1.0.0"
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
generators = "cmake"
exports_sources = "src/*", "CMakeLists.txt"
def _cmake(self):
if not hasattr(self, 'cmake'):
self.cmake = CMake(self)
self.cmake.configure()
return self.cmake
def build(self):
self._cmake().build()
def package(self):
self._cmake().install()
def package_info(self):
self.cpp_info.libs = [self.name]
test_package/main.cpp
:
#include <mylib/mylib.hpp>
int main()
{
mylib();
}
test_package/CMakeLists.txt
:
cmake_minimum_required(VERSION 3.13)
project(unit-test)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_executable(${PROJECT_NAME} main.cpp)
conan_target_link_libraries(${PROJECT_NAME})
test_package/conanfile.py
:
from conans import ConanFile, CMake
class MylibTestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
# No explicit requires of the top-level library, Conan does it by itself!
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
self.run("bin/unit-test")
现在您可以调用 conan create .
,您的 test_package
将自动构建并 运行 在您的本地目录中。
我正在玩柯南。所以我创建了两个小项目: 第一个项目是一个小图书馆"fcdk":https://github.com/lmarzull/fcdk/tree/devel
第二个是一个包含柯南和 circle-ci 东西的项目(我还不知道我是否应该将 library/conan/circle-ci 分组到一个项目中,但是这个还不是重点)。 第二个项目叫做"fcdk-conan"
我decide将库的单元测试放在"test_package"目录下的fcdk-conan项目里面。我这样做是为了避免在我的 "fcdk" 库中对 google 测试产生依赖性 cies 并且在 fcdk-conan 项目中有这种依赖性(不知道这是否是个好主意)
我创建了一个非常小的测试程序:
#include <iostream>
int
main()
{
std::cout << "Hello, world!" << std::endl;
}
一切都很好。
但是现在,我想为我的库添加一些单元测试。所以我需要 find/compile/link "fcdk" 库。所以我将 main.cc 文件更改为这个文件:
#include <iostream>
#include <fcdk/CommandLineOptionFlag.h>
int
main()
{
FCDK::CommandLineOptionFlag show_help('h', "help", "show this help message");
std::cout << "Hello, world!" << std::endl;
}
这里是test_package目录的CMakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(FcdkTest CXX)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_executable(
test-fcdk
main.cc
)
target_include_directories(test-fcdk PUBLIC ${CONAN_INCLUDE_DIRS_FCDK})
target_link_libraries(test-fcdk PUBLIC ${CONAN_LIBS_FCDK})
target_link_libraries(test-fcdk PUBLIC CONAN_PKG::fcdk)
enable_testing()
add_test(NAME test-fcdk
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
COMMAND test-fcdk)
而柯南 recipe:
import os
from conans import ConanFile, CMake, tools
class FcdkTestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
requires = "fcdk/1.0.0"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
if not tools.cross_building(self.settings):
os.chdir("bin")
self.run(".%stest-fcdk" % os.sep)
我无法正确实现 test_package 到 link。
CMakeFiles/test-fcdk.dir/main.cc.o: In function `FCDK::CommandLineOptionFlag::accept(FCDK::VisitorBase&)':
main.cc:(.text._ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE[_ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE]+0xa1): undefined reference to `FCDK::demangleTypename(char const*)'
main.cc:(.text._ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE[_ZN4FCDK21CommandLineOptionFlag6acceptERNS_11VisitorBaseE]+0xdd): undefined reference to `FCDK::demangleTypename(char const*)'
CMakeFiles/test-fcdk.dir/main.cc.o: In function `main':
main.cc:(.text.startup+0x5e): undefined reference to `FCDK::CommandLineOptionFlag::CommandLineOptionFlag(char, std::string, std::string)'
所有上一步:
conan source
conan install
conan build
conan package
conan export-pkg
很好,对我来说似乎是正确的。我把conan包命令的内容放在这里:
package/
package/conaninfo.txt
package/include
package/include/fcdk
package/include/fcdk/Exception.h
package/include/fcdk/CommandLineOption.h
package/include/fcdk/CommandLineOptionWithValue.h
package/include/fcdk/Visitor.h
package/include/fcdk/ABI.h
package/include/fcdk/CommandLineParser.h
package/include/fcdk/CommandLineOptionFlag.h
package/conanmanifest.txt
package/lib
package/lib/libfcdk.a
package/share
package/share/cmake
package/share/cmake/fcdk
package/share/cmake/fcdk/fcdkTargets.cmake
package/share/cmake/fcdk/fcdkTargets-release.cmake
我还查看了 libfcdk.a 中缺少的符号 例如:
U FCDK::demangleTypename[abi:cxx11](char const*)
U FCDK::demangleTypename[abi:cxx11](char const*)
0000000000000000 t _GLOBAL__sub_I__ZN4FCDK16demangleTypenameB5cxx11EPKc
0000000000000000 T FCDK::demangleTypename[abi:cxx11](char const*)
当我 运行 使用 VERBOSE=1 进行 make 时,我在 link 命令上看不到 fcdk 库信息
/usr/bin/cmake -E cmake_link_script CMakeFiles/test-fcdk.dir/link.txt --verbose=1
/usr/bin/c++ -m64 -O3 -DNDEBUG -rdynamic CMakeFiles/test-fcdk.dir/main.cc.o -o bin/test-fcdk
CMakeFiles/test-fcdk.dir/main.cc.o: In function `FCDK::CommandLineOptionFlag::accept(FCDK::VisitorBase&)':
有人可以帮我弄清楚为什么 test_pacakge recipe 不会 link 再次出现在我的 fcdk/1.0.0 包中吗?
非常感谢
编辑:更新了 test_pacakge 的柯南存储库 https://github.com/lmarzull/fcdk-conan/tree/devel
首先,非常感谢@ymochurad
他指示我用给定库的名称填充 self.cpp_info.libs。
但事已至此,故事还要继续。我需要修改
test_package/CMakeLists.txt test_package/conanfile.py
# conanfile.py
def package_info(self):
self.cpp_info.libs = [ "fcdk" ]
和
# test_package/CMakeLists.txt
FIND_PACKAGE(fcdk REQUIRED)
# remove conan_basic_setup(TARGETS)
# and replace with:
conan_basic_setup()
# Add ${CONAN_INCLUDE_DIRS}
target_include_directories(test-fcdk
PRIVATE ${CONAN_INCLUDE_DIRS})
# and also fcdk_LIBRARIES in link directive
target_link_libraries(test-fcdk ${fcdk_LIBRARIES})
和
# test_package/conanfile.py
def config_options(self):
self.settings.compiler.libcxx = "libstdc++11"
所有这些修改都解决了最初的问题。
test_package
文件夹的要点在于,如果它包含一个conanfile.py
带有test()
功能,一旦包完全创建,柯南会自动处理它。
注意:为简单起见,省略了Windows细节。
从以下基本项目结构开始:
.
├── CMakeLists.txt
├── conanfile.py
├── src
│ ├── mylib.cpp
│ └── mylib.hpp
└── test_package
├── CMakeLists.txt
├── conanfile.py
└── main.cpp
Top-level CMakeLists.txt
:
cmake_minimum_required(VERSION 3.13)
project(mylib)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_library(${PROJECT_NAME} src/mylib.cpp src/mylib.hpp)
conan_target_link_libraries(${PROJECT_NAME}) // Note the conan_ prefix here
// This will automatically install at the right place depending on the platform
// e.g. a .DLL file goes to bin while .SO/.A/.LIB files go to lib
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME})
install(DIRECTORY src/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
FILES_MATCHING PATTERN "*.hpp")
Top-level conanfile.py
:
from conans import ConanFile, CMake
class MylibConan(ConanFile):
name = "mylib"
version = "1.0.0"
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
generators = "cmake"
exports_sources = "src/*", "CMakeLists.txt"
def _cmake(self):
if not hasattr(self, 'cmake'):
self.cmake = CMake(self)
self.cmake.configure()
return self.cmake
def build(self):
self._cmake().build()
def package(self):
self._cmake().install()
def package_info(self):
self.cpp_info.libs = [self.name]
test_package/main.cpp
:
#include <mylib/mylib.hpp>
int main()
{
mylib();
}
test_package/CMakeLists.txt
:
cmake_minimum_required(VERSION 3.13)
project(unit-test)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_executable(${PROJECT_NAME} main.cpp)
conan_target_link_libraries(${PROJECT_NAME})
test_package/conanfile.py
:
from conans import ConanFile, CMake
class MylibTestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
# No explicit requires of the top-level library, Conan does it by itself!
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
self.run("bin/unit-test")
现在您可以调用 conan create .
,您的 test_package
将自动构建并 运行 在您的本地目录中。