Cross-compile Irrlicht from Linux to create Windows DLL/EXE

A forum to store posts deemed exceptionally wise and useful
Post Reply

Are you interested in cross-platform development?

Yes! Death to the evil empire!
21
100%
No! Get lost you free-software hippie!
0
No votes
Huh? Who the heck is "ming"?
0
No votes
 
Total votes: 21

pinballwizard
Posts: 67
Joined: Wed Aug 02, 2006 1:47 am

Cross-compile Irrlicht from Linux to create Windows DLL/EXE

Post by pinballwizard »

To my pleasant surprise, I found it quite easy to cross-compile a Windows DLL and executable examples from my Linux box using mingw32.

Environment: Ubuntu Breezy Linux
Irrlicht version: 0.14 (should work for later versions though)

To install mingw32: apt-get install mingw32 mingw32-binutils mingw32-runtime

To compile Irrlicht.dll and libIrrlicht.a use the following Makefile (modified from the old Makefile.win for DEV-C++):

Code: Select all

# Project: Irrlicht

CXX  = i586-mingw32msvc-g++
CC   = i586-mingw32msvc-gcc
OBJ  = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUIToolBar.o CGUIWindow.o CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o CTRTextureGouraudWire.o CZBuffer.o COpenGLDriver.o COpenGLNormalMapRenderer.o COpenGLParallaxMapRenderer.o COpenGLShaderMaterialRenderer.o COpenGLTexture.o CD3D8Driver.o CD3D8NormalMapRenderer.o CD3D8ParallaxMapRenderer.o CD3D8ShaderMaterialRenderer.o CD3D8Texture.o CColorConverter.o CFPSCounter.o CImage.o CImageLoaderBmp.o CImageLoaderJPG.o CImageLoaderPCX.o CImageLoaderPNG.o CImageLoaderPSD.o CImageLoaderTGA.o CNullDriver.o CD3D9Driver.o CD3D9HLSLMaterialRenderer.o CD3D9NormalMapRenderer.o CD3D9ParallaxMapRenderer.o CD3D9ShaderMaterialRenderer.o CD3D9Texture.o CVideoModeList.o C3DSMeshFileLoader.o CAnimatedMeshMD2.o CAnimatedMeshMS3D.o CAnimatedMeshSceneNode.o CBillboardSceneNode.o CCameraFPSSceneNode.o CCameraMayaSceneNode.o CCameraSceneNode.o CColladaFileLoader.o CCSMLoader.o CDefaultMeshFormatLoader.o CDMFLoader.o CDummyTransformationSceneNode.o CEmptySceneNode.o CGeometryCreator.o CLightSceneNode.o CLMTSMeshFileLoader.o CMeshManipulator.o CMeshSceneNode.o CMetaTriangleSelector.o CMY3DMeshFileLoader.o COCTLoader.o COctTreeSceneNode.o COctTreeTriangleSelector.o CParticleBoxEmitter.o CParticleFadeOutAffector.o CParticleGravityAffector.o CParticlePointEmitter.o CParticleSystemSceneNode.o CQ3LevelMesh.o CSceneCollisionManager.o CSceneManager.o CSceneNodeAnimatorCollisionResponse.o CSceneNodeAnimatorDelete.o CSceneNodeAnimatorFlyCircle.o CSceneNodeAnimatorFlyStraight.o CSceneNodeAnimatorFollowSpline.o CSceneNodeAnimatorRotation.o CSceneNodeAnimatorTexture.o CShadowVolumeSceneNode.o CSkyBoxSceneNode.o CStaticMeshOBJ.o CTerrainSceneNode.o CTerrainTriangleSelector.o CTestSceneNode.o CTextSceneNode.o CTriangleBBSelector.o CTriangleSelector.o CWaterSurfaceSceneNode.o CXAnimationPlayer.o CXFileReader.o CXMeshFileLoader.o CFileList.o CFileSystem.o CLimitReadFile.o CMemoryReadFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CZipReader.o irrXML.o zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/uncompr.o zlib/zutil.o jpeglib/cdjpeg.o jpeglib/jcapimin.o jpeglib/jcapistd.o jpeglib/jccoefct.o jpeglib/jccolor.o jpeglib/jcdctmgr.o jpeglib/jchuff.o jpeglib/jcinit.o jpeglib/jcmainct.o jpeglib/jcmarker.o jpeglib/jcmaster.o jpeglib/jcomapi.o jpeglib/jcparam.o jpeglib/jcphuff.o jpeglib/jcprepct.o jpeglib/jcsample.o jpeglib/jctrans.o jpeglib/jdapimin.o jpeglib/jdapistd.o jpeglib/jdatadst.o jpeglib/jdatasrc.o jpeglib/jdcoefct.o jpeglib/jdcolor.o jpeglib/jddctmgr.o jpeglib/jdhuff.o jpeglib/jdinput.o jpeglib/jdmainct.o jpeglib/jdmarker.o jpeglib/jdmaster.o jpeglib/jdmerge.o jpeglib/jdphuff.o jpeglib/jdpostct.o jpeglib/jdsample.o jpeglib/jdtrans.o jpeglib/jerror.o jpeglib/jfdctflt.o jpeglib/jfdctfst.o jpeglib/jfdctint.o jpeglib/jidctflt.o jpeglib/jidctfst.o jpeglib/jidctint.o jpeglib/jidctred.o jpeglib/jmemmgr.o jpeglib/jmemnobs.o jpeglib/jquant1.o jpeglib/jquant2.o jpeglib/jutils.o jpeglib/rdbmp.o jpeglib/rdcolmap.o jpeglib/rdgif.o jpeglib/rdppm.o jpeglib/rdrle.o jpeglib/rdswitch.o jpeglib/rdtarga.o jpeglib/transupp.o jpeglib/wrbmp.o jpeglib/wrgif.o jpeglib/wrppm.o jpeglib/wrrle.o jpeglib/wrtarga.o libpng/png.o libpng/pngerror.o libpng/pngget.o libpng/pngmem.o libpng/pngpread.o libpng/pngread.o libpng/pngrio.o libpng/pngrtran.o libpng/pngrutil.o libpng/pngset.o libpng/pngtrans.o libpng/pngwio.o libpng/pngwrite.o libpng/pngwtran.o libpng/pngwutil.o CIrrDeviceLinux.o CIrrDeviceStub.o CIrrDeviceWin32.o CLogger.o COSOperator.o CStringParameters.o Irrlicht.o os.o CMeshCache.o COpenGLSLMaterialRenderer.o CZBuffer2.o CTRTextureGouraudAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o $(RES)
LINKOBJ  = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUIToolBar.o CGUIWindow.o CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o CTRTextureGouraudWire.o CZBuffer.o COpenGLDriver.o COpenGLNormalMapRenderer.o COpenGLParallaxMapRenderer.o COpenGLShaderMaterialRenderer.o COpenGLTexture.o CD3D8Driver.o CD3D8NormalMapRenderer.o CD3D8ParallaxMapRenderer.o CD3D8ShaderMaterialRenderer.o CD3D8Texture.o CColorConverter.o CFPSCounter.o CImage.o CImageLoaderBmp.o CImageLoaderJPG.o CImageLoaderPCX.o CImageLoaderPNG.o CImageLoaderPSD.o CImageLoaderTGA.o CNullDriver.o CD3D9Driver.o CD3D9HLSLMaterialRenderer.o CD3D9NormalMapRenderer.o CD3D9ParallaxMapRenderer.o CD3D9ShaderMaterialRenderer.o CD3D9Texture.o CVideoModeList.o C3DSMeshFileLoader.o CAnimatedMeshMD2.o CAnimatedMeshMS3D.o CAnimatedMeshSceneNode.o CBillboardSceneNode.o CCameraFPSSceneNode.o CCameraMayaSceneNode.o CCameraSceneNode.o CColladaFileLoader.o CCSMLoader.o CDefaultMeshFormatLoader.o CDMFLoader.o CDummyTransformationSceneNode.o CEmptySceneNode.o CGeometryCreator.o CLightSceneNode.o CLMTSMeshFileLoader.o CMeshManipulator.o CMeshSceneNode.o CMetaTriangleSelector.o CMY3DMeshFileLoader.o COCTLoader.o COctTreeSceneNode.o COctTreeTriangleSelector.o CParticleBoxEmitter.o CParticleFadeOutAffector.o CParticleGravityAffector.o CParticlePointEmitter.o CParticleSystemSceneNode.o CQ3LevelMesh.o CSceneCollisionManager.o CSceneManager.o CSceneNodeAnimatorCollisionResponse.o CSceneNodeAnimatorDelete.o CSceneNodeAnimatorFlyCircle.o CSceneNodeAnimatorFlyStraight.o CSceneNodeAnimatorFollowSpline.o CSceneNodeAnimatorRotation.o CSceneNodeAnimatorTexture.o CShadowVolumeSceneNode.o CSkyBoxSceneNode.o CStaticMeshOBJ.o CTerrainSceneNode.o CTerrainTriangleSelector.o CTestSceneNode.o CTextSceneNode.o CTriangleBBSelector.o CTriangleSelector.o CWaterSurfaceSceneNode.o CXAnimationPlayer.o CXFileReader.o CXMeshFileLoader.o CFileList.o CFileSystem.o CLimitReadFile.o CMemoryReadFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CZipReader.o irrXML.o zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/uncompr.o zlib/zutil.o jpeglib/cdjpeg.o jpeglib/jcapimin.o jpeglib/jcapistd.o jpeglib/jccoefct.o jpeglib/jccolor.o jpeglib/jcdctmgr.o jpeglib/jchuff.o jpeglib/jcinit.o jpeglib/jcmainct.o jpeglib/jcmarker.o jpeglib/jcmaster.o jpeglib/jcomapi.o jpeglib/jcparam.o jpeglib/jcphuff.o jpeglib/jcprepct.o jpeglib/jcsample.o jpeglib/jctrans.o jpeglib/jdapimin.o jpeglib/jdapistd.o jpeglib/jdatadst.o jpeglib/jdatasrc.o jpeglib/jdcoefct.o jpeglib/jdcolor.o jpeglib/jddctmgr.o jpeglib/jdhuff.o jpeglib/jdinput.o jpeglib/jdmainct.o jpeglib/jdmarker.o jpeglib/jdmaster.o jpeglib/jdmerge.o jpeglib/jdphuff.o jpeglib/jdpostct.o jpeglib/jdsample.o jpeglib/jdtrans.o jpeglib/jerror.o jpeglib/jfdctflt.o jpeglib/jfdctfst.o jpeglib/jfdctint.o jpeglib/jidctflt.o jpeglib/jidctfst.o jpeglib/jidctint.o jpeglib/jidctred.o jpeglib/jmemmgr.o jpeglib/jmemnobs.o jpeglib/jquant1.o jpeglib/jquant2.o jpeglib/jutils.o jpeglib/rdbmp.o jpeglib/rdcolmap.o jpeglib/rdgif.o jpeglib/rdppm.o jpeglib/rdrle.o jpeglib/rdswitch.o jpeglib/rdtarga.o jpeglib/transupp.o jpeglib/wrbmp.o jpeglib/wrgif.o jpeglib/wrppm.o jpeglib/wrrle.o jpeglib/wrtarga.o libpng/png.o libpng/pngerror.o libpng/pngget.o libpng/pngmem.o libpng/pngpread.o libpng/pngread.o libpng/pngrio.o libpng/pngrtran.o libpng/pngrutil.o libpng/pngset.o libpng/pngtrans.o libpng/pngwio.o libpng/pngwrite.o libpng/pngwtran.o libpng/pngwutil.o CIrrDeviceLinux.o CIrrDeviceStub.o CIrrDeviceWin32.o CLogger.o COSOperator.o CStringParameters.o Irrlicht.o os.o CMeshCache.o COpenGLSLMaterialRenderer.o CZBuffer2.o CTRTextureGouraudAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o $(RES)
LIBS =  -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lglu32 -lopengl32 
INCS =  -I"/usr/lib"  -I"include"  -I"zlib" 
CXXINCS = -I"include"  -I"zlib" 
BIN  = Irrlicht.dll
CXXFLAGS = $(CXXINCS)-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DIRRLICHT_EXPORTS   -fexpensive-optimizations -O1
CFLAGS = $(INCS)-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DIRRLICHT_EXPORTS   -fexpensive-optimizations -O1

