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

Minor mlib tweaks and fixes #302

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 1 addition & 17 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,7 @@ configure_file (

# Define the mlib target, which is private and header-only. It is not exported
# nor are its headers installed.
add_library (_mongo-mlib INTERFACE)
add_library (mongo::mlib ALIAS _mongo-mlib)
set_property(
TARGET _mongo-mlib
APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS
MLIB_USER
)
include (./src/mlib/mlib.cmake)

# kms-message
add_subdirectory (kms-message)
Expand Down Expand Up @@ -405,12 +399,6 @@ add_test (
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

foreach (test IN ITEMS path str)
add_executable (mlib.${test}.test src/mlib/${test}.test.c)
add_test (mlib.${test} mlib.${test}.test)
target_link_libraries (mlib.${test}.test PRIVATE mongo::mlib)
endforeach ()

# Exclude example-state-machine since it requires native crypto.
if (NOT MONGOCRYPT_CRYPTO STREQUAL none)
# Define example-state-machine
Expand Down Expand Up @@ -453,10 +441,6 @@ install (
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

# This export set is not installed, and is only to allow export() of the mlib-using targets
install (TARGETS _mongo-mlib EXPORT _exports_for_export)
export (EXPORT _exports_for_export)

install (
FILES
${MONGOCRYPT_PUBLIC_HEADERS}
Expand Down
2 changes: 1 addition & 1 deletion src/mlib/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* @return mstr A new string containing the resulting error. Must be freed with
* @ref mstr_free().
*/
static inline mstr
mlib_inline_def mstr
merror_system_error_string (int errn)
{
#ifdef _WIN32
Expand Down
7 changes: 7 additions & 0 deletions src/mlib/linkcheck-1.test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "./str.h"

void *
get_func_addr_1 ()
{
return &mstr_new;
}
7 changes: 7 additions & 0 deletions src/mlib/linkcheck-2.test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "./str.h"

void *
get_func_addr_2 ()
{
return &mstr_new;
}
15 changes: 15 additions & 0 deletions src/mlib/linkcheck.test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdio.h>

extern void *
get_func_addr_1 ();
extern void *
get_func_addr_2 ();

int
main ()
{
if (get_func_addr_1 () != get_func_addr_2 ()) {
fputs ("Multiply-defined symbols were not properly merged.", stderr);
return 1;
}
}
48 changes: 48 additions & 0 deletions src/mlib/macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef MLIB_MACROS_H
#define MLIB_MACROS_H

#include "./user-check.h"

/**
* @macro mlib_inline Expands to the compiler's "inline" keyword. On C99, just
* 'inline'. On older compilers pre-C99, an implementation-defined "inline"
*/

// clang-format off
#if defined(__GNUC__) || defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1900)
#define mlib_inline inline
#elif defined(_MSC_VER)
#define mlib_inline __inline
#else
#define mlib_inline _Do_not_know_how_to_say_inline_on_this_compiler
#endif

/**
* @macro mlib_inline_def
* @brief Declare a function to be inline-defined, but with external linkage.
*
* This has the effect that there will be only one definiton if the final
* program, even if the function is defined in multiple translation units
* (e.g as the result of #inclusion). This mimicks the linkage behavior of
* C++ 'inline' keyword, which is not shared by C99's 'inline'.
*/
#ifdef __INTELLISENSE__
// Give a pretty definition for intellisense readers
#define mlib_inline_def inline
#elif defined(_WIN32)
#ifdef __GNUC__
#define mlib_inline_def extern __attribute__((weak, visibility("hidden")))
#else
// On MSVC/Windows, inline functions are implicitly in COMDAT, even in C
#define mlib_inline_def extern mlib_inline
#endif
#else
// On other platforms, declare the symbol "weak" to cause symbol merging,
// and "hidden" to disable the ability for the symbol to be overridden via
// interposition
#define mlib_inline_def extern __attribute__((weak, visibility("hidden")))
#endif

// clang-format on

#endif // MLIB_MACROS_H
38 changes: 38 additions & 0 deletions src/mlib/mlib.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
set (MLIB_SRC_DIR "${CMAKE_CURRENT_LIST_DIR}")

add_library (_mongo-mlib INTERFACE)
get_filename_component (_inc_dir "${MLIB_SRC_DIR}" DIRECTORY)
target_include_directories (_mongo-mlib INTERFACE "${_inc_dir}")
target_compile_definitions (_mongo-mlib INTERFACE MLIB_USER)
add_library (mongo::mlib ALIAS _mongo-mlib)

set (_components error path str thread user-check)
foreach (comp IN LISTS _components)
set (test_file "${MLIB_SRC_DIR}/${comp}.test.c")
if (EXISTS "${test_file}")
add_executable (mlib.test.${comp} "${test_file}")
target_link_libraries (mlib.test.${comp} PRIVATE mongo::mlib)
add_test (mlib.test.${comp} mlib.test.${comp})
list (APPEND MLIB_SOURCE "${test_file}")
endif ()
endforeach ()

# This is only here to support export() of mongo::mlib-linked targets.
# Nothing is actually installed
install (TARGETS _mongo-mlib EXPORT _mongo-mlib)
export (EXPORT _mongo-mlib)

function (targets_use_mlib)
foreach (t IN LISTS ARGV)
target_link_libraries("${t}" PRIVATE $<BUILD_INTERFACE:mongo::mlib>)
endforeach ()
endfunction ()

add_executable (mlib.test.comdat-link
"${MLIB_SRC_DIR}/linkcheck-1.test.c"
"${MLIB_SRC_DIR}/linkcheck-2.test.c"
"${MLIB_SRC_DIR}/linkcheck.test.c"
)

add_test (mlib.test.comdat-link mlib.test.comdat-link)
targets_use_mlib (mlib.test.comdat-link)
35 changes: 18 additions & 17 deletions src/mlib/path.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "./user-check.h"

#include "./str.h"
#include "./macros.h"

#include <inttypes.h>

Expand Down Expand Up @@ -34,7 +35,7 @@ typedef enum mpath_format {
* @param c A path character
* @param f The path format to use
*/
static inline bool
mlib_inline_def bool
mpath_is_sep (char c, mpath_format f)
{
if (f == MPATH_WIN32) {
Expand All @@ -47,7 +48,7 @@ mpath_is_sep (char c, mpath_format f)
/**
* @brief Obtain the preferred path separator character for the given format
*/
static inline char
mlib_inline_def char
mpath_preferred_sep (mpath_format f)
{
if (f == MPATH_WIN32) {
Expand All @@ -63,7 +64,7 @@ mpath_preferred_sep (mpath_format f)
*
* @return mstr A new string which must be freed with mstr_free()
*/
static inline mstr
mlib_inline_def mstr
mpath_current_path ()
{
#if _WIN32
Expand Down Expand Up @@ -96,7 +97,7 @@ mpath_current_path ()
/**
* @brief Determine whether the given path string has a trailing path separator
*/
static inline bool
mlib_inline_def bool
mpath_has_trailing_sep (mstr_view path, mpath_format f)
{
return path.len && mpath_is_sep (path.data[path.len - 1], f);
Expand All @@ -105,7 +106,7 @@ mpath_has_trailing_sep (mstr_view path, mpath_format f)
/**
* @brief Obtain the parent path of the given path.
*/
static inline mstr_view
mlib_inline_def mstr_view
mpath_parent (mstr_view path, mpath_format f)
{
if (mpath_has_trailing_sep (path, f)) {
Expand Down Expand Up @@ -133,7 +134,7 @@ mpath_parent (mstr_view path, mpath_format f)
* The returned path will include no directory separators. If the given path
* ends with a directory separator, the single-dot '.' path is returned instead.
*/
static inline mstr_view
mlib_inline_def mstr_view
mpath_filename (mstr_view path, mpath_format f)
{
if (!path.len) {
Expand Down Expand Up @@ -163,7 +164,7 @@ mpath_filename (mstr_view path, mpath_format f)
* @param f The path format to use
* @return mstr A new string resulting from the join
*/
static inline mstr
mlib_inline_def mstr
mpath_join (mstr_view base, mstr_view suffix, mpath_format f)
{
if (!base.len) {
Expand Down Expand Up @@ -194,7 +195,7 @@ mpath_join (mstr_view base, mstr_view suffix, mpath_format f)
* For the Windows format, this will return the drive letter, if present.
* Otherwise, this will return an empty string.
*/
static inline mstr_view
mlib_inline_def mstr_view
mpath_root_name (mstr_view path, mpath_format f)
{
if (f == MPATH_WIN32 && path.len > 1) {
Expand All @@ -212,7 +213,7 @@ mpath_root_name (mstr_view path, mpath_format f)
*
* @note This will not include the drive letter of a Win32 path.
*/
static inline mstr_view
mlib_inline_def mstr_view
mpath_root_directory (mstr_view path, mpath_format f)
{
mstr_view rname = mpath_root_name (path, f);
Expand All @@ -229,7 +230,7 @@ mpath_root_directory (mstr_view path, mpath_format f)
*
* This will include both the root name and the root filepath, if present.
*/
static inline mstr_view
mlib_inline_def mstr_view
mpath_root_path (mstr_view path, mpath_format f)
{
mstr_view rname = mpath_root_name (path, f);
Expand All @@ -243,7 +244,7 @@ mpath_root_path (mstr_view path, mpath_format f)
*
* @note A Win32 filepath without a drive letter is not absolute!
*/
static inline bool
mlib_inline_def bool
mpath_is_absolute (mstr_view path, mpath_format f)
{
if (f == MPATH_WIN32) {
Expand All @@ -263,7 +264,7 @@ mpath_is_absolute (mstr_view path, mpath_format f)
* If the path has a root path, returns the content of the path following that
* root path, otherwise returns the same path itself.
*/
static inline mstr_view
mlib_inline_def mstr_view
mpath_relative_path (mstr_view path, mpath_format f)
{
mstr_view root = mpath_root_path (path, f);
Expand All @@ -276,7 +277,7 @@ mpath_relative_path (mstr_view path, mpath_format f)
*
* @note The return value must be freed with mstr_free()
*/
static inline mstr
mlib_inline_def mstr
mpath_to_format (mpath_format from, mstr_view path, mpath_format to)
{
mstr_mut ret = mstr_new (path.len);
Expand All @@ -296,7 +297,7 @@ mpath_to_format (mpath_format from, mstr_view path, mpath_format to)
/**
* @brief Determine whether the given path is relative (not absolute)
*/
static inline bool
mlib_inline_def bool
mpath_is_relative (mstr_view path, mpath_format f)
{
return !mpath_is_absolute (path, f);
Expand All @@ -307,7 +308,7 @@ mpath_is_relative (mstr_view path, mpath_format f)
*
* @note The return value must be freed with mstr_free()
*/
static inline mstr
mlib_inline_def mstr
mpath_absolute (mstr_view path, mpath_format f);

/**
Expand All @@ -320,7 +321,7 @@ mpath_absolute (mstr_view path, mpath_format f);
* @note If `base` is also a relative path, it will also be given to
* mpath_absolute() to resolve it.
*/
static inline mstr
mlib_inline_def mstr
mpath_absolute_from (mstr_view path, mstr_view base, mpath_format f)
{
mstr_view rname = mpath_root_name (path, f);
Expand Down Expand Up @@ -363,7 +364,7 @@ mpath_absolute_from (mstr_view path, mstr_view base, mpath_format f)
}
}

static inline mstr
mlib_inline_def mstr
mpath_absolute (mstr_view path, mpath_format f)
{
if (mpath_is_absolute (path, f)) {
Expand Down
Loading