libyal / libewf-legacy

Legacy version of libewf
GNU Lesser General Public License v3.0
10 stars 5 forks source link

How to build a DLL? #10

Open tedsmith opened 3 years ago

tedsmith commented 3 years ago

Dear @joachimmetz

I reach out to you in the hope you could guide me a little.

I've spent much of the weekend attempting to compile a DLL for Windows of the latest "legacy release" of the library.

I first did so (in error I think) from the "Releases" section using the experimental release to try and get a V3 DLL. That compiled OK, I got a libewf-v3.dll file, but I can't load it with my LoadLibrary routines. It keeps returning zero (nil handle).

So having spent a while longer trying to find a pre-compiled DLL, I read one of your posts where you rightly point out we should be using the legacy releases. So I downloaded that from https://github.com/libyal/libewf-legacy/releases and recompiled. And I got a libewf-v2.dll which would have been fine as I only need the E01 verification routines anyway.

But again, my LoadLibrary routine just keeps returning zero.

So after spending several hours convinced my calls to LoadLibrary routines must be incorrect, and going through with the debugger, I used Depenancy Walker to look at the generated DLLs. DW reports several "errors" (I'm not sure if they are actually proper errors or not but it does not look happy). And I have insufficient experience at DLL compilation to work out how to correct them, or even find them. There seems to be lots of failings, which I am sure will be my fault. Birds eye view in the screenshot.

Strangely though, I can't even load an older version of the DLL that I made back in 2015. Which makes me wonder if it relates to something to do with Windows 10

I also tried (for the first time) to compile it using Visual Studio 2019 by cloning the repository libewf-DLLs.zip but that also listed dozens of errors and I don't really know what I'm doing. So it is probably me.

Suffice to say : is there any scope for you, as the developer, to helpfully compile a release DLL for users that can be added to the repository here, to simply download? It would certainly save folks who want to use the library with their tools some considerable pain (your comments here are of course noted). If not, do you happen to know what I may be doing wrong? I am using Windows 10 x64, with the MSYS2 MinGW 64-bit compiler and the following configure line : CPPFLAGS=-DWINVER=0x0501 ./configure --prefix=/mingw followed by make. The resulting DLL's all look spiffing and valid, except for what Dependency Walker says.

Untitled

As it stands right now, sadly I am thinking I might just have abandon the effort which seems rather tragic considering the immense power and effort that has gone into creating the library. I have attached the v2 DLL, in case anyone reading has the skills to confirm if it is a valid DLL, or not. libewf-DLLs.zip

joachimmetz commented 3 years ago

With MinGW try adding --enable-winapi=yes as per https://github.com/libyal/libewf/wiki/Building#using-minimalist-gnu-for-windows-mingw

joachimmetz commented 3 years ago

Suffice to say : is there any scope for you, as the developer, to helpfully compile a release DLL for users that can be added to the repository here, to simply download?

You could try VS 2017 built https://www.nuget.org/packages/libewf/ note that for re-distribution you'll have include the LGPLv3 and you'll be dependent on the VS runtime DLLs

Just note that downloading random binaries from the internet is bad security practice. The DLL is unsigned because MS/Nuget does not have a no-cost code signing solution.

joachimmetz commented 3 years ago

Strangely though, I can't even load an older version of the DLL that I made back in 2015.

missing dependent DLLs like VS or MinGW runtime DLLs?

tedsmith commented 3 years ago

downloading random binaries from the internet is bad security practice

Totally agree for sure, and that is exactly why I am asking the developer specifically as a trusted provider, instead of downloading one of the many copies that exist on the web, and it's also why I am trying to compile it myself due to the abscence of a "safe version". I ship SQLIte.dll's with my application that I compiled from source and I provide the hash for assurance because for a while I did sign it with a DigiCert cert but it was too expensive for software I was giving away. I'll do the same with this if I get it to work. Otherwise I am shipping a car without an engine.

As for the issue at end...I'll keep trying. I've got Visual Studio 2019 installed and its gobbled up 10Gb of my virtual machine. I'll try again with MinGW as that seems more slick and I've used it already to generate 32 and 64 bit SQLIte DLL's from source so I am now familiar'ish with that process, which makes it all the more frustrating when I can't get this to work.

Thanks as ever for getting back to me. It's great when developers do. I try to as well, to my users, but I don't always get the chance to do so as quickly as you have managed so thank you for that

joachimmetz commented 3 years ago

Totally agree for sure, and that is exactly why I am asking the developer specifically as a trusted provider,

Unfortunately that is no guarantee, not that I'm assuming the developer is malicious, but binaries can be tampered with in storage or in transit (e.g. bundled installers), especially those without any kind of accompanying integrity check. I'd wish Windows had a more mature and open ecosystem for this.

I did sign it with a DigiCert cert but it was too expensive for software I was giving away. I'll do the same with this if I get it to work.

Yeah that is a better approach, at least people can validate that the version was built by you.

which makes it all the more frustrating when I can't get this to work.

Likely something missing in the build or deployment process,

tedsmith commented 3 years ago

OK. So, point 1) it turns out I have asked this question before HERE. How embarrasing! I found it by googling the issue, and found my own question from 5 years ago!

