Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cpp_info.name not used in cmake find generators for dependencies #5973

Merged
merged 3 commits into from Oct 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 8 additions & 7 deletions conans/client/generators/cmake_find_package.py
Expand Up @@ -56,7 +56,8 @@ def _find_for_dep(self, name, cpp_info):
lines = []
if cpp_info.public_deps:
# Here we are generating FindXXX, so find_modules=True
lines = find_dependency_lines(name, cpp_info, find_modules=True)
public_deps_names = [self.deps_build_info[dep].name for dep in cpp_info.public_deps]
lines = find_dependency_lines(name, public_deps_names, find_modules=True)
find_package_header_block = find_package_header.format(name=name, version=cpp_info.version)
find_libraries_block = target_template.format(name=name, deps=deps, build_type_suffix="")
target_props = assign_target_properties.format(name=name, deps=deps)
Expand All @@ -69,26 +70,26 @@ def _find_for_dep(self, name, cpp_info):
return tmp


def find_dependency_lines(name, cpp_info, find_modules):
def find_dependency_lines(name, public_deps_names, find_modules):
lines = ["", "# Library dependencies", "include(CMakeFindDependencyMacro)"]
for dep in cpp_info.public_deps:
for dep_name in public_deps_names:
def property_lines(prop):
lib_t = "%s::%s" % (name, name)
dep_t = "%s::%s" % (dep, dep)
dep_t = "%s::%s" % (dep_name, dep_name)
return ["get_target_property(tmp %s %s)" % (dep_t, prop),
"if(tmp)",
" set_property(TARGET %s APPEND PROPERTY %s ${tmp})" % (lib_t, prop),
'endif()']

if find_modules:
lines.append("find_dependency(%s REQUIRED)" % dep)
lines.append("find_dependency(%s REQUIRED)" % dep_name)
else:
# https://github.com/conan-io/conan/issues/4994
# https://github.com/conan-io/conan/issues/5040
lines.append('if(${CMAKE_VERSION} VERSION_LESS "3.9.0")')
lines.append(' find_package(%s REQUIRED NO_MODULE)' % dep)
lines.append(' find_package(%s REQUIRED NO_MODULE)' % dep_name)
lines.append("else()")
lines.append(' find_dependency(%s REQUIRED NO_MODULE)' % dep)
lines.append(' find_dependency(%s REQUIRED NO_MODULE)' % dep_name)
lines.append("endif()")

lines.extend(property_lines("INTERFACE_LINK_LIBRARIES"))
Expand Down
3 changes: 2 additions & 1 deletion conans/client/generators/cmake_find_package_multi.py
Expand Up @@ -88,7 +88,8 @@ def _find_for_dep(self, name, cpp_info):
lines = []
if cpp_info.public_deps:
# Here we are generating only Config files, so do not search for FindXXX modules
lines = find_dependency_lines(name, cpp_info, find_modules=False)
public_deps_names = [self.deps_build_info[dep].name for dep in cpp_info.public_deps]
lines = find_dependency_lines(name, public_deps_names, find_modules=False)

targets_props = self.target_properties.format(name=name)

Expand Down
53 changes: 53 additions & 0 deletions conans/test/functional/generators/cmake_find_package_multi_test.py
Expand Up @@ -5,6 +5,7 @@

from nose.plugins.attrib import attr

from conans.client.tools import replace_in_file
from conans.test.utils.tools import TestClient
from conans.util.files import load

Expand Down Expand Up @@ -76,3 +77,55 @@ def test_native_export_multi(self):
self.assertIn("Hello World {}!".format(bt), c.out)
self.assertIn("bye World {}!".format(bt), c.out)
os.remove(os.path.join(c.current_folder, "example"))

def cpp_info_name_test(self):
client = TestClient()
client.run("new hello/1.0 -s")
replace_in_file(os.path.join(client.current_folder, "conanfile.py"),
'self.cpp_info.libs = ["hello"]',
'self.cpp_info.libs = ["hello"]\n self.cpp_info.name = "MYHELLO"',
output=client.out)
client.run("create .")
client.run("new hello2/1.0 -s")
replace_in_file(os.path.join(client.current_folder, "conanfile.py"),
'self.cpp_info.libs = ["hello"]',
'self.cpp_info.libs = ["hello"]\n self.cpp_info.name = "MYHELLO2"',
output=client.out)
replace_in_file(os.path.join(client.current_folder, "conanfile.py"),
'exports_sources = "src/*"',
'exports_sources = "src/*"\n requires = "hello/1.0"',
output=client.out)
client.run("create .")
cmakelists = """
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to change it now, we need to do the release. But for the future, please try to use textwrap.dedent() for cleaner tests layout.

project(consumer)
cmake_minimum_required(VERSION 3.1)
find_package(MYHELLO2)

get_target_property(tmp MYHELLO2::MYHELLO2 INTERFACE_LINK_LIBRARIES)
message("Target libs: ${tmp}")
"""
conanfile = """
from conans import ConanFile, CMake


class Conan(ConanFile):
settings = "build_type"
requires = "hello2/1.0"
generators = "cmake_find_package_multi"

def build(self):
cmake = CMake(self)
cmake.configure()
"""
client.save({"conanfile.py": conanfile, "CMakeLists.txt": cmakelists})
client.run("install .")
client.run("build .")
self.assertIn("Target libs: $<$<CONFIG:Release>:CONAN_LIB::MYHELLO2_hello_RELEASE;>;"
"$<$<CONFIG:RelWithDebInfo>:;>;"
"$<$<CONFIG:MinSizeRel>:;>;"
"$<$<CONFIG:Debug>:;>;$"
"<$<CONFIG:Release>:CONAN_LIB::MYHELLO_hello_RELEASE;>;"
"$<$<CONFIG:RelWithDebInfo>:;>;"
"$<$<CONFIG:MinSizeRel>:;>;"
"$<$<CONFIG:Debug>:;>",
client.out)
48 changes: 48 additions & 0 deletions conans/test/functional/generators/cmake_find_package_test.py
@@ -1,9 +1,11 @@
import os
import platform
import six
import unittest

