-
Notifications
You must be signed in to change notification settings - Fork 114
Support build on Windows with MSVC 15.7 (#85) #93
Conversation
mdouaihy
commented
Jun 11, 2018
- Export Symbols
- Add Runtime targets to the install steps. On windows, static libraries are very tricky. shared library is needed.
- Add some MSVC compile options (_SCL_SECURE_NO_WARNINGS). This warning warns about unsafe methods or usage of the stl.
- Add appveyor build file. Credits for @hypnoce
- Add output directory and ignore build folder in git
* Export Symbols * Add Runtime targets to the install steps * Fix failing unit test under Windows * Add some MSVC compile options * Add appveyor build file * add output directory and ignore build folder in git
Thanks @mdouaihy. I'll get to reviewing this soon. |
include/opentracing/dynamic_load.h
Outdated
OPEN_TRACING_EXPORT int OPEN_TRACING_ATT | ||
OpenTracingMakeTracerFactory( | ||
const char* opentracing_version, const void** error_category, | ||
void** tracer_factory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OPEN_TRACING_ATT
doesn't expand to anything on windows, right?
Suppose I have two tracing libraries libTracerA, libTracerB, and then I link them both into my app with the intention of switching between them based on a config -- would that give a multiple definition error on windows because both would define OpenTracingMakeTracerFactory
?
The weak attribute was there to support that scenario. Could we maybe use __declspec(selectany)
for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, OPEN_TRACING_ATT does not expand to anything on Windows.
if we take your example, why would I link directly with the two tracers? I'd rather use the dynamic loading mechanism to load the implementation, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer people use the dynamic loading interface for that as well. But there are a few reasons why they might want to link directly, and it should be a scenario that we support if possible:
- You might want all your dependencies linked into the same file so that it's easier to deploy.
- You may want to use tracer-specific options that aren't available through the JSON configuration. For example, customized logging or transports where you need to pass in a callback in the options.
Envoy, for example, is an application that links in multiple tracers like this and uses some customizations that wouldn't be available through a JSON configuration interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok I understand now your point.
Unfortunately, weak symbols are not exposed by MSVC compiler. selectany works only on data items and not on methods.
https://docs.microsoft.com/en-us/cpp/cpp/selectany
However, we can use the /FORCE:MULTIPLE link flag to force the link of the binary even if multiple definitions of a symbol exists
https://docs.microsoft.com/en-us/cpp/build/reference/force-force-file-output
Also, on windows, using dynamic linking, having the same symbols is not a problem.
This last point is important. If we take again the example, linking TracerA and TracerB statically with OT will cause duplication of the symbols of OT, among them the Global Tracer, which is not what we really want.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you use selectany with a data variable that's a function pointer?
If we take again the example, linking TracerA and TracerB statically with OT will cause duplication of the symbols of OT, among them the Global Tracer, which is not what we really want.
Static libraries are usually built as thin archives (i.e. without the dependent libraries linked in), so there wouldn't be duplication of the OT symbols since OT would be linked in by the app along with the tracing libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
include/opentracing/symbols.h
Outdated
|
||
#ifdef _MSC_VER | ||
|
||
#define OPEN_TRACING_EXPORT __declspec(dllexport) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we s/OPEN_TRACING/OPENTRACING/ to keep the naming convention consistent?
src/dynamic_load_windows.cpp
Outdated
reinterpret_cast<decltype(OpenTracingMakeTracerFactory)*>( | ||
GetProcAddress(handle, "OpenTracingMakeTracerFactory")); | ||
if (make_tracer_factory == nullptr) { | ||
error_message = "An error occurred whike looking up for OpenTracingMakeTracerFactory : " + GetLastError(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An error occurred whike
typo
@rnburn, changes done as per our discussion. |
include/opentracing/symbols.h
Outdated
#endif // OPENTRACING_EXPORTS | ||
#endif // OPENTRACING_STATIC | ||
|
||
#define OPENTRACING_ATT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The OPENTRACING_ATT
macro isn't used anywhere now, right? Can we remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. removed in the latest commit.
src/dynamic_load_unix.cpp
Outdated
dlsym(handle, "OpenTracingMakeTracerFactory")); | ||
if (make_tracer_factory == nullptr) { | ||
if (make_tracer_factory == nullptr || *make_tracer_factory == nullptr) { | ||
error_message = dlerror(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If *make_tracer_factory == nullptr
, won't this need a different error message since dlerror
wouldn't return anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed. you're totally right.
src/dynamic_load_windows.cpp
Outdated
GetProcAddress(handle, "OpenTracingMakeTracerFactory")); | ||
|
||
if (make_tracer_factory == nullptr) { | ||
error_message = "An error occurred while looking up for OpenTracingMakeTracerFactory : " + GetLastError(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This StackOverflow question says that we need to use FormatMessage
along with GetLastError
to get a useful message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. Change done. an example
Failed to load tracer library. An error occurred: The specified module could not be found.
Could we add some brief instructions to README.md for how to install on windows? The current instructions, I think, are unix/linux-specific. |
sure. Very good idea. |
@mdouaihy - Why'd you close? |
I didnt do that on purpose. I might have pressed on the wrong button |
Instructions to generate the Visual Studio solution, to run the build and the tests are added now. Both Release and Debug target are covered. |
include/opentracing/dynamic_load.h
Outdated
\ | ||
int __attribute((weak)) \ | ||
X(const char* opentracing_version, const void** error_category, \ | ||
void** tracer_factory); \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need these declarations:
+__declspec(dllexport) int X(const char* opentracing_version, \
+ const void** error_category, \
+ void** tracer_factory);
+ int __attribute((weak)) \
+ X(const char* opentracing_version, const void** error_category, \
+ void** tracer_factory);
All that needs to be exposed is the variable OpenTracingMakeTracerFactory
. X
can be a static function in the translation unit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This declaration is useful so that
OPENTRACING_DECLARE_IMPL_FACTORY(OpenTracingMakeTracerFactoryFct);
can be declared anywhere in the translation unit.
change done.
mocktracer/src/dynamic_load.cpp
Outdated
@@ -4,7 +4,7 @@ | |||
#include <cstring> | |||
#include <exception> | |||
|
|||
int OpenTracingMakeTracerFactory(const char* opentracing_version, | |||
int OpenTracingMakeTracerFactoryFct(const char* opentracing_version, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make OpenTracingMakeTracerFactoryFct
static?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
@mdouaihy - This looks good. Was there anything else you wanted to add or should I go ahead and merge in? |
@rnburn, nothing to add from my side for the moment. Once you merge, please create a version that we update on Hunter to finalize the Jaeger windows build. Thank you for your time. |