3rd Party DLLs / 32bit64bit / Directories / Loading

Started by
8 comments, last by Reitano 9 years, 10 months ago

So I just got a debug x64 build to compile after building 64bit versions of all 3rd party libs. Im still running the 32bit exe mainly but now I have 64bit exe in the same dir.

The problem is I have a lot of debug/release/32bit/64bit dlls all sitting next to the exe's. Id like to move them to a sub dir in my working folder and spearate the 32bit and 64bit.

Also some libs like libpng spit out the same dll name for both 32bit and 64bit, so they cant be in the same folder. While some libs like physx have some dlls with _x64 _x86 appended, while others have matching 32bit 64bit names. Im not sure of a sane way to go about organizing this any suggestions?

Advertisement
You haven’t mentioned what compiler you are using, but in Visual Studio, set the Output Directory (on all libraries and executables) to:
$(SolutionDir)$(PlatformName)\$(ConfigurationName)
Set the intermediate directories to:
$(PlatformName)\$(ConfigurationName)


$(PlatformName) = Win32 or x64.
$(ConfigurationName) = Release or Debug (or any others you may have added).
Examples:
C:\Project Dir\Win32\Release\MyGame.exe
C:\Project Dir\x64\Release\MyGame.exe
C:\Project Dir\Win32\Debug\MyGame.exe
C:\Project Dir\x64\Debug\MyGame.exe


All files for each build then stay separate from each other. All compilers have a similar option; if you are not using Visual Studio then you will have to find your own way to do the same thing.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I structure my output directoy like this:

- *some general output name*

-- Debug

----x86

----x64

-- Release

----x86

----x64

This can easily be extended if you add more platforms and/or build configurations.

Sorry should have been more specific, Im aware of the various output directories and how they work, but I dont run the exe's from their build directories, they get copied to the root of a content dir. In this folder my own DLLs load from a sub dir, my own dlls have names which differ between 32 and 64 bit, a specific build platform will load the correct dlls.

The problem is with the mounting number of 3rd party dlls which sit in the folder with my exe's, I like to load all of these from from folders in that same sub directory, Then the various dlls that have the same name for different builds could be in separate folders.

program.exe

program_x64.exe

3rdparty1.dll

3rdparty2.dll

3rdparty3.dll

subDir\subDir\<my dlls, my dlls 64>

what Id like

program.exe

program_x64.exe

subDir\subDir\<my dlls, my dlls 64>

subDir\subDir\32bit\<3rd party dlls>

subDir\subDir\64bit\<3rd party dlls>

Would I just build a list of the dlls I need and call LoadLibrary() from the specific folder? Is there a better way?

Taking a different tack on the question --- WHY?

What specific reason do you have for shipping both 64-bit and 32-bit versions of a game?

One of them is going to be the primary platform, the one with all the tests, the one that people use, the one where you probe the nooks and crannies of the system to find all the bugs. The other one won't have the tests and will be full of all kinds of bugs.

Invariably you are going to come across some system specific bugs that are only manifest on 32 or 64 bit variants. Some code might do something funky with alignment, or it might encode a pointer as an int, or some other bugs are going to happen.

Do you have a specific reason to follow this course?

You have the cost of maintaining multiple branches, testing multiple branches, doing fixes on multiple branches, releasing multiple branches. Do you have a reason for incurring this cost?

For most games PC games right now the choice is either 32-bit because you can, or 64-bit because of good reasons. Trying to take both options is probably a bad decision without some very strong business case for it.


Assuming you have a reason, why do you need to do this dynamically? Either you install the 32 bit version or you install the 64 bit version. People are not going to change their operating system mid-game. You don't have cases where you want the 32-bit version of one library and the 64 bit version of another. "I'd like a 32-bit audio driver, a 64-bit graphics driver, and a 16-bit mouse driver". All or nothing. Either you have the 32-bit version of the game or the 64-bit version of the game.

Taking a different tack on the question --- WHY?



Either you have the 32-bit version of the game or the 64-bit version of the game.

Slow down there Nelly.

I maintain both 32- and 64- bit versions of my engine, games I make on it, and all its tools, and I really have had 0 issues; I randomly switch day-by-day or whenever I really feel like it between 32-bit and 64-bit as a means of testing and maintaining them.
While I have enough experience to handle both platforms smoothly, at least I can say a simple strategy such as this really helps, and overall I don’t see it quite as troublesome as you make it to sound even for a moderate beginner (though I concede that alignment and range issues will definitely trick up the less-experienced) with some experience on both platforms. It’s really a breeze once you get used to properly using UINT_PTR (or similar on your platform-of-choice), always considering proper use of ranges (which mostly boils down to simply using matching types—don’t use int when .size() returns size_t), and using size-specific types (never use built-in types directly unless following the previous rule about matching types; always use typedefs that specifically enforce the number of bits and the signs of types). The best way to get used to this way of thinking is to actually maintain a project in both 32- and 64- bit builds.

Even if a client only gets one or the other, that means you still need to maintain both, because if you have more than one client you may still need to ship more than one build. Even if it is troublesome to maintain, it’s still necessary.