from nose.plugins.attrib import attr

from conans.client.tools import replace_in_file
from conans.test.utils.cpp_test_files import cpp_hello_conan_files
from conans.test.utils.tools import TestClient

Expand Down Expand Up @@ -250,3 +252,49 @@ def build(self):
six.assertRegex(self, str(client.out), "Libraries to Link: .*Foundation\\.framework")
six.assertRegex(self, str(client.out), "Target libs: .*Foundation\\.framework")
self.assertIn("Version: 0.1", client.out)

def cpp_info_name_test(self):
client = TestClient()
client.run("new hello/1.0 -s")
replace_in_file(os.path.join(client.current_folder, "conanfile.py"),
'self.cpp_info.libs = ["hello"]',
'self.cpp_info.libs = ["hello"]\n self.cpp_info.name = "MYHELLO"',
output=client.out)
client.run("create .")
client.run("new hello2/1.0 -s")
replace_in_file(os.path.join(client.current_folder, "conanfile.py"),
'self.cpp_info.libs = ["hello"]',
'self.cpp_info.libs = ["hello"]\n self.cpp_info.name = "MYHELLO2"',
output=client.out)
replace_in_file(os.path.join(client.current_folder, "conanfile.py"),
'exports_sources = "src/*"',
'exports_sources = "src/*"\n requires = "hello/1.0"',
output=client.out)
client.run("create .")
cmakelists = """
project(consumer)
cmake_minimum_required(VERSION 3.1)
find_package(MYHELLO2)

get_target_property(tmp MYHELLO2::MYHELLO2 INTERFACE_LINK_LIBRARIES)
message("Target libs: ${tmp}")
"""
conanfile = """
from conans import ConanFile, CMake


class Conan(ConanFile):
requires = "hello2/1.0"
generators = "cmake_find_package"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is repeated here just using a different generator, but not sure where to place it to avoid repeating code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't worry too much, leave it at the moment.


def build(self):
cmake = CMake(self)
cmake.configure()
"""
client.save({"conanfile.py": conanfile, "CMakeLists.txt": cmakelists})
client.run("install .")
client.run("build .")
self.assertIn('Found MYHELLO2: 1.0 (found version "1.0")', client.out)
self.assertIn('Found MYHELLO: 1.0 (found version "1.0")', client.out)
self.assertIn("Target libs: CONAN_LIB::MYHELLO2_hello;;;CONAN_LIB::MYHELLO_hello",
client.out)
81 changes: 55 additions & 26 deletions conans/test/unittests/client/generators/cmake_test.py
Expand Up @@ -2,9 +2,11 @@
import re
import unittest

import six

from conans.client.build.cmake_flags import CMakeDefinitionsBuilder
from conans.client.conf import default_settings_yml
from conans.client.generators import CMakeFindPackageGenerator
from conans.client.generators import CMakeFindPackageGenerator, CMakeFindPackageMultiGenerator
from conans.client.generators.cmake import CMakeGenerator
from conans.client.generators.cmake_multi import CMakeMultiGenerator
from conans.errors import ConanException
Expand Down Expand Up @@ -34,7 +36,9 @@ def compiler(self):
def constraint(self, _):
return self

def get_safe(self, _):
def get_safe(self, name):
if name == "build_type":
return self.build_type
return None

def items(self):
Expand Down Expand Up @@ -345,21 +349,29 @@ def apple_frameworks_test(self):
self.assertIn('set(CONAN_LIBS ${CONAN_FRAMEWORK_OPENGL} '
'${CONAN_FRAMEWORK_OPENCL} ${CONAN_LIBS})', content)

def cpp_info_name_cmake_vars_test(self):
"""
Test cpp_info.names values are applied instead of the reference name
"""
conanfile = ConanFile(TestBufferConanOutput(), None)
conanfile.initialize(Settings({}), EnvValues())

class CMakeCppInfoNameTest(unittest.TestCase):
"""
Test cpp_info.name values are applied in generators instead of the reference name
"""

