conan
conan copied to clipboard
[bug] libraries with components broken in editable mode
Describe the bug
System details
WSL with ubuntu.22.04 under Windows 11 g++-12 (through apt) cmake 3.29.2 (through snap) Conan 2.2.3
The Problem
Similar to https://github.com/conan-io/conan/issues/16162 but for projects using components (game engine example) in editable mode.
Situation
I use components, since some parts of the lib are compatible for some products (low level embedded without real os vs higher level embedded with linux) For developing editable mode is suggested.
Error
[cmake] CMake Error at out/build/linux_config/conan/build/Release/generators/cmakedeps_macros.cmake:67 (message):
[cmake] Library 'testman' not found in package. If 'testman' is a system library,
[cmake] declare it with 'cpp_info.system_libs' property
This happens only in editable mode.
How to reproduce it
modify conanfile.py with something like that
def package_info(self):
self.cpp_info.components["testman"].libs = ["testman"]
and your cmakefile needs somethink like
cmake_minimum_required(VERSION 3.28.0)
project(testmanproj
VERSION 1.0.0
LANGUAGES CXX
)
add_library(testman "${LIBRARY_SOURCE_DIR}/some/dirs/testman.cpp")
install(TARGETS testman)
more details
even through components dont work properly, without them it works!
self.cpp_info.libs = ["testman"]
This will work out without problems. It is the combination of editable with components in libraries.
Have you read the CONTRIBUTING guide?
- [X] I've read the CONTRIBUTING guide
I think this might be the same as discussed in https://github.com/conan-io/conan/issues/16162#issuecomment-2079815977: it is necessary to model the local development "editable" layout in the layout() method, also for components.
Feedback
Yeah you're right. It took me some time but I found the problem.
What happened wrong
for some reason, conan is changing one specific line differently in my generated file:
consumer/conan/build/Release/generators/testman-release-x86_64-data.cmake
set(testman_LIB_DIRS_RELEASE "${testman_PACKAGE_FOLDER_RELEASE}/lib")
should be
set(testman_LIB_DIRS_RELEASE "${testman_PACKAGE_FOLDER_RELEASE}/build/Release/.")
Personal opinion
I think this is a bit counterintuitive, but can be fixed in local conanfiles.py also there are more changes, but they are fine so far.
Question: not sure if the behaviour should be like this
if i have following code in package_info():
| code | result | ${testman_LIB_DIRS_RELEASE} |
|---|---|---|
self.cpp_info.libs = ["left"] |
works | ${testman_PACKAGE_FOLDER_RELEASE}/build/Release/. |
self.cpp_info.components["left"].libs = ["left"] |
fails | ${testman_PACKAGE_FOLDER_RELEASE}/lib |
self.cpp_info.libs = ["left"] self.cpp_info.components["right"].libs = ["right"] |
fails | ${testman_PACKAGE_FOLDER_RELEASE}/lib |
self.cpp_info.components["right"].libs = ["right"] self.cpp_info.libs = ["left"] |
fails | ${testman_PACKAGE_FOLDER_RELEASE}/lib |
Mixed list does not work either. Ordering is not changing the behaviour.
As seen, only the first version is valid. I can't think of a situation where the libs directory should be defaultet to /lib if we already set libs.
It is fixable in a custom conanfile.py, but it feels wrong to be forced to for the mixed case.
Code to test
componentTest.zip To test it: for library in conan cache: (in corresponding directory)
conan build .
conan export-pkg .
for editable mode: (in corresponding directory)
conan add editable .
for the consumer/application
cmake --preset default .
info:
- it fails at configuration step, no build step necessary
- example is using the conan provider file
- provider file was modified (extended) with "--build=editable" to always build editables
- all test cases can be found in
library/conanfily.py/package_info(); just comment/decomment the code - library builds 2 dummy libs called
leftandright
Thanks for the detailed feedback and the reproducible code.
I think the issue in this case from what I see in your conanfile.py is that definition of cpp_info in the package_info() method is not enough for modelling the editable layout.
It is necessary to define it in the layout() method, in the self.cpp.xxx.components[] interfaces with xxx=source/build/package.
Please have a look to https://docs.conan.io/2/tutorial/developing_packages/package_layout.html, like:
def layout(self):
## define project folder structure
self.folders.source = "."
self.folders.build = os.path.join("build", str(self.settings.build_type))
self.folders.generators = os.path.join(self.folders.build, "generators")
## cpp.package information is for consumers to find the package contents in the Conan cache
self.cpp.package.libs = ["say"]
self.cpp.package.includedirs = ["include"] # includedirs is already set to 'include' by
# default, but declared for completion
self.cpp.package.libdirs = ["lib"] # libdirs is already set to 'lib' by
# default, but declared for completion
## cpp.source and cpp.build information is specifically designed for editable packages:
# this information is relative to the source folder that is '.'
self.cpp.source.includedirs = ["include"] # maps to ./include
It would be like that, but also defining components in those interfaces. The package_info() alone is not enough to model the editable layouts, it must be in the layout() method.
Hi @Sickeroni
Any further feedback here? Did the above explanation about components definition in layout() helped?