3

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

Jason
  • 97
  • 7

0 Answers0