Why does JUCE hate me?

OK after reading around the forums and included documentation I simply cannot get even a basic “empty” application to compile. I know it’s not my build environment because the demos build properly.

To start off with I have a single file, “pcano.cpp” which contains this code:

#include "juce_amalgamated.h"

class PianoWindow : public DocumentWindow
{
	public:
		PianoWindow() : DocumentWindow(T("PCAno"), Colour(0.5f,0.5f,0.5f,1.0f), closeButton, true)
		{
		};	
};

class PCAnoApp : public JUCEApplication
{
	PianoWindow* MainWindow;

	public:
	
		PCAnoApp() : MainWindow(0)
		{
			
		}

		~PCAnoApp()
		{
		}

		void initialise(const String& CommandLine)
		{
			MainWindow = new PianoWindow();
			MainWindow->setBounds(100,100,720,128);
			MainWindow->setVisible(true);
		}
	
		void shutdown()
		{
			delete MainWindow;
		}
		
		const String getApplicationName()
		{
			return T("PCAno");
		}

		const String getApplicationVersion()
		{
			return T("0.4.0");
		}
};

START_JUCE_APPLICATION (PCAnoApp)

I have a makefile containing this code:

pcano:
	gcc -I.. -o./bin/pcano -DLINUX pcano.cpp -lfreetype -lpthread -lX11

I’m using Linux, and GCC is working perfectly.

Output is:

