Merge pull request #54 from cynnyx/master

miscellaneous utilities + interfaces + docs + bug fixing
This commit is contained in:
Michele Caini 2016-08-25 17:36:05 +02:00 committed by GitHub
commit b8a45f040d
16 changed files with 284 additions and 247 deletions

View File

@ -195,8 +195,8 @@ tcp->bind("127.0.0.1", 4242);
tcp->listen();
```
Note also that `uvw::TcpHandle` already supports _IPv6_ out-of-the-box. The statement above is equivalent to `tcp->bind<uvw::net::IPv4>("127.0.0.1", 4242)`.<br/>
It's suffice to explicitly specify `uvw::net::IPv6` as the underlying protocol to use it.
Note also that `uvw::TcpHandle` already supports _IPv6_ out-of-the-box. The statement above is equivalent to `tcp->bind<uvw::IPv4>("127.0.0.1", 4242)`.<br/>
It's suffice to explicitly specify `uvw::IPv6` as the underlying protocol to use it.
The API reference is the recommended documentation for further details about resources and their methods.

View File

@ -7,7 +7,7 @@
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {
@ -214,7 +214,7 @@ public:
* @param port A valid port number.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void getNameInfo(std::string ip, unsigned int port, int flags = 0) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::AddrFunc(ip.data(), port, &addr);
@ -226,7 +226,7 @@ public:
* @param addr A valid instance of Addr.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void getNameInfo(Addr addr, int flags = 0) {
getNameInfo<I>(addr.ip, addr.port, flags);
}
@ -237,7 +237,7 @@ public:
* @param port A valid port number.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
auto getNameInfoSync(std::string ip, unsigned int port, int flags = 0) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::AddrFunc(ip.data(), port, &addr);
@ -251,7 +251,7 @@ public:
* @param addr A valid instance of Addr.
* @param flags Optional flags that modify the behavior of `getnameinfo`.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
auto getNameInfoSync(Addr addr, int flags = 0) {
getNameInfoSync<I>(addr.ip, addr.port, flags);
}

View File

@ -8,7 +8,7 @@
#include <uv.h>
#include "event.hpp"
#include "request.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {

View File

@ -7,7 +7,7 @@
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {

View File

@ -7,7 +7,7 @@
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {

View File

@ -6,7 +6,7 @@
#include <memory>
#include <uv.h>
#include "resource.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {

View File

@ -1,112 +0,0 @@
#pragma once
#include <type_traits>
#include <stdexcept>
#include <cstddef>
#include <utility>
#include <string>
#include <uv.h>
#include "util.hpp"
namespace uvw {
namespace net {
struct IPv4 { };
struct IPv6 { };
}
namespace details {
template<typename>
struct IpTraits;
template<>
struct IpTraits<net::IPv4> {
using Type = sockaddr_in;
using AddrFuncType = int(*)(const char *, int, sockaddr_in *);
using NameFuncType = int(*)(const sockaddr_in *, char *, std::size_t);
static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
static constexpr NameFuncType nameFunc = &uv_ip4_name;
};
template<>
struct IpTraits<net::IPv6> {
using Type = sockaddr_in6;
using AddrFuncType = int(*)(const char *, int, sockaddr_in6 *);
using NameFuncType = int(*)(const sockaddr_in6 *, char *, std::size_t);
static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
static constexpr NameFuncType nameFunc = &uv_ip6_name;
};
template<typename I>
Addr address(const typename IpTraits<I>::Type *aptr, int len) noexcept {
std::pair<std::string, unsigned int> addr{};
char name[len];
int err = IpTraits<I>::nameFunc(aptr, name, len);
if(0 == err) {
addr = { std::string{name}, ntohs(aptr->sin_port) };
}
/**
* See Boost/Mutant idiom:
* https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Boost_mutant
*/
return reinterpret_cast<Addr&>(addr);
}
template<typename I, typename F, typename H>
Addr address(F &&f, const H *handle) noexcept {
sockaddr_storage ssto;
int len = sizeof(ssto);
Addr addr{};
int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
if(0 == err) {
typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
addr = address<I>(aptr, len);
}
return addr;
}
template<typename F, typename H, typename..., std::size_t N = 128>
std::string path(F &&f, H *handle) noexcept {
std::size_t size = N;
char buf[size];
std::string str{};
auto err = std::forward<F>(f)(handle, buf, &size);
if(UV_ENOBUFS == err) {
std::unique_ptr<char[]> data{new char[size]};
err = std::forward<F>(f)(handle, data.get(), &size);
if(0 == err) {
str = data.get();
}
} else {
str.assign(buf, size);
}
return str;
}
}
}

View File

@ -9,7 +9,7 @@
#include "event.hpp"
#include "request.hpp"
#include "stream.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {
@ -148,7 +148,7 @@ public:
*/
HandleType receive() noexcept {
auto type = uv_pipe_pending_type(get<uv_pipe_t>());
return guessHandle(type);
return Utilities::guessHandle(type);
}
private:

View File

@ -7,7 +7,7 @@
#include <uv.h>
#include "event.hpp"
#include "handle.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {

View File

@ -8,7 +8,7 @@
#include "event.hpp"
#include "handle.hpp"
#include "stream.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {

View File

@ -10,7 +10,7 @@
#include "event.hpp"
#include "request.hpp"
#include "stream.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {
@ -32,7 +32,7 @@ enum class UVTcpFlags: std::underlying_type_t<uv_tcp_flags> {
*
* TCP handles are used to represent both TCP streams and servers.<br/>
* By default, _IPv4_ is used as a template parameter. The handle already
* supports _IPv6_ out-of-the-box by using `uvw::net::IPv6`.
* supports _IPv6_ out-of-the-box by using `uvw::IPv6`.
*/
class TcpHandle final: public StreamHandle<TcpHandle, uv_tcp_t> {
explicit TcpHandle(std::shared_ptr<Loop> ref)
@ -138,7 +138,7 @@ public:
* @param port The port to which to bind.
* @param flags Optional additional flags.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
@ -161,7 +161,7 @@ public:
* @param addr A valid instance of Addr.
* @param flags Optional additional flags.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
bind<I>(addr.ip, addr.port, flags);
}
@ -170,7 +170,7 @@ public:
* @brief Gets the current address to which the handle is bound.
* @return A valid instance of Addr, an empty one in case of errors.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
Addr sock() const noexcept {
return details::address<I>(&uv_tcp_getsockname, get<uv_tcp_t>());
}
@ -179,7 +179,7 @@ public:
* @brief Gets the address of the peer connected to the handle.
* @return A valid instance of Addr, an empty one in case of errors.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
Addr peer() const noexcept {
return details::address<I>(&uv_tcp_getpeername, get<uv_tcp_t>());
}
@ -194,7 +194,7 @@ public:
* @param ip The address to which to bind.
* @param port The port to which to bind.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void connect(std::string ip, unsigned int port) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
@ -218,7 +218,7 @@ public:
*
* @param addr A valid instance of Addr.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void connect(Addr addr) {
connect<I>(addr.ip, addr.port);
}

View File

@ -7,7 +7,7 @@
#include <uv.h>
#include "event.hpp"
#include "stream.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {
@ -117,23 +117,17 @@ public:
/**
* @brief Gets the current Window size.
* @return The current Window size or `{0, 0}` in case of errors.
* @return The current Window size or `{-1, -1}` in case of errors.
*/
WinSize getWinSize() {
std::pair<int, int> size{0, 0};
int width;
int height;
WinSize size;
if(0 == invoke(&uv_tty_get_winsize, get<uv_tty_t>(), &width, &height)) {
size.first = width;
size.second = height;
if(0 != invoke(&uv_tty_get_winsize, get<uv_tty_t>(), &size.width, &size.height)) {
size.width = -1;
size.height = -1;
}
/**
* See Boost/Mutant idiom:
* https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Boost_mutant
*/
return reinterpret_cast<WinSize&>(size);
return size;
}
private:

View File

@ -9,7 +9,7 @@
#include "event.hpp"
#include "request.hpp"
#include "handle.hpp"
#include "misc.hpp"
#include "util.hpp"
namespace uvw {
@ -103,13 +103,12 @@ public:
*
* UDP handles encapsulate UDP communication for both clients and servers.<br/>
* By default, _IPv4_ is used as a template parameter. The handle already
* supports _IPv6_ out-of-the-box by using `uvw::net::IPv6`.
* supports _IPv6_ out-of-the-box by using `uvw::IPv6`.
*/
class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
template<typename I>
static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
typename details::IpTraits<I>::Type *aptr = reinterpret_cast<const typename details::IpTraits<I>::Type *>(addr);
int len = sizeof(*addr);
UDPHandle &udp = *(static_cast<UDPHandle*>(handle->data));
// data will be destroyed no matter of what the value of nread is
@ -117,12 +116,12 @@ class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
if(nread > 0) {
// data available (can be truncated)
udp.publish(UDPDataEvent{details::address<I>(aptr, len), std::move(data), nread, flags & UV_UDP_PARTIAL});
udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), nread, flags & UV_UDP_PARTIAL});
} else if(nread == 0 && addr == nullptr) {
// no more data to be read, doing nothing is fine
} else if(nread == 0 && addr != nullptr) {
// empty udp packet
udp.publish(UDPDataEvent{details::address<I>(aptr, len), std::move(data), nread, false});
udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), nread, false});
} else {
// transmission error
udp.publish(ErrorEvent(nread));
@ -201,7 +200,7 @@ public:
* @param port The port to which to bind.
* @param flags Optional additional flags.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
@ -223,7 +222,7 @@ public:
* @param addr A valid instance of Addr.
* @param flags Optional additional flags.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
bind<I>(addr.ip, addr.port, flags);
}
@ -232,7 +231,7 @@ public:
* @brief Get the local IP and port of the UDP handle.
* @return A valid instance of Addr, an empty one in case of errors.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
Addr sock() const noexcept {
return details::address<I>(&uv_udp_getsockname, get<uv_udp_t>());
}
@ -249,7 +248,7 @@ public:
* @param interface Interface address.
* @param membership Action to be performed.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void multicastMembership(std::string multicast, std::string interface, Membership membership) {
invoke(&uv_udp_set_membership, get<uv_udp_t>(), multicast.data(), interface.data(), static_cast<uv_membership>(membership));
}
@ -277,7 +276,7 @@ public:
* @brief Sets the multicast interface to send or receive data on.
* @param interface Interface address.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void multicastInterface(std::string interface) {
invoke(&uv_udp_set_multicast_interface, get<uv_udp_t>(), interface.data());
}
@ -313,7 +312,7 @@ public:
* @param data The data to be sent.
* @param len The lenght of the submitted data.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void send(std::string ip, unsigned int port, std::unique_ptr<char[]> data, ssize_t len) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
@ -342,7 +341,7 @@ public:
* @param len The lenght of the submitted data.
* @return Number of bytes written.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
int trySend(std::string ip, unsigned int port, std::unique_ptr<char[]> data, ssize_t len) {
typename details::IpTraits<I>::Type addr;
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
@ -368,7 +367,7 @@ public:
* An UDPDataEvent event will be emitted when the handle receives data.<br/>
* An ErrorEvent event will be emitted in case of errors.
*/
template<typename I = net::IPv4>
template<typename I = IPv4>
void recv() {
invoke(&uv_udp_recv_start, get<uv_udp_t>(), &allocCallback, &recvCallback<I>);
}

View File

@ -2,10 +2,12 @@
#include <type_traits>
#include <algorithm>
#include <stdexcept>
#include <cstddef>
#include <utility>
#include <string>
#include <vector>
#include <uv.h>
@ -149,29 +151,13 @@ private:
};
/**
* @brief Address representation.
*
* Pair alias (see Boost/Mutant idiom) used to pack together an ip and a
* port.<br/>
* Instead of `first` and `second`, the two parameters are named:
*
* * `ip`, that is of type `std::string`
* * `port`, that is of type `unsigned int`
*/
struct Addr { std::string ip; unsigned int port; };
/**
* @brief Windows size representation.
*
* Pair alias (see Boost/Mutant idiom) used to pack together a width and a
* height.<br/>
* Instead of `first` and `second`, the two parameters are named:
*
* * `width`, that is of type `int`
* * `height`, that is of type `int`
*/
struct WinSize { int width; int height; };
struct WinSize {
int width; /*!< The _width_ of the given window. */
int height; /*!< The _height_ of the given window. */
};
using HandleType = details::UVHandleType;
@ -187,67 +173,238 @@ using Gid = uv_gid_t;
/**
* @brief Gets the type of the stream to be used with the given descriptor.
* @brief The IPv4 tag.
*
* Returns the type of stream that should be used with a given file
* descriptor.<br/>
* Usually this will be used during initialization to guess the type of the
* stdio streams.
*
* @param file A valid descriptor.
* @return One of the following types:
*
* * `HandleType::UNKNOWN`
* * `HandleType::PIPE`
* * `HandleType::TCP`
* * `HandleType::TTY`
* * `HandleType::UDP`
* * `HandleType::FILE`
* To be used as template parameter to switch between IPv4 and IPv6.
*/
HandleType guessHandle(FileHandle file) {
auto type = uv_guess_handle(file);
struct IPv4 { };
switch(type) {
case UV_ASYNC:
return HandleType::ASYNC;
case UV_CHECK:
return HandleType::CHECK;
case UV_FS_EVENT:
return HandleType::FS_EVENT;
case UV_FS_POLL:
return HandleType::FS_POLL;
case UV_HANDLE:
return HandleType::HANDLE;
case UV_IDLE:
return HandleType::IDLE;
case UV_NAMED_PIPE:
return HandleType::PIPE;
case UV_POLL:
return HandleType::POLL;
case UV_PREPARE:
return HandleType::PREPARE;
case UV_PROCESS:
return HandleType::PROCESS;
case UV_STREAM:
return HandleType::STREAM;
case UV_TCP:
return HandleType::TCP;
case UV_TIMER:
return HandleType::TIMER;
case UV_TTY:
return HandleType::TTY;
case UV_UDP:
return HandleType::UDP;
case UV_SIGNAL:
return HandleType::SIGNAL;
case UV_FILE:
return HandleType::FILE;
default:
return HandleType::UNKNOWN;
/**
* @brief The IPv6 tag.
*
* To be used as template parameter to switch between IPv4 and IPv6.
*/
struct IPv6 { };
/**
* @brief Address representation.
*/
struct Addr {
std::string ip; /*!< Either an IPv4 or an IPv6. */
unsigned int port; /*!< A valid service identifier. */
};
/**
* \brief Interface address.
*/
struct Interface {
std::string name; /*!< The name of the interface (as an example _eth0_). */
std::string physical; /*!< The physical address. */
bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
Addr address; /*!< The address of the given interface. */
Addr netmask; /*!< The netmask of the given interface. */
};
namespace details {
template<typename>
struct IpTraits;
template<>
struct IpTraits<IPv4> {
using Type = sockaddr_in;
using AddrFuncType = int(*)(const char *, int, Type *);
using NameFuncType = int(*)(const Type *, char *, std::size_t);
static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
static constexpr NameFuncType nameFunc = &uv_ip4_name;
static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
};
template<>
struct IpTraits<IPv6> {
using Type = sockaddr_in6;
using AddrFuncType = int(*)(const char *, int, Type *);
using NameFuncType = int(*)(const Type *, char *, std::size_t);
static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
static constexpr NameFuncType nameFunc = &uv_ip6_name;
static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
};
template<typename I, typename..., std::size_t N = 128>
Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
Addr addr;
char name[N];
int err = details::IpTraits<I>::nameFunc(aptr, name, N);
if(0 == err) {
addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
addr.ip = std::string{name};
}
return addr;
}
template<typename I, typename F, typename H>
Addr address(F &&f, const H *handle) noexcept {
sockaddr_storage ssto;
int len = sizeof(ssto);
Addr addr{};
int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
if(0 == err) {
typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
addr = address<I>(aptr);
}
return addr;
}
template<typename F, typename H, typename..., std::size_t N = 128>
std::string path(F &&f, H *handle) noexcept {
std::size_t size = N;
char buf[size];
std::string str{};
auto err = std::forward<F>(f)(handle, buf, &size);
if(UV_ENOBUFS == err) {
std::unique_ptr<char[]> data{new char[size]};
err = std::forward<F>(f)(handle, data.get(), &size);
if(0 == err) {
str = data.get();
}
} else {
str.assign(buf, size);
}
return str;
}
}
/**
* @brief Miscellaneous utilities.
*
* Miscellaneous functions that dont really belong to any other class.
*/
struct Utilities {
/**
* @brief Gets the type of the stream to be used with the given descriptor.
*
* Returns the type of stream that should be used with a given file
* descriptor.<br/>
* Usually this will be used during initialization to guess the type of the
* stdio streams.
*
* @param file A valid descriptor.
* @return One of the following types:
*
* * `HandleType::UNKNOWN`
* * `HandleType::PIPE`
* * `HandleType::TCP`
* * `HandleType::TTY`
* * `HandleType::UDP`
* * `HandleType::FILE`
*/
static HandleType guessHandle(FileHandle file) {
auto type = uv_guess_handle(file);
switch(type) {
case UV_ASYNC:
return HandleType::ASYNC;
case UV_CHECK:
return HandleType::CHECK;
case UV_FS_EVENT:
return HandleType::FS_EVENT;
case UV_FS_POLL:
return HandleType::FS_POLL;
case UV_HANDLE:
return HandleType::HANDLE;
case UV_IDLE:
return HandleType::IDLE;
case UV_NAMED_PIPE:
return HandleType::PIPE;
case UV_POLL:
return HandleType::POLL;
case UV_PREPARE:
return HandleType::PREPARE;
case UV_PROCESS:
return HandleType::PROCESS;
case UV_STREAM:
return HandleType::STREAM;
case UV_TCP:
return HandleType::TCP;
case UV_TIMER:
return HandleType::TIMER;
case UV_TTY:
return HandleType::TTY;
case UV_UDP:
return HandleType::UDP;
case UV_SIGNAL:
return HandleType::SIGNAL;
case UV_FILE:
return HandleType::FILE;
default:
return HandleType::UNKNOWN;
}
}
/**
* @brief Gets a set of descriptors of all the available interfaces.
*
* This function can be used to query the underlying system and get a set of
* descriptors of all the available interfaces, either internal or not.
*
* @return A set of descriptors of all the available interfaces.
*/
static std::vector<Interface> interfaces() noexcept {
std::vector<Interface> interfaces;
uv_interface_address_t *ifaces;
int count;
uv_interface_addresses(&ifaces, &count);
std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
Interface interface;
interface.name = iface.name;
interface.physical = iface.phys_addr;
interface.internal = iface.is_internal;
if(iface.address.address4.sin_family == AF_INET) {
interface.address = details::address<IPv4>(&iface.address.address4);
interface.netmask = details::address<IPv4>(&iface.netmask.netmask4);
} else if(iface.address.address4.sin_family == AF_INET6) {
interface.address = details::address<IPv6>(&iface.address.address6);
interface.netmask = details::address<IPv6>(&iface.netmask.netmask6);
}
interfaces.push_back(std::move(interface));
});
uv_free_interface_addresses(ifaces, count);
return interfaces;
}
};
/**
* TODO
*
@ -256,8 +413,6 @@ HandleType guessHandle(FileHandle file) {
* * uv_getrusage
* * uv_cpu_info
* * uv_free_cpu_info
* * uv_interface_addresses
* * uv_free_interface_addresses
* * uv_loadavg
* * uv_exepath
* * uv_cwd

View File

@ -33,7 +33,7 @@ set(TARGET_WORK work)
# Test TARGET_MAIN
set(TARGET_MAIN_SOURCES main.cpp)
set(TARGET_MAIN_SOURCES odr.cpp main.cpp)
add_executable(${TARGET_MAIN} ${TARGET_MAIN_SOURCES})
target_include_directories(${TARGET_MAIN} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_MAIN} PRIVATE ${COMMON_LINK_LIBS})
@ -41,7 +41,7 @@ add_test(NAME ${TARGET_MAIN} COMMAND ${TARGET_MAIN})
# Test TARGET_ASYNC
set(TARGET_ASYNC_SOURCES uvw/async.cpp)
set(TARGET_ASYNC_SOURCES odr.cpp uvw/async.cpp)
add_executable(${TARGET_ASYNC} ${TARGET_ASYNC_SOURCES})
target_include_directories(${TARGET_ASYNC} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_ASYNC} PRIVATE ${COMMON_LINK_LIBS})
@ -49,7 +49,7 @@ add_test(NAME ${TARGET_ASYNC} COMMAND ${TARGET_ASYNC})
# Test TARGET_CHECK
set(TARGET_CHECK_SOURCES uvw/check.cpp)
set(TARGET_CHECK_SOURCES odr.cpp uvw/check.cpp)
add_executable(${TARGET_CHECK} ${TARGET_CHECK_SOURCES})
target_include_directories(${TARGET_CHECK} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_CHECK} PRIVATE ${COMMON_LINK_LIBS})
@ -57,7 +57,7 @@ add_test(NAME ${TARGET_CHECK} COMMAND ${TARGET_CHECK})
# Test TARGET_EMITTER
set(TARGET_EMITTER_SOURCES uvw/emitter.cpp)
set(TARGET_EMITTER_SOURCES odr.cpp uvw/emitter.cpp)
add_executable(${TARGET_EMITTER} ${TARGET_EMITTER_SOURCES})
target_include_directories(${TARGET_EMITTER} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_EMITTER} PRIVATE ${COMMON_LINK_LIBS})
@ -65,7 +65,7 @@ add_test(NAME ${TARGET_EMITTER} COMMAND ${TARGET_EMITTER})
# Test TARGET_IDLE
set(TARGET_IDLE_SOURCES uvw/idle.cpp)
set(TARGET_IDLE_SOURCES odr.cpp uvw/idle.cpp)
add_executable(${TARGET_IDLE} ${TARGET_IDLE_SOURCES})
target_include_directories(${TARGET_IDLE} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_IDLE} PRIVATE ${COMMON_LINK_LIBS})
@ -73,7 +73,7 @@ add_test(NAME ${TARGET_IDLE} COMMAND ${TARGET_IDLE})
# Test TARGET_LOOP
set(TARGET_LOOP_SOURCES uvw/loop.cpp)
set(TARGET_LOOP_SOURCES odr.cpp uvw/loop.cpp)
add_executable(${TARGET_LOOP} ${TARGET_LOOP_SOURCES})
target_include_directories(${TARGET_LOOP} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_LOOP} PRIVATE ${COMMON_LINK_LIBS})
@ -81,7 +81,7 @@ add_test(NAME ${TARGET_LOOP} COMMAND ${TARGET_LOOP})
# Test TARGET_PREPARE
set(TARGET_PREPARE_SOURCES uvw/prepare.cpp)
set(TARGET_PREPARE_SOURCES odr.cpp uvw/prepare.cpp)
add_executable(${TARGET_PREPARE} ${TARGET_PREPARE_SOURCES})
target_include_directories(${TARGET_PREPARE} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_PREPARE} PRIVATE ${COMMON_LINK_LIBS})
@ -89,7 +89,7 @@ add_test(NAME ${TARGET_PREPARE} COMMAND ${TARGET_PREPARE})
# Test TARGET_SIGNAL
set(TARGET_SIGNAL_SOURCES uvw/signal.cpp)
set(TARGET_SIGNAL_SOURCES odr.cpp uvw/signal.cpp)
add_executable(${TARGET_SIGNAL} ${TARGET_SIGNAL_SOURCES})
target_include_directories(${TARGET_SIGNAL} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_SIGNAL} PRIVATE ${COMMON_LINK_LIBS})
@ -97,7 +97,7 @@ add_test(NAME ${TARGET_SIGNAL} COMMAND ${TARGET_SIGNAL})
# Test TARGET_TIMER
set(TARGET_TIMER_SOURCES uvw/timer.cpp)
set(TARGET_TIMER_SOURCES odr.cpp uvw/timer.cpp)
add_executable(${TARGET_TIMER} ${TARGET_TIMER_SOURCES})
target_include_directories(${TARGET_TIMER} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_TIMER} PRIVATE ${COMMON_LINK_LIBS})
@ -105,7 +105,7 @@ add_test(NAME ${TARGET_TIMER} COMMAND ${TARGET_TIMER})
# Test TARGET_WORK
set(TARGET_WORK_SOURCES uvw/work.cpp)
set(TARGET_WORK_SOURCES odr.cpp uvw/work.cpp)
add_executable(${TARGET_WORK} ${TARGET_WORK_SOURCES})
target_include_directories(${TARGET_WORK} PRIVATE ${COMMON_INCLUDE_DIRS})
target_link_libraries(${TARGET_WORK} PRIVATE ${COMMON_LINK_LIBS})

1
test/odr.cpp Normal file
View File

@ -0,0 +1 @@
#include <uvw.hpp>