I run into a situation where I need to decouple the conan installation folder from the import root folder. The main goal is to have a working Visual Studio open folder solution when at the same time I want to be able to test my binaries running conan test tests Mylibrary/0.1@user/testing
My example package consists of four folders the src that contains the sources, the examples that produce an executable the test_package that test if the package links correctly and the tests that contains some gtests for the package.
root
|_ src
|_ examples
|_ test_package
|_ tests
|_ conanfile.py
|_ CMakeLists.txt
When I want to develop the package I use the open folder functionality of Visual Studio in the root folder. Because I want to have the latest changes when I run my examples and tests in Visual Studio I have set the CMAKE_RUNTIME_OUTPUT_DIRECTORY to point to ${CMAKE_BINARY_DIR}/bin in my CMakeSettings.json (well I can also set this in the main CMakeLists.txt). Now inside tests folder resides my conanfile.py that copies the gtest.dll to the root bin folder.
tests/conanfile.py
def imports(self):
self.copy("*.dll", dst="../bin", src="bin")
To prevent conan_cmake_run to change the output directories I use NO_OUTPUT_DIRS flag inside the tests/CMakeLists.txt.
conan_cmake_run(CONANFILE conanfile.py
BASIC_SETUP CMAKE_TARGETS NO_OUTPUT_DIRS)
However, using this setup when I call conan test tests MyLibrary/0.1@user/testing the gtest binaries are copied outside the build folder... What I did was to copy the dlls in the current folder.
tests/conanfile.py
def imports(self):
self.copy("*.dll", dst="../bin", src="bin")
self.copy("*.dll", dst="", src="bin")
This is an ugly solution to this problem because copies dlls twice. Also, I tried to set the INSTALL_FOLDER to ${CMAKE_BINARY_DIR} but then conan.cmake complains (ln 388) that conanbuildinfo doesn't exist in ${CMAKE_CURRENT_BINARY_DIR}. Is any elegant solution to this? Am I missing something?
CMakeLists.txt
# Main ExternalDevicesLibrary Library
cmake_minimum_required(VERSION 3.12)
project(ExternalDevicesLibrary LANGUAGES CXX)
# add project code
add_subdirectory(src)
# add example code
add_subdirectory(examples)
# add unit tests
enable_testing()
add_subdirectory(tests)
tests/CMakeLists.txt
# ExternalDevices Tests
cmake_minimum_required(VERSION 3.12)
project(ExternalDevicesTests LANGUAGES CXX)
include(${CMAKE_CURRENT_SOURCE_DIR}/../conan.cmake)
# Make sure to use conanfile.py to define dependencies, to stay consistent
conan_cmake_run(CONANFILE conanfile.py
BASIC_SETUP CMAKE_TARGETS NO_OUTPUT_DIRS)
# dependencies
enable_testing()
find_package(GTest MODULE REQUIRED)
if(NOT TARGET LLTB::ExternalDevices) # if not part of the project find the installed library
find_package(ExternalDevices CONFIG REQUIRED)
endif()
# target definitions
add_executable(ExternalDevicesTests ExternalDevices_tests.cpp)
target_link_libraries(ExternalDevicesTests
PRIVATE
LLTB::ExternalDevices
GTest::Main
)
add_test(NAME ExternalDevices.UnitTests
COMMAND ExternalDevicesTests
)
tests/conanfile.py
import os
from conans import ConanFile, CMake
class ExternaldevicesTests(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
requires = (
"gtest/1.8.1@bincrafters/stable"
)
default_options = (
"*:shared=True",
"gtest:build_gmock=False"
)
def build(self):
cmake = CMake(self, generator='Ninja')
# Current dir is "tests/build/<build_id>" and CMakeLists.txt is
# in "tests"
cmake.configure()
cmake.build()
def imports(self):
self.copy("*.dll", dst="../bin", src="bin")
self.copy("*.dll", dst="", src="bin")
def test(self):
cmake = CMake(self)
self.run("ctest -VV -C %s" % cmake.build_type)
The expected behavior is in both cases to have my dlls in ${CMAKE_BINARY/DIR}/bin folder.
What I see as an acceptable solution is the following: The imports will contain only the one line
tests/conanfile.py
def imports(self):
self.copy("*.dll", dst="bin", src="bin")
then I should be able to call the conan_cmake_run with an IMPORT_FOLDER argument. e.g.
tests/CMakeLists.txt
conan_cmake_run(CONANFILE conanfile.py
BASIC_SETUP NO_OUTPUT_DIRS
IMPORT_FOLDER ${CMAKE_BINARY_DIR})
However, import folder functionality is not present and I have to find a way to simulate this behavior using cmake.
PS#1. I know I can use gtest as static lib but I don't want to. This is a proof of concept example that I can integrate cmake conan and VS open folder without causing problems to the standard conan workflow.
PS#2. The full code can be downloaded through: git clone https://jason5480@bitbucket.org/jason5480/externaldevices.git