Use dllimport/dllexport and/or a .def file on Windows?

The current CMake builds for Windows produce quite a few warnings about linkage on Windows. The reason is that we use both .def files such as gvc.def and a fairly complicated (and most certainly in a few place incorrect) combination of defines such as GVDLL, GVC_EXPORTS and _BLD_gvc to conditionally redefine the extern keyword in e.g. gvc.h and globals.h. In some files, other macros are defined and used to declare external functions and variables such as CGRAPH_API in cgraph.h.

According to this Microsoft article you don’t need to use both mechanisms.

I would like to clean this up, but I would like to hear what the pros and cons are with the two approaches from people more experienced than me with C and C++ (@smattr?). If we happen to have anybody reading this that has experience also with such development using Windows that would like to comment, that would be exceptional.

I think that using defines for this purpose has been around in Graphviz since the beginning of times, while the use of a .def file is a later innovation.

The current warnings are (I know how to fix these, but not which way is the best):

C:\Users\magja\graphviz\lib\common\geom.c(23,1): warning C4273: 'mkbox': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(44,1): warning C4273: 'mkboxf': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(87,1): warning C4273: 'lineToBox': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(199,1): warning C4273: 'rect2poly': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(234,1): warning C4273: 'cwrotatep': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(262,1): warning C4273: 'cwrotatepf': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(290,1): warning C4273: 'ccwrotatep': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(318,1): warning C4273: 'ccwrotatepf': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(346,1): warning C4273: 'flip_rec_box': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(362,1): warning C4273: 'flip_rec_boxf': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(388,1): warning C4273: 'ptToLine2': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
C:\Users\magja\graphviz\lib\common\geom.c(405,1): warning C4273: 'line_intersect': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\common\common_obj.vcxproj]
LINK : warning LNK4217: symbol 'ptToLine2' defined in 'geom.obj' is imported by 'emit.obj' in function 'check_control_points' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
LINK : warning LNK4217: symbol 'rect2poly' defined in 'geom.obj' is imported by 'emit.obj' in function 'emit_map_rect' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
LINK : warning LNK4217: symbol 'ccwrotatepf' defined in 'geom.obj' is imported by 'postproc.obj' in function 'gv_postprocess' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
LINK : warning LNK4286: symbol 'ccwrotatepf' defined in 'geom.obj' is imported by 'shapes.obj' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
LINK : warning LNK4217: symbol 'flip_rec_boxf' defined in 'geom.obj' is imported by 'shapes.obj' in function 'record_path' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
LINK : warning LNK4217: symbol 'cwrotatepf' defined in 'geom.obj' is imported by 'shapes.obj' in function 'compassPoint' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
LINK : warning LNK4217: symbol 'lineToBox' defined in 'geom.obj' is imported by 'utils.obj' in function 'overlap_bezier' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
LINK : warning LNK4217: symbol 'zmalloc' defined in 'memory.obj' is imported by 'label.lib(xlabels.obj)' in function 'placeLabels' [C:\Users\magja\graphviz\build\lib\gvc\gvc.vcxproj]
C:\Users\magja\graphviz\cmd\dot\no_builtins.c(13,37): warning C4273: 'lt_preloaded_symbols': inconsistent dll linkage [C:\Users\magja\graphviz\build\cmd\dot\dot.vcxproj]
LINK : warning LNK4217: symbol 'lt_preloaded_symbols' defined in 'no_builtins.obj' is imported by 'dot.obj' in function 'main' [C:\Users\magja\graphviz\build\cmd\dot\dot.vcxproj]
C:\Users\magja\graphviz\lib\gvc\gvcproc.h(118,55): warning C4273: 'gvFreeLayout': inconsistent dll linkage [C:\Users\magja\graphviz\build\cmd\tools\gvpack.vcxproj]
C:\Users\magja\graphviz\lib\gvc\gvcproc.h(119,55): warning C4273: 'gvLayoutJobs': inconsistent dll linkage [C:\Users\magja\graphviz\build\cmd\tools\gvpack.vcxproj]
C:\Users\magja\graphviz\cmd\tools\gvpack.c(37,37): warning C4273: 'lt_preloaded_symbols': inconsistent dll linkage [C:\Users\magja\graphviz\build\cmd\tools\gvpack.vcxproj]
C:\Users\magja\graphviz\lib\gvpr\gvpr.c(931,1): warning C4273: 'gvpr': inconsistent dll linkage [C:\Users\magja\graphviz\build\lib\gvpr\gvpr.vcxproj]

I should say that the reason I started to investigate this is that I accidentally increased the number of such warnings during my work with the new C++ API as part of the new C++ test suite.

Worth reading:

Of relevance: fix multiple definitions of CDT variables under MinGW on Windows (!1760) · Merge requests · graphviz / graphviz · GitLab

You’re right, redefining extern is just wrong. The equivalent of __declspec(dllimport) and __declspec(dllexport) is not extern. IIUC it is __attribute__((visibility("hidden"))) and __attribute__((visibility("default"))).

My vote is to rebase and land the MR I referenced, as it’s at least an improvement. Then move away from .def files as well as away from redefining extern.

1 Like

Excellent. That was the direction I was hoping for. It’s a pity I didn’t remember that issue. It could have saved me quite a few hours if I had.