.PHONY: all all-before all-after clean clean-custom

all: all-before Irrlicht.dll all-after


clean: clean-custom
	rm -f $(OBJ) $(BIN)

STATICLIB=libIrrlicht.a

$(BIN): $(LINKOBJ)
	$(CXX) -shared -o $(BIN) $(LINKOBJ) $(LIBS) -Wl,--out-implib,$(STATICLIB)
After compiling, you have Irrlicht.dll and libIrrlicht.a.

Copy libIrrlicht.a into ../../lib/Win32-gcc. I also deleted the existing libIrrlicht.def file in ../../lib/Win32-gcc; it seems unnecessary.

Copy Irrlicht.dll into ../../bin/Win32-gcc (probably not necessary though, only needed for running)

Use the following makefile to compile the 01.HelloWorld example:

Code: Select all


CPP = i586-mingw32msvc-g++ 
OPTS =  -I"../../include" -L"../../lib/Win32-gcc" -lIrrlicht -lopengl32 -lglu32 -lm

all:
        $(CPP) main.cpp -o example $(OPTS)

clean:
        rm example
Rename example to example.exe. Copy example.exe and irrlicht.dll to a Windows machine, and bingo! It works! I tested both the software renderer and the OpenGL renderer (by changing the main.cpp file).

So, cross-platform development (Linux development environment producing windows executables) is possible.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

