Recognize linux distribution in conan - conan

I created a Ncurses conan package for some projects where I use Ncurses. I use a conanfile.py for configuration. Now I have the problem that under Centos terminfo is in /usr/lib and under Debian-based system it is in /lib.
Therefor I have to set an argument in conanfile.py depending on the distribution:
.
.
.
settings = "os", "compiler", "build_type", "arch"
.
.
.
def build(self):
env_build = AutoToolsBuildEnvironment(self)
env_build.configure(configure_dir="src", build=False, host=False, target=False)
args = ["--without-debug"]
# if debian-based
args += ["--datadir=/lib"]
if self.options.shared:
args += ["--with-shared", "--without-normal"]
env_build.configure(configure_dir="src", args=args, build=False, host=False, target=False)
env_build.make()
How can I implement the if statement # if debian-based? What would be best practice in this case?

You can use the OSInfo helper, which is a wrapper around uname and other OS functions. In your case you would like something like:
from conans.tools import OSInfo
info = OSInfo()
if info.is_linux and info.linux_distro in ("debian", "ubuntu"):
# your logic here

Related

conan doesn't upload export/conanfile.py to remote

I have created customized OpenCV package using conan package manager and uploaded it to a remote storage.
Workflow:
create package
cd c:\path\to\conanfile.py
conan create . smart/4.26 --profile ue4
Export with conan export . opencv-ue4/3.4.0#smart/4.26
Result:
c:\path\> conan export . opencv-ue4/3.4.0#smart/4.26
[HOOK - attribute_checker.py] pre_export(): WARN: Conanfile doesn't have 'url'. It is recommended to add it as attribute
Exporting package recipe
opencv-ue4/3.4.0#smart/4.26 exports_sources: Copied 3 '.patch' files: cmakes.patch, check_function.patch, typedefs.patch
opencv-ue4/3.4.0#smart/4.26: The stored package has not changed
opencv-ue4/3.4.0#smart/4.26: Exported revision: ceee251590f4bf50c4ff48f6dc27c2ed
I upload everything to the remote:
c:\path> conan upload -r bart opencv-ue4/3.4.0#rs7-smart/4.26 --all
Uploading to remote 'bart':
Uploading opencv-ue4/3.4.0#smart/4.26 to remote 'bart'
Recipe is up to date, upload skipped
Uploading package 1/1: 1d79899922d252aec6da136ce61bff640124c1c4 to 'bart'
Uploaded conan_package.tgz -> opencv-ue4/3.4.0#smart/4.26:1d79 [23667.97k]
Uploaded conaninfo.txt -> opencv-ue4/3.4.0#smart/4.26:1d79 [0.75k]
Uploaded conanmanifest.txt -> opencv-ue4/3.4.0#smart/4.26:1d79 [11.81k]
Our remote storage runs on the Artifactory, and I can see in a browser that conanfile.py is not listed anywhere.
I can also verify that directory C:\Users\user\.conan\data\opencv-ue4\3.4.0\smart\4.26\export on my Windows PC does contain both conanfile.py and conanmanifest.txt
I am using Windows PC for doing all above.
Now I'm trying to consume that package on another machine, running Ubuntu Linux.
Here is my conanfile.txt
[requires]
opencv-ue4/3.4.0#smart/4.26
[generators]
json
Command and results
> conan install -g json . opencv-ue4/3.4.0#smart/4.26
Configuration:
[settings]
arch=x86_64
arch_build=x86_64
build_type=Release
compiler=gcc
compiler.libcxx=libstdc++
compiler.version=9
os=Linux
os_build=Linux
[options]
[build_requires]
[env]
opencv-ue4/3.4.0#smart/4.26: Not found in local cache, looking in remotes...
opencv-ue4/3.4.0#smart/4.26: Trying with 'bart'...
Downloading conanmanifest.txt completed [0.33k]
opencv-ue4/3.4.0#-smart/4.26: Downloaded recipe revision 0
ERROR: opencv-ue4/3.4.0#smart/4.26: Cannot load recipe.
Error loading conanfile at '/home/user/.conan/data/opencv-ue4/3.4.0/smart/4.26/export/conanfile.py': /home/user/.conan/data/opencv-ue4/3.4.0/smart/4.26/export/conanfile.py not found!
Running ls -la /home/user/.conan/data/opencv-ue4/3.4.0/smart/4.26/export/ shows that the directory indeed contains only file conanmanifest.txt
Below is the relevant part of the conanfile.py that I've used to build the package
from conans import ConanFile, CMake, tools
class OpenCVUE4Conan(ConanFile):
name = "opencv-ue4"
version = "3.4.0"
url = ""
description = "OpenCV custom build for UE4"
license = "BSD"
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"
exports_sources = 'patches/cmakes.patch', 'patches/check_function.patch', 'patches/typedefs.patch'
def requirements(self):
self.requires("ue4util/ue4#adamrehn/profile")
self.requires("zlib/ue4#adamrehn/{}".format(self.channel))
self.requires("UElibPNG/ue4#adamrehn/{}".format(self.channel))
def cmake_flags(self):
flags = [
"-DOPENCV_ENABLE_NONFREE=OFF",
# cut
]
return flags
def source(self):
self.run("git clone --depth=1 https://github.com/opencv/opencv.git -b {}".format(self.version))
self.run("git clone --depth=1 https://github.com/opencv/opencv_contrib.git -b {}".format(self.version))
def build(self):
# Patch OpenCV to avoid build errors
for p in self.exports_sources:
if p.endswith(".patch"):
tools.patch(base_path='opencv', patch_file=p, fuzz=True)
cmake = CMake(self)
cmake.configure(source_folder="opencv", args=self.cmake_flags())
cmake.build()
cmake.install()
def package_info(self):
self.cpp_info.libs = tools.collect_libs(self)
Conan version both in Windows and in Linux is 1.54.0
How do I correctly upload and consume the package?
Update.
After conversation with #drodri in comments I have removed conanfile.py from exports_sources, deleted all conan-generated files in all PCs and removed uploaded files from the Artifactory.
Then I've rebuilt the package, re-exported and re-uploaded it.
The issue was in restrictions of our Artifactory. Admins have forbidden uploading .py files.