/tmp/cc55Rp0U.o: In function `main':
pcano.cpp:(.text+0x4a): undefined reference to `juce::JUCEApplication::main(int, char**, juce::JUCEApplication*)'
/tmp/cc55Rp0U.o: In function `PCAnoApp::PCAnoApp()':
pcano.cpp:(.text._ZN8PCAnoAppC1Ev[PCAnoApp::PCAnoApp()]+0xd): undefined reference to `juce::JUCEApplication::JUCEApplication()'
/tmp/cc55Rp0U.o: In function `PCAnoApp::getApplicationVersion()':
pcano.cpp:(.text._ZN8PCAnoApp21getApplicationVersionEv[PCAnoApp::getApplicationVersion()]+0x18): undefined reference to `juce::String::String(wchar_t const*)'
/tmp/cc55Rp0U.o: In function `PCAnoApp::getApplicationName()':
pcano.cpp:(.text._ZN8PCAnoApp18getApplicationNameEv[PCAnoApp::getApplicationName()]+0x18): undefined reference to `juce::String::String(wchar_t const*)'
/tmp/cc55Rp0U.o: In function `PianoWindow::PianoWindow()':
pcano.cpp:(.text._ZN11PianoWindowC1Ev[PianoWindow::PianoWindow()]+0x33): undefined reference to `juce::Colour::Colour(float, float, float, float)'
pcano.cpp:(.text._ZN11PianoWindowC1Ev[PianoWindow::PianoWindow()]+0x46): undefined reference to `juce::String::String(wchar_t const*)'
pcano.cpp:(.text._ZN11PianoWindowC1Ev[PianoWindow::PianoWindow()]+0x6f): undefined reference to `juce::DocumentWindow::DocumentWindow(juce::String const&, juce::Colour const&, int, bool)'
pcano.cpp:(.text._ZN11PianoWindowC1Ev[PianoWindow::PianoWindow()]+0x80): undefined reference to `juce::String::~String()'
pcano.cpp:(.text._ZN11PianoWindowC1Ev[PianoWindow::PianoWindow()]+0x8b): undefined reference to `juce::Colour::~Colour()'
pcano.cpp:(.text._ZN11PianoWindowC1Ev[PianoWindow::PianoWindow()]+0xc2): undefined reference to `juce::String::~String()'
pcano.cpp:(.text._ZN11PianoWindowC1Ev[PianoWindow::PianoWindow()]+0xd9): undefined reference to `juce::Colour::~Colour()'
/tmp/cc55Rp0U.o: In function `PCAnoApp::initialise(juce::String const&)':
pcano.cpp:(.text._ZN8PCAnoApp10initialiseERKN4juce6StringE[PCAnoApp::initialise(juce::String const&)]+0x55): undefined reference to `juce::Component::setBounds(int, int, int, int)'
/tmp/cc55Rp0U.o: In function `PianoWindow::~PianoWindow()':
pcano.cpp:(.text._ZN11PianoWindowD0Ev[PianoWindow::~PianoWindow()]+0x28): undefined reference to `juce::DocumentWindow::~DocumentWindow()'
/tmp/cc55Rp0U.o: In function `PianoWindow::~PianoWindow()':
pcano.cpp:(.text._ZN11PianoWindowD1Ev[PianoWindow::~PianoWindow()]+0x28): undefined reference to `juce::DocumentWindow::~DocumentWindow()'
/tmp/cc55Rp0U.o: In function `PCAnoApp::~PCAnoApp()':
pcano.cpp:(.text._ZN8PCAnoAppD0Ev[PCAnoApp::~PCAnoApp()]+0x28): undefined reference to `juce::JUCEApplication::~JUCEApplication()'
/tmp/cc55Rp0U.o: In function `PCAnoApp::~PCAnoApp()':
pcano.cpp:(.text._ZN8PCAnoAppD1Ev[PCAnoApp::~PCAnoApp()]+0x28): undefined reference to `juce::JUCEApplication::~JUCEApplication()'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x10): undefined reference to `juce::JUCEApplication::getNextCommandTarget()'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x14): undefined reference to `juce::JUCEApplication::getAllCommands(juce::Array<int, juce::DummyCriticalSection>&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x18): undefined reference to `juce::JUCEApplication::getCommandInfo(int, juce::ApplicationCommandInfo&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x1c): undefined reference to `juce::JUCEApplication::perform(juce::ApplicationCommandTarget::InvocationInfo const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x30): undefined reference to `juce::JUCEApplication::moreThanOneInstanceAllowed()'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x34): undefined reference to `juce::JUCEApplication::anotherInstanceStarted(juce::String const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x38): undefined reference to `juce::JUCEApplication::systemRequestedQuit()'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x3c): undefined reference to `juce::JUCEApplication::unhandledException(std::exception const*, juce::String const&, int)'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x40): undefined reference to `juce::JUCEApplication::actionListenerCallback(juce::String const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV8PCAnoApp[vtable for PCAnoApp]+0x54): undefined reference to `non-virtual thunk to juce::JUCEApplication::actionListenerCallback(juce::String const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTI8PCAnoApp[typeinfo for PCAnoApp]+0x8): undefined reference to `typeinfo for juce::JUCEApplication'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x10): undefined reference to `juce::Component::mouseMove(juce::MouseEvent const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x14): undefined reference to `juce::Component::mouseEnter(juce::MouseEvent const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x18): undefined reference to `juce::Component::mouseExit(juce::MouseEvent const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x1c): undefined reference to `juce::ResizableWindow::mouseDown(juce::MouseEvent const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x20): undefined reference to `juce::ResizableWindow::mouseDrag(juce::MouseEvent const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x24): undefined reference to `juce::Component::mouseUp(juce::MouseEvent const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x28): undefined reference to `juce::DocumentWindow::mouseDoubleClick(juce::MouseEvent const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x2c): undefined reference to `juce::Component::mouseWheelMove(juce::MouseEvent const&, float, float)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x34): undefined reference to `juce::DocumentWindow::setName(juce::String const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x38): undefined reference to `juce::Component::setVisible(bool)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x3c): undefined reference to `juce::ResizableWindow::visibilityChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x40): undefined reference to `juce::TopLevelWindow::addToDesktop(int, void*)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x44): undefined reference to `juce::DocumentWindow::userTriedToCloseWindow()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x48): undefined reference to `juce::Component::minimisationStateChanged(bool)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x4c): undefined reference to `juce::DocumentWindow::parentHierarchyChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x50): undefined reference to `juce::Component::childrenChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x54): undefined reference to `juce::Component::hitTest(int, int)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x58): undefined reference to `juce::Component::contains(int, int)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x5c): undefined reference to `juce::DocumentWindow::lookAndFeelChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x60): undefined reference to `juce::Component::createFocusTraverser()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x64): undefined reference to `juce::Component::enablementChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x68): undefined reference to `juce::Component::getMouseCursor()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x6c): undefined reference to `juce::DocumentWindow::paint(juce::Graphics&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x70): undefined reference to `juce::Component::paintOverChildren(juce::Graphics&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x74): undefined reference to `juce::Component::keyPressed(juce::KeyPress const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x78): undefined reference to `juce::Component::keyStateChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x7c): undefined reference to `juce::Component::modifierKeysChanged(juce::ModifierKeys const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x80): undefined reference to `juce::Component::focusGained(juce::Component::FocusChangeType)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x84): undefined reference to `juce::Component::focusLost(juce::Component::FocusChangeType)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x88): undefined reference to `juce::TopLevelWindow::focusOfChildComponentChanged(juce::Component::FocusChangeType)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x8c): undefined reference to `juce::DocumentWindow::resized()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x90): undefined reference to `juce::ResizableWindow::moved()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x94): undefined reference to `juce::ResizableWindow::childBoundsChanged(juce::Component*)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x98): undefined reference to `juce::ResizableWindow::parentSizeChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0x9c): undefined reference to `juce::Component::broughtToFront()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xa0): undefined reference to `juce::Component::handleCommandMessage(int)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xa4): undefined reference to `juce::Component::canModalEventBeSentToComponent(juce::Component const*)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xa8): undefined reference to `juce::Component::inputAttemptWhenModal()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xac): undefined reference to `juce::Component::colourChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xb4): undefined reference to `juce::Component::internalRepaint(int, int, int, int)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xb8): undefined reference to `juce::Component::createNewPeer(int, void*)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xbc): undefined reference to `juce::Component::handleMessage(juce::Message const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xc0): undefined reference to `juce::DocumentWindow::activeWindowStatusChanged()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xc4): undefined reference to `juce::DocumentWindow::getDesktopWindowStyleFlags() const'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xc8): undefined reference to `juce::DocumentWindow::getBorderThickness()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xcc): undefined reference to `juce::DocumentWindow::getContentComponentBorder()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xd0): undefined reference to `juce::DocumentWindow::closeButtonPressed()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xd4): undefined reference to `juce::DocumentWindow::minimiseButtonPressed()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xd8): undefined reference to `juce::DocumentWindow::maximiseButtonPressed()'
/tmp/cc55Rp0U.o:(.rodata._ZTV11PianoWindow[vtable for PianoWindow]+0xec): undefined reference to `non-virtual thunk to juce::Component::handleMessage(juce::Message const&)'
/tmp/cc55Rp0U.o:(.rodata._ZTI11PianoWindow[typeinfo for PianoWindow]+0x8): undefined reference to `typeinfo for juce::DocumentWindow'
collect2: ld returned 1 exit status
make: *** [pcano] Error 1

The “-I…” part is because I have juce_amalgamated.h/.cpp in the parent directory, they are getting included just fine.

When I run this, however, I get a bazillion errors from GCC about undefined references! Yet this code is practically the same as the demos I’ve seen, it just doesn’t do anything yet other than create and display a window.

I don’t want to copy and paste anything because I’m not learning anything that way, so could someone please explain this to me?

I don’t use the amalgamated stuff, but a quick look at the readme says you need to be compiling and linking in juce_amalgamated.cpp as well…

OK adding #include <juce_amalgamated.cpp> results in a different set of errors that seems to suggest my linux header files are wrong, but again the demo compiles properly so it’s nothing to do with that.

Removed unhelpful output to save space in the thread.

EDIT: Being nosy and looking into the “juce_amalgamated.cpp” file itself reveals this:

/*  Got a build error here? You'll need to install the freetype library...

    The name of the package to install is "libfreetype6-dev".
*/
#include <ft2build.h>
#include FT_FREETYPE_H

I already have that installed, hence the demo was able to compile. But why is the compiler choking on that (what seems to be a) macro?

At first I thought it could be a bug in the latest version of JUCE (I got it from SVN today, after already having to checkout again because of the AudioCDReader bug), but yet again, THE DEMO COMPILES!

So why why why is it not working for me? Is there some secret magic word I have to say to the computer to get it to compile my own JUCE apps?

I thought JUCE was supposed to be easy to use - So far I’ve had more fun making a “Hello World” bootloader in ASM that enters 32-bit protected mode and displays the text!!

EDIT 2: A simple -I in the makefile solved the FreeType stuff, but now I’m getting told off about my code. Take a look:

gcc -I.. -o./bin/pcano -D "LINUX=1" pcano.cpp -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound -I "/usr/include" -I "/usr/include/freetype2" -O2 -s -L"/usr/X11R6/lib/"
In file included from pcano.cpp:1:
../juce_amalgamated.cpp: In function ‘int OggVorbisNamespace::_vorbis_pack_info(OggVorbisNamespace::oggpack_buffer*, OggVorbisNamespace::vorbis_info*)’:
../juce_amalgamated.cpp:137906: warning: deprecated conversion from string constant to ‘char*’
../juce_amalgamated.cpp: In function ‘int OggVorbisNamespace::_vorbis_pack_comment(OggVorbisNamespace::oggpack_buffer*, OggVorbisNamespace::vorbis_comment*)’:
../juce_amalgamated.cpp:137930: warning: deprecated conversion from string constant to ‘char*’
../juce_amalgamated.cpp: In function ‘int OggVorbisNamespace::_vorbis_pack_books(OggVorbisNamespace::oggpack_buffer*, OggVorbisNamespace::vorbis_info*)’:
../juce_amalgamated.cpp:137961: warning: deprecated conversion from string constant to ‘char*’
In file included from pcano.cpp:1:
../juce_amalgamated.cpp: In function ‘int OggVorbisNamespace::ov_crosslap(OggVorbisNamespace::OggVorbis_File*, OggVorbisNamespace::OggVorbis_File*)’:
../juce_amalgamated.cpp:188786: warning: deprecated conversion from string constant to ‘char*’
../juce_amalgamated.cpp:188787: warning: deprecated conversion from string constant to ‘char*’
../juce_amalgamated.cpp: In constructor ‘juce::OggWriter::OggWriter(juce::OutputStream*, double, int, int, int)’:
../juce_amalgamated.cpp:191461: warning: deprecated conversion from string constant to ‘char*’
In file included from pcano.cpp:1:
../juce_amalgamated.cpp: In function ‘void juce::juce_runSystemCommand(const juce::String&)’:
../juce_amalgamated.cpp:257100: warning: ignoring return value of ‘int system(const char*)’, declared with attribute warn_unused_result
pcano.cpp: At global scope:
pcano.cpp:4: error: expected class-name before ‘{’ token
pcano.cpp: In constructor ‘PianoWindow::PianoWindow()’:
pcano.cpp:6: error: class ‘PianoWindow’ does not have any field named ‘DocumentWindow’
pcano.cpp:6: error: ‘Colour’ was not declared in this scope
pcano.cpp:6: error: ‘closeButton’ was not declared in this scope
pcano.cpp: At global scope:
pcano.cpp:12: error: expected class-name before ‘{’ token
pcano.cpp:26: error: expected ‘,’ or ‘...’ before ‘&’ token
pcano.cpp:26: error: ISO C++ forbids declaration of ‘String’ with no type
pcano.cpp:38: error: ‘String’ does not name a type
pcano.cpp:43: error: ‘String’ does not name a type
pcano.cpp: In member function ‘void PCAnoApp::initialise(int)’:
pcano.cpp:29: error: ‘class PianoWindow’ has no member named ‘setBounds’
pcano.cpp:30: error: ‘class PianoWindow’ has no member named ‘setVisible’
pcano.cpp: In function ‘int main(int, char**)’:
pcano.cpp:49: error: no matching function for call to ‘juce::JUCEApplication::main(int&, char**&, PCAnoApp*)’
../juce_amalgamated.cpp:16123: note: candidates are: static int juce::JUCEApplication::main(juce::String&, juce::JUCEApplication*)
../juce_amalgamated.cpp:16234: note:                 static int juce::JUCEApplication::main(int, char**, juce::JUCEApplication*)
make: *** [pcano] Error 1

Someone please tell me the problem?

While #including may have solved part of the problem, I think it’s more ‘correct’ to add it as a dependency in the makefile… .cpp files should compile into .o’s (under linux) and then be linked together by the linker…

As for your next problem, I suggest you take the time to figure this one out on your own… maybe search the forums, and, as you did for the freetype problem, look in the headers and source files… The experiential reward to understanding how to resolve compile and link errors will serve you well…

Yes you’re right - I already figured out how to do it and am now well underway with development of my program, learning JUCE as I go along :slight_smile:

The solution was to have the amalgamated .cpp file #included in a separate header (which will also include any config #defines I decide to add later), and have that compiled as an object then linked in, being referred to by the amalgamated .h file wherever necessary within the program.

I think there should be a tutorial somewhere on how to create a makefile because not everyone is as “adventurous” as I am :stuck_out_tongue:

When I eventually get around to compiling this on Windows with MinGW, what changes would I need to make to the makefile?