I'm currently playing around with conan. So I've created two small project: The first project is a small library "fcdk": https://github.com/lmarzull/fcdk/tree/devel
The second is a project holding the conan and circle-ci stuff (don't know yet if I should group the library/conan/circle-ci in a single project, but this is not yet the point). The second project is called "fcdk-conan"
I decide to put the unit test of the library inside the fcdk-conan project in the "test_package" directory. I do so to avoid a dependencies on google test in my "fcdk" library and to rather have this dependency in the fcdk-conan project (don't know if it's a good idea)
I've create a very litte test program:
#include <iostream>
int
main()
{
std::cout << "Hello, world!" << std::endl;
}
And all is fine.
But now, I want to add some Unit test of my library. So I need to find/compile/link the "fcdk" library. So I change the main.cc file to this one:
#include <iostream>
#include <fcdk/CommandLineOptionFlag.h>
int
main()
{
FCDK::CommandLineOptionFlag show_help('h', "help", "show this help message");
std::cout << "Hello, world!" << std::endl;
}
Here the CMakeLists.txt of the test_package directory:
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)
And the conan 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)
I could not achieve the test_package to link correctly.
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)'
All the previous step:
conan source
conan install
conan build
conan package
conan export-pkg
was fine and seems correct to me. I put here the content of the conan package command:
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
I've also look at the missing symbol in the libfcdk.a For example:
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*)
When I run the make with VERBOSE=1, I do not see the fcdk library information on the link command
/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&)':
Could someone help me to figure out whay the test_pacakge recipe does not link agains my fcdk/1.0.0 package please ?
Thank you very much
EDIT: Conan repository with test_pacakge updated https://github.com/lmarzull/fcdk-conan/tree/devel
The point of the test_package
folder is that, if it contains a conanfile.py
with a test()
function, Conan will automatically handle it once the package is fully created.
Starting from the following basic project structure, let's build a simple library with a single dependency:
.
├── 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)
find_package(fmt REQUIRED) // Version is handled by Conan
add_library(${PROJECT_NAME} src/mylib.cpp src/mylib.hpp)
target_link_library(${PROJECT_NAME} PRIVATE fmt::fmt)
// 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 conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
class MylibConan(ConanFile):
name = "mylib"
version = "1.0.0"
settings = "os", "compiler", "build_type", "arch"
requires = "fmt/9.1.0"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
generators = "CMakeToolchain", "CMakeDeps"
exports_sources = "CMakeLists.txt", "src/*"
def layout(self):
cmake_layout(self)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
CMake(self).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(test_package)
find_package(mylib QUIET)
if(NOT mylib_FOUND)
message(FATAL_ERROR "This project can only be built with a 'conan create' command in the parent directory!")
endif()
add_executable(${PROJECT_NAME} main.cpp)
// Put the exe in the same place for both Single- and Multi-Config generators
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY bin/$<0:>)
target_link_libraries(${PROJECT_NAME} mylib::mylib)
test_package/conanfile.py
:
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
from os.path import join
class MylibTestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
def requirements(self):
self.requires(self.tested_reference_str)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
self.run(join(self.build_folder, "bin", "test_package"))
Now you can call conan create .
and your test_package
will automatically get built and run in your local directory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With