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

Conan v2 #2805

Merged
merged 9 commits into from
Feb 17, 2024
15 changes: 5 additions & 10 deletions .conan/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
cmake_minimum_required(VERSION 3.2.0)
project(test_package CXX)
cmake_minimum_required(VERSION 3.15)
project(PackageTest CXX)

include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
conan_basic_setup()
find_package(Catch2 CONFIG REQUIRED)

find_package(Catch2 REQUIRED CONFIG)

add_executable(${PROJECT_NAME} test_package.cpp)

target_link_libraries(${PROJECT_NAME} Catch2::Catch2WithMain)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 14)
add_executable(test_package test_package.cpp)
target_link_libraries(test_package catch2::catch2main)
25 changes: 19 additions & 6 deletions .conan/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from conans import ConanFile, CMake
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
from conan.tools.build import can_run
import os


class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake_find_package_multi", "cmake"
generators = "CMakeToolchain", "CMakeDeps"

def requirements(self):
self.requires(self.tested_reference_str)

def layout(self):
cmake_layout(self)

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def test(self):
assert os.path.isfile(os.path.join(
self.deps_cpp_info["catch2"].rootpath, "licenses", "LICENSE.txt"))
bin_path = os.path.join("bin", "test_package")
self.run("%s -s" % bin_path, run_environment=True)
if can_run(self):
cmd = os.path.join(self.cpp.build.bindir, "test_package")
self.run(cmd, env="conanrun")

# If we are on conan 2 we can check the license info is populated
if hasattr(self, 'dependencies'):
catch2 = self.dependencies["catch2"]
assert os.path.exists(f'{catch2.package_folder}/licenses/LICENSE.txt')
assert catch2.license == 'BSL-1.0'
31 changes: 31 additions & 0 deletions .github/workflows/package-manager-builds.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Package Manager Builds

on: [push, pull_request]

jobs:
conan_builds:
name: Conan ${{matrix.conan_version}}
runs-on: ubuntu-20.04
strategy:
matrix:
conan_version:
- '1.62'
- '2.0'

include:
# Conan 1 has default profiles installed
- conan_version: '1.62'
profile_generate: 'false'

steps:
- uses: actions/checkout@v4

- name: Install conan
run: pip install conan==${{matrix.conan_version}}

- name: Setup conan profiles
if: matrix.profile_generate != 'false'
run: conan profile detect

- name: Run conan package create
run: conan create . -tf .conan/test_package
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Build
cmake-build-*
benchmark-dir
.conan/test_package/build
.conan/test_package/CMakeUserPresets.json
bazel-*
build-fuzzers
debug-build
Expand Down
97 changes: 68 additions & 29 deletions conanfile.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#!/usr/bin/env python
from conans import ConanFile, CMake, tools
from conan import ConanFile, tools, __version__ as conan_version
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout
from conan.tools import files, scm
import os
import shutil
import re


class CatchConan(ConanFile):
name = "catch2"
Expand All @@ -8,53 +14,86 @@ class CatchConan(ConanFile):
url = "https://github.com/catchorg/Catch2"
homepage = url
license = "BSL-1.0"
version = "latest"

exports = "LICENSE.txt"
exports_sources = ("src/*", "CMakeLists.txt", "CMake/*", "extras/*")

settings = "os", "compiler", "build_type", "arch"

generators = "cmake"
def set_version(self):
pattern = re.compile(r"\w*VERSION (\d+\.\d+\.\d+) # CML version placeholder, don't delete")
with open("CMakeLists.txt") as file:
for line in file:
result = pattern.search(line)
if result:
self.version = result.group(1)

self.output.info(f'Using version: {self.version}')

def layout(self):
cmake_layout(self)

def generate(self):
tc = CMakeToolchain(self)
tc.generate()

deps = CMakeDeps(self)
deps.generate()

def _configure_cmake(self):
cmake = CMake(self)
cmake.definitions["BUILD_TESTING"] = "OFF"
cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
cmake.definitions["CATCH_INSTALL_EXTRAS"] = "ON"
cmake.configure(build_folder="build")

# These are option variables. The toolchain in conan 2 doesn't appear to
# set these correctly so you have to do it in the configure variables.
cmake.configure(variables= {
"BUILD_TESTING": "OFF",
"CATCH_INSTALL_DOCS": "OFF",
"CATCH_INSTALL_EXTRAS": "ON",
}
)
return cmake