Point 2) it turned out that I have been compiling a 32-bit DLL!! And not a 64-bit one!! I determined that by using Microsoft "SigCheck" tool and noticed it says "32-bit" under the machine value! So when I then attempted to use it with my 32-bit IDE, it worked...at least, the 32-bit one did!

Point 3) The instructions of "Start the MSYS shell: C:\MinGW\msys\1.0\msys.bat" seemingly launches the 32-bit shell. At least on my system, even though I run the 64-bit OS. So I ensured I launched the 64-bit shell from the desktop.

Point 4) The user serius777 very helpfully points out in the issue I wrote 5 years ago that a suitable configure script is :

CPPFLAGS=-DWINVER=0x0501 ./configure --host=x86_64-w64-mingw32

And seemingly, if you run that in the 32-bit shell, you get a 32-bit DLL. And I assumed if you run it in the 64-bit shell, you get a 64-bit DLL. Well, you do. Except the 64-bit DLL still doesn't work for me, yet the 32-bit one does. So I tried again this time using

CPPFLAGS=-DWINVER=0x0501 ./configure --prefix=/mingw --enable-winapi=yes

64-bit DLL is generated. But still no joy, even after ensuring zlib.dll are there (as 64-bit) and also libgcc_s_dw2-1.dll (which I did notice is 32-bit...does that matter? No 64-bit available that I could find in MinGW).

So I am at a frustrating cross roads. Having got 32-bit working, I can't help but feel I am close with 64. But I've spent litterally days of my weekends and most evenings on this now and pulling my hair out in frustration. For my own records as much as anything else, I document below my steps:

Download the latest "legacy" release and not the "experimental" release Unzip to C:\MinGW\lib\libewf Start a CMD command prompt and change into the MinGW binaries directory:

cmd.exe cd C:\mingw\bin\

To install the required MinGW and MSYS packages, run the following (in CMD): mingw-get install binutils mingw-runtime w32api libgmp libmpc libiconv pthreads gettext libz gcc-core mingw32-make msys

To create a 32-bit DLL, start the MSYS shell:

C:\MinGW\msys\1.0\msys.bat

To create a 64-bit DLL, start the MSYS shell from the desktop icon ensuring it says "MINGW64" in purple, as this is the 64-bit shell.

Now, using either the 32 or 64 bit shell (not CMD), make sure the MinGW directory is mounted, otherwise run the following command to mount:

mkdir /mingw mount C:\MinGW /mingw

For 32-bit, run Configure and build: CPPFLAGS=-DWINVER=0x0501 ./configure --host=x86_64-w64-mingw32 make

For 64-bit, run Configure and build: CPPFLAGS=-DWINVER=0x0501 ./configure --prefix=/mingw --enable-winapi=yes make

Then libewf-v2.dll will now be in libewf.libs (e.g. C:\msys64\mingw64\lib\libewf\libewf.libs) Copy it to your project folder and rename as you need. Then copy C:\msys64\mingw64\bin\zlib-1.dll to your project too, rename it zlib.dll, next to libew-v2.dll Then copy C:\msys64\mingw64\bin\libgcc_s_dw2-1.dll and copy that too.
Check each DLL is either 32 or 64 bit as required using SigCheck or by browsing the DLL header in Hex and looking for :

