diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..c4223c7 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,26 @@ +version: '{build}' + +image: Visual Studio 2017 + +init: + - cmd: git config --global core.autocrlf true + +platform: + - x64 + +configuration: + - Debug + - Release + +before_build: + - cmake -H. -Bbuild -A%PLATFORM% -DBUILD_TESTING=ON + +build: + project: build\opentracing-cpp.sln + parallel: false + verbosity: normal + +test_script: +- ps: | + cd build + ctest -V -C $env:configuration --timeout 600 --output-on-failure \ No newline at end of file diff --git a/.gitignore b/.gitignore index c09aba1..a9424d3 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,9 @@ *.out *.app +# Cmake Build Directory +build + # Ignore all bazel-* symlinks. There is no full list since this can change # based on the name of the directory bazel is cloned into. /bazel-* diff --git a/BUILD.bazel b/BUILD.bazel index d01d631..c57dc9f 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,6 +1,6 @@ cc_library( name = "opentracing", - srcs = glob(["src/**/*.cpp"], exclude=["src/dynamic_load_unsupported.cpp"]), + srcs = glob(["src/**/*.cpp"], exclude=["src/dynamic_load_unsupported.cpp", "src/dynamic_load_windows.cpp"]), hdrs = glob(["include/opentracing/**/*.h"]) + [ ":include/opentracing/config.h", ":include/opentracing/version.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cf3c88..4fa5829 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,10 @@ SET(CPACK_PACKAGE_VERSION_MINOR ${OPENTRACING_VERSION_MINOR}) SET(CPACK_PACKAGE_VERSION_PATCH ${OPENTRACING_VERSION_PATCH}) include(CPack) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output) + # ============================================================================== # Configure compilers @@ -40,6 +44,8 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") -Wno-padded") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_RELEASE} -D_SCL_SECURE_NO_WARNINGS") endif() # ============================================================================== @@ -74,9 +80,11 @@ option(BUILD_MOCKTRACER "Build mocktracer library" ON) option(BUILD_DYNAMIC_LOADING "Build with dynamic loading support" ON) if (BUILD_DYNAMIC_LOADING) - if (NOT SUPPORTS_WEAK_SYMBOLS OR NOT UNIX) - message(WARNING "Building without dynamic loading support.") - set(BUILD_DYNAMIC_LOADING OFF) + if (NOT WIN32) + if (NOT SUPPORTS_WEAK_SYMBOLS OR NOT UNIX) + message(WARNING "Building without dynamic loading support.") + set(BUILD_DYNAMIC_LOADING OFF) + endif() endif() endif() @@ -116,7 +124,11 @@ set(SRCS src/propagation.cpp src/ext/tags.cpp) if (BUILD_DYNAMIC_LOADING) - list(APPEND SRCS src/dynamic_load_unix.cpp) + if (WIN32) + list(APPEND SRCS src/dynamic_load_windows.cpp) + else() + list(APPEND SRCS src/dynamic_load_unix.cpp) + endif() else() list(APPEND SRCS src/dynamic_load_unsupported.cpp) endif() @@ -133,7 +145,9 @@ if (BUILD_SHARED_LIBS) target_include_directories(opentracing INTERFACE "$") set_target_properties(opentracing PROPERTIES VERSION ${OPENTRACING_VERSION_STRING} SOVERSION ${OPENTRACING_VERSION_MAJOR}) + target_compile_definitions(opentracing PRIVATE OPENTRACING_EXPORTS) install(TARGETS opentracing EXPORT OpenTracingTargets + RUNTIME DESTINATION ${LIB_INSTALL_DIR} LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) if (CLANG_TIDY_EXE) @@ -145,7 +159,11 @@ endif() if (BUILD_STATIC_LIBS) add_library(opentracing-static STATIC ${SRCS}) target_link_libraries(opentracing-static ${LIBRARIES}) - set_target_properties(opentracing-static PROPERTIES OUTPUT_NAME opentracing) + # Windows generates a lib and dll files for a shared library. using the same name will override the lib file generated by the shared target + if (NOT WIN32) + set_target_properties(opentracing-static PROPERTIES OUTPUT_NAME opentracing) + endif() + target_compile_definitions(opentracing-static PRIVATE OPENTRACING_STATIC) target_include_directories(opentracing-static INTERFACE "$") install(TARGETS opentracing-static EXPORT OpenTracingTargets ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) diff --git a/README.md b/README.md index 94c27e6..2df6aaf 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ In order to understand the C++ platform API, one must first be familiar with the ## Compile and install +#### Linux/MacOS + ```bash mkdir .build cd .build @@ -25,6 +27,32 @@ To test: make test ``` +#### Windows + +```bash +mkdir .build +cd .build +cmake -G "Visual Studio 15 2017 Win64" .. +``` +To build the targets in debug mode +```bash +MSBuild.exe opentracing-cpp.sln /p:Configuration=Debug /Target=Build +``` +To build the targets in release mode +```bash +MSBuild.exe opentracing-cpp.sln /p:Configuration=Release /Target=Build +``` + +To test: +Run the below command to run the tests with the debug targets +```bash +ctest -C Debug +``` +Run the below command to run the tests with the release targets +```bash +ctest -C Release +``` + ## API overview for those adding instrumentation Everyday consumers of this `opentracing` package really only need to worry diff --git a/example/dynamic_load/dynamic_load-example.cpp b/example/dynamic_load/dynamic_load-example.cpp index 8ef1cb1..f49996f 100644 --- a/example/dynamic_load/dynamic_load-example.cpp +++ b/example/dynamic_load/dynamic_load-example.cpp @@ -13,6 +13,11 @@ #include #include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + int main(int argc, char* argv[]) { if (argc != 3) { std::cerr << "Usage: \n"; diff --git a/example/tutorial/CMakeLists.txt b/example/tutorial/CMakeLists.txt index e72cce7..11daf16 100644 --- a/example/tutorial/CMakeLists.txt +++ b/example/tutorial/CMakeLists.txt @@ -1,6 +1,6 @@ if (BUILD_MOCKTRACER AND BUILD_SHARED_LIBS) include_directories(../../mocktracer/include) add_executable(tutorial-example tutorial-example.cpp) - target_link_libraries(tutorial-example opentracing_mocktracer) - add_test(tutorial-example tutorial-example) + target_link_libraries(tutorial-example opentracing_mocktracer) + add_test(NAME tutorial-example COMMAND tutorial-example) endif() diff --git a/include/opentracing/dynamic_load.h b/include/opentracing/dynamic_load.h index 1d265ef..6d11e54 100644 --- a/include/opentracing/dynamic_load.h +++ b/include/opentracing/dynamic_load.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_DYNAMIC_LOAD_H #define OPENTRACING_DYNAMIC_LOAD_H +#include #include #include #include @@ -35,14 +36,37 @@ // assert(error_category != nullptr); // std::error_code error{rcode, *error_category}; // } -extern "C" { -#ifdef OPENTRACING_BUILD_DYNAMIC_LOADING -int __attribute((weak)) -OpenTracingMakeTracerFactory(const char* opentracing_version, - const void** error_category, - void** tracer_factory); + +using OpenTracingMakeTracerFactoryType = int(const char* opentracing_version, + const void** error_category, + void** tracer_factory); + +#ifdef WIN32 + +#define OPENTRACING_DECLARE_IMPL_FACTORY(X) \ + extern "C" { \ + \ +extern __declspec(dllexport) \ + OpenTracingMakeTracerFactoryType* const OpenTracingMakeTracerFactory; \ + \ +__declspec(selectany) OpenTracingMakeTracerFactoryType* const \ + OpenTracingMakeTracerFactory = X; \ + } // extern "C" + +#else + +#define OPENTRACING_DECLARE_IMPL_FACTORY(X) \ + extern "C" { \ + \ +__attribute((weak)) extern OpenTracingMakeTracerFactoryType* const \ + OpenTracingMakeTracerFactory; \ + \ + OpenTracingMakeTracerFactoryType* const OpenTracingMakeTracerFactory = X; \ + } // extern "C" + #endif -} // extern "C" + + namespace opentracing { BEGIN_OPENTRACING_ABI_NAMESPACE @@ -52,7 +76,7 @@ BEGIN_OPENTRACING_ABI_NAMESPACE // See // http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html // https://ned14.github.io/boost.outcome/md_doc_md_03-tutorial_b.html -const std::error_category& dynamic_load_error_category(); +OPENTRACING_API const std::error_category& dynamic_load_error_category(); // `dynamic_load_failure_error` occurs when dynamically loading a tracer library // fails. Possible reasons could be the library doesn't exist or it is missing @@ -117,7 +141,8 @@ class DynamicTracingLibraryHandle { // } // // See DynamicTracingLibraryHandle, TracerFactory -expected DynamicallyLoadTracingLibrary( +OPENTRACING_API expected +DynamicallyLoadTracingLibrary( const char* shared_library, std::string& error_message) noexcept; END_OPENTRACING_ABI_NAMESPACE } // namespace opentracing diff --git a/include/opentracing/ext/tags.h b/include/opentracing/ext/tags.h index 9918c26..cd4c140 100644 --- a/include/opentracing/ext/tags.h +++ b/include/opentracing/ext/tags.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_EXT_TAGS_H #define OPENTRACING_EXT_TAGS_H +#include #include #include @@ -19,13 +20,13 @@ namespace ext { // --------------------------------------------------------------------------- // span_kind hints at relationship between spans, e.g. client/server // --------------------------------------------------------------------------- -extern const opentracing::string_view span_kind; +OPENTRACING_API extern const opentracing::string_view span_kind; // Marks a span representing the client-side of an RPC or other remote call -extern const opentracing::string_view span_kind_rpc_client; +OPENTRACING_API extern const opentracing::string_view span_kind_rpc_client; // Marks a span representing the server-side of an RPC or other remote call -extern const opentracing::string_view span_kind_rpc_server; +OPENTRACING_API extern const opentracing::string_view span_kind_rpc_server; // --------------------------------------------------------------------------- // error indicates whether a Span ended in an error state. diff --git a/include/opentracing/noop.h b/include/opentracing/noop.h index 9509c90..5313489 100644 --- a/include/opentracing/noop.h +++ b/include/opentracing/noop.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_NOOP_H #define OPENTRACING_NOOP_H +#include #include #include #include @@ -20,7 +21,7 @@ BEGIN_OPENTRACING_ABI_NAMESPACE // (see Tracer::Global and Tracer::InitGlobal functions). // // WARNING: NoopTracer does not support baggage propagation. -std::shared_ptr MakeNoopTracer() noexcept; +OPENTRACING_API std::shared_ptr MakeNoopTracer() noexcept; END_OPENTRACING_ABI_NAMESPACE } // namespace opentracing diff --git a/include/opentracing/propagation.h b/include/opentracing/propagation.h index 923cb16..bb889c5 100644 --- a/include/opentracing/propagation.h +++ b/include/opentracing/propagation.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_PROPAGATION_H #define OPENTRACING_PROPAGATION_H +#include #include #include #include @@ -62,7 +63,7 @@ enum class SpanReferenceType { // See // http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html // https://ned14.github.io/boost.outcome/md_doc_md_03-tutorial_b.html -const std::error_category& propagation_error_category(); +OPENTRACING_API const std::error_category& propagation_error_category(); // `invalid_span_context_error` occurs when Tracer::Inject() is asked to operate // on a SpanContext which it is not prepared to handle (for example, since it diff --git a/include/opentracing/symbols.h b/include/opentracing/symbols.h new file mode 100644 index 0000000..d34f473 --- /dev/null +++ b/include/opentracing/symbols.h @@ -0,0 +1,34 @@ +#ifndef OPENTRACING_SYMBOLS_H +#define OPENTRACING_SYMBOLS_H + +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4251) +#endif + +#ifdef _MSC_VER + +#define OPENTRACING_EXPORT __declspec(dllexport) + +// Export if this is our own source, otherwise import: +#ifndef OPENTRACING_STATIC +#ifdef OPENTRACING_EXPORTS +#define OPENTRACING_API __declspec(dllexport) +#else // OPENTRACING_STATIC +#define OPENTRACING_API __declspec(dllimport) +#endif // OPENTRACING_EXPORTS +#endif // OPENTRACING_STATIC + +#endif // _MSC_VER + +#ifndef OPENTRACING_EXPORT +#define OPENTRACING_EXPORT +#endif + +#ifndef OPENTRACING_API +#define OPENTRACING_API +#endif + +#endif // OPENTRACING_SYMBOLS_H diff --git a/include/opentracing/tracer.h b/include/opentracing/tracer.h index b085dee..2beadab 100644 --- a/include/opentracing/tracer.h +++ b/include/opentracing/tracer.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_TRACER_H #define OPENTRACING_TRACER_H +#include #include #include #include @@ -57,7 +58,7 @@ class StartSpanOption { // Tracer is a simple, thin interface for Span creation and SpanContext // propagation. -class Tracer { +class OPENTRACING_API Tracer { public: virtual ~Tracer() = default; diff --git a/include/opentracing/tracer_factory.h b/include/opentracing/tracer_factory.h index c2d0354..622fa5b 100644 --- a/include/opentracing/tracer_factory.h +++ b/include/opentracing/tracer_factory.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_TRACER_FACTORY_H #define OPENTRACING_TRACER_FACTORY_H +#include #include #include @@ -11,7 +12,7 @@ BEGIN_OPENTRACING_ABI_NAMESPACE // See // http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html // https://ned14.github.io/boost.outcome/md_doc_md_03-tutorial_b.html -const std::error_category& tracer_factory_error_category(); +OPENTRACING_API const std::error_category& tracer_factory_error_category(); // `configuration_parse_error` occurs when the configuration string used to // construct a tracer does not adhere to the expected format. @@ -24,7 +25,7 @@ const std::error_code invalid_configuration_error( 2, tracer_factory_error_category()); // TracerFactory constructs tracers from configuration strings. -class TracerFactory { +class OPENTRACING_API TracerFactory { public: virtual ~TracerFactory() = default; diff --git a/mocktracer/CMakeLists.txt b/mocktracer/CMakeLists.txt index 57076cd..5165744 100644 --- a/mocktracer/CMakeLists.txt +++ b/mocktracer/CMakeLists.txt @@ -16,15 +16,22 @@ if (BUILD_SHARED_LIBS) target_include_directories(opentracing_mocktracer INTERFACE "$") set_target_properties(opentracing_mocktracer PROPERTIES VERSION ${OPENTRACING_VERSION_STRING} SOVERSION ${OPENTRACING_VERSION_MAJOR}) - target_link_libraries(opentracing_mocktracer opentracing) + target_link_libraries(opentracing_mocktracer PUBLIC opentracing) + target_compile_definitions(opentracing_mocktracer PRIVATE OPENTRACING_MOCK_TRACER_EXPORTS) install(TARGETS opentracing_mocktracer EXPORT OpenTracingTargets LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) + + endif() if (BUILD_STATIC_LIBS) add_library(opentracing_mocktracer-static STATIC ${SRCS}) - set_target_properties(opentracing_mocktracer-static PROPERTIES OUTPUT_NAME opentracing_mocktracer) + # Windows generates a lib and dll files for a shared library. using the same name will override the lib file generated by the shared target + if (NOT WIN32) + set_target_properties(opentracing_mocktracer-static PROPERTIES OUTPUT_NAME opentracing_mocktracer) + endif() + target_compile_definitions(opentracing_mocktracer-static PRIVATE OPENTRACING_MOCK_TRACER_STATIC) target_include_directories(opentracing_mocktracer-static INTERFACE "$") target_link_libraries(opentracing_mocktracer-static opentracing-static) install(TARGETS opentracing_mocktracer-static EXPORT OpenTracingTargets diff --git a/mocktracer/include/opentracing/mocktracer/in_memory_recorder.h b/mocktracer/include/opentracing/mocktracer/in_memory_recorder.h index b379e86..709816d 100644 --- a/mocktracer/include/opentracing/mocktracer/in_memory_recorder.h +++ b/mocktracer/include/opentracing/mocktracer/in_memory_recorder.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_MOCKTRACER_IN_MEMORY_RECORDER_H #define OPENTRACING_MOCKTRACER_IN_MEMORY_RECORDER_H +#include #include #include #include @@ -9,7 +10,7 @@ namespace opentracing { BEGIN_OPENTRACING_ABI_NAMESPACE namespace mocktracer { // InMemoryRecorder stores finished spans and provides accessors to them. -class InMemoryRecorder : public Recorder { +class OPENTRACING_MOCK_TRACER_API InMemoryRecorder : public Recorder { public: void RecordSpan(SpanData&& span_data) noexcept override; diff --git a/mocktracer/include/opentracing/mocktracer/json.h b/mocktracer/include/opentracing/mocktracer/json.h index 99f42a3..d80dde1 100644 --- a/mocktracer/include/opentracing/mocktracer/json.h +++ b/mocktracer/include/opentracing/mocktracer/json.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_MOCKTRACER_JSON_H #define OPENTRACING_MOCKTRACER_JSON_H +#include #include #include @@ -8,7 +9,7 @@ namespace opentracing { BEGIN_OPENTRACING_ABI_NAMESPACE namespace mocktracer { // Serialize provided spans to JSON. -void ToJson(std::ostream& writer, const std::vector& spans); +OPENTRACING_MOCK_TRACER_API void ToJson(std::ostream& writer, const std::vector& spans); } // namespace mocktracer END_OPENTRACING_ABI_NAMESPACE } // namespace opentracing diff --git a/mocktracer/include/opentracing/mocktracer/json_recorder.h b/mocktracer/include/opentracing/mocktracer/json_recorder.h index b452a94..cca55aa 100644 --- a/mocktracer/include/opentracing/mocktracer/json_recorder.h +++ b/mocktracer/include/opentracing/mocktracer/json_recorder.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_MOCKTRACER_JSON_RECORDER_H #define OPENTRACING_MOCKTRACER_JSON_RECORDER_H +#include #include #include #include @@ -14,7 +15,7 @@ namespace mocktracer { // format. // // See also FromJson. -class JsonRecorder : public Recorder { +class OPENTRACING_MOCK_TRACER_API JsonRecorder : public Recorder { public: explicit JsonRecorder(std::unique_ptr&& out); diff --git a/mocktracer/include/opentracing/mocktracer/recorder.h b/mocktracer/include/opentracing/mocktracer/recorder.h index 3104c94..d6b8554 100644 --- a/mocktracer/include/opentracing/mocktracer/recorder.h +++ b/mocktracer/include/opentracing/mocktracer/recorder.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_MOCKTRACER_RECORDER_H #define OPENTRACING_MOCKTRACER_RECORDER_H +#include #include #include @@ -70,7 +71,7 @@ inline bool operator!=(const SpanData& lhs, const SpanData& rhs) { std::ostream& operator<<(std::ostream& out, const SpanData& span_data); -class Recorder { +class OPENTRACING_MOCK_TRACER_API Recorder { public: virtual ~Recorder() = default; diff --git a/mocktracer/include/opentracing/mocktracer/symbols.h b/mocktracer/include/opentracing/mocktracer/symbols.h new file mode 100644 index 0000000..9c63628 --- /dev/null +++ b/mocktracer/include/opentracing/mocktracer/symbols.h @@ -0,0 +1,21 @@ +#ifndef OPENTRACING_MOCK_TRACER_SYMBOLS_H +#define OPENTRACING_MOCK_TRACER_SYMBOLS_H + +#include + +#ifdef _MSC_VER +// Export if this is our own source, otherwise import: +#ifndef OPENTRACING_MOCK_TRACER_STATIC +#ifdef OPENTRACING_MOCK_TRACER_EXPORTS +#define OPENTRACING_MOCK_TRACER_API __declspec(dllexport) +#else +#define OPENTRACING_MOCK_TRACER_API __declspec(dllimport) +#endif +#endif +#endif // _MSC_VER + +#ifndef OPENTRACING_MOCK_TRACER_API +#define OPENTRACING_MOCK_TRACER_API +#endif + +#endif // OPENTRACING_SYMBOLS_H diff --git a/mocktracer/include/opentracing/mocktracer/tracer.h b/mocktracer/include/opentracing/mocktracer/tracer.h index 646375d..63af2cb 100644 --- a/mocktracer/include/opentracing/mocktracer/tracer.h +++ b/mocktracer/include/opentracing/mocktracer/tracer.h @@ -1,6 +1,7 @@ #ifndef OPENTRACING_MOCKTRACER_TRACER_H #define OPENTRACING_MOCKTRACER_TRACER_H +#include #include #include #include @@ -36,8 +37,8 @@ struct MockTracerOptions { // MockTracer provides implements the OpenTracing Tracer API. It provides // convenient access to finished spans in such a way as to support testing. -class MockTracer : public Tracer, - public std::enable_shared_from_this { +class OPENTRACING_MOCK_TRACER_API MockTracer : public Tracer, + public std::enable_shared_from_this { public: explicit MockTracer(MockTracerOptions&& options); diff --git a/mocktracer/include/opentracing/mocktracer/tracer_factory.h b/mocktracer/include/opentracing/mocktracer/tracer_factory.h index 49227e0..19106ff 100644 --- a/mocktracer/include/opentracing/mocktracer/tracer_factory.h +++ b/mocktracer/include/opentracing/mocktracer/tracer_factory.h @@ -1,13 +1,14 @@ #ifndef OPENTRACING_MOCKTRACER_TRACER_FACTORY_H #define OPENTRACING_MOCKTRACER_TRACER_FACTORY_H +#include #include namespace opentracing { BEGIN_OPENTRACING_ABI_NAMESPACE namespace mocktracer { -class MockTracerFactory : public TracerFactory { +class OPENTRACING_MOCK_TRACER_API MockTracerFactory : public TracerFactory { public: expected> MakeTracer(const char* configuration, std::string& error_message) const diff --git a/mocktracer/src/dynamic_load.cpp b/mocktracer/src/dynamic_load.cpp index 3aad32a..9df0361 100644 --- a/mocktracer/src/dynamic_load.cpp +++ b/mocktracer/src/dynamic_load.cpp @@ -4,7 +4,7 @@ #include #include -int OpenTracingMakeTracerFactory(const char* opentracing_version, +static int OpenTracingMakeTracerFactoryFct(const char* opentracing_version, const void** error_category, void** tracer_factory) { if (error_category == nullptr || tracer_factory == nullptr) { @@ -28,3 +28,5 @@ int OpenTracingMakeTracerFactory(const char* opentracing_version, return 0; } + +OPENTRACING_DECLARE_IMPL_FACTORY(OpenTracingMakeTracerFactoryFct); diff --git a/mocktracer/src/tracer.cpp b/mocktracer/src/tracer.cpp index a099326..e5f9127 100644 --- a/mocktracer/src/tracer.cpp +++ b/mocktracer/src/tracer.cpp @@ -6,6 +6,12 @@ #include "mock_span_context.h" #include "propagation.h" +#include +#include +#include +#include +#include + namespace opentracing { BEGIN_OPENTRACING_ABI_NAMESPACE namespace mocktracer { diff --git a/mocktracer/test/CMakeLists.txt b/mocktracer/test/CMakeLists.txt index 32bbae2..f12033e 100644 --- a/mocktracer/test/CMakeLists.txt +++ b/mocktracer/test/CMakeLists.txt @@ -6,16 +6,16 @@ endif() add_executable(mocktracer_tracer_test tracer_test.cpp) target_link_libraries(mocktracer_tracer_test ${OPENTRACING_MOCKTRACER_LIBRARY}) -add_test(mocktracer_tracer_test mocktracer_tracer_test) +add_test(NAME mocktracer_tracer_test COMMAND mocktracer_tracer_test) add_executable(mocktracer_tracer_factory_test tracer_factory_test.cpp) target_link_libraries(mocktracer_tracer_factory_test ${OPENTRACING_MOCKTRACER_LIBRARY}) -add_test(mocktracer_tracer_factory_test mocktracer_tracer_factory_test) +add_test(NAME mocktracer_tracer_factory_test COMMAND mocktracer_tracer_factory_test) add_executable(mocktracer_propagation_test propagation_test.cpp) target_link_libraries(mocktracer_propagation_test ${OPENTRACING_MOCKTRACER_LIBRARY}) -add_test(mocktracer_propagation_test mocktracer_propagation_test) +add_test(NAME mocktracer_propagation_test COMMAND mocktracer_propagation_test) add_executable(mocktracer_json_test json_test.cpp) target_link_libraries(mocktracer_json_test ${OPENTRACING_MOCKTRACER_LIBRARY}) -add_test(mocktracer_json_test mocktracer_json_test) +add_test(NAME mocktracer_json_test COMMAND mocktracer_json_test) diff --git a/mocktracer/test/json_test.cpp b/mocktracer/test/json_test.cpp index 4068125..d53d29b 100644 --- a/mocktracer/test/json_test.cpp +++ b/mocktracer/test/json_test.cpp @@ -71,5 +71,6 @@ TEST_CASE("json") { expected_serialization.end(), [](char c) { return std::isspace(c); }), expected_serialization.end()); + CHECK(oss.str() == expected_serialization); } diff --git a/src/dynamic_load_unix.cpp b/src/dynamic_load_unix.cpp index f1a0676..a4e85cc 100644 --- a/src/dynamic_load_unix.cpp +++ b/src/dynamic_load_unix.cpp @@ -45,16 +45,23 @@ DynamicallyLoadTracingLibrary(const char* shared_library, new DynamicLibraryHandleUnix{handle}}; const auto make_tracer_factory = - reinterpret_cast( + reinterpret_cast( dlsym(handle, "OpenTracingMakeTracerFactory")); if (make_tracer_factory == nullptr) { error_message = dlerror(); return make_unexpected(dynamic_load_failure_error); } + if (*make_tracer_factory == nullptr) { + error_message = + "An error occurred while looking up for OpenTracingMakeTracerFactory. " + "It seems that it was set to nullptr."; + return make_unexpected(dynamic_load_failure_error); + } + const void* error_category = nullptr; void* tracer_factory = nullptr; - const auto rcode = make_tracer_factory(OPENTRACING_VERSION, &error_category, + const auto rcode = (*make_tracer_factory)(OPENTRACING_VERSION, &error_category, &tracer_factory); if (rcode != 0) { if (error_category != nullptr) { diff --git a/src/dynamic_load_windows.cpp b/src/dynamic_load_windows.cpp new file mode 100644 index 0000000..cda2a5e --- /dev/null +++ b/src/dynamic_load_windows.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include + +namespace opentracing { +BEGIN_OPENTRACING_ABI_NAMESPACE +namespace { + + + +// Returns the last Win32 error, in string format. Returns an empty string if +// there is no error. +inline std::string GetLastErrorAsString() { + // Get the error message, if any. + DWORD errorMessageID = ::GetLastError(); + if (errorMessageID == 0) + return std::string(); // No error message has been recorded + + LPSTR messageBuffer = nullptr; + size_t size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&messageBuffer, 0, NULL); + + std::string message(messageBuffer, size); + + // Free the buffer. + LocalFree(messageBuffer); + + return message; +} + + + + class DynamicLibraryHandleWindows : public DynamicLibraryHandle { + public: + explicit DynamicLibraryHandleWindows(HINSTANCE handle) : handle_{handle} {} + + ~DynamicLibraryHandleWindows() override { FreeLibrary(handle_); } + + private: + HINSTANCE handle_; +}; + +} // namespace + +expected +DynamicallyLoadTracingLibrary(const char* shared_library, + std::string& error_message) noexcept try { + const auto handle = LoadLibrary(shared_library); + if (handle == nullptr) { + error_message = "An error occurred: " + GetLastErrorAsString(); + return make_unexpected(dynamic_load_failure_error); + } + + std::unique_ptr dynamic_library_handle{ + new DynamicLibraryHandleWindows{handle}}; + + const auto make_tracer_factory = + reinterpret_cast( + GetProcAddress(handle, "OpenTracingMakeTracerFactory")); + + if (make_tracer_factory == nullptr) { + error_message = + "An error occurred while looking up for OpenTracingMakeTracerFactory " + ": " + + GetLastErrorAsString(); + return make_unexpected(dynamic_load_failure_error); + } + + if (*make_tracer_factory == nullptr) { + error_message = + "An error occurred while looking up for OpenTracingMakeTracerFactory. " + "It seems that it was set to nullptr."; + return make_unexpected(dynamic_load_failure_error); + } + + const void* error_category = nullptr; + void* tracer_factory = nullptr; + const auto rcode = (*make_tracer_factory)(OPENTRACING_VERSION, &error_category, + &tracer_factory); + if (rcode != 0) { + if (error_category != nullptr) { + return make_unexpected(std::error_code{ + rcode, *static_cast(error_category)}); + } else { + error_message = "failed to construct a TracerFactory: unknown error code"; + return make_unexpected(dynamic_load_failure_error); + } + } + + if (tracer_factory == nullptr) { + error_message = + "failed to construct a TracerFactory: `tracer_factory` is null"; + return make_unexpected(dynamic_load_failure_error); + } + + return DynamicTracingLibraryHandle{ + std::unique_ptr{ + static_cast(tracer_factory)}, + std::move(dynamic_library_handle)}; +} catch (const std::bad_alloc&) { + return make_unexpected(std::make_error_code(std::errc::not_enough_memory)); +} +END_OPENTRACING_ABI_NAMESPACE +} // namespace opentracing diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ac39669..1610662 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,22 +6,22 @@ endif() add_executable(tracer_test tracer_test.cpp) target_link_libraries(tracer_test ${OPENTRACING_LIBRARY}) -add_test(tracer_test tracer_test) +add_test(NAME tracer_test COMMAND tracer_test) add_executable(string_view_test string_view_test.cpp) -add_test(string_view_test string_view_test) +add_test(NAME string_view_test COMMAND string_view_test) add_executable(value_test value_test.cpp) -add_test(value_test value_test) +add_test(NAME value_test COMMAND value_test) add_executable(util_test util_test.cpp) -add_test(util_test util_test) +add_test(NAME util_test COMMAND util_test) if (BUILD_SHARED_LIBS AND BUILD_MOCKTRACER AND BUILD_DYNAMIC_LOADING) add_executable(dynamic_load_test dynamic_load_test.cpp) target_link_libraries(dynamic_load_test ${OPENTRACING_LIBRARY}) add_dependencies(dynamic_load_test opentracing_mocktracer) - add_test(dynamic_load_test dynamic_load_test + add_test(NAME dynamic_load_test COMMAND dynamic_load_test --mocktracer_library - ${CMAKE_BINARY_DIR}/mocktracer/${CMAKE_SHARED_LIBRARY_PREFIX}opentracing_mocktracer${CMAKE_SHARED_LIBRARY_SUFFIX}) + $) endif()