Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions conan/cps/cps.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def __init__(self, component_type=None):
self.requires = []
self.location = None
self.link_location = None
self.link_languages = None
self.link_libraries = None # system libraries

def serialize(self):
Expand All @@ -56,6 +57,8 @@ def serialize(self):
component["link_location"] = self.link_location
if self.link_libraries:
component["link_libraries"] = self.link_libraries
if self.link_languages:
component["link_languages"] = self.link_languages
return component

@staticmethod
Expand All @@ -68,6 +71,7 @@ def deserialize(data):
comp.location = data.get("location")
comp.link_location = data.get("link_location")
comp.link_libraries = data.get("link_libraries")
comp.link_languages = data.get("link_languages")
return comp

@staticmethod
Expand All @@ -90,12 +94,15 @@ def from_cpp_info(cpp_info, conanfile, libname=None):
cps_comp.location = cpp_info.location
cps_comp.link_location = cpp_info.link_location
cps_comp.link_libraries = cpp_info.system_libs
langs = {"C": "c", "C++": "cpp"}
cps_comp.link_languages = [langs[lang] for lang in cpp_info.languages or []]
required = cpp_info.requires
cps_comp.requires = [f":{c}" if "::" not in c else c.replace("::", ":") for c in required]
return cps_comp

def update(self, conf, conf_def):
# TODO: conf not used at the moent
self.link_languages = self.link_languages or conf_def.get("link_languages")
self.location = self.location or conf_def.get("location")
self.link_location = self.link_location or conf_def.get("link_location")
self.link_libraries = self.link_libraries or conf_def.get("link_libraries")
Expand Down Expand Up @@ -223,6 +230,29 @@ def strip_prefix(dirs):
basefile = basefile[3:]
cpp_info.libs = [basefile]
# FIXME: Missing requires
elif comp.type is CPSComponentType.DYLIB:
if comp.link_location:
link_location = comp.link_location
link_location = link_location.replace("@prefix@/", "")
cpp_info.libdirs = [os.path.dirname(link_location)]
filename = os.path.basename(link_location)
basefile, ext = os.path.splitext(filename)
if basefile.startswith("lib") and ext != ".lib":
basefile = basefile[3:]
cpp_info.libs = [basefile]
location = comp.location
location = location.replace("@prefix@/", "")
cpp_info.bindirs = [os.path.dirname(location)]
else: # TODO: same as archive, refactor
location = comp.location
location = location.replace("@prefix@/", "")
cpp_info.libdirs = [os.path.dirname(location)]
filename = os.path.basename(location)
basefile, ext = os.path.splitext(filename)
if basefile.startswith("lib") and ext != ".lib":
basefile = basefile[3:]
cpp_info.libs = [basefile]
# FIXME: Missing requires
cpp_info.system_libs = comp.link_libraries
else:
for comp_name, comp in self.components.items():
Expand Down
3 changes: 2 additions & 1 deletion conan/tools/cmake/cmakedeps2/cmakedeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ def generate(self):
pkg_name = self._cmakedeps.get_cmake_filename(dep)
# https://cmake.org/cmake/help/v3.22/guide/using-dependencies/index.html
if cmake_find_mode == FIND_MODE_NONE:
cps = glob.glob(f"**/{pkg_name}.cps", root_dir=dep.package_folder, recursive=True)
cps = glob.glob(os.path.join(dep.package_folder, f"**/{pkg_name}.cps"),
recursive=True)
if cps:
loc = os.path.dirname(os.path.join(dep.package_folder, cps[0]))
loc = loc.replace("\\", "/")
Expand Down
9 changes: 6 additions & 3 deletions test/functional/toolchains/cmake/test_cps.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@


