On 12 December 2011 17:18, Jeremy O'Donoghue <jeremy.odonog...@gmail.com> wrote:
> Hi Dave, all,
>
> This is fantastic news - especially the bit about GHCi. I have put a couple
> of general comments inline, but it looks like you have found most of the
> issues, at least on Linux.
>
> I think that at least some of the issues would go away if, as you say,
>
> "we could have an entirely separate cabal project (perhaps "wxc") for this
> shared library, and then have wxcore depend on it?"
>
> In this case, we would be able to ensure that libwxc.so.x.y.z (or wxc.dll or
> libwxc.dylib or whatever) was in a 'normal' place before wxcore gets built.
>
> On 9 December 2011 14:13, Dave Tapley <duked...@gmail.com> wrote:
>>
>> On 8 December 2011 22:34, Dave Tapley <duked...@gmail.com> wrote:
>> > Hello everyone,
>> >
>> > I wrote a story, and I invite you all to comment and help me make it
>> > better.
>> > As an experiment I've decided to put it on hpaste instead of having
>> > the mail thread get out of hand (I'm also cross posting it to the
>> > cabal list and have mentioned it in #haskell, and I want to keep all
>> > correspondence in one place):
>> > http://hpaste.org/55027
>>
>> Ha, well that was good timing for hpaste to go down!
>> Here's it is:
>>
>> I've been trying to resurrect the idea of building a shared library
>> for the C++ component of the wxhaskell library.
>>
>> Jeremy (to my knowledge) first put this forward, here:
>>
>> http://wewantarock.wordpress.com/2010/11/01/working-around-the-static-libstdc-restriction/
>>
>> In addition to the advantages he lists there, I have the following reason:
>> When building wx-core (in its current incarnation) cabal will *always*
>> rebuild all the C++ code, which takes a majority of the build time.
>> This becomes very frustrating when you change one line of Haskell and
>> have to wait seven minutes to rebuild.
>> I complained about it here:
>> http://sourceforge.net/mailarchive/message.php?msg_id=28099997
>>
>> So, I decided to try and stop this complete C++ rebuild, I partially
>> succeed, but I eventually got stuck for reasons I complained here:
>> http://www.haskell.org/pipermail/cabal-devel/2011-October/007816.html
>>
>> Side note: I did eventually discover why (or, where) the c-sources
>> (cSources) list is used to compile and link, and it is here:
>>
>> http://hackage.haskell.org/packages/archive/Cabal/latest/doc/html/src/Distribution-Simple-GHC.html#buildLib
>> You can see:
>> "| filename <- cSources libBi]" under "-- build any C sources", and
>> you can see:
>> "cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))
>> (cSources libBi)"
>> under "-- link:".
>> Is this assumption correct?
>
>
> This is correct - it's the standard way Cabal builds C/C++ code. To be
> honest, this is really a consequence of the fact that Cabal is more of a
> tool for simple distribution than a Make replacement, and the developers
> probably didn't expect Cabal would be used to build large bodies of C++
> code.
>
> My approach is far from perfect, too - in fact it is incorrect because I
> don't do dependency tracking on header files, so if you edit a header, it
> (incorrectly) fails to rebuild. This is because I wasn't keen on rewriting
> 'make' in the wxHaskell build system - it seems to me like something Cabal
> could usefully support. I did play with some very hacky code which
> automatically rebuilt all of the C++ code if any header is newer than any
> C++ source. This is aesthetically dreadful, but it somewhat captures the
> reality, since in practice, pretty much all of the C++ files depend on all
> of the headers (and it's easy to write).
>
> On reflection, we should probably do this as what exists at present could
> lead to unexpectedly incorrect code being generated if someone is in full
> flow of development. I'll see if I can dig up some code - I think I have it
> somewhere.

You know, I'm surprised this didn't occur to me until now:
Does the C++ code actually need to use cabal at all?
If it's a separate project, perhaps it would be more sensible to use a
C++ oriented build system?
Then, unless I'm missing something, it can install the headers
somewhere, and wxcore can run wxdirect on the headers are currently.

The big disadvantage I can see with moving the C++ out of the wxcore
project is lots of pain for users when they 'cabal update' and
suddenly wxcore fails because they need to update the C++ headers /
library.

Another disadvantage is that this will make development a little more
painful (although the time saved not having to rebuild all the C++ is
a huge bonus) because you wouldn't (without some hackery) be able to
use cabal-dev as described here:
http://haskell.org/haskellwiki/WxHaskell/Development/Environment#Building_and_testing_wxHaskell

I happened upon this (dead) project, which I seems to have the goal I
am outlining:
http://wxc.sourceforge.net/

>
>> At this point I thought about either:
>> 1. Getting the cabal source and starting to write code to give
>> BuildInfo a "cObjs" in addition to "cSources".
>> 2. Picking up Jeremy's shared library code, so wxhaskell would have
>> its own code to build the library, in which I could do sensible
>> re-compilation.
>>
>> Given that there were other advantages to 2, I went with that.
>>
>> Jeremy had written one blog post on building a such a shared library,
>> here:
>>
>> http://wewantarock.wordpress.com/2010/11/03/building-a-shared-library-in-cabal/
>> In response to an email on the wxhaskell-devel list he also kindly put
>> up this gist, with the code he'd been working on:
>> https://gist.github.com/1301115
>>
>> I dutifully took this gist, and have now attempted to integrate in to
>> my wxhaskell-dev branch, which you can find here:
>> http://darcsden.com/DukeDave/wxhaskell-dev
>> (note: I haven't pushed any of the shared library code to darcsden
>> yet, for reasons I'm about to explain)
>>
>> This is where things got interesting, after a few hours of hacking I
>> have built a shared library, but in this very back-handed way:
>>
>> Firstly, in Jeremy's code the to-be-compiled shared library is added
>> to the wxcore BuildInfo through a custom hook.
>> We can see this because:
>> > let all_dlls   = parseDLLs ["x-dll-name", "x-dll-extra-libraries"]
>> > custom_bi
>> (the modified wxcore.cabal contains the line: "x-dll-name: wxc")
>>
>> However on a clean build of wxcore we get the following error:
>>
>> setup: Missing dependency on a foreign library:
>> * Missing C library: wxc
>> This problem can usually be solved by installing the system package that
>> provides this library (you may need the "-dev" version). If the library is
>> already installed but in a non-standard location then you can use the
>> flags
>> --extra-include-dirs= and --extra-lib-dirs= to specify where it is.
>
>
> My code worked for Windows - but this is a better cross-platform solution.

Interesting.
I found this fixed feature on cabal:
http://hackage.haskell.org/trac/hackage/ticket/262
It suggests that cabal uses Autoconf to resolve dependencies,
specifically the AC_CHECK_LIB macro.
I have zero knowledge of build systems in Windows, but is it
reasonable to suggest that Autoconf could be more relaxed?

I really should get a Windows build environment set up..

>
>>
>> The error is dumped *before* cabal calls myBuildHook, and since this
>> actually builds the library the error makes sense; cabal is looking
>> for the shared library before we've built it.
>>
>> To get around this I modified the offending line, thus:
>> > let all_dlls   = parseDLLs ["x-dll-extra-libraries"] custom_bi
>>
>> With that modification cabal would now get to myBuildHook, but then
>> another curious error arose:
>> We see that the actual linking is called here:
>> > runProgram verbose gcc (opts' ++ objs' ++ lib_dirs' ++ libs')
>>
>> But on hitting that line the following error is spat out:
>> /usr/bin/ld: cannot open output file  dist/build/libwxc.so.0.13.1: No
>> such file or directory
>
>
> Windows doesn't behave this way - this part worked for me as well.
>
>>
>> I checked all my permissions and couldn't see anything wrong, I could
>> touch the file.
>> Conveniently I noticed that, if the verbosity is set high enough,
>> runProgram will call printRawCommandAndArgs:
>>
>> http://hackage.haskell.org/packages/archive/Cabal/latest/doc/html/src/Distribution-Simple-Utils.html#printRawCommandAndArgs
>>
>> The output (i.e. the linker invocation) looks like this:
>> /usr/bin/gcc -fno-stack-protector -shared -Wl,-soname,libwxc.so.0 -o
>> dist/build/libwxc.so.0.13.1 dist/build/src/cpp/apppath.o
>> dist/build/src/cpp/dragimage.o dist/build/src/cpp/eljaccelerator.o
>> [snip-rest-of-.o-files] -L/usr/local/lib -lstdc++ -lwx_baseu-2.9
>> [snip-rest-of-wx-libs]
>>
>> Now if I cd into the wxcore and paste the command *verbatim* then gcc
>> works and generates libwxc.so.0.13.1 as expected.
>> You can see in Jeremy's code the linkShareLib function contains:
>> > cwd <- getCurrentDirectory
>>
>> I used this to confirm that the we were in ./wxcore and we are, even
>> making the path for -o absolute didn't sovle the issue.
>> I ended up replacing runProgram line with this, less satisfactory line:
>> > system $ (unwords ([show . locationPath . programLocation $ gcc] ++
>> > opts' ++ objs' ++ lib_dirs' ++ libs'))
>>
>> Which works, but still doesn't explain why runProgram doesn't.
>> Any suggestions?
>
>
> I've tried this on Linux. You're absolutely right and I'm stumped as to why.
> I think we should pull this specific part of the thread out and post to the
> Haskell list. Maybe someone who knows Cabal and/or GHC would have an idea
> why this is the case.

Ah, good to know it works on Windows.
I'll try and replicate it in isolation and send a mail to the cabal list.

>
>>
>> So with that complete I was able to link a shared library to:
>> wxcore/dist/build/libwxc.so.0.13.1
>>
>> Of course, at this point we've generated the shared library, but
>> wxcore still isn't aware of it, so the build completes successfully,
>> but any attempt to compile against it results (understandably) in
>> hundreds of linker errors.
>> To resolve this I had to add "x-dll-name" (read in from wxcore.cabal
>> as "wxc") back to parseDLLs:
>> > let all_dlls   = parseDLLs ["x-dll-name", "x-dll-extra-libraries"]
>> > custom_bi
>>
>> Well, not quite, attempt to build wxcore again and we're back to this
>> error:
>> * Missing C library: wxc
>>
>> Of course, the .so isn't in a 'normal' place, so add its location as
>> an extra lib directory:
>> > { extraLibDirs = extraLibDirs libbi ++ extraLibDirs wx ++
>> > ["/full/path/to/wxcore/dist/build"]
>> (note: I tried using just "dist/build", but cabal said: "library-dirs:
>> dist/build is a relative path")
>
>
> I think we need a more robust solution in the longer run, as
> <wxhaskell>/wcore/dirt/build is really a temporary location.

I guess the 'correct' solution would be to 'install' the library to
somewhere like LD_LIBRARY_PATH in Linux.
Again I don't know how this fits in with Windows.

It's also a pain for people developing wxhaskell, because as I
mentioned before, you'd have to 'install' a potentially unstable,
development version of the shared library in order to be able to
reference it.

>
>>
>> This still isn't quite enough, it took one more kludge:
>> /full/path/to/wxcore/dist/build/$ ln -s
>> /full/path/to/wxcore/dist/build/libwxc.so.0.13.1 libwxc.so
>
>
> Earlier you mentioned that, at least on Linux, the build command is:
>
>
> /usr/bin/gcc -fno-stack-protector -shared -Wl,-soname,libwxc.so.0 -o
> dist/build/libwxc.so.0.13.1 dist/build/src/cpp/apppath.o
> dist/build/src/cpp/dragimage.o dist/build/src/cpp/eljaccelerator.o
> [snip-rest-of-.o-files] -L/usr/local/lib -lstdc++ -lwx_baseu-2.9
> [snip-rest-of-wx-libs]
>
> I know GCC generated this and not you, but it looks like the root of the
> issue. I am slightly confused though. ld.so is supposed to *know* that
> libwxc.so.0.13.1 is a valid instance of libwxc.so.0

Firstly, I'm a little confused by your statement "GCC generated this
and not you", that build command is generated by linkCxxOpts, not GCC?

This is curious: The name of the symlink has to be "libwxc.so", not
even "libwxc.so.0".
I think this makes sense though, the only "information" the simple
build system gets about the dependency is the parsing of this line in
wxcore.cabal by parseDLLs:
  x-dll-name: wxc

I assume that the "wxc" is some how turned in to "libwxc.so", I'd like
to know how, and if it is possible to specify the major revision of a
shared library passed; this would have to be some convention in the
naming, because extraLibs is just [String]:
http://hackage.haskell.org/packages/archive/Cabal/latest/doc/html/Distribution-PackageDescription.html#v:extraLibs

>
> In normal Linux-land, you run /sbin/ldconfig after installing a new library,
> and it creates these symlinks automatically You could do this by executing
> something like (not tested)
>
> /sbin/ldconfig -n <path-to-directory>

Thanks for the tip, that makes more sense.
I can now see that the symlink which "ldconfig -n" generates is
extracted from the -soname given at link time.
So, by modifying the -soname to *not* specify the major revision, i.e:
This:
>    "-Wl,-soname,lib" ++ basename ++ ".so",
Instead of this:
>    "-Wl,-soname,lib" ++ basename ++ ".so" ++ maj_ver,

I can now use "ldconfig -n" in dist/build/ to create the symlink (to
libwxc.so), instead of doing it by hand, I suppose this is a little
less broken.

>
>> I'd like to think there's a more elegant solution than this and I'm
>> open to suggestions.
>> I should note that at this point I became aware that we could have an
>> entirely separate cabal project (perhaps "wxc") for this shared
>> library, and then have wxcore depend on it?
>>
>> Running one more time I *thought* I was finally there, until I noticed
>> this line, hidden in cabal's output:
>> /full/path/to/wxcore/dist/build/libwxc.so: file not recognized: File
>> truncated
>>
>> As far as I can tell, this occurs because we now load(?)
>> "libwxc.so.0.13.1" in myConfHook, but then in myBuildHook we want to
>> use it as the destination for the linker. Worse still it seems that
>> 'truncated' actually means 'deleted'. To get around this I had to one
>> again remove "x-dll-name" from the parseDLLs call (so I could get to
>> myBuildHook and create "libwxc.so.0.13.1" again), build wxcore, then
>> add "x-dll-name" back again, but this time also comment out the call
>> to linkSharedLib (and so stop cabal attempting to open
>> "libwxc.so.0.13.1") before building wxcore one last time.
>>
>> Finally everything seemed to work.
>>
>> Now, I should note that I have been using cabal-dev, and so I now have
>> a package-conf I need to reference when building with my new shared
>> library wxhaskell. To test it I built the wxhaskell HelloWorld sample
>> thus:
>> /full/path/to/samples/wxcore$ ghc --make -package-conf
>> ../../cabal-dev/packages-7.0.3.conf HelloWorld.hs
>>
>> It worked, but then when I try to run HelloWorld I get:
>> ./HelloWorld: error while loading shared libraries: libwxc.so.0:
>> cannot open shared object file: No such file or directory
>>
>> Okay, again, libwxc.so.0 isn't in a 'normal' place, so I kludged it
>> with another symlink:
>> /full/path/to/samples/wxcore$ ln -s
>> /full/path/to/wxcore/dist/build/libwxc.so libwxc.so.0
>>
>> And now, I can report that HelloWorld runs.
>> [imagine a screen shot of the HelloWorld sample application running here]
>> Rejoice.
>>
>> But wait, there's more:
>> One of the promises of the shared library approach is that we'd all be
>> able to use wxhaskell with ghci again, and to my utter disbelief, it's
>> true:
>> /full/path/to/samples/wxcore$ ghci -package-conf
>> ../../cabal-dev/packages-7.0.3.conf HelloWorld.hs
>> Ok, modules loaded: Main.
>> Prelude Main> main
>>
>> [imagine a screen shot of the HelloWorld sample application running here]
>> Double rejoice.
>>
>>
>>
>> >
>> > Dave,
>>
>>
>> ------------------------------------------------------------------------------
>> Cloud Services Checklist: Pricing and Packaging Optimization
>> This white paper is intended to serve as a reference, checklist and point
>> of
>> discussion for anyone considering optimizing the pricing and packaging
>> model
>> of a cloud services business. Read Now!
>> http://www.accelacomm.com/jaw/sfnl/114/51491232/
>> _______________________________________________
>> wxhaskell-devel mailing list
>> wxhaskell-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/wxhaskell-devel
>
>

------------------------------------------------------------------------------
Learn Windows Azure Live!  Tuesday, Dec 13, 2011
Microsoft is holding a special Learn Windows Azure training event for 
developers. It will provide a great way to learn Windows Azure and what it 
provides. You can attend the event by watching it streamed LIVE online.  
Learn more at http://p.sf.net/sfu/ms-windowsazure
_______________________________________________
wxhaskell-devel mailing list
wxhaskell-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wxhaskell-devel

Reply via email to