50 45 00 00 64 86 13 00 : PE..d†.. (for 64-bit) 50 45 00 00 4C 01 12 00 : PE..L.. (for 32-bit)

joachimmetz commented 3 years ago

Are you sure MSyS 1 supports 64-bit? Not that you need MSyS 2?

tedsmith commented 3 years ago

:-) I'm not sure of anything anymore. I'm pretty sure it is 64-bit and the DLL's coming out of it are...see screenshot. Untitled

joachimmetz commented 3 years ago

for what it is worth, the desktop icon indicates msys2 that should support 64-bit

C:\MinGW\msys\1.0\msys.bat this is what threw me off, but it looks like you're using that for the 32-bit builds

tedsmith commented 3 years ago

OK, the masses can now rejoice. After a week of evening and weekend compiling, making, and re-compiling, and more making, I have done it! I'm going to write it here again for my own records as well as anybody else. @joachimmetz feel free to use any bits you feel need adding\updating to your "How to Build" article as IMHO there are one or two bits that need updating.

Windows 10, 64-bit OS.

Install MSYS2, 64-bit shell and 32-bit shell (note that the URL http://www.mingw.org/ as listed in the How to Build article is now defunct, as of May 2021).

Add the following paths to your Windows OS PATH environment for YOUR USER in "Advanced Windows Settings" --> Environment (not sure if this was actually needed but I read somewhere it was) Untitled

Install the dependencies as instructed in the How to Build article. Or, in my case (not sure if this helped or not) in the MSYS2 shell, I also executed the following, which in turn ensured further dependencies were installed automatically too : pacman -S gcc make zip unzip

Download the legacy libewf build, not experimental

Unzip

Copy content of zip to a new subfolder of C:\mingw64\lib. In my case, C:\mingw64\lib\libewf

Launch MSYS2 shell

cd to C:\mingw64\lib\libewf using forward slashes C:/mingw64/lib/libewf cd C:/mingw64/lib/libewf

Run configure script : CPPFLAGS=-DWINVER=0x0501 ./configure --host=x86_64-w64-mingw32 (this worked for me)

Other potential options if this fails are CPPFLAGS=-DWINVER=0x0501 ./configure --prefix=/mingw --enable-winapi=yes or (as Joachim directs) CPPFLAGS=-DWINVER=0x0501 ./configure --prefix=/mingw

Wait

Run make make

Wait even longer. On completion, copy the libewf-2.dll from C:\msys64\mingw64\lib\libewf\libewf.libs to your project folder.

Then (and this is important and I didn't see it mentioned anywhere):

copy C:\msys64\mingw64\bin\libwinpthread-1.dll to the project were you need to run libewf-2.dll from. I only worked this out after using Dependancy Walker and having attempted to compile and build about 15 times.

Then (and this is also important) copy zlib1.dll from C:\msys64\mingw64\bin to the project were you need to run libewf-2.dll from, and do not rename it to zlib.dll as it seems to need to be named zlib1.dll. If someone can guide me on this or mis-understanding on my part, shout.

Then (and this is also important) copy libgcc_s_dw2-1.dll from C:\MinGW\bin (NOT C:\msys64\mingw64\bin) as mentioned in Joachims instructions. Do not rename that either.

Lastly, always ensure your IDE is 64-bit too, when trying to load this libraries in your code. Don't use any 32-bit variants, except for the 32-bit DLL's (school boy errors).

Repeat as above for using the 32-bit MSYS shell for any 32-bit DLL's. I have both now, and both seem to be loadable. I am yet to actually try and use them though! :-)

You can also check each one using SigCheck Untitled

And that is it. I'm probably go and have a week off before returning when I will begin the fun of using the super library, which is, without doubt, the most comprehensive of its kind!

@joachimmetz thank you for the help and tuition through the process.

joachimmetz commented 3 years ago

Note the copyright and licenses of the DLLs you are copying, these need to be included on redistribution.

joachimmetz commented 3 years ago

@tedsmith thx for the detailed write up, when time permits I'll see if I can update the build instructions based on it.