That's pretty cool 8) I just thought about moving parts of the Makefile.win to Makefile because I'm fed up with occasional errors on my system when choosing the wrong Makefile :evil: So I planned for a 'make dll' target which could use parts of your makefile as well, enabling proper makes for all platforms.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Are all these libraries and defines really necessary, or is it a "dev-cpp-default"? I guess that some defines are default for the compiler?
pinballwizard
Posts: 67
Joined: Wed Aug 02, 2006 1:47 am

Cross compiling 1.1 and static link

Post by pinballwizard »

After a lot of menial work I got Irrlicht 1.1 to cross-compile and statically-link from Linux producing a single Windows EXE with no DLL dependencies.

This isn't a detailed step-by-step explanation but basically it was as follows:

1. Modify Linux Makefile to compile everything with the cross-compiler and build a static-lib:

CXX = i586-mingw32msvc-g++
CC = i586-mingw32msvc-gcc
AR = i586-mingw32msvc-ar
RANLIB = i586-mingw32msvc-ranlib
CFLAGS/CXXFLAGS as in above post

It's not enough just to define these variables - you have to check what the Makefile is doing and make sure to use the variables you defined (e.g. make sure the makefile calls $(CXX) and not g++ directly).

2. This apparently builds the static library but when I tried to compile and statically link the 01.HelloWorld example I got a lot of linker errors with zlib, libpng, and libjpeg symbols.