How to link against to specific packageid in Conan

I have a package with 2 binaries. The binaries only differ by a single option.
The package is a library. How can now link this package to a specific package that I require?
There are few options:
You can use cmake_paths and discover the library name:
First, you add a conanfile.txt, declaring package name and cmake_paths generator
[requires]
my_package/0.1.0#user/channel
[generators]
cmake_paths
Second, you search the desired library from the package, by its name in your cmake file:
cmake_minimum_required(VERSION 3.0)
project(myapp)
find_library(MY_LIBRARY foo REQUIRED) # the library name foo in this example
add_executable(myapp app.cpp)
target_link_libraries (myapp ${MY_LIBRARY})
And finally, you pass the cmake_paths to cmake, so it will find your library
mkdir build && cd build
conan install ..
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_paths.cmake
cmake --build .
./myapp
It works, but it's a bit fragile, as the consumer need to now the library name and there is no warning from CMake when the library is found, you have to add a condition to check it.
The second possible option is using Components feature, but requires a recipe modification, you can provide a different target for each library:
First, you need to update your conanfile.py, adding the components:
from conans import ConanFile, CMake
class MyPackage(ConanFile):
name = "my_package"
version = "0.1.0"
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False]}
default_options = {"shared": False}
generators = "cmake"
exports_sources = "src/*"
def build(self):
cmake = CMake(self)
cmake.configure(source_folder="src")
cmake.build()
def package(self):
self.copy("*.h", dst="include", src="src")
self.copy("*.lib", dst="lib", keep_path=False)
self.copy("*.dll", dst="bin", keep_path=False)
self.copy("*.dylib*", dst="lib", keep_path=False)
self.copy("*.so", dst="lib", keep_path=False)
self.copy("*.a", dst="lib", keep_path=False)
def package_info(self):
self.cpp_info.names["cmake_find_package"] = "MyPackage"
self.cpp_info.names["cmake_find_package_multi"] = "MyPackage"
self.cpp_info.components["libfoo"].names["cmake_find_package"] = "foo"
self.cpp_info.components["libfoo"].names["cmake_find_package_multi"] = "foo"
self.cpp_info.components["libfoo"].libs = ["foo"]
self.cpp_info.components["libbar"].names["cmake_find_package"] = "bar"
self.cpp_info.components["libbar"].names["cmake_find_package_multi"] = "bar"
self.cpp_info.components["libbar"].libs = ["bar"]
As you can see, the recipe builds a package with 2 libraries, foo and bar, and use different components for each one. As CamelCase is preferred for CMake targets, the name MyPackage will be used for the file name and target namespace. The result will be MyPackage::foo and MyPackage::bar.
As consumer, you have to update your project too:
Now we will use cmake_find_package generator, to avoid CMAKE_TOOLCHAIN_FILE in the command line:
[requires]
my_package/0.1.0#user/channel
[generators]
cmake_find_package
The CMake file now requires the package name, but it's checked by CMake:
cmake_minimum_required(VERSION 3.0)
project(myapp)
find_package(MyPackage REQUIRED)
add_executable(myapp app.cpp)
target_link_libraries (myapp MyPackage::foo) # We only need libfoo here
And finally, but simpler now, the command line:
mkdir build && cd build
conan install ..
cmake ..
cmake --build .
./myapp
Conan will generate FindMyPackage.cmake in build/ which will be loaded by your CMakeLists.txt.
Both demonstrations achieve what you asked, but I prefer the second, because is safer, as you can create a specific target, and avoid any mistake from the customer side.
NOTE: The feature Components requires Conan >=1.27.