def setUp(self):
self.conanfile = ConanFile(TestBufferConanOutput(), None)
settings = _MockSettings()
settings.build_type = "Debug"
self.conanfile.initialize(settings, EnvValues())
ref = ConanFileReference.loads("my_pkg/0.1@lasote/stables")
cpp_info = CppInfo("dummy_root_folder1")
cpp_info.name = "MyPkG"
conanfile.deps_cpp_info.update(cpp_info, ref.name)
self.conanfile.deps_cpp_info.update(cpp_info, ref.name)
ref = ConanFileReference.loads("my_pkg2/0.1@lasote/stables")
cpp_info = CppInfo("dummy_root_folder2")
cpp_info.name = "MyPkG2"
conanfile.deps_cpp_info.update(cpp_info, ref.name)
generator = CMakeGenerator(conanfile)
cpp_info.public_deps = ["my_pkg"]
self.conanfile.deps_cpp_info.update(cpp_info, ref.name)

def cmake_test(self):
generator = CMakeGenerator(self.conanfile)
content = generator.content
self.assertIn("set(CONAN_DEPENDENCIES my_pkg my_pkg2)", content)
content = content.replace("set(CONAN_DEPENDENCIES my_pkg my_pkg2)", "")
Expand All @@ -370,21 +382,22 @@ def cpp_info_name_cmake_vars_test(self):
self.assertNotIn('CONAN_PKG::my_pkg', content)
self.assertNotIn('CONAN_PKG::my_pkg2', content)

def cpp_info_name_cmake_find_package_test(self):
"""
Test cpp_info.names values are applied instead of the reference name
"""
conanfile = ConanFile(TestBufferConanOutput(), None)
conanfile.initialize(Settings({}), EnvValues())
ref = ConanFileReference.loads("my_pkg/0.1@lasote/stables")
cpp_info = CppInfo("dummy_root_folder1")
cpp_info.name = "MyPkG"
conanfile.deps_cpp_info.update(cpp_info, ref.name)
ref = ConanFileReference.loads("my_pkg2/0.1@lasote/stables")
cpp_info = CppInfo("dummy_root_folder2")
cpp_info.name = "MyPkG2"
conanfile.deps_cpp_info.update(cpp_info, ref.name)
generator = CMakeFindPackageGenerator(conanfile)
def cmake_multi_test(self):
generator = CMakeMultiGenerator(self.conanfile)
content = generator.content
self.assertIn("set(CONAN_DEPENDENCIES_DEBUG my_pkg my_pkg2)",
content["conanbuildinfo_debug.cmake"])
self.assertNotIn("my_pkg", content["conanbuildinfo_multi.cmake"])
self.assertNotIn("MY_PKG", content["conanbuildinfo_multi.cmake"])
self.assertIn('add_library(CONAN_PKG::MyPkG INTERFACE IMPORTED)',
content["conanbuildinfo_multi.cmake"])
self.assertIn('add_library(CONAN_PKG::MyPkG2 INTERFACE IMPORTED)',
content["conanbuildinfo_multi.cmake"])
self.assertNotIn('CONAN_PKG::my_pkg', content["conanbuildinfo_multi.cmake"])
self.assertNotIn('CONAN_PKG::my_pkg2', content["conanbuildinfo_multi.cmake"])

def cmake_find_package_test(self):
generator = CMakeFindPackageGenerator(self.conanfile)
content = generator.content
self.assertIn("FindMyPkG.cmake", content.keys())
self.assertIn("FindMyPkG2.cmake", content.keys())
Expand All @@ -394,4 +407,20 @@ def cpp_info_name_cmake_find_package_test(self):
self.assertNotIn("MY_PKG", content["FindMyPkG2.cmake"])
self.assertIn("add_library(MyPkG::MyPkG INTERFACE IMPORTED)", content["FindMyPkG.cmake"])
self.assertIn("add_library(MyPkG2::MyPkG2 INTERFACE IMPORTED)", content["FindMyPkG2.cmake"])
self.assertIn("find_dependency(MyPkG REQUIRED)", content["FindMyPkG2.cmake"])

def cmake_find_package_multi_test(self):
generator = CMakeFindPackageMultiGenerator(self.conanfile)
content = generator.content
six.assertCountEqual(self, ['MyPkG2Targets.cmake', 'MyPkGConfig.cmake', 'MyPkG2Config.cmake',
'MyPkGTargets.cmake', 'MyPkGTarget-debug.cmake',
'MyPkG2Target-debug.cmake'], content.keys())
self.assertNotIn("my_pkg", content["MyPkGConfig.cmake"])
self.assertNotIn("MY_PKG", content["MyPkGConfig.cmake"])
self.assertNotIn("my_pkg", content["MyPkG2Config.cmake"])
self.assertNotIn("MY_PKG", content["MyPkG2Config.cmake"])
self.assertIn("add_library(MyPkG::MyPkG INTERFACE IMPORTED)",
content["MyPkGTargets.cmake"])
self.assertIn("add_library(MyPkG2::MyPkG2 INTERFACE IMPORTED)",
content["MyPkG2Targets.cmake"])
self.assertIn("find_dependency(MyPkG REQUIRED NO_MODULE)", content["MyPkG2Config.cmake"])