def build(self):
# We need this workaround until the toolchains feature
# to inject stuff like MD/MT
line_to_replace = 'list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")'
tools.replace_in_file("CMakeLists.txt", line_to_replace,
'''{}
include("{}/conanbuildinfo.cmake")
conan_basic_setup()'''.format(line_to_replace, self.install_folder.replace("\\", "/")))

cmake = self._configure_cmake()
cmake.build()

def package(self):
self.copy(pattern="LICENSE.txt", dst="licenses")
cmake = self._configure_cmake()
cmake.install()

os.mkdir(f'{self.package_folder}/licenses/')
shutil.copy2(f'{self.recipe_folder}/LICENSE.txt', f'{self.package_folder}/licenses/')

def package_info(self):
lib_suffix = "d" if self.settings.build_type == "Debug" else ""

self.cpp_info.names["cmake_find_package"] = "Catch2"
self.cpp_info.names["cmake_find_package_multi"] = "Catch2"
# Catch2
self.cpp_info.components["catch2base"].names["cmake_find_package"] = "Catch2"
self.cpp_info.components["catch2base"].names["cmake_find_package_multi"] = "Catch2"
self.cpp_info.components["catch2base"].names["pkg_config"] = "Catch2"
self.cpp_info.components["catch2base"].libs = ["Catch2" + lib_suffix]
self.cpp_info.components["catch2base"].builddirs.append("lib/cmake/Catch2")
# Catch2WithMain
self.cpp_info.components["catch2main"].names["cmake_find_package"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].names["cmake_find_package_multi"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].names["pkg_config"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].libs = ["Catch2Main" + lib_suffix]
self.cpp_info.components["catch2main"].requires = ["catch2base"]
if conan_version < scm.Version("2.0.0"):
self.cpp_info.names["cmake_find_package"] = "Catch2"
self.cpp_info.names["cmake_find_package_multi"] = "Catch2"
# Catch2
self.cpp_info.components["catch2base"].names["cmake_find_package"] = "Catch2"
self.cpp_info.components["catch2base"].names["cmake_find_package_multi"] = "Catch2"
self.cpp_info.components["catch2base"].names["pkg_config"] = "Catch2"
self.cpp_info.components["catch2base"].libs = ["Catch2" + lib_suffix]
self.cpp_info.components["catch2base"].builddirs.append("lib/cmake/Catch2")
# Catch2WithMain
self.cpp_info.components["catch2main"].names["cmake_find_package"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].names["cmake_find_package_multi"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].names["pkg_config"] = "Catch2WithMain"
self.cpp_info.components["catch2main"].libs = ["Catch2Main" + lib_suffix]
self.cpp_info.components["catch2main"].requires = ["catch2base"]
else:
self.cpp_info.set_property("cmake_file_name", "Catch2")

# Catch2
self.cpp_info.components["catch2base"].set_property("cmake_file_name", "Catch2")
self.cpp_info.components["catch2base"].set_property("pkg_config_name", "Catch2")
self.cpp_info.components["catch2base"].libs = ["Catch2" + lib_suffix]
self.cpp_info.components["catch2base"].builddirs.append("lib/cmake/Catch2")

# Catch2WithMain
self.cpp_info.components["catch2main"].set_property("cmake_file_name", "Catch2WithMain")
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do specify cmake_target_name similar to
https://github.com/conan-io/conan-center-index/blob/master/recipes/catch2/3.x.x/conanfile.py#L168

That way you would be able to correctly use Catch2::Catch2WithMain target instead of the lowercase.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think i did this. I kept the cmake_file_name but not sure if that matters.

I also didn't realize that the conan file for conan.io is separate from this repo. So will this close the issue in reference? Maybe if it is maintained over there we just drop the conan files here

Copy link
Contributor

Choose a reason for hiding this comment

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

The Conan Center policy is to maintain recipes for the default repo so in-source conanfiles are only needed for project-specific development. I'm not sure how many people require it so it's up to the maintainer in here to decide if it's still needed.

Regarding this specific PR - cmake_target_name is used for the target name. It needs to be specified with namespace because of the different filename to namespace to target to component conventions different projects have. cmake_file_name is needed only for the find_package syntax, it's not useful for components and it doesn't make sense to specify the target name in there. The global level cmake_target_name I think refers to the target which is wired on Conan-level global component dependencies, it's not actually used in CMake.

Additionally, prefer os.path.join over the / directory separator for cross-environment compatibility.

self.cpp_info.components["catch2main"].set_property("pkg_config_name", "Catch2WithMain")
self.cpp_info.components["catch2main"].libs = ["Catch2Main" + lib_suffix]
self.cpp_info.components["catch2main"].requires = ["catch2base"]
Loading