Yocto load kernel module

I try to add a kernel module to a yocto image and load it on boot.
I create a recipe to build and install a kernel module. Here's a part of the Makefile content:
modules_install: test_driver.ko
install -d $(MODULES_DIR)
install -m 0755 $< $(MODULES_DIR)
In my build/conf/local.conf, I add the package (subsystem being the name of my module recipe):
IMAGE_INSTALL_append = " subsystem"
After building the image, I can find the .ko file inside the MODULES_DIR directory (being /lib/modules/(shell uname -r)/kernel/drivers/test).
I want to do now is to load this module on boot. I found some clues about KERNEL_MODULE_AUTOLOAD and MACHINE_ESSENTIAL_*/MACHINE_EXTRA_*.
So I try KERNEL_MODULE_AUTOLOAD += "subsystem" or even KERNEL_MODULE_AUTOLOAD += "test_driver" in build/conf/local.conf or in my module recipe, but I couldn't have the driver loaded on boot.
I'm working against the fsl-image-machine-test image (sumo version).
The KERNEL_MODULE_AUTOLOAD need to be outside of the local.conf file. I put it now in my module recipe.
It needs to load the name of the module not the recipe, in my case :
KERNEL_MODULE_AUTOLOAD += "test_driver".

CMake unable to generate search path because of library conflict

Dear Colleagues,
I'm a newcommer to LINUX and am trying to use CMake to build a Geant4 example. After the following command
$cmake ~/Geant4/geant4.10.05.p01-install/share/Geant4-10.5.1/examples/basic/B1/
I get this error message:
Cannot generate a safe runtime search path for target exampleB1 because files in some directories
may conflict with libraries in implicit directories:
runtime library [libexpat.so.1] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/dakar/anaconda3/lib
Some of these libraries may not be found correctly.
The warning is correct and when I run $ make -j6 I get the error message
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSM.so: undefined reference to
‘uuid_generate#UUID_1.0’
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libSM.so: undefined reference
to‘uuid_unparse_lower#UUID_1.0’
This problem has been encountered before and some solutions are described in detail here:
https://github.com/pism/pism/issues/356
The page the URL links to say that for Conda 4.4+ this issue shouldn't occur. I'm using Conda 4.6.14 but the page adds that if does occur: you can set the NOCONDA_PATH variable in your .bashrc (or similar) just before you add conda to your path like so:
export NOCONDA_PATH=$PATH
export PATH=$HOME/anaconda3/bin:$PATH
I tried this and my .bashrc now reads:
# >>> conda init >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$(CONDA_REPORT_ERRORS=false '/home/dakar/anaconda3/bin/conda' shell.bash hook 2> /dev/null$
if [ $? -eq 0 ]; then
\eval "$__conda_setup"
else
if [ -f "/home/dakar/anaconda3/etc/profile.d/conda.sh" ]; then
. "/home/dakar/anaconda3/etc/profile.d/conda.sh"
CONDA_CHANGEPS1=false conda activate base
else
# \export NOCONDA_PATH=$PATH
\export PATH="/home/dakar/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda init <<<
export CLHEP_DIR=/home/dakar/CLHEP/2.3.3.2/CLHEP-install/
export CLHEP_INCLUDE_DIR=${CLHEP_DIR}/include/
export CLHEP_LIBRARY=${CLHEP_DIR}/lib/
export LD_LIBRARY_PATH=${CLHEP_LIBRARY}:${LD_LIBRARY_PATH}
export PATH=$CLHEP_DIR/bin/:$PATH
export TOPAS_G4_DATA_DIR=~/G4Data
export LD_LIBRARY_PATH=~/topas/libexternal/:$LD_LIBRARY_PATH
#export LD_LIBRARY_PATH=~/anaconda3/lib/gcc/lib:$LD_LIBRARY_PATH
#CERN ROOT
#export ROOTSYS=/usr/local/root
#export PATH=$ROOTSYS/bin:$PATH
#export PYTHONDIR=$ROOTSYS
#export LD_LIBRARY_PATH=$ROOTSYS/lib:$PYTHONDIR/lib:$ROOTSYS/bindings/pyroot:$LD_LIBRARY_PATH
#export PYTHONPATH=$ROOTSYS/lib:$PYTHONPATH:$ROOTSYS/bindings/pyroot
source ~/Geant4/geant4.10.05.p01-install/bin/geant4.sh
#source ~/Geant4/geant4.10.05.p01-install/share/Geant4-10.5.1/geant4make/geant4make.sh
export NOCONDA_PATH=$PATH
export PATH="/home/dakar/anaconda3/bin:$PATH"
This still hasn't solved the problem. When I run echo $PATH I can still see conda directories:
$ echo $PATH
/home/dakar/anaconda3/bin:/home/dakar/Geant4/geant4.10.05.p01-install/bin:/home/dakar/CLHEP/2.3.3.2/CLHEP-install//bin/:/home/dakar/anaconda3/bin:/home/dakar/anaconda3/condabin:/usr/local/cuda-8.0/bin:/home/dakar/bin:/home/dakar/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Does anybody have any further advice? Would uninstalling Conda itself be a solution.
Thanks for your time.
L
The error message suggests that you are missing libuuid in your linker invocation.
Try to add -luuid to your linker flags.
Does your build system use pkg-config? In this case you could edit /usr/lib/x86_64-linux-gnu/pkgconfig/sm.pc and add -luuid to the Libs-Section.
This looks like a bug in your Linux-Distro.

