Does Conan support non-compiled packages? - conan

I have a group of class files which are shared by several of our projects. We would like to start refactoring these classes, so I am starting by building a Conan package to allow us to version them. The sticky part is that they do not build on their own; there is coupling both ways between the shared classes and the consuming classes.
As such, I've been trying to build a Conan package which simply includes the .h & .cpp files but does not attempt to build them. My conanfile.py looks like this:
from conans import ConanFile, CMake
import os
class SharedcodeConan(ConanFile):
name = "SharedCode"
version = "1.0"
author = "me myemail"
description = ""
generators = "cmake", "visual_studio"
exports_sources = "*"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def package(self):
self.copy("*.h", dst="include")
self.copy("*.cpp", dst="src")
self.copy("*.rc", dst="src")
def package_info(self):
self.cpp_info.includedirs = ['include']
This all works well. I can create the package (specifying --test-folder=None). When I pull it down from Artifactory, the include & src folders contain the files I expect.
What I cannot figure is how to bring the .cpp files into my Visual Studio project. The Conan VS extension conveniently adds Visual Studio macros for the includes, linker, etc., but not for the source files. As such, my project finds the header files, but linking fails. In looking through the docs & the Conan source, I haven't seen an indication that this is currently possible.
Is there a way to dynamically reference the src folder?
Update: In light of the comments below stating this isn't supported currently, any workaround ideas are also welcome.

Related

Cmake find_package does not work with Doxygen

