├── .gitignore ├── rustfmt.toml ├── .github └── CODEOWNERS ├── src ├── install │ ├── remote │ │ └── test.rs │ ├── profile.rs │ ├── remote.rs │ ├── build_info.rs │ ├── test.rs │ └── build_info │ │ ├── build_dependency.rs │ │ ├── test.rs │ │ └── build_settings.rs ├── lib.rs ├── util │ └── test.rs ├── build │ └── tests.rs ├── util.rs ├── package │ └── tests.rs ├── build.rs ├── package.rs └── install.rs ├── Cargo.toml ├── LICENSE-MIT ├── test ├── conanbuildinfo1.json ├── conanbuildinfo2.json ├── conanbuildinfo4.json ├── conanbuildinfo3.json └── conanbuildinfo5.json ├── LICENSE-APACHE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | .idea/ 5 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | reorder_imports = true 2 | max_width = 120 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # File auto-generated and managed by Devops 2 | /.github/workflows @devolutions/devops 3 | /.github/randy.yml @devolutions/devops 4 | /.github/CODEOWNERS @devolutions/devops 5 | /.github/scripts/ @devolutions/devops 6 | /.github/dependabot.yml @devolutions/security-managers 7 | -------------------------------------------------------------------------------- /src/install/remote/test.rs: -------------------------------------------------------------------------------- 1 | use super::get_remote_list; 2 | 3 | #[test] 4 | fn test_conan_remote_list() { 5 | let conan_remote_list = get_remote_list(); 6 | if let Ok(conan_remote_list) = conan_remote_list { 7 | assert!(conan_remote_list.len() > 0); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod build; 2 | mod install; 3 | mod package; 4 | mod util; 5 | 6 | // API 7 | pub use build::{BuildCommand, BuildCommandBuilder}; 8 | pub use install::{ 9 | build_info::{BuildDependency, BuildInfo, BuildSettings}, 10 | BuildPolicy, InstallCommand, InstallCommandBuilder, 11 | }; 12 | pub use package::{ConanPackage, PackageCommand, PackageCommandBuilder}; 13 | -------------------------------------------------------------------------------- /src/util/test.rs: -------------------------------------------------------------------------------- 1 | use super::{find_program, find_version}; 2 | 3 | #[test] 4 | fn test_find_program() { 5 | if let Some(path) = find_program() { 6 | println!("Conan path: {}", path.to_str().unwrap()); 7 | } 8 | } 9 | #[test] 10 | fn test_find_version() { 11 | if let Some(version) = find_version() { 12 | println!("Conan version: {}", version); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/install/profile.rs: -------------------------------------------------------------------------------- 1 | use super::ConanInstallError; 2 | use std::process::Command; 3 | 4 | #[allow(dead_code)] 5 | pub fn get_profile_list() -> Result, ConanInstallError> { 6 | let output = Command::new("conan") 7 | .arg("profile") 8 | .arg("list") 9 | .output() 10 | .map_err(ConanInstallError::ConanInstallFailed)?; 11 | 12 | let output_stdout = String::from_utf8(output.stdout).map_err(ConanInstallError::Utf8Error)?; 13 | 14 | Ok(output_stdout.lines().map(|x| x.to_string()).collect()) 15 | } 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "conan" 3 | version = "0.4.2" 4 | readme = "README.md" 5 | license = "MIT/Apache-2.0" 6 | keywords = ["conan", "cmake", "build-dependencies"] 7 | repository = "https://github.com/devolutions/conan-rs" 8 | homepage = "https://github.com/devolutions/conan-rs" 9 | documentation = "https://docs.rs/conan" 10 | authors = ["Marc-André Moreau "] 11 | categories = ["development-tools::build-utils"] 12 | description = """ 13 | A Rust wrapper of the conan C/C++ package manager (conan.io) to simplify usage in build scripts 14 | """ 15 | edition = "2018" 16 | 17 | [dependencies] 18 | regex = "1.0" 19 | indexmap = "1.0" 20 | which = { version = "3.0", default-features = false, features = [] } 21 | serde = { version = "1.0", features = ["derive"] } 22 | serde_json = "1.0" 23 | lazy_static = "1.0" 24 | thiserror = "1.0.50" 25 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /src/build/tests.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_default_build_command() { 5 | let build_command = BuildCommand::default(); 6 | let args = build_command.args().unwrap(); 7 | 8 | let expected = vec!["build", "."]; 9 | 10 | assert_eq!(args, expected); 11 | } 12 | 13 | #[test] 14 | fn test_custom_build_command() { 15 | let build_command = BuildCommandBuilder::new() 16 | .with_recipe_path(PathBuf::from("./recipe")) 17 | .with_build_path(PathBuf::from("./build")) 18 | .with_install_path(PathBuf::from("./install")) 19 | .with_package_path(PathBuf::from("./package")) 20 | .with_source_path(PathBuf::from("./source")) 21 | .should_configure(true) 22 | .should_build(true) 23 | .should_install(true) 24 | .build(); 25 | 26 | let args = build_command.args().unwrap(); 27 | 28 | let expected = vec![ 29 | "build", 30 | "./recipe", 31 | "--build-folder", 32 | "./build", 33 | "--install-folder", 34 | "./install", 35 | "--package-folder", 36 | "./package", 37 | "--source-folder", 38 | "./source", 39 | "--configure", 40 | "--build", 41 | "--install", 42 | ]; 43 | 44 | assert_eq!(args, expected); 45 | } 46 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod test; 3 | 4 | use lazy_static::lazy_static; 5 | use regex::Regex; 6 | use std::env; 7 | use std::path::PathBuf; 8 | use std::process::Command; 9 | 10 | lazy_static! { 11 | static ref REGEX_CONAN_VERSION: Regex = Regex::new(r"version (\d+)\.(\d+).(\d+)$").unwrap(); 12 | } 13 | 14 | pub fn find_program() -> Option { 15 | if let Ok(conan) = env::var("CONAN") { 16 | return Some(PathBuf::from(conan)); 17 | } 18 | which::which("conan").ok() 19 | } 20 | 21 | // NOTE: Will be used in the future 22 | #[allow(dead_code)] 23 | pub fn find_version() -> Option { 24 | let conan_program = find_program()?; 25 | let conan_program = conan_program.as_path().to_str().unwrap().to_string(); 26 | 27 | let output = Command::new(&conan_program).arg("--version").output(); 28 | 29 | // $ conan --version 30 | // Conan version 1.14.3 31 | 32 | if let Ok(output) = output { 33 | let output_stdout = String::from_utf8(output.stdout).unwrap(); 34 | let captures = REGEX_CONAN_VERSION.captures(output_stdout.as_str().trim()).unwrap(); 35 | 36 | let version_major = captures[1].parse::().unwrap(); 37 | let version_minor = captures[2].parse::().unwrap(); 38 | let version_micro = captures[3].parse::().unwrap(); 39 | 40 | let version = format!("{}.{}.{}", version_major, version_minor, version_micro); 41 | 42 | return Some(version); 43 | } 44 | 45 | None 46 | } 47 | -------------------------------------------------------------------------------- /src/package/tests.rs: -------------------------------------------------------------------------------- 1 | use super::PackageCommandBuilder; 2 | use std::path::PathBuf; 3 | 4 | #[test] 5 | fn test_default_args_generation() { 6 | let command = PackageCommandBuilder::new() 7 | .build(); 8 | let args = command.args().expect("Failed to generate args"); 9 | assert_eq!(args, vec!["package", "."]); 10 | } 11 | 12 | #[test] 13 | fn test_successful_args_generation() { 14 | let recipe_path = PathBuf::from("path/to/recipe"); 15 | let build_path = PathBuf::from("path/to/build"); 16 | let install_path = PathBuf::from("path/to/install"); 17 | let package_path = PathBuf::from("path/to/package"); 18 | let source_path = PathBuf::from("path/to/source"); 19 | 20 | let command = PackageCommandBuilder::new() 21 | .with_recipe_path(recipe_path.clone()) 22 | .with_build_path(build_path.clone()) 23 | .with_install_path(install_path.clone()) 24 | .with_package_path(package_path.clone()) 25 | .with_source_path(source_path.clone()) 26 | .build(); 27 | 28 | let args = command.args().expect("Failed to generate args"); 29 | 30 | assert_eq!( 31 | args, 32 | vec![ 33 | "package", 34 | "path/to/recipe", 35 | "--build-folder", 36 | "path/to/build", 37 | "--install-folder", 38 | "path/to/install", 39 | "--package-folder", 40 | "path/to/package", 41 | "--source-folder", 42 | "path/to/source", 43 | ] 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /src/install/remote.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | pub mod test; 3 | 4 | use super::ConanInstallError; 5 | use lazy_static::lazy_static; 6 | use regex::Regex; 7 | use std::fmt; 8 | use std::process::Command; 9 | 10 | lazy_static! { 11 | static ref REGEX_CONAN_REMOTE: Regex = Regex::new(r"(\S+):\s+(\S+)\s+(.*)").unwrap(); 12 | } 13 | 14 | #[derive(Clone)] 15 | pub struct Remote { 16 | pub name: String, 17 | pub url: String, 18 | } 19 | 20 | impl fmt::Debug for Remote { 21 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 22 | write!(f, "{}: {}", self.name, self.url) 23 | } 24 | } 25 | 26 | impl fmt::Display for Remote { 27 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 28 | write!(f, "{}: {}", self.name, self.url) 29 | } 30 | } 31 | 32 | // NOTE: This function will be used later 33 | #[allow(dead_code)] 34 | pub fn get_remote_list() -> Result, ConanInstallError> { 35 | let output = Command::new("conan") 36 | .arg("remote") 37 | .arg("list") 38 | .output() 39 | .expect("failed to execute conan"); 40 | 41 | let output_stdout = String::from_utf8(output.stdout).map_err(ConanInstallError::Utf8Error)?; 42 | 43 | Ok(output_stdout 44 | .lines() 45 | .map(|x| { 46 | let captures = REGEX_CONAN_REMOTE.captures(x.trim()).unwrap(); 47 | Remote { 48 | name: captures[1].to_string(), 49 | url: captures[2].to_string(), 50 | } 51 | }) 52 | .collect()) 53 | } 54 | -------------------------------------------------------------------------------- /test/conanbuildinfo1.json: -------------------------------------------------------------------------------- 1 | { 2 | "deps_env_info": {}, 3 | "deps_user_info": { 4 | "openssl": {} 5 | }, 6 | "dependencies": [ 7 | { 8 | "version": "1.1.1b-2", 9 | "description": "TLS/SSL and crypto library", 10 | "rootpath": "/home/awake/.conan/data/openssl/1.1.1b-2/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6", 11 | "sysroot": "", 12 | "include_paths": [ 13 | "/home/awake/.conan/data/openssl/1.1.1b-2/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/include" 14 | ], 15 | "lib_paths": [ 16 | "/home/awake/.conan/data/openssl/1.1.1b-2/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/lib" 17 | ], 18 | "bin_paths": [], 19 | "build_paths": [ 20 | "/home/awake/.conan/data/openssl/1.1.1b-2/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/" 21 | ], 22 | "res_paths": [], 23 | "libs": [ 24 | "ssl", 25 | "crypto" 26 | ], 27 | "defines": [], 28 | "cflags": [], 29 | "cxxflags": [], 30 | "sharedlinkflags": [], 31 | "exelinkflags": [], 32 | "cppflags": [], 33 | "name": "openssl" 34 | } 35 | ], 36 | "settings": { 37 | "arch": "x86_64", 38 | "arch_build": "x86_64", 39 | "build_type": "Release", 40 | "compiler": "gcc", 41 | "compiler.libcxx": "libstdc++", 42 | "compiler.version": "4.8", 43 | "os": "Linux", 44 | "os_build": "Linux" 45 | }, 46 | "options": { 47 | "openssl": {} 48 | } 49 | } -------------------------------------------------------------------------------- /src/install/build_info.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod test; 3 | 4 | pub mod build_dependency; 5 | pub mod build_settings; 6 | 7 | use std::fs::File; 8 | use std::path::Path; 9 | 10 | use serde::{Deserialize, Serialize}; 11 | 12 | pub use build_dependency::BuildDependency; 13 | pub use build_settings::BuildSettings; 14 | 15 | // conan build info 16 | #[derive(Serialize, Deserialize)] 17 | pub struct BuildInfo { 18 | pub(crate) dependencies: Vec, 19 | pub(crate) settings: BuildSettings, 20 | } 21 | 22 | impl BuildInfo { 23 | pub fn from_str(json: &str) -> Option { 24 | let result = serde_json::from_str(&json); 25 | if let Err(error) = result { 26 | eprintln!("failed to parse conan build info: {:?}", error); 27 | return None; 28 | } 29 | result.ok() 30 | } 31 | 32 | pub fn from_file(path: &Path) -> Option { 33 | if let Ok(json_file) = File::open(path) { 34 | serde_json::from_reader(&json_file).ok() 35 | } else { 36 | None 37 | } 38 | } 39 | 40 | pub fn get_dependency(&self, name: &str) -> Option<&BuildDependency> { 41 | self.dependencies.iter().find(|&x| x.name == name) 42 | } 43 | 44 | pub fn dependencies(&self) -> &Vec { 45 | &self.dependencies 46 | } 47 | 48 | pub fn cargo_emit(&self) { 49 | for dependency in &self.dependencies { 50 | for lib_path in &dependency.lib_paths { 51 | println!("cargo:rustc-link-search=native={}", lib_path); 52 | } 53 | 54 | for lib in &dependency.libs { 55 | println!("cargo:rustc-link-lib={}", lib); 56 | } 57 | 58 | if let Some(syslibs) = &dependency.system_libs { 59 | for syslib in syslibs { 60 | println!("cargo:rustc-link-lib={}", syslib); 61 | } 62 | } 63 | 64 | for include_path in &dependency.include_paths { 65 | println!("cargo:include={}", include_path); 66 | } 67 | 68 | println!("cargo:rerun-if-env-changed=CONAN"); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/install/test.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | build_info::{build_settings::BuildType, BuildSettings}, 3 | BuildPolicy, InstallCommandBuilder, 4 | }; 5 | 6 | #[test] 7 | fn test_install_builder() -> Result<(), Box> { 8 | let build_settings = BuildSettings::new().build_type(BuildType::Release); 9 | let command = InstallCommandBuilder::new() 10 | .with_profile("linux-x86_64") 11 | .build_settings(build_settings) 12 | .build_policy(BuildPolicy::Missing) 13 | .build(); 14 | assert_eq!( 15 | command.args()?, 16 | [ 17 | "install", 18 | "-g", 19 | "json", 20 | "--profile:host", 21 | "linux-x86_64", 22 | "-b", 23 | "missing", 24 | "-s", 25 | "build_type=Release" 26 | ] 27 | ); 28 | 29 | Ok(()) 30 | } 31 | 32 | #[test] 33 | fn test_install_builder_cross() -> Result<(), Box> { 34 | let build_settings = BuildSettings::new().build_type(BuildType::Debug); 35 | let command = InstallCommandBuilder::new() 36 | .with_host_profile("windows-x86_64") 37 | .with_build_profile("linux-x86_64") 38 | .build_settings(build_settings) 39 | .build_policy(BuildPolicy::Always) 40 | .build(); 41 | assert_eq!( 42 | command.args()?, 43 | [ 44 | "install", 45 | "-g", 46 | "json", 47 | "--profile:host", 48 | "windows-x86_64", 49 | "--profile:build", 50 | "linux-x86_64", 51 | "-b", 52 | "-s", 53 | "build_type=Debug" 54 | ] 55 | ); 56 | 57 | Ok(()) 58 | } 59 | 60 | #[test] 61 | fn test_install_builder_with_options() -> Result<(), Box> { 62 | let build_settings = BuildSettings::new().build_type(BuildType::Release); 63 | let command = InstallCommandBuilder::new() 64 | .with_profile("linux-x86_64") 65 | .build_settings(build_settings) 66 | .with_options(&["shared=True", "build_type=Release"]) 67 | .build_policy(BuildPolicy::Missing) 68 | .build(); 69 | assert_eq!( 70 | command.args()?, 71 | [ 72 | "install", 73 | "-g", 74 | "json", 75 | "--profile:host", 76 | "linux-x86_64", 77 | "-b", 78 | "missing", 79 | "-o", 80 | "shared=True", 81 | "-o", 82 | "build_type=Release", 83 | "-s", 84 | "build_type=Release" 85 | ] 86 | ); 87 | 88 | Ok(()) 89 | } 90 | -------------------------------------------------------------------------------- /test/conanbuildinfo2.json: -------------------------------------------------------------------------------- 1 | { 2 | "deps_env_info": {}, 3 | "deps_user_info": { 4 | "curl": {}, 5 | "mbedtls": {} 6 | }, 7 | "dependencies": [ 8 | { 9 | "version": "7.58.0", 10 | "description": "An open source, portable, easy to use, readable and flexible SSL library", 11 | "rootpath": "/home/awake/.conan/data/curl/7.58.0/devolutions/stable/package/6d50802fb93e3f17a5a273d736f7668422d5d7e1", 12 | "sysroot": "", 13 | "include_paths": [ 14 | "/home/awake/.conan/data/curl/7.58.0/devolutions/stable/package/6d50802fb93e3f17a5a273d736f7668422d5d7e1/include" 15 | ], 16 | "lib_paths": [ 17 | "/home/awake/.conan/data/curl/7.58.0/devolutions/stable/package/6d50802fb93e3f17a5a273d736f7668422d5d7e1/lib" 18 | ], 19 | "bin_paths": [], 20 | "build_paths": [ 21 | "/home/awake/.conan/data/curl/7.58.0/devolutions/stable/package/6d50802fb93e3f17a5a273d736f7668422d5d7e1/" 22 | ], 23 | "res_paths": [], 24 | "libs": [ 25 | "curl" 26 | ], 27 | "defines": [], 28 | "cflags": [], 29 | "cxxflags": [], 30 | "sharedlinkflags": [], 31 | "exelinkflags": [], 32 | "cppflags": [], 33 | "name": "curl" 34 | }, 35 | { 36 | "version": "2.4.1", 37 | "description": "An open source, portable, easy to use, readable and flexible SSL library", 38 | "rootpath": "/home/awake/.conan/data/mbedtls/2.4.1/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6", 39 | "sysroot": "", 40 | "include_paths": [ 41 | "/home/awake/.conan/data/mbedtls/2.4.1/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/include" 42 | ], 43 | "lib_paths": [ 44 | "/home/awake/.conan/data/mbedtls/2.4.1/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/lib" 45 | ], 46 | "bin_paths": [], 47 | "build_paths": [ 48 | "/home/awake/.conan/data/mbedtls/2.4.1/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/" 49 | ], 50 | "res_paths": [], 51 | "libs": [ 52 | "mbedtls", 53 | "mbedcrypto", 54 | "mbedx509" 55 | ], 56 | "defines": [], 57 | "cflags": [], 58 | "cxxflags": [], 59 | "sharedlinkflags": [], 60 | "exelinkflags": [], 61 | "cppflags": [], 62 | "name": "mbedtls" 63 | } 64 | ], 65 | "settings": { 66 | "arch": "x86_64", 67 | "arch_build": "x86_64", 68 | "build_type": "Release", 69 | "compiler": "gcc", 70 | "compiler.libcxx": "libstdc++", 71 | "compiler.version": "4.8", 72 | "os": "Linux", 73 | "os_build": "Linux" 74 | }, 75 | "options": { 76 | "curl": {}, 77 | "mbedtls": {} 78 | } 79 | } -------------------------------------------------------------------------------- /test/conanbuildinfo4.json: -------------------------------------------------------------------------------- 1 | { 2 | "deps_env_info": {}, 3 | "deps_user_info": { 4 | "curl": {}, 5 | "mbedtls": {} 6 | }, 7 | "dependencies": [ 8 | { 9 | "version": "7.58.0", 10 | "description": "An open source, portable, easy to use, readable and flexible SSL library", 11 | "rootpath": "/Users/mamoreau/.conan/data/curl/7.58.0/devolutions/stable/package/f79b7367d54a0af59003d63281f21f5c4c5c9a83", 12 | "sysroot": "", 13 | "include_paths": [ 14 | "/Users/mamoreau/.conan/data/curl/7.58.0/devolutions/stable/package/f79b7367d54a0af59003d63281f21f5c4c5c9a83/include" 15 | ], 16 | "lib_paths": [ 17 | "/Users/mamoreau/.conan/data/curl/7.58.0/devolutions/stable/package/f79b7367d54a0af59003d63281f21f5c4c5c9a83/lib" 18 | ], 19 | "bin_paths": [], 20 | "build_paths": [ 21 | "/Users/mamoreau/.conan/data/curl/7.58.0/devolutions/stable/package/f79b7367d54a0af59003d63281f21f5c4c5c9a83/" 22 | ], 23 | "res_paths": [], 24 | "libs": [ 25 | "curl" 26 | ], 27 | "defines": [], 28 | "cflags": [], 29 | "cppflags": [], 30 | "sharedlinkflags": [], 31 | "exelinkflags": [], 32 | "name": "curl" 33 | }, 34 | { 35 | "version": "2.4.1", 36 | "description": "An open source, portable, easy to use, readable and flexible SSL library", 37 | "rootpath": "/Users/mamoreau/.conan/data/mbedtls/2.4.1/devolutions/stable/package/d08730c03d74fe9275d8668c8ea31e5963dce87a", 38 | "sysroot": "", 39 | "include_paths": [ 40 | "/Users/mamoreau/.conan/data/mbedtls/2.4.1/devolutions/stable/package/d08730c03d74fe9275d8668c8ea31e5963dce87a/include" 41 | ], 42 | "lib_paths": [ 43 | "/Users/mamoreau/.conan/data/mbedtls/2.4.1/devolutions/stable/package/d08730c03d74fe9275d8668c8ea31e5963dce87a/lib" 44 | ], 45 | "bin_paths": [], 46 | "build_paths": [ 47 | "/Users/mamoreau/.conan/data/mbedtls/2.4.1/devolutions/stable/package/d08730c03d74fe9275d8668c8ea31e5963dce87a/" 48 | ], 49 | "res_paths": [], 50 | "libs": [ 51 | "mbedtls", 52 | "mbedcrypto", 53 | "mbedx509" 54 | ], 55 | "defines": [], 56 | "cflags": [], 57 | "cppflags": [], 58 | "sharedlinkflags": [], 59 | "exelinkflags": [], 60 | "name": "mbedtls" 61 | } 62 | ], 63 | "settings": { 64 | "arch": "x86_64", 65 | "arch_build": "x86_64", 66 | "build_type": "Release", 67 | "compiler": "clang", 68 | "compiler.libcxx": "libstdc++", 69 | "compiler.version": "3.8", 70 | "os": "Android", 71 | "os.api_level": "21", 72 | "os_build": "Linux" 73 | }, 74 | "options": { 75 | "curl": {}, 76 | "mbedtls": {} 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/install/build_info/build_dependency.rs: -------------------------------------------------------------------------------- 1 | use serde::de::{SeqAccess, Visitor}; 2 | use serde::{Deserialize, Deserializer, Serialize}; 3 | use std::fmt; 4 | 5 | fn deserialize_optional_string_or_string_vec<'de, D>(deserializer: D) -> Result, D::Error> 6 | where 7 | D: Deserializer<'de>, 8 | { 9 | struct JsonStringOrStringVecVisitor; 10 | 11 | impl<'de> Visitor<'de> for JsonStringOrStringVecVisitor { 12 | type Value = Option; 13 | 14 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 15 | formatter.write_str("null, a string, or an array of strings") 16 | } 17 | 18 | fn visit_str(self, v: &str) -> Result { 19 | Ok(Some(v.to_owned())) 20 | } 21 | 22 | fn visit_none(self) -> Result { 23 | Ok(None) 24 | } 25 | 26 | fn visit_some>(self, deserializer: D) -> Result { 27 | deserializer.deserialize_any(JsonStringOrStringVecVisitor) 28 | } 29 | 30 | fn visit_seq>(self, mut seq: A) -> Result { 31 | let mut concatenated = String::new(); 32 | while let Some(elem) = seq.next_element::()? { 33 | concatenated += &elem; 34 | } 35 | 36 | Ok(Some(concatenated)) 37 | } 38 | } 39 | 40 | deserializer.deserialize_option(JsonStringOrStringVecVisitor) 41 | } 42 | 43 | /// A build dependency. 44 | #[derive(Serialize, Deserialize)] 45 | pub struct BuildDependency { 46 | pub(crate) version: String, 47 | #[serde(deserialize_with = "deserialize_optional_string_or_string_vec")] 48 | pub(crate) description: Option, 49 | pub(crate) rootpath: String, 50 | pub(crate) sysroot: String, 51 | pub(crate) include_paths: Vec, 52 | pub(crate) lib_paths: Vec, 53 | pub(crate) bin_paths: Vec, 54 | pub(crate) build_paths: Vec, 55 | pub(crate) res_paths: Vec, 56 | pub(crate) libs: Vec, 57 | pub(crate) system_libs: Option>, 58 | pub(crate) defines: Vec, 59 | pub(crate) cflags: Vec, 60 | pub(crate) cxxflags: Option>, 61 | pub(crate) sharedlinkflags: Vec, 62 | pub(crate) exelinkflags: Vec, 63 | pub(crate) cppflags: Option>, 64 | pub(crate) name: String, 65 | } 66 | 67 | impl BuildDependency { 68 | pub fn get_root_dir(&self) -> Option<&str> { 69 | Some(self.rootpath.as_str()) 70 | } 71 | 72 | pub fn get_library_dir(&self) -> Option<&str> { 73 | self.lib_paths.get(0).map(|x| &**x) 74 | } 75 | 76 | pub fn get_include_dirs(&self) -> Vec<&str> { 77 | self.include_paths.iter().map(|x| &**x).collect() 78 | } 79 | 80 | pub fn get_binary_dir(&self) -> Option<&str> { 81 | self.bin_paths.get(0).map(|x| &**x) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/conanbuildinfo3.json: -------------------------------------------------------------------------------- 1 | { 2 | "deps_env_info": {}, 3 | "deps_user_info": { 4 | "curl": {}, 5 | "mbedtls": {} 6 | }, 7 | "dependencies": [ 8 | { 9 | "version": "7.58.0", 10 | "description": "An open source, portable, easy to use, readable and flexible SSL library", 11 | "rootpath": "C:\\Users\\Administrator\\.conan\\data\\curl\\7.58.0\\devolutions\\stable\\package\\dd7f174cf517f55a3df023a7c0d0636bb8248008", 12 | "sysroot": "", 13 | "include_paths": [ 14 | "C:\\Users\\Administrator\\.conan\\data\\curl\\7.58.0\\devolutions\\stable\\package\\dd7f174cf517f55a3df023a7c0d0636bb8248008\\include" 15 | ], 16 | "lib_paths": [ 17 | "C:\\Users\\Administrator\\.conan\\data\\curl\\7.58.0\\devolutions\\stable\\package\\dd7f174cf517f55a3df023a7c0d0636bb8248008\\lib" 18 | ], 19 | "bin_paths": [], 20 | "build_paths": [ 21 | "C:\\Users\\Administrator\\.conan\\data\\curl\\7.58.0\\devolutions\\stable\\package\\dd7f174cf517f55a3df023a7c0d0636bb8248008\\" 22 | ], 23 | "res_paths": [], 24 | "libs": [ 25 | "libcurl", 26 | "ncrypt" 27 | ], 28 | "defines": [], 29 | "cflags": [], 30 | "cxxflags": [], 31 | "sharedlinkflags": [], 32 | "exelinkflags": [], 33 | "cppflags": [], 34 | "name": "curl" 35 | }, 36 | { 37 | "version": "2.4.1", 38 | "description": "An open source, portable, easy to use, readable and flexible SSL library", 39 | "rootpath": "C:\\Users\\Administrator\\.conan\\data\\mbedtls\\2.4.1\\devolutions\\stable\\package\\df81ad20137149d7a51276fd3e24009b45e5964a", 40 | "sysroot": "", 41 | "include_paths": [ 42 | "C:\\Users\\Administrator\\.conan\\data\\mbedtls\\2.4.1\\devolutions\\stable\\package\\df81ad20137149d7a51276fd3e24009b45e5964a\\include" 43 | ], 44 | "lib_paths": [ 45 | "C:\\Users\\Administrator\\.conan\\data\\mbedtls\\2.4.1\\devolutions\\stable\\package\\df81ad20137149d7a51276fd3e24009b45e5964a\\lib" 46 | ], 47 | "bin_paths": [], 48 | "build_paths": [ 49 | "C:\\Users\\Administrator\\.conan\\data\\mbedtls\\2.4.1\\devolutions\\stable\\package\\df81ad20137149d7a51276fd3e24009b45e5964a\\" 50 | ], 51 | "res_paths": [], 52 | "libs": [ 53 | "mbedtls", 54 | "mbedcrypto", 55 | "mbedx509" 56 | ], 57 | "defines": [], 58 | "cflags": [], 59 | "cxxflags": [], 60 | "sharedlinkflags": [], 61 | "exelinkflags": [], 62 | "cppflags": [], 63 | "name": "mbedtls" 64 | } 65 | ], 66 | "settings": { 67 | "arch": "x86_64", 68 | "arch_build": "x86_64", 69 | "build_type": "Release", 70 | "compiler": "Visual Studio", 71 | "compiler.runtime": "MT", 72 | "compiler.version": "14", 73 | "os": "Windows", 74 | "os_build": "Windows" 75 | }, 76 | "options": { 77 | "curl": {}, 78 | "mbedtls": {} 79 | } 80 | } -------------------------------------------------------------------------------- /src/install/build_info/test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_conan_build_info() { 5 | let build_info = BuildInfo::from_str(include_str!("../../../test/conanbuildinfo1.json")).unwrap(); 6 | 7 | let openssl = build_info.get_dependency("openssl").unwrap(); 8 | assert_eq!(openssl.get_binary_dir(), None); 9 | let openssl_dir = openssl.get_root_dir().unwrap(); 10 | let openssl_lib_dir = openssl.get_library_dir().unwrap(); 11 | let openssl_inc_dir = openssl.get_include_dirs(); 12 | assert_eq!( 13 | openssl_dir, 14 | "/home/awake/.conan/data/openssl/1.1.1b-2/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6" 15 | ); 16 | assert_eq!(openssl_lib_dir, "/home/awake/.conan/data/openssl/1.1.1b-2/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/lib"); 17 | assert_eq!(openssl_inc_dir.first().unwrap().to_owned(), "/home/awake/.conan/data/openssl/1.1.1b-2/devolutions/stable/package/de9c231f84c85def9df09875e1785a1319fa8cb6/include"); 18 | 19 | let dependencies = build_info.dependencies(); 20 | assert_eq!(dependencies.len(), 1); 21 | 22 | let settings = build_info.settings; 23 | assert_eq!(settings.arch, Some("x86_64".to_string())); 24 | assert_eq!(settings.arch_build, Some("x86_64".to_string())); 25 | assert_eq!(settings.build_type, Some("Release".to_string())); 26 | assert_eq!(settings.compiler, Some("gcc".to_string())); 27 | assert_eq!(settings.compiler_libcxx, Some("libstdc++".to_string())); 28 | assert_eq!(settings.compiler_version, Some("4.8".to_string())); 29 | assert_eq!(settings.os, Some("Linux".to_string())); 30 | assert_eq!(settings.os_build, Some("Linux".to_string())); 31 | 32 | let build_info = BuildInfo::from_str(include_str!("../../../test/conanbuildinfo2.json")).unwrap(); 33 | 34 | let curl = build_info.get_dependency("curl").unwrap(); 35 | assert_eq!(curl.version, "7.58.0"); 36 | 37 | let mbedtls = build_info.get_dependency("mbedtls").unwrap(); 38 | assert_eq!(mbedtls.libs, ["mbedtls", "mbedcrypto", "mbedx509"]); 39 | 40 | let dependencies = build_info.dependencies(); 41 | assert_eq!(dependencies.len(), 2); 42 | 43 | let build_info = BuildInfo::from_str(include_str!("../../../test/conanbuildinfo3.json")).unwrap(); 44 | 45 | let dependencies = build_info.dependencies(); 46 | assert_eq!(dependencies.len(), 2); 47 | 48 | let settings = build_info.settings; 49 | assert_eq!(settings.compiler, Some("Visual Studio".to_string())); 50 | 51 | let build_info = BuildInfo::from_str(include_str!("../../../test/conanbuildinfo4.json")).unwrap(); 52 | let dependencies = build_info.dependencies(); 53 | assert_eq!(dependencies.len(), 2); 54 | 55 | let settings = build_info.settings; 56 | assert_eq!(settings.compiler, Some("clang".to_string())); 57 | } 58 | 59 | #[test] 60 | fn test_conan_build_info_syslibs() { 61 | let build_info = BuildInfo::from_str(include_str!("../../../test/conanbuildinfo5.json")).unwrap(); 62 | let dependencies = build_info.dependencies(); 63 | assert_eq!(dependencies.len(), 10); 64 | 65 | let libsystemd = build_info.get_dependency("libsystemd").unwrap(); 66 | assert_eq!(libsystemd.libs, ["systemd"]); 67 | 68 | let system_libs = libsystemd.system_libs.as_ref().unwrap().as_slice(); 69 | assert_eq!(system_libs, ["rt", "pthread", "dl"]); 70 | } 71 | 72 | #[test] 73 | fn test_cargo_build_info() { 74 | let build_info = BuildInfo::from_str(include_str!("../../../test/conanbuildinfo1.json")).unwrap(); 75 | build_info.cargo_emit(); 76 | } 77 | 78 | #[test] 79 | fn test_cargo_build_info_syslibs() { 80 | let build_info = BuildInfo::from_str(include_str!("../../../test/conanbuildinfo5.json")).unwrap(); 81 | build_info.cargo_emit(); 82 | } 83 | -------------------------------------------------------------------------------- /src/build.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests; 3 | 4 | use std::{ 5 | path::PathBuf, 6 | process::{Command, ExitStatus}, 7 | }; 8 | use thiserror::Error; 9 | 10 | use crate::util::find_program; 11 | 12 | #[derive(Debug, Error)] 13 | pub enum ConanBuildError {} 14 | 15 | /// A command for building a Conan package. 16 | pub struct BuildCommand { 17 | recipe_path: Option, 18 | build_path: Option, 19 | install_path: Option, 20 | package_path: Option, 21 | source_path: Option, 22 | should_configure: bool, 23 | should_build: bool, 24 | should_install: bool, 25 | } 26 | 27 | /// Builder pattern for creating a `BuildCommand` 28 | #[derive(Default)] 29 | pub struct BuildCommandBuilder { 30 | recipe_path: Option, 31 | build_path: Option, 32 | install_path: Option, 33 | package_path: Option, 34 | source_path: Option, 35 | should_configure: bool, 36 | should_build: bool, 37 | should_install: bool, 38 | } 39 | 40 | impl Default for BuildCommand { 41 | fn default() -> Self { 42 | BuildCommand { 43 | recipe_path: Some(PathBuf::from(".")), 44 | build_path: None, 45 | install_path: None, 46 | package_path: None, 47 | source_path: None, 48 | should_configure: false, 49 | should_build: false, 50 | should_install: false, 51 | } 52 | } 53 | } 54 | 55 | impl BuildCommandBuilder { 56 | pub fn new() -> BuildCommandBuilder { 57 | BuildCommandBuilder::default() 58 | } 59 | 60 | pub fn with_recipe_path(mut self, recipe_path: PathBuf) -> Self { 61 | self.recipe_path = Some(recipe_path); 62 | self 63 | } 64 | 65 | pub fn with_build_path(mut self, build_path: PathBuf) -> Self { 66 | self.build_path = Some(build_path); 67 | self 68 | } 69 | 70 | pub fn with_install_path(mut self, install_path: PathBuf) -> Self { 71 | self.install_path = Some(install_path); 72 | self 73 | } 74 | 75 | pub fn with_package_path(mut self, package_path: PathBuf) -> Self { 76 | self.package_path = Some(package_path); 77 | self 78 | } 79 | 80 | pub fn with_source_path(mut self, source_path: PathBuf) -> Self { 81 | self.source_path = Some(source_path); 82 | self 83 | } 84 | 85 | pub fn should_configure(mut self, should_configure: bool) -> Self { 86 | self.should_configure = should_configure; 87 | self 88 | } 89 | 90 | pub fn should_build(mut self, should_build: bool) -> Self { 91 | self.should_build = should_build; 92 | self 93 | } 94 | 95 | pub fn should_install(mut self, should_install: bool) -> Self { 96 | self.should_install = should_install; 97 | self 98 | } 99 | 100 | pub fn build(self) -> BuildCommand { 101 | BuildCommand { 102 | recipe_path: self.recipe_path, 103 | build_path: self.build_path, 104 | install_path: self.install_path, 105 | package_path: self.package_path, 106 | source_path: self.source_path, 107 | should_configure: self.should_configure, 108 | should_build: self.should_build, 109 | should_install: self.should_install, 110 | } 111 | } 112 | } 113 | 114 | impl BuildCommand { 115 | pub fn args(&self) -> Result, ConanBuildError> { 116 | let mut args: Vec<&str> = Vec::new(); 117 | 118 | // NOTE: Here self.recipe_path is guaranteed to be Some 119 | args.extend(&["build", self.recipe_path.as_ref().unwrap().to_str().unwrap()]); 120 | 121 | if let Some(build_path) = &self.build_path { 122 | args.extend(&["--build-folder", build_path.to_str().unwrap()]); 123 | } 124 | 125 | if let Some(install_path) = &self.install_path { 126 | args.extend(&["--install-folder", install_path.to_str().unwrap()]); 127 | } 128 | 129 | if let Some(package_path) = &self.package_path { 130 | args.extend(&["--package-folder", package_path.to_str().unwrap()]); 131 | } 132 | 133 | if let Some(source_path) = &self.source_path { 134 | args.extend(&["--source-folder", source_path.to_str().unwrap()]); 135 | } 136 | 137 | if self.should_configure { 138 | args.push("--configure"); 139 | } 140 | 141 | if self.should_build { 142 | args.push("--build"); 143 | } 144 | 145 | if self.should_install { 146 | args.push("--install"); 147 | } 148 | 149 | Ok(args.iter().map(|s| s.to_string()).collect()) 150 | } 151 | 152 | pub fn run(&self) -> Option { 153 | let args = self.args().ok()?; 154 | let conan_bin = find_program()?; 155 | let mut command = Command::new(conan_bin); 156 | Some(command.args(args).status().ok()?) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/install/build_info/build_settings.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | use serde::{Deserialize, Serialize}; 4 | 5 | /// Conan build type 6 | #[allow(dead_code)] 7 | #[derive(Clone, PartialEq)] 8 | pub enum BuildType { 9 | None, 10 | Debug, 11 | Release, 12 | RelWithDebInfo, 13 | MinSizeRel, 14 | } 15 | 16 | impl ToString for BuildType { 17 | fn to_string(&self) -> String { 18 | self.as_str().to_string() 19 | } 20 | } 21 | 22 | impl BuildType { 23 | pub fn as_str(&self) -> &str { 24 | match self { 25 | &BuildType::None => "None", 26 | &BuildType::Debug => "Debug", 27 | &BuildType::Release => "Release", 28 | &BuildType::RelWithDebInfo => "RelWithDebInfo", 29 | &BuildType::MinSizeRel => "MinSizeRel", 30 | } 31 | } 32 | } 33 | 34 | /// Conan build settings 35 | #[derive(Serialize, Deserialize)] 36 | pub struct BuildSettings { 37 | pub(crate) arch: Option, 38 | pub(crate) arch_build: Option, 39 | pub(crate) build_type: Option, 40 | pub(crate) compiler: Option, 41 | #[serde(rename = "compiler.libcxx")] 42 | pub(crate) compiler_libcxx: Option, 43 | #[serde(rename = "compiler.version")] 44 | pub(crate) compiler_version: Option, 45 | pub(crate) os: Option, 46 | pub(crate) os_build: Option, 47 | } 48 | 49 | impl Default for BuildSettings { 50 | fn default() -> Self { 51 | Self::new() 52 | } 53 | } 54 | 55 | impl BuildSettings { 56 | pub fn new() -> Self { 57 | Self { 58 | arch: None, 59 | arch_build: None, 60 | build_type: None, 61 | compiler: None, 62 | compiler_libcxx: None, 63 | compiler_version: None, 64 | os: None, 65 | os_build: None, 66 | } 67 | } 68 | 69 | pub fn args(&self) -> Vec { 70 | let mut settings = Vec::new(); 71 | 72 | if let Some(arch) = &self.arch { 73 | settings.push(format!("{}={}", "arch", arch)); 74 | } 75 | 76 | if let Some(arch_build) = &self.arch_build { 77 | settings.push(format!("{}={}", "arch_build", arch_build)); 78 | } 79 | 80 | if let Some(build_type) = self.build_type.clone().or_else(|| self.detect_build_type()) { 81 | settings.push(format!("{}={}", "build_type", build_type)); 82 | } 83 | 84 | if let Some(compiler) = &self.compiler { 85 | settings.push(format!("{}={}", "compiler", compiler)); 86 | } 87 | 88 | if let Some(compiler_libcxx) = &self.compiler_libcxx { 89 | settings.push(format!("{}={}", "compiler.libcxx", compiler_libcxx)); 90 | } 91 | 92 | if let Some(compiler_version) = &self.compiler_version { 93 | settings.push(format!("{}={}", "compiler.version", compiler_version)); 94 | } 95 | 96 | if let Some(os) = &self.os { 97 | settings.push(format!("{}={}", "os", os)); 98 | } 99 | 100 | if let Some(os_build) = &self.os_build { 101 | settings.push(format!("{}={}", "os_build", os_build)); 102 | } 103 | 104 | settings 105 | .iter() 106 | .map(|x| ["-s".to_string(), x.clone()]) 107 | .collect::>() 108 | .concat() 109 | } 110 | 111 | pub fn arch(mut self, arch: String) -> Self { 112 | self.arch = Some(arch); 113 | self 114 | } 115 | 116 | pub fn arch_build(mut self, arch_build: String) -> Self { 117 | self.arch_build = Some(arch_build); 118 | self 119 | } 120 | 121 | pub fn build_type(mut self, build_type: T) -> Self { 122 | self.build_type = Some(build_type.to_string()); 123 | self 124 | } 125 | 126 | fn detect_build_type(&self) -> Option { 127 | if self.build_type.is_some() { 128 | return self.build_type.clone(); 129 | } else if let Ok(profile) = env::var("PROFILE") { 130 | return match profile.as_str() { 131 | "debug" => Some("Debug".into()), 132 | "release" => Some("Release".into()), 133 | _ => None, 134 | }; 135 | } 136 | None 137 | } 138 | 139 | pub fn compiler(mut self, compiler: String) -> Self { 140 | self.compiler = Some(compiler); 141 | self 142 | } 143 | 144 | pub fn compiler_libcxx(mut self, compiler_libcxx: String) -> Self { 145 | self.compiler_libcxx = Some(compiler_libcxx); 146 | self 147 | } 148 | 149 | pub fn compiler_version(mut self, compiler_version: String) -> Self { 150 | self.compiler_version = Some(compiler_version); 151 | self 152 | } 153 | 154 | pub fn os(mut self, os: String) -> Self { 155 | self.os = Some(os); 156 | self 157 | } 158 | 159 | pub fn os_build(mut self, os_build: String) -> Self { 160 | self.os_build = Some(os_build); 161 | self 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/package.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests; 3 | 4 | use super::util::find_program; 5 | use std::fs; 6 | use std::path::PathBuf; 7 | use std::process::Command; 8 | use std::process::ExitStatus; 9 | use thiserror::Error; 10 | 11 | #[derive(Debug, Error)] 12 | pub enum ConanPackageError { 13 | #[error("The recipe path is missing")] 14 | MissingRecipePath, 15 | 16 | #[error("Invalid Unicode in path")] 17 | InvalidUnicodeInPath, 18 | 19 | #[error("Conan binary not found")] 20 | ConanNotFound, 21 | 22 | #[error("Command execution failed")] 23 | CommandExecutionFailed, 24 | 25 | #[error("I/O error: {0}")] 26 | Io(#[from] std::io::Error), 27 | 28 | #[error("Invalid file name: {0}")] 29 | InvalidFileName(String), 30 | 31 | #[error("Other error: {0}")] 32 | Other(String), 33 | } 34 | 35 | /// Thin Wrapper around binary packages that contain libraries and headers 36 | pub struct ConanPackage { 37 | path: PathBuf, 38 | } 39 | 40 | /// "conan package" command runner 41 | #[derive(Default)] 42 | pub struct PackageCommand { 43 | build_path: Option, 44 | install_path: Option, 45 | package_path: Option, 46 | source_path: Option, 47 | recipe_path: Option, 48 | } 49 | 50 | impl Default for PackageCommandBuilder { 51 | fn default() -> Self { 52 | PackageCommandBuilder { 53 | build_path: None, 54 | install_path: None, 55 | package_path: None, 56 | source_path: None, 57 | recipe_path: Some(PathBuf::from(".")), 58 | } 59 | } 60 | } 61 | 62 | /// Command arguments builder for "conan package" 63 | pub struct PackageCommandBuilder { 64 | build_path: Option, 65 | install_path: Option, 66 | package_path: Option, 67 | source_path: Option, 68 | recipe_path: Option, 69 | } 70 | 71 | impl PackageCommandBuilder { 72 | pub fn new() -> Self { 73 | PackageCommandBuilder::default() 74 | } 75 | 76 | pub fn with_build_path(mut self, build_path: PathBuf) -> Self { 77 | self.build_path = Some(build_path); 78 | self 79 | } 80 | 81 | pub fn with_install_path(mut self, install_path: PathBuf) -> Self { 82 | self.install_path = Some(install_path); 83 | self 84 | } 85 | 86 | pub fn with_package_path(mut self, package_path: PathBuf) -> Self { 87 | self.package_path = Some(package_path); 88 | self 89 | } 90 | 91 | pub fn with_source_path(mut self, source_path: PathBuf) -> Self { 92 | self.source_path = Some(source_path); 93 | self 94 | } 95 | 96 | pub fn with_recipe_path(mut self, recipe_path: PathBuf) -> Self { 97 | self.recipe_path = Some(recipe_path); 98 | self 99 | } 100 | 101 | pub fn build(self) -> PackageCommand { 102 | PackageCommand { 103 | build_path: self.build_path, 104 | install_path: self.install_path, 105 | package_path: self.package_path, 106 | source_path: self.source_path, 107 | recipe_path: self.recipe_path, 108 | } 109 | } 110 | } 111 | 112 | impl PackageCommand { 113 | pub fn args(&self) -> Result, ConanPackageError> { 114 | let mut args: Vec<&str> = Vec::new(); 115 | 116 | args.extend(&["package", self.recipe_path.as_ref().unwrap().to_str().unwrap()]); 117 | 118 | if let Some(build_path) = &self.build_path { 119 | args.extend(&[ 120 | "--build-folder", 121 | build_path.to_str().ok_or(ConanPackageError::InvalidUnicodeInPath)?, 122 | ]); 123 | } 124 | 125 | if let Some(install_path) = &self.install_path { 126 | args.extend(&[ 127 | "--install-folder", 128 | install_path.to_str().ok_or(ConanPackageError::InvalidUnicodeInPath)?, 129 | ]); 130 | } 131 | 132 | if let Some(package_path) = &self.package_path { 133 | args.extend(&[ 134 | "--package-folder", 135 | package_path.to_str().ok_or(ConanPackageError::InvalidUnicodeInPath)?, 136 | ]); 137 | } 138 | 139 | if let Some(source_path) = &self.source_path { 140 | args.extend(&[ 141 | "--source-folder", 142 | source_path.to_str().ok_or(ConanPackageError::InvalidUnicodeInPath)?, 143 | ]); 144 | } 145 | 146 | Ok(args.iter().map(|s| s.to_string()).collect()) 147 | } 148 | 149 | pub fn run(&self) -> Option { 150 | let args = self.args().ok()?; 151 | let conan_bin = find_program()?; 152 | let mut command = Command::new(conan_bin); 153 | Some(command.args(args).status().ok()?) 154 | } 155 | } 156 | 157 | impl Default for ConanPackage { 158 | fn default() -> Self { 159 | ConanPackage { 160 | path: PathBuf::from("./package/"), 161 | } 162 | } 163 | } 164 | 165 | impl ConanPackage { 166 | pub fn new(path: PathBuf) -> Self { 167 | ConanPackage { path } 168 | } 169 | 170 | pub fn emit_cargo_libs_linkage(&self, libs_dir: PathBuf) -> Result<(), ConanPackageError> { 171 | let libs_dir_path = self.path.join(libs_dir); 172 | 173 | let entries = fs::read_dir(libs_dir_path.clone())?; 174 | 175 | for entry in entries { 176 | let lib_path = entry?.path(); 177 | if lib_path.is_file() { 178 | let lib_name = lib_path 179 | .file_stem() 180 | .and_then(|n| n.to_str()) 181 | .ok_or_else(|| ConanPackageError::InvalidFileName(lib_path.display().to_string()))?; 182 | 183 | let lib_name = if lib_name.starts_with("lib") { 184 | &lib_name[3..] 185 | } else { 186 | lib_name 187 | }; 188 | 189 | if let Some(lib_suffix) = lib_path.extension().and_then(|s| s.to_str()) { 190 | let lib_type = match lib_suffix { 191 | "so" | "dll" | "dylib" => "dylib", 192 | "a" | "lib" => "static", 193 | _ => continue, 194 | }; 195 | println!("cargo:rustc-link-lib={}={}", lib_type, lib_name); 196 | } 197 | } 198 | } 199 | println!("cargo:rustc-link-search=native={}", libs_dir_path.display()); 200 | 201 | Ok(()) 202 | } 203 | 204 | pub fn emit_cargo_rpath_linkage(&self, f: F) 205 | where 206 | F: Fn(&PathBuf) -> PathBuf, 207 | { 208 | println!("cargo:rustc-link-arg=-Wl,-rpath={}", f(&self.path).display()); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/install.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod test; 3 | 4 | pub mod build_info; 5 | 6 | mod profile; 7 | mod remote; 8 | 9 | use crate::util::find_program; 10 | use std::env; 11 | use std::path::{Path, PathBuf}; 12 | use std::process::Command; 13 | use thiserror::Error; 14 | 15 | use build_info::{build_settings::BuildSettings, BuildInfo}; 16 | 17 | #[derive(Debug, Error)] 18 | pub enum ConanInstallError { 19 | #[error("Conan not found")] 20 | ConanNotFound, 21 | #[error("Failed to execute Conan: {0}")] 22 | ConanInstallFailed(#[from] std::io::Error), 23 | #[error("Install directory not found")] 24 | ConanInstallDirNotFound, 25 | #[error("Failed to convert output to UTF-8: {0}")] 26 | Utf8Error(#[from] std::string::FromUtf8Error), 27 | #[error("{0}")] 28 | Other(String), 29 | } 30 | 31 | /// Conan build policy 32 | #[derive(Clone, PartialEq)] 33 | pub enum BuildPolicy { 34 | Never, 35 | Always, 36 | Missing, 37 | Outdated, 38 | } 39 | 40 | /// "conan install" command runner 41 | pub struct InstallCommand<'a> { 42 | profile_host: Option<&'a str>, 43 | profile_build: Option<&'a str>, 44 | remote: Option<&'a str>, 45 | build_settings: BuildSettings, 46 | build_options: Option>, 47 | build_policy: Option, 48 | recipe_path: Option, 49 | output_dir: Option, 50 | update_check: bool, 51 | } 52 | 53 | /// "conan install" command arguments builder 54 | #[derive(Default)] 55 | pub struct InstallCommandBuilder<'a> { 56 | profile_host: Option<&'a str>, 57 | profile_build: Option<&'a str>, 58 | remote: Option<&'a str>, 59 | build_settings: Option, 60 | build_options: Option>, 61 | build_policy: Option, 62 | recipe_path: Option, 63 | output_dir: Option, 64 | update_check: bool, 65 | } 66 | 67 | impl<'a> InstallCommandBuilder<'a> { 68 | pub fn new() -> InstallCommandBuilder<'a> { 69 | InstallCommandBuilder::default() 70 | } 71 | 72 | /// Apply the specified profile to the host machine. 73 | pub fn with_profile(self, profile: &'a str) -> Self { 74 | self.with_host_profile(profile) 75 | } 76 | 77 | /// Apply the specified profile to the host machine. 78 | pub fn with_host_profile(mut self, profile: &'a str) -> Self { 79 | self.profile_host = Some(profile); 80 | self 81 | } 82 | 83 | /// Apply the specified profile to the build machine. 84 | pub fn with_build_profile(mut self, profile: &'a str) -> Self { 85 | self.profile_build = Some(profile); 86 | self 87 | } 88 | 89 | pub fn with_remote(mut self, remote: &'a str) -> Self { 90 | self.remote = Some(remote); 91 | self 92 | } 93 | 94 | pub fn build_settings(mut self, build_settings: BuildSettings) -> Self { 95 | self.build_settings = Some(build_settings); 96 | self 97 | } 98 | 99 | pub fn build_policy(mut self, build_policy: BuildPolicy) -> Self { 100 | self.build_policy = Some(build_policy); 101 | self 102 | } 103 | 104 | pub fn with_options(mut self, opts: &[&'a str]) -> Self { 105 | if self.build_options.is_none() { 106 | self.build_options = Some(Vec::new()); 107 | } 108 | // NOTE: Here self.build_options is guaranteed to be Some 109 | self.build_options.as_mut().unwrap().extend(opts); 110 | self 111 | } 112 | 113 | pub fn recipe_path(mut self, recipe_path: &Path) -> Self { 114 | self.recipe_path = Some(recipe_path.to_path_buf()); 115 | self 116 | } 117 | 118 | pub fn output_dir(mut self, output_dir: &Path) -> Self { 119 | self.output_dir = Some(output_dir.to_path_buf()); 120 | self 121 | } 122 | 123 | pub fn update_check(mut self) -> Self { 124 | self.update_check = true; 125 | self 126 | } 127 | 128 | pub fn build(self) -> InstallCommand<'a> { 129 | InstallCommand { 130 | profile_host: self.profile_host, 131 | profile_build: self.profile_build, 132 | remote: self.remote, 133 | build_settings: self.build_settings.unwrap_or_default(), 134 | build_options: self.build_options, 135 | build_policy: self.build_policy, 136 | recipe_path: self.recipe_path, 137 | output_dir: self.output_dir, 138 | update_check: self.update_check, 139 | } 140 | } 141 | } 142 | 143 | impl<'a> InstallCommand<'a> { 144 | pub fn args(&self) -> Result, ConanInstallError> { 145 | let mut args: Vec<&str> = Vec::new(); 146 | 147 | args.push("install"); 148 | args.extend(&["-g", "json"]); 149 | 150 | if let Some(profile) = &self.profile_host { 151 | args.extend(&["--profile:host", profile]); 152 | } 153 | 154 | if let Some(profile) = &self.profile_build { 155 | args.extend(&["--profile:build", profile]); 156 | } 157 | 158 | if let Some(remote) = &self.remote { 159 | args.extend(&["-r", remote]); 160 | } 161 | 162 | if self.update_check { 163 | args.push("-u"); 164 | } 165 | 166 | if let Some(build_policy) = &self.build_policy { 167 | match build_policy { 168 | BuildPolicy::Never => { 169 | args.extend(&["-b", "never"]); 170 | } 171 | BuildPolicy::Always => { 172 | args.extend(&["-b"]); 173 | } 174 | BuildPolicy::Missing => { 175 | args.extend(&["-b", "missing"]); 176 | } 177 | BuildPolicy::Outdated => { 178 | args.extend(&["-b", "outdated"]); 179 | } 180 | } 181 | } 182 | 183 | if let Some(build_options) = &self.build_options { 184 | args.extend(build_options.iter().map(|x| ["-o", *x]).flatten()); 185 | } 186 | 187 | let output_dir = self.output_dir(); 188 | if let Some(output_dir) = &output_dir { 189 | let current_dir = env::current_dir()?.to_path_buf(); 190 | if output_dir != ¤t_dir { 191 | args.extend(&["-if", output_dir.to_str().unwrap()]); 192 | } 193 | } 194 | 195 | let build_settings_args = self.build_settings.args(); 196 | args.extend(build_settings_args.iter().map(String::as_str)); 197 | 198 | if let Some(recipe_path) = &self.recipe_path { 199 | args.push(recipe_path.to_str().unwrap()); 200 | } 201 | 202 | Ok(args.iter().map(|x| x.to_string()).collect()) 203 | } 204 | 205 | pub fn output_dir(&self) -> Option { 206 | self.output_dir 207 | .clone() 208 | .or_else(|| env::var("OUT_DIR").ok().map(PathBuf::from)) 209 | .or_else(|| env::current_dir().ok()) 210 | } 211 | 212 | pub fn output_file(&self) -> Option { 213 | let mut output_file = self.output_dir()?; 214 | output_file.push("conanbuildinfo.json"); 215 | Some(output_file) 216 | } 217 | 218 | pub fn generate(&self) -> Option { 219 | let args = self.args().ok()?; 220 | let program = find_program()?; 221 | let output_file = self.output_file()?; 222 | let mut command = Command::new(program); 223 | if command.args(args).status().is_ok() { 224 | BuildInfo::from_file(output_file.as_path()) 225 | } else { 226 | None 227 | } 228 | } 229 | 230 | pub fn generate_if_no_buildinfo(&self) -> Option { 231 | BuildInfo::from_file(self.output_file()?.as_path()).or_else(|| self.generate()) 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

