Skip to content

Commit

Permalink
Re: Add conan support (#753)
Browse files Browse the repository at this point in the history
related: #684 

This PR contains below:

- Add `"package" = {version = "...", registry = "conan-v1"}` syntax
- `"package" = {version = "..."}` and `"package" = {version = "...",
registry = "poac"}` is same as `"package" = "..."`
- Add conan v1 support
- About 10 days ago, conan v2 had been released. **This PR doesn't
support that.**

See https://github.com/wx257osn2/poac-conan-demo for usage.

---------

Co-authored-by: qqiangwu <wqzhiep@gmail.com>
Co-authored-by: Ken Matsui <26405363+ken-matsui@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 5, 2023
1 parent 175ec07 commit 3052403
Show file tree
Hide file tree
Showing 26 changed files with 667 additions and 76 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ jobs:
../poac run
working-directory: build

- name: Install Conan
id: conan
uses: turtlebrowser/get-conan@main
with:
version: 1.59.0

- name: Test conan dependency
# FIXME: memory leak on Ninja
# https://github.com/poacpm/poac/runs/6859118992?check_suite_focus=true#step:16:21
if: matrix.build_type == 'Release'
run: |
git clone https://github.com/wx257osn2/poac-conan-demo.git
cd poac-conan-demo
../build/poac build
- name: Print coverage
if: success() && matrix.coverage == 'on'
run: |
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,15 @@ jobs:
cd hello_world
../poac run
working-directory: build

- name: Install Conan
id: conan
uses: turtlebrowser/get-conan@main
with:
version: 1.59.0

- name: Test conan dependency
run: |
git clone https://github.com/wx257osn2/poac-conan-demo.git
cd poac-conan-demo
../build/poac build
3 changes: 3 additions & 0 deletions include/poac/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ inline const Path main_cpp_file(src_dir / "main.cpp");
inline constexpr StringRef POAC_OUT = "poac-out";
inline const Path out_dir(cwd / POAC_OUT);

inline const Path conan_deps_dir(out_dir / ".conan");
inline const Path conan_deps_file(conan_deps_dir / "conan_poac.json");

} // namespace poac::config
14 changes: 11 additions & 3 deletions include/poac/core/resolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,19 @@ using IncorrectSha256sum = Error<
"issue on GitHub of the package and stopping using this package:\n"
" {}: {}",
String, String, String, String>;
using RedefinePredefinedRegistryEntry = Error<
"Registry entry named `{}` is predefined and can't be overwritten.\n",
String>;
using DuplicateRegistryEntry =
Error<"Registry entry named `{}` is duplicated.\n", String>;
using UnknownRegistryType = Error<
"Registry entry named `{}` has unknown registry type `{}`.\n", String,
String>;
using Unknown = Error<"unknown error occurred: {}", String>;

inline Fn get_install_name(const resolve::Package& package)->String {
return boost::replace_first_copy(package.name, "/", "-") + "-"
+ package.version_rq;
+ package.dep_info.version_rq;
}