@pytest.mark.tool("cmake", "4.2")
def test_cps():
@pytest.mark.parametrize("shared", [False, True])
def test_cps(shared):
c = TestClient()
c.run("new cmake_lib")
conanfile = textwrap.dedent("""\
Expand Down Expand Up @@ -67,7 +68,9 @@ def package_info(self):
# First, try with the standard mypkg-config.cmake consumption
c.save({"conanfile.py": conanfile,
"CMakeLists.txt": cmake})
c.run("create")

shared_arg = "-o &:shared=True" if shared else ""
c.run(f"create {shared_arg}")
assert "mypkg/0.1: Hello World Release!" in c.out

# Lets consume directly with CPS
Expand Down Expand Up @@ -119,5 +122,5 @@ def test(self):
shutil.rmtree(os.path.join(c.current_folder, "test_package", "build"))
c.save({"test_package/conanfile.py": test_conanfile,
"test_package/CMakeLists.txt": test_cmake})
c.run("create --build=missing -c tools.cmake.cmakedeps:new=will_break_next")
c.run(f"create {shared_arg} --build=never -c tools.cmake.cmakedeps:new=will_break_next")
assert "mypkg/0.1: Hello World Release!" in c.out
98 changes: 83 additions & 15 deletions test/integration/cps/test_cps.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,38 +122,106 @@ def package_info(self):
assert 'set(zlib_LIBS_RELEASE zlib)' in cmake


def test_cps_merge():
folder = temp_folder()
cps_base = textwrap.dedent("""
def test_cps_shared_in_pkg():
c = TestClient()
cps = textwrap.dedent("""\
{
"components" : {
"mypkg" : {
"components" :
{
"mypkg" :
{
"includes" : [ "@prefix@/include" ],
"type" : "archive"
"type" : "dylib"
}
},
"cps_version" : "0.12.0",
"name" : "mypkg",
"version" : "1.0"
"cps_path" : "@prefix@/cps",
"cps_version" : "0.13.0",
"name" : "mypkg"
}
""")
cps_conf = textwrap.dedent("""
cps_release = textwrap.dedent("""\
{
"components" : {
"mypkg" : {
"link_languages" : [ "cpp" ],
"location" : "@prefix@/lib/mypkg.lib"
"components" :
{
"mypkg" :
{
"link_location" : "@prefix@/lib/mypkg.lib",
"location" : "@prefix@/bin/mypkg.dll"
}
},
"configuration" : "Release",
"name" : "mypkg"
}
""")
cps = "".join(cps.splitlines())
cps_release = "".join(cps_release.splitlines())
conanfile = textwrap.dedent(f"""
import os, json
from conan.tools.files import save
from conan import ConanFile
class Pkg(ConanFile):
name = "mypkg"
version = "1.0"

def package(self):
cps = '{cps}'
cps_path = os.path.join(self.package_folder, "mypkg.cps")
save(self, cps_path, cps)
cps = '{cps_release}'
cps_path = os.path.join(self.package_folder, "[email protected]")
save(self, cps_path, cps)

def package_info(self):
from conan.cps import CPS
self.cpp_info = CPS.load("mypkg.cps").to_conan()
""")
c.save({"pkg/conanfile.py": conanfile})
c.run("create pkg")

settings = "-s os=Windows -s compiler=msvc -s compiler.version=191 -s arch=x86_64"

c.run(f"install --requires=mypkg/1.0 {settings} -g CMakeDeps")
cmake = c.load("mypkg-release-x86_64-data.cmake")
assert 'set(mypkg_INCLUDE_DIRS_RELEASE "${mypkg_PACKAGE_FOLDER_RELEASE}/include")' in cmake
assert 'set(mypkg_LIB_DIRS_RELEASE "${mypkg_PACKAGE_FOLDER_RELEASE}/lib")'
assert 'set(mypkg_LIBS_RELEASE mypkg)' in cmake


def test_cps_merge():
folder = temp_folder()

cps_base = textwrap.dedent("""{
"components": {
"mypkg":{
"includes": ["@prefix@/include"],
"type": "archive"
}
},
"cps_path": "@prefix@/cps",
"cps_version": "0.13.0",
"name": "mypkg"
}
""")
cps_conf = textwrap.dedent("""{
"components" : {
"mypkg" : {
"link_languages" : [ "cpp" ],
"location" : "@prefix@/lib/mypkg.lib"
}
},
"configuration" : "Release",
"name" : "mypkg"
}
""")
save_files(folder, {"mypkg.cps": cps_base,
"[email protected]": cps_conf})
cps = CPS.load(os.path.join(folder, "mypkg.cps"))
json_cps = cps.serialize()
print(json.dumps(json_cps, indent=2))
mypkg = json_cps["components"]["mypkg"]
assert mypkg["includes"] == ["@prefix@/include"]
assert mypkg["location"] == "@prefix@/lib/mypkg.lib"
assert mypkg["type"] == "archive"
assert mypkg["link_languages"] == ["cpp"]


def test_extended_cpp_info():
Expand Down
Loading