conan-rs

6 | 7 |

A Rust wrapper of the conan C/C++ package manager (conan.io) to simplify usage in build scripts

8 | 9 | 17 | 18 | ## TLDR 19 | 20 | Add conan to the build-dependencies section: 21 | 22 | ```bash 23 | cargo add conan --build 24 | ``` 25 | 26 | Modify the project `build.rs` script to invoke cargo and emit the conan build 27 | information automatically. Using conan profiles with names derived from the 28 | cargo target information is recommended: 29 | 30 | NOTE: The conan executable is assumed to be `conan` unless the `CONAN` 31 | environment variable is set. 32 | 33 | ```rust 34 | use std::path::Path; 35 | use std::env; 36 | 37 | use conan::*; 38 | 39 | fn main() { 40 | let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); 41 | let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); 42 | let conan_profile = format!("{}-{}", target_os, target_arch); 43 | 44 | let command = InstallCommandBuilder::new() 45 | .with_profile(&conan_profile) 46 | .build_policy(BuildPolicy::Missing) 47 | .with_option("sign", "True") 48 | .recipe_path(Path::new("conanfile.txt")) 49 | .build(); 50 | 51 | if let Some(build_info) = command.generate() { 52 | println!("using conan build info"); 53 | build_info.cargo_emit(); 54 | } 55 | 56 | let build_command = BuildCommandBuilder::new() 57 | .with_recipe_path(PathBuf::from("../../../conanfile.py")) 58 | .with_build_path(PathBuf::from("../../../build/")) 59 | .build(); 60 | 61 | if let Some(exit_status) = build_command.run() { 62 | println!("conan build exited with {}", exit_status); 63 | } 64 | } 65 | ``` 66 | 67 | The simplest approach is to add a conanfile.txt file alongside build.rs: 68 | 69 | ``` 70 | [requires] 71 | openssl/1.1.1l@devolutions/stable 72 | ``` 73 | 74 | To test if the conan packages are properly imported, run `cargo -vv build`, and 75 | look for output similar to this: 76 | 77 | ```bash 78 | [conan-test 0.1.0] using conan build info 79 | [conan-test 0.1.0] cargo:rustc-link-search=native=/Users/mamoreau/.conan/data/openssl/1.1.1l/devolutions/stable/package/ce597277d61571523403b5b500bda70acd77cd8a/lib 80 | [conan-test 0.1.0] cargo:rustc-link-lib=crypto 81 | [conan-test 0.1.0] cargo:rustc-link-lib=ssl 82 | [conan-test 0.1.0] cargo:include=/Users/mamoreau/.conan/data/openssl/1.1.1l/devolutions/stable/package/ce597277d61571523403b5b500bda70acd77cd8a/include 83 | [conan-test 0.1.0] cargo:rerun-if-env-changed=CONAN 84 | ``` 85 | 86 | This sample conan recipe is available 87 | [here](https://github.com/Devolutions/conan-public), even if it is not available 88 | in a public conan repository. 89 | 90 | ## Documentation 91 | 92 | ### Conan Install 93 | 94 | The `InstallCommand` struct represents the "conan install" command, facilitating 95 | package installation and dependency management in Rust projects. 96 | `InstallCommandBuilder` provides a fluent API for constructing an 97 | `InstallCommand`. 98 | 99 | ### Example 100 | 101 | ```rust 102 | use conan::{InstallCommandBuilder, BuildPolicy}; 103 | use std::path::Path; 104 | 105 | fn main() -> Result<(), Box> { 106 | let install_command = InstallCommandBuilder::new() 107 | .with_profile("default") 108 | .build_policy(BuildPolicy::Missing) 109 | .recipe_path(Path::new("conanfile.txt")) 110 | .output_dir(Path::new("output_directory")) 111 | .build(); 112 | 113 | if install_command.generate().is_some() { 114 | println!("Packages installed successfully!"); 115 | } else { 116 | println!("Failed to install packages."); 117 | } 118 | 119 | Ok(()) 120 | } 121 | ``` 122 | 123 | In this example, `InstallCommandBuilder` configures the Conan install command 124 | with a profile, build policy, recipe file path, and output directory. 125 | `generate()` executes the command, returning `Some(BuildInfo)` on success or 126 | `None` on failure. 127 | 128 | ### Conan Build 129 | 130 | The `BuildCommand` struct represents the "conan build" command, facilitating the 131 | build process of Conan packages in Rust projects. `BuildCommandBuilder` provides 132 | a fluent API to construct a `BuildCommand`. 133 | 134 | ### Example 135 | 136 | ```rust 137 | use conan::BuildCommandBuilder; 138 | use std::path::PathBuf; 139 | 140 | fn main() -> Result<(), Box> { 141 | let build_command = BuildCommandBuilder::new() 142 | .with_recipe_path(PathBuf::from("conanfile.py")) 143 | .with_build_path(PathBuf::from("build")) 144 | .should_configure(true) 145 | .should_build(true) 146 | .should_install(true) 147 | .build(); 148 | 149 | match build_command.run() { 150 | Some(status) if status.success() => println!("Build succeeded!"), 151 | _ => println!("Build failed."), 152 | } 153 | 154 | Ok(()) 155 | } 156 | ``` 157 | 158 | In this example, _BuildCommandBuilder_ is used to configure the Conan build 159 | command with paths and options. _run()_ executes the command, returning 160 | _Some(ExitStatus)_ on success or _None_ on failure. 161 | 162 | ### Conan Package 163 | 164 | The `PackageCommand` struct represents the "conan package" command and is used 165 | for creating packages. The `PackageCommandBuilder` provides a fluent API for 166 | constructing a `PackageCommand`. 167 | 168 | The `ConanPackage` struct provides functionality for managing Conan packages 169 | that generate C++ libraries, and it aids in linking these libraries with Rust. 170 | 171 | #### Example Usage: 172 | 173 | ```rust 174 | use conan::{PackageCommandBuilder, PackageComman, ConanPackage}; 175 | use std::path::PathBuf; 176 | 177 | fn main() -> Result<(), Box> { 178 | let package_command = PackageCommandBuilder::new() 179 | .with_recipe_path(PathBuf::from("conanfile.py")) 180 | .build(); 181 | 182 | if let Some(status) = package_command.run() { 183 | if !status.success() { 184 | println!("Package command failed."); 185 | return Ok(()); 186 | } 187 | } 188 | 189 | let conan_package = ConanPackage::new(PathBuf::from("./package/")); 190 | conan_package.emit_cargo_libs_linkage(PathBuf::from("lib"))?; 191 | 192 | Ok(()) 193 | } 194 | ``` 195 | 196 | ## Use Case: Integrating Rust into a legacy c++/conan1 codebase 197 | 198 | Integrating Rust into a legacy C++ codebase can be a strategic move to leverage 199 | Rust's memory safety features while maintaining existing C++ functionality. In 200 | this guide, we will explore how to integrate Rust into a legacy C++/Conan 201 | codebase using `conan-rs` and `autocxx`. 202 | 203 | ### Existing C++ Conan Codebase Structure 204 | 205 | Your existing C++ codebase with Conan and CMake might look like this: 206 | 207 | ``` 208 | . 209 | ├── build 210 | │ ├── bin 211 | │ │ └── target_bin 212 | │ ├── lib 213 | │ │ ├── lib1.a 214 | │ │ ├── lib2.a 215 | │ │ ├── lib3.so 216 | │ │ ├── lib4.so 217 | │ │ ├── ... 218 | │ │ └── libn.a 219 | ├── CMakeLists.txt 220 | ├── conanfile.py 221 | ├── include 222 | │ └── ... 223 | ├── profiles 224 | │ ├── ... 225 | ├── src 226 | │ ├── target_bin 227 | │ │ ├── ... 228 | │ ├── lib1 229 | │ │ ├── CMakeLists.txt 230 | │ │ ├── include 231 | │ │ │ └── ... 232 | │ │ ├── src 233 | │ │ │ └── ... 234 | │ ├── ... 235 | │ ├── libn 236 | │ │ ├── CMakeLists.txt 237 | │ │ ├── include 238 | │ │ │ └── ... 239 | │ │ ├── src 240 | │ │ │ └── ... 241 | ``` 242 | 243 | Make sure that after a build the build dir look like this(Your configuration may 244 | vary): 245 | 246 | ``` 247 | ├── build 248 | │ ├── bin 249 | │ │ └── target_bin 250 | │ ├── lib 251 | │ │ ├── lib1.a 252 | │ │ ├── lib2.a 253 | │ │ ├── lib3.so 254 | │ │ ├── lib4.so 255 | │ │ ├── ... 256 | │ │ └── libn.a 257 | ``` 258 | 259 | Also, the `package()` method in your conanfile should organize your libs and 260 | associated includes in a config akin to: 261 | 262 | ``` 263 | package 264 | ├── conaninfo.txt 265 | ├── conanmanifest.txt 266 | ├── include 267 | └── lib 268 | ├── lib1.a 269 | ├── ... 270 | └── libn.so 271 | ``` 272 | 273 | ### Creating the Rust "Bridge" Crate 274 | 275 | Create a Rust library crate within the codebase to act as the "bridge" between 276 | the C++ and Rust code: 277 | 278 | ``` 279 | . 280 | ├── build.rs 281 | ├── Cargo.lock 282 | ├── Cargo.toml 283 | └── src 284 | ├── lib.rs 285 | └── main.rs 286 | ``` 287 | 288 | ### Setting Up Dependencies 289 | 290 | Install `conan-rs` and `autocxx`: 291 | 292 | ```bash 293 | cargo add conan-rs autocxx --build 294 | cargo add autocxx 295 | ``` 296 | 297 | ### Setting the build script: 298 | 299 | In your crate's build script (`build.rs`), configure the integration: 300 | 301 | ```rust 302 | use conan::{ 303 | BuildCommandBuilder, BuildPolicy, ConanPackage, InstallCommandBuilder, PackageCommandBuilder, 304 | }; 305 | use std::env; 306 | use std::path::{Path, PathBuf}; 307 | use std::process; 308 | 309 | fn main() { 310 | println!("cargo:rerun-if-changed=build.rs"); 311 | println!("cargo:rerun-if-changed=../../path/to/your/conanfile.py"); 312 | println!("cargo:rerun-if-changed=../../path/to/your/build/directory"); 313 | 314 | let out_dir = env::var("OUT_DIR").map(PathBuf::from).unwrap_or_else(|_| { 315 | eprintln!("Error: OUT_DIR environment variable is not set"); 316 | process::exit(1); 317 | }); 318 | 319 | println!("OUT_DIR: {:?}", out_dir); 320 | 321 | let conan_profile = env::var("CONAN_PROFILE").unwrap_or_else(|_| "default".to_string()); 322 | let install_command = InstallCommandBuilder::new() 323 | .with_profile(&conan_profile) 324 | .with_remote("your_remote") 325 | .build_policy(BuildPolicy::Missing) 326 | .with_profile("../../path/to/your/conan/profile") 327 | .recipe_path(Path::new("../../path/to/your/conanfile.py")) 328 | .output_dir(Path::new("../../path/to/your/build/directory")) 329 | .with_options(&["option1=True", "option2=True"]) 330 | .update_check() 331 | .build(); 332 | 333 | if let Some(build_info) = install_command.generate() { 334 | println!("using conan build info"); 335 | build_info.cargo_emit(); 336 | } else { 337 | eprintln!("Error: failed to run conan install"); 338 | process::exit(1); 339 | } 340 | 341 | BuildCommandBuilder::new() 342 | .with_recipe_path(PathBuf::from("../../path/to/your/conanfile.py")) 343 | .with_build_path(PathBuf::from("../../path/to/your/build/directory")) 344 | .build() 345 | .run() 346 | .unwrap_or_else(|| { 347 | eprintln!("Error: Unable to run conan build"); 348 | process::exit(1); 349 | }); 350 | 351 | let package_command = PackageCommandBuilder::new() 352 | .with_recipe_path(PathBuf::from("../../path/to/your/conanfile.py")) 353 | .with_build_path(PathBuf::from("../../path/to/your/build/directory")) 354 | .with_package_path(out_dir.clone()) 355 | .build(); 356 | 357 | if let Some(exit_status) = package_command.run() { 358 | println!("conan package exited with {}", exit_status); 359 | } 360 | 361 | let conan_package = ConanPackage::new(out_dir.clone()); 362 | if let Err(err) = conan_package.emit_cargo_libs_linkage("lib".into()) { 363 | eprintln!("Error: Unable to emit cargo linkage: {:?}", err); 364 | process::exit(1); 365 | } 366 | 367 | let include_path = out_dir.join("include"); 368 | let mut builder = autocxx_build::Builder::new("src/lib.rs", &[include_path]) 369 | .build() 370 | .unwrap_or_else(|err| { 371 | eprintln!("Error: Unable to generate bindings: {:?}", err); 372 | process::exit(1); 373 | }); 374 | 375 | builder.flag_if_supported("-std=c++14").compile("foo_bar"); 376 | println!("cargo:rerun-if-changed=src/main.rs"); 377 | } 378 | ``` 379 | 380 | ### Using C++ Libraries in Rust 381 | 382 | Finally, use the C++ libraries in `lib.rs`: 383 | 384 | ```rust 385 | use autocxx::prelude::*; 386 | 387 | include_cpp! { 388 | #include "path/to/header.h" 389 | safety!(unsafe_ffi) 390 | generate!("FunctionFromCpp") 391 | } 392 | 393 | pub fn use_cpp_function() { 394 | let result = ffi::FunctionFromCpp(); 395 | // Use result as needed 396 | } 397 | ``` 398 | -------------------------------------------------------------------------------- /test/conanbuildinfo5.json: -------------------------------------------------------------------------------- 1 | { 2 | "deps_env_info": { 3 | "PATH": [ 4 | "/home/user/.conan/data/pcre2/10.42/_/_/package/7e82c9c8d32cbe0951c733288be673b1886fa50a/bin", 5 | "/home/user/.conan/data/bzip2/1.0.8/_/_/package/ad18e1e856ff78d73ad6f3c9a214f85abf2d0550/bin" 6 | ] 7 | }, 8 | "deps_user_info": { 9 | "libsystemd": {}, 10 | "libcap": {}, 11 | "libmount": {}, 12 | "libselinux": {}, 13 | "lz4": {}, 14 | "xz_utils": {}, 15 | "zstd": {}, 16 | "pcre2": {}, 17 | "zlib": {}, 18 | "bzip2": {} 19 | }, 20 | "dependencies": [ 21 | { 22 | "version": "252", 23 | "description": "System and Service Manager API library", 24 | "rootpath": "/home/user/.conan/data/libsystemd/252.4/_/_/package/ce0bd9004fa2d91408cafd7acc9ea3fde00c8ad1", 25 | "sysroot": "", 26 | "include_paths": [ 27 | "/home/user/.conan/data/libsystemd/252.4/_/_/package/ce0bd9004fa2d91408cafd7acc9ea3fde00c8ad1/include" 28 | ], 29 | "lib_paths": [ 30 | "/home/user/.conan/data/libsystemd/252.4/_/_/package/ce0bd9004fa2d91408cafd7acc9ea3fde00c8ad1/lib" 31 | ], 32 | "bin_paths": [], 33 | "build_paths": [ 34 | "/home/user/.conan/data/libsystemd/252.4/_/_/package/ce0bd9004fa2d91408cafd7acc9ea3fde00c8ad1/" 35 | ], 36 | "res_paths": [], 37 | "libs": [ 38 | "systemd" 39 | ], 40 | "system_libs": [ 41 | "rt", 42 | "pthread", 43 | "dl" 44 | ], 45 | "defines": [], 46 | "cflags": [], 47 | "cxxflags": [], 48 | "sharedlinkflags": [], 49 | "exelinkflags": [], 50 | "frameworks": [], 51 | "framework_paths": [], 52 | "names": {}, 53 | "filenames": {}, 54 | "build_modules": {}, 55 | "build_modules_paths": {}, 56 | "cppflags": [], 57 | "name": "libsystemd" 58 | }, 59 | { 60 | "version": "2.66", 61 | "description": "This is a library for getting and setting POSIX.1e (formerly POSIX 6) draft 15 capabilities", 62 | "rootpath": "/home/user/.conan/data/libcap/2.66/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c", 63 | "sysroot": "", 64 | "include_paths": [ 65 | "/home/user/.conan/data/libcap/2.66/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/include" 66 | ], 67 | "lib_paths": [ 68 | "/home/user/.conan/data/libcap/2.66/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib" 69 | ], 70 | "bin_paths": [], 71 | "build_paths": [], 72 | "res_paths": [], 73 | "libs": [ 74 | "cap" 75 | ], 76 | "system_libs": [], 77 | "defines": [], 78 | "cflags": [], 79 | "cxxflags": [], 80 | "sharedlinkflags": [], 81 | "exelinkflags": [], 82 | "frameworks": [], 83 | "framework_paths": [], 84 | "names": {}, 85 | "filenames": {}, 86 | "build_modules": {}, 87 | "build_modules_paths": {}, 88 | "cppflags": [], 89 | "name": "libcap" 90 | }, 91 | { 92 | "version": "2.36.2", 93 | "description": "The libmount library is used to parse /etc/fstab, /etc/mtab and /proc/self/mountinfo files, manage the mtab file, evaluate mount options, etc", 94 | "rootpath": "/home/user/.conan/data/libmount/2.36.2/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c", 95 | "sysroot": "", 96 | "include_paths": [ 97 | "/home/user/.conan/data/libmount/2.36.2/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/include", 98 | "/home/user/.conan/data/libmount/2.36.2/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/include/libmount" 99 | ], 100 | "lib_paths": [ 101 | "/home/user/.conan/data/libmount/2.36.2/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib" 102 | ], 103 | "bin_paths": [ 104 | "/home/user/.conan/data/libmount/2.36.2/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/bin" 105 | ], 106 | "build_paths": [ 107 | "/home/user/.conan/data/libmount/2.36.2/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/" 108 | ], 109 | "res_paths": [], 110 | "libs": [ 111 | "mount", 112 | "blkid" 113 | ], 114 | "system_libs": [ 115 | "rt" 116 | ], 117 | "defines": [], 118 | "cflags": [], 119 | "cxxflags": [], 120 | "sharedlinkflags": [], 121 | "exelinkflags": [], 122 | "frameworks": [], 123 | "framework_paths": [], 124 | "names": {}, 125 | "filenames": {}, 126 | "build_modules": {}, 127 | "build_modules_paths": {}, 128 | "cppflags": [], 129 | "name": "libmount" 130 | }, 131 | { 132 | "version": "3.3", 133 | "description": "Security-enhanced Linux is a patch of the Linux kernel and a number of utilities with enhanced security functionality designed to add mandatory access controls to Linux", 134 | "rootpath": "/home/user/.conan/data/libselinux/3.3/_/_/package/8c6c9e6ae1f4f254a8b94054c1146c7652c54203", 135 | "sysroot": "", 136 | "include_paths": [ 137 | "/home/user/.conan/data/libselinux/3.3/_/_/package/8c6c9e6ae1f4f254a8b94054c1146c7652c54203/include" 138 | ], 139 | "lib_paths": [ 140 | "/home/user/.conan/data/libselinux/3.3/_/_/package/8c6c9e6ae1f4f254a8b94054c1146c7652c54203/lib" 141 | ], 142 | "bin_paths": [], 143 | "build_paths": [], 144 | "res_paths": [], 145 | "libs": [ 146 | "selinux", 147 | "sepol" 148 | ], 149 | "system_libs": [], 150 | "defines": [], 151 | "cflags": [], 152 | "cxxflags": [], 153 | "sharedlinkflags": [], 154 | "exelinkflags": [], 155 | "frameworks": [], 156 | "framework_paths": [], 157 | "names": {}, 158 | "filenames": {}, 159 | "build_modules": {}, 160 | "build_modules_paths": {}, 161 | "cppflags": [], 162 | "name": "libselinux" 163 | }, 164 | { 165 | "version": "1.9.4", 166 | "description": "Extremely Fast Compression algorithm", 167 | "rootpath": "/home/user/.conan/data/lz4/1.9.4/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c", 168 | "sysroot": "", 169 | "include_paths": [ 170 | "/home/user/.conan/data/lz4/1.9.4/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/include" 171 | ], 172 | "lib_paths": [ 173 | "/home/user/.conan/data/lz4/1.9.4/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib" 174 | ], 175 | "bin_paths": [], 176 | "build_paths": [ 177 | "/home/user/.conan/data/lz4/1.9.4/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/" 178 | ], 179 | "res_paths": [], 180 | "libs": [ 181 | "lz4" 182 | ], 183 | "system_libs": [], 184 | "defines": [], 185 | "cflags": [], 186 | "cxxflags": [], 187 | "sharedlinkflags": [], 188 | "exelinkflags": [], 189 | "frameworks": [], 190 | "framework_paths": [], 191 | "names": { 192 | "pkg_config": "liblz4" 193 | }, 194 | "filenames": {}, 195 | "build_modules": { 196 | "cmake_find_package": [ 197 | "lib/cmake/conan-official-lz4-targets.cmake" 198 | ], 199 | "cmake_find_package_multi": [ 200 | "lib/cmake/conan-official-lz4-targets.cmake" 201 | ] 202 | }, 203 | "build_modules_paths": { 204 | "cmake_find_package": [ 205 | "/home/user/.conan/data/lz4/1.9.4/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib/cmake/conan-official-lz4-targets.cmake" 206 | ], 207 | "cmake_find_package_multi": [ 208 | "/home/user/.conan/data/lz4/1.9.4/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib/cmake/conan-official-lz4-targets.cmake" 209 | ] 210 | }, 211 | "cppflags": [], 212 | "name": "lz4" 213 | }, 214 | { 215 | "version": "5.4.0", 216 | "description": "XZ Utils is free general-purpose data compression software with a high compression ratio. XZ Utils were written for POSIX-like systems, but also work on some not-so-POSIX systems. XZ Utils are the successor to LZMA Utils.", 217 | "rootpath": "/home/user/.conan/data/xz_utils/5.4.0/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c", 218 | "sysroot": "", 219 | "include_paths": [ 220 | "/home/user/.conan/data/xz_utils/5.4.0/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/include" 221 | ], 222 | "lib_paths": [ 223 | "/home/user/.conan/data/xz_utils/5.4.0/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib" 224 | ], 225 | "bin_paths": [ 226 | "/home/user/.conan/data/xz_utils/5.4.0/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/bin" 227 | ], 228 | "build_paths": [ 229 | "/home/user/.conan/data/xz_utils/5.4.0/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/" 230 | ], 231 | "res_paths": [], 232 | "libs": [ 233 | "lzma" 234 | ], 235 | "system_libs": [ 236 | "pthread" 237 | ], 238 | "defines": [ 239 | "LZMA_API_STATIC" 240 | ], 241 | "cflags": [], 242 | "cxxflags": [], 243 | "sharedlinkflags": [], 244 | "exelinkflags": [], 245 | "frameworks": [], 246 | "framework_paths": [], 247 | "names": { 248 | "cmake_find_package": "LibLZMA", 249 | "cmake_find_package_multi": "LibLZMA" 250 | }, 251 | "filenames": {}, 252 | "build_modules": { 253 | "cmake_find_package": [ 254 | "lib/cmake/conan-official-xz_utils-variables.cmake" 255 | ] 256 | }, 257 | "build_modules_paths": { 258 | "cmake_find_package": [ 259 | "/home/user/.conan/data/xz_utils/5.4.0/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib/cmake/conan-official-xz_utils-variables.cmake" 260 | ] 261 | }, 262 | "cppflags": [], 263 | "name": "xz_utils" 264 | }, 265 | { 266 | "version": "1.5.4", 267 | "description": "Zstandard - Fast real-time compression algorithm", 268 | "rootpath": "/home/user/.conan/data/zstd/1.5.4/_/_/package/a323f39846aa3d854d842186765e8538851a7f92", 269 | "sysroot": "", 270 | "include_paths": [ 271 | "/home/user/.conan/data/zstd/1.5.4/_/_/package/a323f39846aa3d854d842186765e8538851a7f92/include" 272 | ], 273 | "lib_paths": [ 274 | "/home/user/.conan/data/zstd/1.5.4/_/_/package/a323f39846aa3d854d842186765e8538851a7f92/lib" 275 | ], 276 | "bin_paths": [], 277 | "build_paths": [], 278 | "res_paths": [], 279 | "libs": [ 280 | "zstd" 281 | ], 282 | "system_libs": [ 283 | "pthread" 284 | ], 285 | "defines": [], 286 | "cflags": [], 287 | "cxxflags": [], 288 | "sharedlinkflags": [], 289 | "exelinkflags": [], 290 | "frameworks": [], 291 | "framework_paths": [], 292 | "names": {}, 293 | "filenames": {}, 294 | "build_modules": {}, 295 | "build_modules_paths": {}, 296 | "cppflags": [], 297 | "name": "zstd" 298 | }, 299 | { 300 | "version": "10.42", 301 | "description": "Perl Compatible Regular Expressions", 302 | "rootpath": "/home/user/.conan/data/pcre2/10.42/_/_/package/7e82c9c8d32cbe0951c733288be673b1886fa50a", 303 | "sysroot": "", 304 | "include_paths": [ 305 | "/home/user/.conan/data/pcre2/10.42/_/_/package/7e82c9c8d32cbe0951c733288be673b1886fa50a/include" 306 | ], 307 | "lib_paths": [ 308 | "/home/user/.conan/data/pcre2/10.42/_/_/package/7e82c9c8d32cbe0951c733288be673b1886fa50a/lib" 309 | ], 310 | "bin_paths": [ 311 | "/home/user/.conan/data/pcre2/10.42/_/_/package/7e82c9c8d32cbe0951c733288be673b1886fa50a/bin" 312 | ], 313 | "build_paths": [], 314 | "res_paths": [], 315 | "libs": [ 316 | "pcre2-posix", 317 | "pcre2-8", 318 | "pcre2-16", 319 | "pcre2-32" 320 | ], 321 | "system_libs": [], 322 | "defines": [ 323 | "PCRE2_STATIC" 324 | ], 325 | "cflags": [], 326 | "cxxflags": [], 327 | "sharedlinkflags": [], 328 | "exelinkflags": [], 329 | "frameworks": [], 330 | "framework_paths": [], 331 | "names": { 332 | "cmake_find_package": "PCRE2", 333 | "cmake_find_package_multi": "PCRE2", 334 | "pkg_config": "libpcre2" 335 | }, 336 | "filenames": {}, 337 | "build_modules": {}, 338 | "build_modules_paths": {}, 339 | "cppflags": [], 340 | "name": "pcre2" 341 | }, 342 | { 343 | "version": "1.2.13", 344 | "description": "A Massively Spiffy Yet Delicately Unobtrusive Compression Library (Also Free, Not to Mention Unencumbered by Patents)", 345 | "rootpath": "/home/user/.conan/data/zlib/1.2.13/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c", 346 | "sysroot": "", 347 | "include_paths": [ 348 | "/home/user/.conan/data/zlib/1.2.13/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/include" 349 | ], 350 | "lib_paths": [ 351 | "/home/user/.conan/data/zlib/1.2.13/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/lib" 352 | ], 353 | "bin_paths": [], 354 | "build_paths": [ 355 | "/home/user/.conan/data/zlib/1.2.13/_/_/package/d13c97721d7bdc192ca6529684f2b79beeae8a7c/" 356 | ], 357 | "res_paths": [], 358 | "libs": [ 359 | "z" 360 | ], 361 | "system_libs": [], 362 | "defines": [], 363 | "cflags": [], 364 | "cxxflags": [], 365 | "sharedlinkflags": [], 366 | "exelinkflags": [], 367 | "frameworks": [], 368 | "framework_paths": [], 369 | "names": { 370 | "cmake_find_package": "ZLIB", 371 | "cmake_find_package_multi": "ZLIB" 372 | }, 373 | "filenames": {}, 374 | "build_modules": {}, 375 | "build_modules_paths": {}, 376 | "cppflags": [], 377 | "name": "zlib" 378 | }, 379 | { 380 | "version": "1.0.8", 381 | "description": "bzip2 is a free and open-source file compression program that uses the Burrows Wheeler algorithm.", 382 | "rootpath": "/home/user/.conan/data/bzip2/1.0.8/_/_/package/ad18e1e856ff78d73ad6f3c9a214f85abf2d0550", 383 | "sysroot": "", 384 | "include_paths": [ 385 | "/home/user/.conan/data/bzip2/1.0.8/_/_/package/ad18e1e856ff78d73ad6f3c9a214f85abf2d0550/include" 386 | ], 387 | "lib_paths": [ 388 | "/home/user/.conan/data/bzip2/1.0.8/_/_/package/ad18e1e856ff78d73ad6f3c9a214f85abf2d0550/lib" 389 | ], 390 | "bin_paths": [ 391 | "/home/user/.conan/data/bzip2/1.0.8/_/_/package/ad18e1e856ff78d73ad6f3c9a214f85abf2d0550/bin" 392 | ], 393 | "build_paths": [ 394 | "/home/user/.conan/data/bzip2/1.0.8/_/_/package/ad18e1e856ff78d73ad6f3c9a214f85abf2d0550/" 395 | ], 396 | "res_paths": [], 397 | "libs": [ 398 | "bz2" 399 | ], 400 | "system_libs": [], 401 | "defines": [], 402 | "cflags": [], 403 | "cxxflags": [], 404 | "sharedlinkflags": [], 405 | "exelinkflags": [], 406 | "frameworks": [], 407 | "framework_paths": [], 408 | "names": { 409 | "cmake_find_package": "BZip2", 410 | "cmake_find_package_multi": "BZip2" 411 | }, 412 | "filenames": {}, 413 | "build_modules": { 414 | "cmake_find_package": [ 415 | "lib/cmake/conan-official-bzip2-variables.cmake" 416 | ] 417 | }, 418 | "build_modules_paths": { 419 | "cmake_find_package": [ 420 | "/home/user/.conan/data/bzip2/1.0.8/_/_/package/ad18e1e856ff78d73ad6f3c9a214f85abf2d0550/lib/cmake/conan-official-bzip2-variables.cmake" 421 | ] 422 | }, 423 | "cppflags": [], 424 | "name": "bzip2" 425 | } 426 | ], 427 | "settings": { 428 | "arch": "x86_64", 429 | "arch_build": "x86_64", 430 | "build_type": "Debug", 431 | "compiler": "gcc", 432 | "compiler.libcxx": "libstdc++11", 433 | "compiler.version": "12", 434 | "os": "Linux", 435 | "os_build": "Linux" 436 | }, 437 | "options": { 438 | "libsystemd": { 439 | "fPIC": "True", 440 | "shared": "False", 441 | "with_lz4": "True", 442 | "with_selinux": "True", 443 | "with_xz": "True", 444 | "with_zstd": "True" 445 | } 446 | } 447 | } --------------------------------------------------------------------------------