Closer investigation revealed that zlib, libpng, and libjpeg were the only sources compiled with $(CC) and not $(CXX) i.e. with the plain C compiler, not C++. This apparently caused static linking problems due to name mangling (my hypothesis). Apparently this works in the dynamic/DLL case because the Windows runtime linker correctly finds the symbols (C or C++) at runtime. This is just my guess.

3. So I changed CC to also use CC = i586-mingw32msvc-g++ (not gcc), so all code would be compiled with the same g++ compiler which hopefully would eliminate linker errors.

Then I had problems compiling Irrlicht's zlib because of lots of non-ansi K&R-style function definitions clashing with the ANSI-C-style function declarations, which gcc allows but g++ prohibits. I changed all K&R-style function definitions in zlib to be ANSI-C-style (with the help of an Emacs macro - The One True Editor is great!)

Also there were some non-ANSI implicit pointer casts in libpng, which I had to fix to compile with g++.

I think libjpeg compiled cleanly with g++.

4. I tried to statically link 01.HelloWorld and got some link errors about _jpeg_XXX symbols not found.

This is because in the file CImageLoaderJPG.h, the jpeglib include file is included within an extern "C" block, implying C-style name mangling/lookup of jpeglib symbols, but we now compiled jpeglib with g++ so its symbols are in C++-mangled format. So I removed the extern "C" statement in CImageLoaderJPG.h.

