Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re: Add conan support #753

Merged
merged 12 commits into from
Apr 5, 2023
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