inline Fn get_extracted_path(const resolve::Package& package)->Path {
Expand Down Expand Up @@ -79,7 +87,7 @@ inline Fn convert_to_download_link(StringRef repository)->String {
// So, find the end of `tree/`.
const usize end = repository.find('/', start);
// Retrieve both sides: `https://github.com/tree/tree/`
StringRef left = repository.substr(0, start);
const StringRef left = repository.substr(0, start);
// `/tree/v0.1.0`: this side is just a tag.
// Mostly, we do not include `tree`, but we can.
StringRef right = repository.substr(end);
Expand All @@ -89,7 +97,7 @@ inline Fn convert_to_download_link(StringRef repository)->String {
[[nodiscard]] inline Fn get_download_link(const resolve::Package& package)
->Result<std::pair<String, String>, String> {
Let[repository, sha256sum] =
Try(util::net::api::repoinfo(package.name, package.version_rq));
Try(util::net::api::repoinfo(package.name, package.dep_info.version_rq));
return Ok(std::make_pair(convert_to_download_link(repository), sha256sum));
}

Expand Down
31 changes: 31 additions & 0 deletions include/poac/core/resolver/registry.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

// external
#include <boost/functional/hash.hpp>

// internal
#include "poac/util/result.hpp"
#include "poac/util/rustify.hpp"

namespace poac::core::resolver::registry {

// NOLINTNEXTLINE(bugprone-exception-escape)
struct Registry {
String index;
String type;
};

inline Fn operator==(const Registry& lhs, const Registry& rhs)->bool {
return lhs.index == rhs.index && lhs.type == rhs.type;
}

inline Fn hash_value(const Registry& r)->usize {
usize seed = 0;
boost::hash_combine(seed, r.index);
boost::hash_combine(seed, r.type);
return seed;
}

using Registries = HashMap<String, Registry>;

} // namespace poac::core::resolver::registry
39 changes: 32 additions & 7 deletions include/poac/core/resolver/resolve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,49 @@ template <typename W>
using DupDeps = typename DuplicateDeps<W>::Type;

// NOLINTNEXTLINE(bugprone-exception-escape)
struct Package {
/// Package name
String name;

struct DependencyInfo {
/// Version Requirement
///
/// Sometimes, this is like `1.66.0` or like `>=1.64.0 and <2.0.0`.
String version_rq;

/// Registry Index
String index;

/// Package type
String type;
};

inline Fn operator==(const DependencyInfo& lhs, const DependencyInfo& rhs)
->bool {
return lhs.version_rq == rhs.version_rq && lhs.index == rhs.index
&& lhs.type == rhs.type;
}

inline Fn hash_value(const DependencyInfo& d)->usize {
usize seed = 0;
boost::hash_combine(seed, d.version_rq);
boost::hash_combine(seed, d.index);
boost::hash_combine(seed, d.type);
return seed;
}

// NOLINTNEXTLINE(bugprone-exception-escape)
struct Package {
/// Package name
String name;

DependencyInfo dep_info;
};

inline Fn operator==(const Package& lhs, const Package& rhs)->bool {
return lhs.name == rhs.name && lhs.version_rq == rhs.version_rq;
return lhs.name == rhs.name && lhs.dep_info == rhs.dep_info;
}

inline Fn hash_value(const Package& p)->usize {
usize seed = 0;
boost::hash_combine(seed, p.name);
boost::hash_combine(seed, p.version_rq);
boost::hash_combine(seed, p.dep_info);
return seed;
}

Expand All @@ -68,7 +93,7 @@ template <typename W>
using UniqDeps = std::conditional_t<
W::value, HashMap<Package, Deps>,
// <name, ver_req>
HashMap<String, String>>;
HashMap<String, DependencyInfo>>;

inline Fn get_package(const UniqDeps<WithDeps>::value_type& deps) noexcept
-> const Package& {
Expand Down
13 changes: 13 additions & 0 deletions include/poac/util/file.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

// internal
#include "poac/util/result.hpp"
#include "poac/util/rustify.hpp"

namespace poac::util::file {

Fn write_file(const Path& p, StringRef content)->Result<void>;

using WriteFileFailed = Error<"writing `{}` failed", String>;

} // namespace poac::util::file
47 changes: 27 additions & 20 deletions include/poac/util/net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <spdlog/spdlog.h> // NOLINT(build/include_order)

// internal
#include "poac/core/resolver/resolve.hpp"
#include "poac/util/format.hpp"
#include "poac/util/log.hpp"
#include "poac/util/meta.hpp"
Expand Down Expand Up @@ -95,51 +96,54 @@ class MultiPartForm {
using ConstSelfReference = const MultiPartForm&;

private:
String m_crlf = "\r\n";
String m_header;
String m_boundary;
String m_footer;
String m_content_disposition = "Content-Disposition: form-data; ";
Vec<String> m_form_param;
Vec<std::tuple<FileNameType, FilePathType, HeaderType>> m_file_param;
// Note: false positive
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
String _crlf = "\r\n";
String _header;
String _boundary;
String _footer;
// Note: false positive
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
String _content_disposition = "Content-Disposition: form-data; ";
Vec<String> _form_param;
Vec<std::tuple<FileNameType, FilePathType, HeaderType>> _file_param;

public:
MultiPartForm()
: m_boundary(boost::uuids::to_string(boost::uuids::random_generator{}())),
m_footer(format("{}--{}--{}", m_crlf, m_boundary, m_crlf)) {}
: _boundary(boost::uuids::to_string(boost::uuids::random_generator{}())),
_footer(format("{}--{}--{}", _crlf, _boundary, _crlf)) {}

[[nodiscard]] inline Fn get_header() const->String { return m_header; }
[[nodiscard]] inline Fn get_footer() const->String { return m_footer; }
[[nodiscard]] inline Fn get_header() const->String { return _header; }
[[nodiscard]] inline Fn get_footer() const->String { return _footer; }

inline void set(const FileNameType& name, const String& value) {
m_form_param.emplace_back(format(
_form_param.emplace_back(format(
"--{boundary}{crlf}{cd}name=\"{name}\"{crlf}{crlf}{value}",
"boundary"_a = m_boundary, "crlf"_a = m_crlf,
"cd"_a = m_content_disposition, "name"_a = name, "value"_a = value
"boundary"_a = _boundary, "crlf"_a = _crlf,
"cd"_a = _content_disposition, "name"_a = name, "value"_a = value
));
generate_header(); // re-generate
}
inline void
set(const FileNameType& name, const FilePathType& value,
const HeaderType& h) {
m_file_param.emplace_back(name, value, h);
_file_param.emplace_back(name, value, h);
generate_header(); // re-generate
}
template <typename Request>
inline void set_req(const Request& req) {
const std::ostringstream ss;
ss << req;
m_form_param.insert(m_form_param.begin(), ss.str());
_form_param.insert(_form_param.begin(), ss.str());
generate_header(); // re-generate
}

[[nodiscard]] inline Fn content_type() const->String {
return format("multipart/form-data; boundary={}", m_boundary);
return format("multipart/form-data; boundary={}", _boundary);
}
[[nodiscard]] inline Fn content_length() const->std::uintmax_t {
return std::accumulate(
m_file_param.begin(), m_file_param.end(),
m_header.size() + m_footer.size(),
_file_param.begin(), _file_param.end(), _header.size() + _footer.size(),
[](std::uintmax_t acc, Let& f) {
return acc + fs::file_size(std::get<1>(f));
}
Expand Down Expand Up @@ -439,6 +443,8 @@ class Requests {

void ssl_set_tlsext() const;

// Note: false positive
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
inline void lookup() const {
// Look up the domain name
Let results = resolver->resolve(host, port);
Expand All @@ -464,7 +470,8 @@ call(StringRef path, const Option<String>& body = None) noexcept
->Result<boost::property_tree::ptree, String>;

[[nodiscard]] Fn deps(StringRef name, StringRef version)
->Result<HashMap<String, String>, String>;
->Result<
HashMap<String, poac::core::resolver::resolve::DependencyInfo>, String>;

[[nodiscard]] Fn versions(StringRef name)->Result<Vec<String>, String>;

Expand Down
30 changes: 30 additions & 0 deletions include/poac/util/registry/conan/v1/manifest.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

// std
#include <string>

// external
#include <boost/property_tree/ptree.hpp>

// internal
#include "poac/util/result.hpp"
#include "poac/util/rustify.hpp"

namespace poac::util::registry::conan::v1::manifest {

Fn gather_conan_conf(
const boost::property_tree::ptree& pt, const std::string& field,
const std::string& prefix
)
->Vec<String>;

struct ConanManifest {
Vec<String> defines;
Vec<String> includes;
Vec<String> libdirs;
Vec<String> libraries;
};

Fn gather_conan_deps()->Result<ConanManifest>;

} // namespace poac::util::registry::conan::v1::manifest
29 changes: 29 additions & 0 deletions include/poac/util/registry/conan/v1/resolver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

// internal
#include "poac/core/resolver/resolve.hpp"
#include "poac/util/rustify.hpp"

namespace poac::util::registry::conan::v1::resolver {

using ConanNotFound = Error<"conan is not found">;
using ConanIsNotV1 =
Error<"your conan is not v1. conan-v1 registry needs conan v1.">;

Fn check_conan_command()->Result<void>;

Fn install_conan_generator()->Result<void>;

Fn format_conan_requires(const Vec<core::resolver::resolve::Package>& packages)
->String;

Fn get_conan_config()->String;

Fn install_conan_packages()->Result<void>;

Fn fetch_conan_packages(const Vec<core::resolver::resolve::Package>& packages
) noexcept -> Result<void>;

Fn is_conan(const core::resolver::resolve::Package& package) noexcept -> bool;

} // namespace poac::util::registry::conan::v1::resolver
4 changes: 2 additions & 2 deletions lib/cmd/graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Fn create_graph()->Result<std::pair<Graph, Vec<String>>> {
const core::resolver::resolve::Package package = dep.value().first;

g[index].name = package.name;
g[index].version = package.version_rq;
g[index].version = package.dep_info.version_rq;
}

// Add edge
Expand All @@ -79,7 +79,7 @@ Fn create_graph()->Result<std::pair<Graph, Vec<String>>> {
Vec<String> names;
for (Let & [ package, deps ] : resolved_deps) {
static_cast<void>(deps);
names.push_back(package.name + ": " + package.version_rq);
names.push_back(package.name + ": " + package.dep_info.version_rq);
}
return Ok(std::make_pair(g, names));
}
Expand Down
1 change: 1 addition & 0 deletions lib/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_poac_target(poac_core
poac_util_format
poac_util_log
poac_util_result
poac_util_registry_conan_v1_resolver
toml11::toml11
)

Expand Down
1 change: 1 addition & 0 deletions lib/core/builder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ add_poac_target(poac_core_builder
poac_util_log
poac_util_result
poac_util_rustify
poac_util_registry_conan_v1_manifest
)
Loading

0 comments on commit 3052403

Please sign in to comment.