Objective
I am trying to have CMake find Doxygen on a bunch of different systems and configurations:
Online documentation is generated on Ubuntu
Local tests and development is done on Macos
Doxygen can be installed system-wide, through brew or through conan depending on the use case
Problem
I struggle finding a uniform approach that does not involve a lot of OS-specific operations. I am vaguely tempted to glue together the 3 following approaches, but I am still surprised/concerned/unsure a more elegant solution does not exist.
Sub-solution 1
What I have presently works only for system-wide installations:
find_package(Doxygen
REQUIRED dot
OPTIONAL_COMPONENTS mscgen dia)
if(DOXYGEN_FOUND)
# doxygen settings can be set here, prefixed with "DOXYGEN_"
# ...
# this target will only be built if specifically asked to.
# run "make docs" to create the doxygen documentation
doxygen_add_docs(
docs
${PROJECT_SOURCE_DIR}
COMMENT "Generate API-documents."
)
else (DOXYGEN_FOUND)
message([WARNING] " Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
Sub-solution 2:
I am aware I can try to access Conan-installed executable through CONAN_BIN_DIRS_DOXYGEN/doxygen, as explained here
Sub-solution 3:
I am also aware I can try to locate Homebrew installations as described here.
Following #drodri comments, the following conan/conanfile.py achieves the desired result for my header-only library:
from conans import ConanFile, CMake
from conan.tools.cmake import CMakeDeps
class MyConan(ConanFile):
name = "mylib"
version = "0.1"
settings = "os", "compiler", "arch", "build_type"
exports_sources = "include/*", "CMakeLists.txt", "test/*", "cmake/*", "docs/*"
no_copy_source = True
generators = "cmake", "CMakeToolchain", "CMakeDeps"
requires = "boost/[>=1.78.0]", "gdal/[>=3.4.3]"
tool_requires = "cmake/3.24.2", "doxygen/1.9.4"
def generate(self):
cmake = CMakeDeps(self)
# generate the config files for the tool require
cmake.build_context_activated = ["doxygen/1.9.4"]
cmake.generate()
def build(self): # this is not building a library, just tests
cmake = CMake(self)
cmake.configure()
cmake.build()
cmake.test(output_on_failure=True)
def package(self):
self.copy("*.h")
def package_id(self):
self.info.clear()
It can be called with conan install conan/conanfile.py --build=missing --install-folder=build -pr:b=conan/profiles/clang_13 -pr:h=conan/profiles/clang_13

Yocto / OE : recipe with CMake install a shared library .so

I need to figure out how to manage a recipe for a package based on CMake creating a very simple shared library.
The goal is to provide the .so library into the Yocto build system in an atomic way, so can be used by other recipes managing application level.
This is the simple cpp code
#include <iostream>
#include "Student.h"
using namespace std;
Student::Student(string name):name(name){}
void Student::display(){
cout << "A student with name " << this->name << endl;
}
This is kind of CMakeList.txt
cmake_minimum_required(VERSION 2.8.9)
project(directory_test)
set(CMAKE_BUILD_TYPE Release)
#Bring the headers, such as Student.h into the project
include_directories(include)
#However, the file(GLOB...) allows for wildcard additions:
file(GLOB SOURCES "*.cpp")
#Generate the shared library from the sources
add_library(testStudent SHARED ${SOURCES})
#Set the location for library installation
install(TARGETS testStudent DESTINATION lib)
install(FILES student.h DESTINATION include)
This is the recipe studentlib_0.1.bb
SUMMARY = "Cmake application - creates a library"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "\
file://CMakeLists.txt \
file://student.cpp \
file://student.h \
"
S = "${WORKDIR}"
inherit cmake
EXTRA_OECMAKE = ""
The problem is when I build the specific recipe studentlib
$ bitbake studentlib
...
Build Configuration:
BB_VERSION = "1.38.0"
BUILD_SYS = "x86_64-linux"
NATIVELSBSTRING = "universal"
TARGET_SYS = "arm-poky-linux-gnueabi"
MACHINE = "qemuarm"
DISTRO = "poky"
DISTRO_VERSION = "2.5.2"
TUNE_FEATURES = "arm armv5 thumb dsp"
TARGET_FPU = "soft"
...
NOTE: Executing RunQueue Tasks
ERROR: studentlib-0.1-r0 do_package_qa: QA Issue: -dev package contains non-symlink .so: studentlib-dev path '/work/armv5e-poky-linux-gnueabi/studentlib/0.1-r0/packages-split/studentlib-dev/usr/lib/libtestStudent.so' [dev-elf]
ERROR: studentlib-0.1-r0 do_package_qa: QA run found fatal errors. Please consider fixing them.
ERROR: studentlib-0.1-r0 do_package_qa: Function failed: do_package_qa
ERROR: Logfile of failure stored in: /home/me/yocto-qemuarm-sumo/poky/build/tmp/work/armv5e-poky-linux-gnueabi/studentlib/0.1-r0/temp/log.do_package_qa.21681
ERROR: Task (/home/me/yocto-qemuarm-sumo/poky/meta-me/recipes-cmake/studentlib/studentlib_0.1.bb:do_package_qa) failed with exit code '1'
How can I solve this Issue?
I can't find any example for explanation.
Thanks
In Yocto, files (which are installed in ${D} either manually in do_install or by the make, cmake, autotools, etc... in e.g. do_compile) are put in a package when they match one of the regular expression (or glob, not entirely sure about that) contained in FILES_foo.
One recipe can (and usually does) provide multiple packages. So you'd have multiple FILES_foo1 with their own paths to match.
In Yocto, the file is put in the first package where one of the paths in its FILE_foo matches the file. Even if the file matches the paths of other packages, it'll ever be in only one package, the first one.
FWIW, packages are created from leftmost to rightmost in PACKAGES variable in the recipe. By default, the PACKAGES variable is ${PN}-src ${PN}-dbg ${PN}-staticdev ${PN}-dev ${PN}-doc ${PN}-locale ${PACKAGE_BEFORE_PN} ${PN} (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n292).
The default FILES_* variables are defined in bitbake.conf as well, c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf. Look for everything starting with FILES_.
In there, you can see that by default, FILES_${PN} has ${libdir}/lib*${SOLIBS} (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n296) packaged. SOLIBS is, by default, .so.* (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n280), which means only dot versions of libraries are packaged in the ${PN} package (if they are not matched by another package before). FILES_${PN}-dev on the other hand packages ${FILES_SOLIBSDEV} which defaults to ${base_libdir}/lib*${SOLIBSDEV} ${libdir}/lib*${SOLIBSDEV}, with SOLIBSDEV in turns defaults to .so (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n313, http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n314 and http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n283). Please note that library filenames should all start with lib to be able to be matched by the default FILES_*.
TL;DR: By default, lib*.so.* in FILES_${PN} and lib*.so in FILES_${PN}-dev.
That's the background needed to understand what is expected in which package. The issue is that -dev package should only contain lib*.so symlinks to versioned libraries (i.e. lib*.so.*).
People usually expect versioned libraries so it's easy to know which version is installed and against which version a particular software should be linked against. If the version does not matter or if the major version only matters, those will then link to the unversioned or major versioned symlinks to the versioned library.
Best practice dictates that behavior.
Two possible cases, either you only provide the unversioned library in which case the solution is to version your library in your cmake or in your recipe. Then everything works out of the box.
Or you have a copy of your versioned library named as an unversioned library, in which case you should delete your copy and just make a symlink to the versioned library.
If that is not an option (but please really consider it), you can try to find a way so that ${PN}-dev does not have this library.
There are multiple options: add lib*.so to FILES_${PN} and either remove the ${PN}-dev from the PACKAGES, remove lib*.so from FILES_${PN}-dev, unset FILES_${PN}-dev, ...

Is there is any way to build the Conan without cmake

I just started to explore both conan and cmake for building and packaging C++ files. Here is a sample conanfile.py
from conans import ConanFile, CMake
class PocoTimerConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
requires = "Poco/1.7.8p3#pocoproject/stable"
generators = "cmake", "gcc", "txt"
default_options = {"Poco:shared": True, "OpenSSL:shared": True}
def imports(self):
self.copy("*.dll", dst="bin", src="bin") # From bin to bin
self.copy("*.dylib*", dst="bin", src="lib") # From lib to bin
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
Is there any option to build the same without the use of cmake. Thanks in advance.
Yes, Conan is Cross platform, build system agnostic
There is a list with all integrations available, which includes MS Build, QMake and Autotools.
If you don't want to use integration tools, you can run directly the build commands, including running the compiler commands:
def build(self):
self.run("gcc ...")
No, Conan uses whatever build system the library is using, wrapping it. In this case, Poco is using the CMake build system, so CMake is necessary to build it. It is not possible to replace a given build system by another one automatically, that level of automation does not exist.
That doesn't mean that Conan needs CMake to operate. Conan can work with any build system, including proprietary ones. For example:
Creating and using packages with Visual Studio
Create and reuse packages with Makefiles
How to create integrations for new and custom build systems
Also, take into account that the build system used to create the package can be different to the one to consume that package. Conan "generators" can generate files for the consuming build system on the fly.
Maybe you are interested in the concept of "build-requires". You can use Conan to automatically install the cmake version that you want as a Conan package, and use it, injecting it automatically to packages to be build. Check the documentation of "build-requires" here

How to deploy a Find*.cmake file for an Autotools library in the correct place for Yocto?

I created a new layer over an existing Yocto git for my company project.
In this layer I added a few external autotools based libraries.
A few applications need to link against this libraries and the application projects are all cmake based.
Taking one of this libraries (e.g. libcoap) I could easily find some FindCoAP.cmake to add to my library recipe.
Now if I was running on PC, it would simply be a matter of placing this FindCoAP.cmake file in cmake's ${CMAKE_ROOT}/Modules dir, but how should I, from inside a bitbake recipe (do_install hook), proceed to make my Find*.cmake modules available to anyone's dependent projects?
Should I try to get Yocto's cmake CMAKE_ROOT variable from system-information like this or is it a safer and more reliable way?
do_install_append() {
cmake --system-information | grep CMAKE_ROOT | cut -d \" -f2
install -d ${D}/$CMAKE_ROOT}/Modules
install ${S}/FindCoAP.cmake ${D}/$CMAKE_ROOT}/Modules
}
Thanks in advance.
To ship FindFoo.cmake with non-yet-cmake project
The ideal way is to update upstream project itself. So you will update your recipe and package FindFoo.cmake appropriately.
If you want to do it right now:
Add FindFoo.cmake to your layer (into the files directory next to your recipe).
Add that cmake file to SRC_URI (i.e. SRC_URI += "file://FindFoo.cmake").
Install it in do_install into the directory ${D}${datadir}/cmake/Modules/ for example.
Package it to the dev package by FILES_${PN}-dev variable (see example recipes below).
To use that cmake by other recipe
The usual way is to package .cmake files into the ${PN}-dev package. In your case, your application (which depends on the libcoap) will just set DEPENDS = "libcoap" and all the needed files (like headers, libraries and cmake file) will be copied (well, hardlinked) to the sysroot of your application.
CMake modules are packaged in various recipes for example:
libeigen
opencv
json-spirit
Your application is cmake based, so you will use inherit cmake in the recipe. Native module search path is set in cmake.bbclass.
(BTW, I do a build test of libcoap recipe from homeassistant layer and it worked, but obviously there is no cmake shipped.)

