Cross Compile on Linux for Win32


#1

I successfully built a Juce lib cross compiled Win32 target in Linux as a Debug build, but when I switched to Release build I got this error:

i586-mingw32msvc-g++ -I/usr/i586-mingw32msvc/include -I/usr/lib/gcc/i586-mingw32msvc/3.4.5/include -I/usr/lib/gcc/i586-mingw32msvc/3.4.5/include/c++ -I/usr/lib/gcc/i586-mingw32msvc/3.4.5/include/c++/backward -I/usr/lib/gcc/i586-mingw32msvc/3.4.5/include/c++/i586-mingw32msvc -c /home/bill/dev/CBWorkspace/juce-SVN312-win32/src/juce_appframework/gui/graphics/colour/juce_ColourGradient.cpp -o …/…/…/bin/intermediate_win32/Release/src/juce_appframework/gui/graphics/colour/juce_ColourGradient.o
/home/bill/dev/CBWorkspace/juce-SVN312-win32/src/juce_appframework/gui/graphics/colour/…/colour/juce_PixelFormats.h: In member function `juce::PixelARGB* juce::ColourGradient::createLookupTable(int&) const’:
/home/bill/dev/CBWorkspace/juce-SVN312-win32/src/juce_appframework/gui/graphics/colour/…/colour/juce_PixelFormats.h:120: sorry, unimplemented: inlining failed in call to ‘void juce::PixelARGB::tween(const Pixel&, juce::uint32) throw () [with Pixel = juce::PixelARGB]’: function body not available
/home/bill/dev/CBWorkspace/juce-SVN312-win32/src/juce_appframework/gui/graphics/colour/juce_ColourGradient.cpp:161: sorry, unimplemented: called from here

If I change one parameter in the Release target, the problem magically disappears, I add: define _DEBUG=1

My guess is the issue might concern juce_PlatformDefs.h line 345:

#ifndef JUCE_DEBUG
#define forcedinline inline attribute((always_inline))
#else
#define forcedinline inline
#endif

This is SVN312 code. The cross compiler is GCC 3.4.5. Any thoughts?

Bill


#2

Someone else mentioned having trouble with that forcedinline directive on gcc recently… (It’s not a problem in newer versions of gcc though)


#3

Ok, that makes sense, as I had no trouble with the non-debug build using native gcc 4.1.2 with a native Linux target.

Bill


#4

I am now using cross compiler gcc 4.2.1 (Ubuntu Gutsy and the Debian Testing mingw packages) and the Release build compiles fine, including fixing a minor issue with the shlobj.h file not having the CSIDL_MYMUSIC and CSIDL_MYVIDEO defines which Juce needs.

Bill

P.S. Ubuntu Gutsy is a bit unstable at this time - I advise caution.


#5

Tried cross compiling the DemoJuceFilter and (ironically) the Windows build works (tested in Windows FL Studio and eXT2, both running under Wine, lol ), and the Linux version builds but does not run in Linux native eXT2. Here are a few notes:

  1. In the Windows build I modified juce_VSTWrapper.cpp around line 1523 to remove a few lines, like this:

#ifndef GNUC
extern “C” __declspec (dllexport) void* main (audioMasterCallback audioMaster)
{
return (void*) pluginEntryPoint (audioMaster);
}
#endif

because I was getting an error that (void *) was not (int) for main. Some (older) hosts might need main, so my “fix” is probably not the right approach.

  1. The Linux build has some similar wrangling in Juce_VSTWrapper.cpp around line 1494 like this:

extern “C” attribute ((visibility (“default”))) AEffect* main_plugin (audioMasterCallback audioMaster) asm (“main”);

#define main main_plugin

extern “C” attribute ((visibility (“default”))) AEffect* main (audioMasterCallback audioMaster)
{
initialiseJuce_GUI();
SharedMessageThread::getInstance();

return pluginEntryPoint (audioMaster);

}

And then in aeffect.h (from the VST SDK, not Juce) around line 40 I added:

#elif defined(GNUC) && defined(LINUX)
#pragma pack(push,8)
#define VSTCALLBACK

and a && defined(WIN32) before that to differentiate between Windows GCC vs Linux GCC.

Again this may not be the best, or even viable, approach, but this much I am reasonably sure, that Linux eXT2 wants main to be exported (which I can confirm using nm), and this works in other non-Juce VSTs I have built. Nevertheless, the Juce demo filter does not work in native Linux eXT2. Since eXT2 is very beta-ish, this may mean nothing in particular. In fact, the Windows demo filter does not export main, but rather VSTPluginMain, and the Windows eXT2 uses that entry point, so I would anticipate the Linux eXT2 following this criteria, eventually.

  1. One question is whether the Linux demo filter vst is known to work, and if so, what host? eXT2 is the only one I know of that does not use Wine, aka is a real Linux VST host.

Bill


#6

linux demo filter is known to work with eXT2 and Jost in linux… they are the only 2 native vst hosts out there (of course you can consider also the juce host in extras folder !).

i suggest you to compile it with vstsdk 2.3, it is compiling straightforward without making any changes to the sdk. and about main… you actually are exporting main_plugin with “main” asm export symbol (thus actually exporting main). My plugins are all working with both hosts, and they are using the vst wrapper…


#7

Still not working with vstsdk 2.3, but I am using Juce SVN312, so all I can think is that you are using something earlier.

One possible bug is that in extras/audio plugins/demo/build/VST_Linux/premake.lua, line #10 there is:

package.kind = “dll”

which I changed to

package.kind = “so”

Without this change I was getting a link error:

Linking JucePluginDemo
/usr/bin/ld: unrecognized option ‘–out-implib=build/liblibJucePluginDemo.a’

Also I copied over a runpremake script and changed it to:

#!/bin/bash
premake --file premake.lua --cc gcc --target gnu

And I assume that invoaction is correct, no?

In addition to these items, I tried my standard tricks to export main via main_plugin, and added a VSTPluginMain, which is easier to read than to explain, so…(in juce_VSTWrapper.cpp line 1494-ish)

// Linux startup code…
#elif JUCE_LINUX

extern “C” attribute ((visibility(“default”))) AEffect* VSTPluginMain (audioMasterCallback audioMaster)
{
initialiseJuce_GUI();
SharedMessageThread::getInstance();

return pluginEntryPoint (audioMaster);

}

extern “C” attribute ((visibility(“default”))) AEffect* main_plugin (audioMasterCallback audioMaster) asm (“main”);

#define main main_plugin

extern “C” attribute ((visibility(“default”))) AEffect* main (audioMasterCallback audioMaster)
{
return VSTPluginMain (audioMaster);
}

But this does not work either. I’m not in any particular hurry to get this working, so no worries. Just knowing someone out there has something working native Linux is good enough.

Bill


#8

correct. i actually have this:

[code]extern “C” AEffect* main_plugin (audioMasterCallback audioMaster) asm (“main”);

extern “C” AEffect* main_plugin (audioMasterCallback audioMaster)
{
initialiseJuce_GUI();

SharedMessageThread::getInstance();

return pluginEntryPoint (audioMaster);

}[/code]

and it works without any problems.


#9

Okay, your suggestion to take out the

#define main main_plugin

with the dual main_plugin() works fine as far as I can see - main is exported.

At this point the only thing I can say is that I put printf statements in all the potential entry points: VSTPluginMain (as I recoded and exported it), main_plugin, myPluginInit, and myPluginFini, and none of them are getting called. eXT2 unhappy about something maybe, but eXT has no complaints (or positive comments either) from the command line.

Bill


#10

So boiling down all those posts, is this the sensible thing for me to change it to:

[code]extern “C” AEffect* VSTPluginMain (audioMasterCallback audioMaster)
{
initialiseJuce_GUI();
SharedMessageThread::getInstance();

return pluginEntryPoint (audioMaster);

}

extern “C” AEffect* main_plugin (audioMasterCallback audioMaster) asm (“main”);

extern “C” AEffect* main_plugin (audioMasterCallback audioMaster)
{
return VSTPluginMain (audioMaster);
}
[/code]


#11

My limited understanding is that some older hosts want to see main, while new ones are supposed to look for VSTPluginMain, so that would make sense.

I had trouble compiling the Win32 target with GCC due to the “main is int, not void* error” so I wonder if something similar would make sense for the Win32 section (not tested, I’m wingin it):

// Win32 startup code…

#else

extern “C” __declspec (dllexport) AEffect* VSTPluginMain (audioMasterCallback audioMaster)
{
return pluginEntryPoint (audioMaster);
}

#ifdef GNUC
extern “C” __declspec (dllexport) AEffect* main_plugin (audioMasterCallback audioMaster) asm (“main”);

extern “C” __declspec (dllexport) AEffect* main_plugin (audioMasterCallback audioMaster)
{
return (void*) VSTPluginMain (audioMaster);
}

#elif // else if not GCC compiler

extern “C” __declspec (dllexport) void* main (audioMasterCallback audioMaster)
{
return (void*) VSTPluginMain (audioMaster);
}

#endif // GNUC

Some input from others more knowledgeable would be a good thing though.

Bill


#12