5. Finally I compiled and statically linked 01.HelloWorld.exe.

I don't have Windows here to test, so I ran the resulting .EXE, with WINE and an empty WINE directory (i.e. no extra DLL's) and it worked, so I'm pretty sure the produced EXE is valid and has no DLL dependencies.

I'm not sure why the cross-compiled g++ code couldn't link with the cross-compiled gcc code. Maybe there were extra/missing extern "C" blocks - not sure. Anyway, that's how I got it to work.

Hope this helps anyone else working with cross-compiling (is there anyone else?)
xhrit
Posts: 140
Joined: Mon Jun 14, 2004 8:54 am
Location: earth
Contact:

Re: Cross compiling 1.1 and static link

Post by xhrit »

pinballwizard wrote:Hope this helps anyone else working with cross-compiling (is there anyone else?)
Me! I hate windows.

Copy and paste your makefile does not work; i had to copy and paste each line, and edit it; the 'code' tag seems to do strange things with the tabs/spaces, and make is picky about that sort ov thing...
Core2Duo E8400 3.0ghz - 2048mb DDR2 800 - geForce 9600 - Slackware12.1

Word-image-symbol programming limits, controls, and imprisons the individual.
Smash the control images, smash the control machine.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

yeah with the code tags you need to click quote to get the original text in a text box instead of as html output
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
xhrit
Posts: 140
Joined: Mon Jun 14, 2004 8:54 am
Location: earth
Contact:

Post by xhrit »

bitplane wrote:yeah with the code tags you need to click quote to get the original text in a text box instead of as html output
yeah, that works better then before. Still doesn't work correctly tho; make gives me this error :

make: *** No rule to make target `CGUIButton.cpp', needed by `CGUIButton.o'. Stop.
Core2Duo E8400 3.0ghz - 2048mb DDR2 800 - geForce 9600 - Slackware12.1

Word-image-symbol programming limits, controls, and imprisons the individual.
Smash the control images, smash the control machine.
pinballwizard
Posts: 67
Joined: Wed Aug 02, 2006 1:47 am

Post by pinballwizard »

xhrit wrote:
bitplane wrote:yeah with the code tags you need to click quote to get the original text in a text box instead of as html output
yeah, that works better then before. Still doesn't work correctly tho; make gives me this error :

make: *** No rule to make target `CGUIButton.cpp', needed by `CGUIButton.o'. Stop.
What Irrlicht version are you compiling? Did you use the Makefile exactly as posted above? I've been experimenting with different versions and compiling strategies, so it's possible there's an error in the Makefile I posted.

Does the file CGUIButton.cpp exist? Sometimes the Irrlicht Makefile and the files on disk have different cAPitaLIzaTIon, probably because some operating systems from the evil empire tend to mess up and/or ignore filename capitalization. So one thing to always check is that the capitalization of the filenames in the Makefile is the same as those on disk.
Post Reply