How can I get the source directory from an imported target?

I'm working on a C++ game library. The game library is exporting a package from it's source tree like this:
set(GAMELIB_CONFIG_PATH "lib/cmake/gamelib")
# installation target
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/${GAMELIB_CONFIG_PATH}/gamelibConfig.cmake"
DESTINATION ${GAMELIB_CONFIG_PATH}
)
install(
EXPORT gamelibTargets FILE gamelibTargets.cmake
NAMESPACE gamelib::
DESTINATION ${GAMELIB_CONFIG_PATH}
)
# export package from build directory
export(
EXPORT gamelibTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/gamelibTargets.cmake"
NAMESPACE gamelib::
)
export(PACKAGE gamelib)
So then I got two choices to consume the game library: I can either install the game library and let other project use it from the installation, or I can import it directly from the built source tree, which makes it convenient to develop the engine while also developing a game.
Game are simply importing the package like that:
find_package(gamelib REQUIRED)
target_link_libraries(game PUBLIC gamelib::gamelib)
Here's my problem: How can I get the source path for an imported cmake package? And how can I get a different path when the package is actually installed? I want to ship predefined assets directly from the game lib instead of copying them manually into games. The game will need to read the files from the game library to load them. So I need thier paths either in the source tree, or in the installed path.
When importing, I have gamelib_DIR defined, but that point to the binary dir.
I am familiar with generator expression to set a different value in different contexts:
target_include_directories(gamelib-common INTERFACE
$<INSTALL_INTERFACE:${GAMELIB_INSTALL_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
)
Can something similar be done with source directory and installed path?