Using conan to package multiple configurations of preexisting binaries

I have a set of third-party binaries that I am trying to put into a conan package. The binaries are in folders for the build configuration: Linux32, Win32, Win64, Win32.
I have been able to produce a conan package for the Win64 configuration using the following conanfile.py:
from conans import ConanFile
class LibNameConan(ConanFile):
name = "LibName"
version = "1.1.1"
settings = "os", "compiler", "build_type", "arch"
description = "Package for LibName"
url = "None"
license = "None"
def package(self):
self.copy("*", dst="lib", src="lib")
self.copy("*.c", dst="include", src="include", keep_path=False)
def package_info(self):
self.cpp_info.libs = self.collect_libs()
I run the following commands in powershell:
conan install
mkdir pkg
cd pkg
conan package .. --build_folder=../
cd ..
conan export name/testing
conan package_files libname/1.1.1#name/testing
For the Win64 this works as expected. When I repeat the steps with Win32 binaries I do not get a different hash for the package.
I have tried running:
conan install -s arch=x86
However, this still results in the package having the same hash as the x86_64 configuration.
How is the configuration supposed to be set for generating a package from preexisting binaries?
If you are just packaging pre-built binaries, you are fine without the package() method, that is only relevant when building from the recipe:
from conans import ConanFile
class LibNameConan(ConanFile):
name = "LibName"
version = "1.1.1"
settings = "os", "compiler", "build_type", "arch"
description = "Package for LibName"
url = "None"
license = "None"
def package_info(self):
self.cpp_info.libs = self.collect_libs()
Unless there is some important reason you want to package the sources too, do you want them to be able to debug your dependencies too? In that case, please condition it to the build_type.
However this could be mostly irrelevant for your question. As your package doesn't have dependencies and you are not using any generator either, you don't need a conan install, and the settings you use there, have no effect.
You have to specify the settings for your binary configuration when you package_files:
$ conan package_files libname/1.1.1#name/testing # using your default config
$ conan package_files libname/1.1.1#name/testing -s arch=x86 # 32 bits instead of 64
...
Probably the recommended way is to use profiles:
$ conan package_files libname/1.1.1#name/testing # using your default profile
$ conan package_files libname/1.1.1#name/testing -pr=myprofile2
The documentation got recently a re-write, you might want to check: https://docs.conan.io/en/latest/creating_packages/existing_binaries.html