www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Dub packages: Best practices for windows support

reply Johannes Pfau <nospam example.com> writes:
I want to add proper windows support to the cairoD dub package. cairoD
is a wrapper for the [cairo](http://cairographics.org/) C library. As
it can be difficult to obtain cairo DLLs on windows I want to ship
these DLLs with cairoD. It is also possible to enable or disable
additional cairo features. I want to use the DLLs from the [MSYS2
project](http://msys2.github.io/) which enable all relevant features.
Because of that, the MSYS2 cairo DLL depends on _13_ other DLLs.

On linux it would be common practice to simply have a "libs": ["foo"]
entry in the dub configuration for cairoD. This way applications using
the library won't have to manually link the C library. And everything
(dub run, dub test) will just work.

Now on windows, things are more complicated. First of all, I can't seem
to simply use "libs": ["foo"] as the linker won't find the C
import .lib file. Then apparently there's no way to add a library search
path with the MSVC linker? So I have to use the full path:
"libs": [$PACKAGE_DIR\\path\\foo]. Without $PACKAGE_DIR paths are
incorrect for applications using the library because of a dub problem.
And then I'll have to use different import libraries and paths for -m32,
-m64 and -m32mscoff.

Additionally, applications can't run without the DLLs in the same
directory as the target application executable. So dub run and dub test
won't work. As a solution it is possible to do this in the cairoD dub
configuration:
"copyFiles": ["lib\\dmc32\\*.dll"]
The path again depends on -m32 vs -m64 and -m32mscoff



All this leads to the following questions:
* Should cairoD copy the DLLs for all applications using cairoD? This
  way simply adding a dependency will work. However, if users want to
  use a self compiled cairo DLL with fewer dependencies there's no easy
  way to disable the file copying?
* Should cairoD link in the .lib DLL import file? This might be useful
  even when not copying the DLLs. But if users want to link a custom
  import library that would be difficult. OTOH not copying DLLs and/or
  not linking the import library will make dub.json much more
  complicated for simple applications, especially if these applications
  want to support -m32, -m32mscoff and -m64.
* What's the best way to support all of -m32, -m32mscoff and -m64? I've
  got working import libraries and DLLs for all configurations, but how
  to support this in dub.json? I think the best way would be to have
  -ms32coff as a special architecture or flag for dub, but I can't seem
  to find any documentation about that. -m64 can be detected by x86_64
  in platforms, but how to detect -m32 vs -m32mscoff?

  Alternatively I could simply let users choose the configurations
  manually. But adding dflags: ["-m32mscoff"] does not build the
  Derelict dependencies with the m32mscoff flag so linking will fail...

  DFLAGS="-m32mscoff" doesn't work with dub test as the dub test
  command ignores the DFLAGS variable. I'd have to check whether it
  works for applications, but then there's still no way to use the
  correct cairo import library in cairoDs dub.json....
Jan 29
next sibling parent Johannes Pfau <nospam example.com> writes:
Am Fri, 29 Jan 2016 20:46:40 +0100
schrieb Johannes Pfau <nospam example.com>:

   DFLAGS="-m32mscoff" doesn't work with dub test as the dub test
   command ignores the DFLAGS variable. I'd have to check whether it
   works for applications, but then there's still no way to use the
   correct cairo import library in cairoDs dub.json....
Should have mentioned DFLAGS is an environment in that example, e.g using dub like this: DFLAGS="-m32mscoff" dub run DFLAGS="-m32mscoff" dub test
Jan 29
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 29 January 2016 at 19:46:40 UTC, Johannes Pfau wrote:

 Now on windows, things are more complicated. First of all, I 
 can't seem
 to simply use "libs": ["foo"] as the linker won't find the C
 import .lib file. Then apparently there's no way to add a 
 library search
 path with the MSVC linker? So I have to use the full path:
 "libs": [$PACKAGE_DIR\\path\\foo]. Without $PACKAGE_DIR paths 
 are
 incorrect for applications using the library because of a dub 
 problem.
 And then I'll have to use different import libraries and paths 
 for -m32,
 -m64 and -m32mscoff.
Now you know my motivation for creating Derelict.
 All this leads to the following questions:
 * Should cairoD copy the DLLs for all applications using 
 cairoD? This
   way simply adding a dependency will work. However, if users 
 want to
   use a self compiled cairo DLL with fewer dependencies there's 
 no easy
   way to disable the file copying?
 * Should cairoD link in the .lib DLL import file? This might be 
 useful
   even when not copying the DLLs. But if users want to link a 
 custom
   import library that would be difficult. OTOH not copying DLLs 
 and/or
   not linking the import library will make dub.json much more
   complicated for simple applications, especially if these 
 applications
   want to support -m32, -m32mscoff and -m64.
IMO, no to both of these (for now). Including all of these dependencies is going to mean that all of your users, no matter the platform, will pull the down with every new version of gtkd. I recommend you provide all of the precompiled DLLs and import libraries as a separate download and let the user do the configuration needed to get it to link. Most Windows developers are used to it. You can provide instructions for those who aren't. Hopefully one day dub will have the ability to pull down library dependencies on demand, or based on the current platform and architecture by default, then this problem goes away.
 * What's the best way to support all of -m32, -m32mscoff and 
 -m64? I've
   got working import libraries and DLLs for all configurations, 
 but how
   to support this in dub.json? I think the best way would be to 
 have
   -ms32coff as a special architecture or flag for dub, but I 
 can't seem
   to find any documentation about that. -m64 can be detected by 
 x86_64
   in platforms, but how to detect -m32 vs -m32mscoff?

   Alternatively I could simply let users choose the 
 configurations
   manually. But adding dflags: ["-m32mscoff"] does not build the
   Derelict dependencies with the m32mscoff flag so linking will 
 fail...

   DFLAGS="-m32mscoff" doesn't work with dub test as the dub test
   command ignores the DFLAGS variable. I'd have to check 
 whether it
   works for applications, but then there's still no way to use 
 the
   correct cairo import library in cairoDs dub.json....
There's an issue for this at [1]. Until support for -m32mscoff is baked in, distributing any libraries with a dub project will be problematic.
Jan 29
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Saturday, 30 January 2016 at 01:17:13 UTC, Mike Parker wrote:

 Hopefully one day dub will have the ability to pull down 
 library dependencies on demand, or based on the current 
 platform and architecture by default, then this problem goes 
 away.
I should say "precompiled library dependencies".
Jan 29
prev sibling next sibling parent Mike Parker <aldacron gmail.com> writes:
On Saturday, 30 January 2016 at 01:17:13 UTC, Mike Parker wrote:

 There's an issue for this at [1]. Until support for -m32mscoff 
 is baked in, distributing any libraries with a dub project will 
 be problematic.
[1] https://github.com/D-Programming-Language/dub/issues/628
Jan 29
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Sat, 30 Jan 2016 01:17:13 +0000
schrieb Mike Parker <aldacron gmail.com>:

 On Friday, 29 January 2016 at 19:46:40 UTC, Johannes Pfau wrote:
 
 Now on windows, things are more complicated. First of all, I 
 can't seem
 to simply use "libs": ["foo"] as the linker won't find the C
 import .lib file. Then apparently there's no way to add a 
 library search
 path with the MSVC linker? So I have to use the full path:
 "libs": [$PACKAGE_DIR\\path\\foo]. Without $PACKAGE_DIR paths 
 are
 incorrect for applications using the library because of a dub 
 problem.
 And then I'll have to use different import libraries and paths 
 for -m32,
 -m64 and -m32mscoff.  
Now you know my motivation for creating Derelict.
 All this leads to the following questions:
 * Should cairoD copy the DLLs for all applications using 
 cairoD? This
   way simply adding a dependency will work. However, if users 
 want to
   use a self compiled cairo DLL with fewer dependencies there's 
 no easy
   way to disable the file copying?
 * Should cairoD link in the .lib DLL import file? This might be 
 useful
   even when not copying the DLLs. But if users want to link a 
 custom
   import library that would be difficult. OTOH not copying DLLs 
 and/or
   not linking the import library will make dub.json much more
   complicated for simple applications, especially if these 
 applications
   want to support -m32, -m32mscoff and -m64.  
IMO, no to both of these (for now). Including all of these dependencies is going to mean that all of your users, no matter the platform, will pull the down with every new version of gtkd. I recommend you provide all of the precompiled DLLs and import libraries as a separate download and let the user do the configuration needed to get it to link. Most Windows developers are used to it. You can provide instructions for those who aren't.
Thanks for the detailed answer. Thinking about this some more, copying the DLLs automatically is really a bad idea. The cairo dll depends on Freetype, so I'd have to ship a Freetype dll as well. But cairoD depends on DerelictFT and if DerelictFT then decided to also install DLLs automatically anything could happen. So even in this simple case installing DLLs for the user is not a good idea.
Jan 30
prev sibling parent Guillaume Piolat <name.lastname gmail.com> writes:
On Saturday, 30 January 2016 at 01:17:13 UTC, Mike Parker wrote:
 On Friday, 29 January 2016 at 19:46:40 UTC, Johannes Pfau wrote:

 Now on windows, things are more complicated. First of all, I 
 can't seem
 to simply use "libs": ["foo"] as the linker won't find the C
 import .lib file. Then apparently there's no way to add a 
 library search
 path with the MSVC linker? So I have to use the full path:
 "libs": [$PACKAGE_DIR\\path\\foo]. Without $PACKAGE_DIR paths 
 are
 incorrect for applications using the library because of a dub 
 problem.
 And then I'll have to use different import libraries and paths 
 for -m32,
 -m64 and -m32mscoff.
Now you know my motivation for creating Derelict.
+1, make a Derelict-style binding and never deal with import library ever again.
Jan 30