And these days it is common to need both a 32-bit and a 64-bit build, with 32-bit iOS and Android (native) devices still a prominent marketplace, and 32-bit versions of Windows taking a large share of your audience in Asia. When you update your graphics or sound drivers, they definitely have both 32- and 64- bit versions, and for a reason.

As for needing things loaded dynamically, I agree that this is probably just stupid if the 3rd-party DLL’s are really exclusively 32-bit (he or she needs to clarify). My impression is that he wants them in different directories because one set is all 32-bit and the other set is 64-bit, but he doesn’t want to change their names to avoid run-time hassle in calling LoadLibraryW() (you do call the Unicode function, right? It’s fairly useless otherwise).

He or she needs to be more clear on what he or she is attempting to do, but my advice would be to do what he or she is already doing with his or her DLL’s: Name them accordingly (postfix “x64”) and in your executable build just use a macro and add “x64” to the file name when loading in 64-bit builds.

Otherwise, the 3rd-party DLL’s he or she listed in his or her first post are all static-link-enabled.

Frankly I don’t see the purpose in using DLL’s at all. Why not just static-link to them and save yourself build hassle and the run-time hassle of LoadLibraryW()?

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Taking a different tack on the question --- WHY?

What specific reason do you have for shipping both 64-bit and 32-bit versions of a game?

One of them is going to be the primary platform, the one with all the tests, the one that people use, the one where you probe the nooks and crannies of the system to find all the bugs. The other one won't have the tests and will be full of all kinds of bugs.

Invariably you are going to come across some system specific bugs that are only manifest on 32 or 64 bit variants. Some code might do something funky with alignment, or it might encode a pointer as an int, or some other bugs are going to happen.

Do you have a specific reason to follow this course?

You have the cost of maintaining multiple branches, testing multiple branches, doing fixes on multiple branches, releasing multiple branches. Do you have a reason for incurring this cost?

For most games PC games right now the choice is either 32-bit because you can, or 64-bit because of good reasons. Trying to take both options is probably a bad decision without some very strong business case for it.


Assuming you have a reason, why do you need to do this dynamically? Either you install the 32 bit version or you install the 64 bit version. People are not going to change their operating system mid-game. You don't have cases where you want the 32-bit version of one library and the 64 bit version of another. "I'd like a 32-bit audio driver, a 64-bit graphics driver, and a 16-bit mouse driver". All or nothing. Either you have the 32-bit version of the game or the 64-bit version of the game.

Putting aside the fact that I never mentioned shipping both versions, long story short all the exporters and tools run the libs/dlls from the engine build, certain memory and stability benefits from moving to 64bit tools (3DS max 64/32 Maya 64/32) have created a requirement that I need 64bit everything, plus Id like to future proof, end of story.

Now in the case of something like lib png, which I build any way, I suppose I could change the name of the 64bit dll. But in the case of some pre-built binaries where

I dont have the source and they are packaged in folders "x86" "x64" etc. while using the same name Id like to load the correct one for the correct build.

Up to this point I havent had many 3rd party libs to deal with, If I need "libpng16.dll" I just put it in the exe's directory. But now I would simply like to sort things into sub folders. With the exception of my dlls, Ive never called load library on 3rd party dlls, theyve simply loaded from the exe's dir.

Now Id like to move them, and Im wondering whats the best way to go about it.

Up to this point I havent had many 3rd party libs to deal with, If I need "libpng16.dll" I just put it in the exe's directory. But now I would simply like to sort things into sub folders. With the exception of my dlls, Ive never called load library on 3rd party dlls, theyve simply loaded from the exe's dir.
Now Id like to move them, and Im wondering whats the best way to go about it.

Again, why not just statically link to them and screw the DLL hell?
What you have listed so far all have the ability to statically link to them.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


But now I would simply like to sort things into sub folders. With the exception of my dlls, Ive never called load library on 3rd party dlls, theyve simply loaded from the exe's dir.
Now Id like to move them, and Im wondering whats the best way to go about it.


If you don't want to link statically, move your executables into separate subdirectories along with the bit-specific DLLs.

/app/bin32/*32.(exe,dll)
/app/bin64/*64.(exe/dll)

Then you can continue to link with the import libraries and the DLLs will be loaded automatically as normal. As for loading resources and your custom dlls, you can use the Win32 API to determine the directory in which the executable lives and use that as the base for finding the resource directories. Or, since you mentioned PhysFS, it provides a cross-platform way to do this. Look into PHSYFS_getBaseDir. Or, assuming you've configured PHSYFS to put the base directory (or the directory above it, which would be more appropriate in your case) on the search path, you can use the PHYSFS API to load the files and not worry about specifying the full path.


I had the same issue recently. My solution: have batch files that copy all DLLs from a platform-specific subfolder to the executable folder (silently overwriting existing files). For example:

xcopy /Y bin/x64/*.dll bin/

In your case you'd have one for the 32 bit DLLs and one for the 64 bit DLLs. Run the batch file corresponding to the version you're testing either manually or automatically as a post-build event in Visual Studio.

This topic is closed to new replies.

Advertisement