FRUT icon indicating copy to clipboard operation
FRUT copied to clipboard

BinaryData.h might be included from two different folders, causing errors

Open danra opened this issue 5 years ago • 4 comments

I had a JuceLibraryCode folder with BinaryData.h under my root project folder from a previous non-FRUT build, and after building with FRUT also under build/JuceLibraryCode.

The two files both got included in some source files, causing variable redefinition errors.

Perhaps add a step to the README suggesting to remove JuceLibraryCode from non-FRUT builds to make sure this doesn't happen?

Or, try to handle it via include paths, but I guess this could prove tricky for all projects (e.g. in my project I had ../../ as an include path, which is what Xcode needs to find some include folders under the project's root folder (without explicitly specifying ../../ every time in the include).

danra avatar Dec 29 '19 10:12 danra

I initially thought this was an issue with my own project, but apparently JUCE's example projects also demonstrate this behavior. All that's needed to reproduce the duplicate definitions error is to first build with the Xcode project exported by the Projucer as usual, then try building with cmake (via FRUT).

danra avatar Jan 13 '20 14:01 danra

All that's needed to reproduce the duplicate definitions error is to first build with the Xcode project exported by the Projucer as usual, then try building with cmake (via FRUT).

I don't understand how building with the Xcode project exported by Projucer would have any impact on what the CMake-based build system does. Are you using the Builds/MacOSX folder as the binary directory for the CMake build?

McMartin avatar Jan 13 '20 15:01 McMartin

I can reproduce the issue when building the DemoRunner example from JUCE 5.4.5 in FRUT (https://github.com/McMartin/FRUT/tree/master/generated/JUCE-5.4.5/examples/DemoRunner):

[ 22%] Building CXX object CMakeFiles/DemoRunner.dir/Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/Main.cpp.o
In file included from /Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/Main.cpp:28:
In file included from /Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/../../Assets/DemoUtilities.h:22:
/Users/alain/dev/FRUT/generated/JUCE-5.4.5/examples/DemoRunner/build/JuceLibraryCode/../JuceLibraryCode/JuceHeader.h:48:24: error: redefinition of 'projectName'
    const char* const  projectName    = "DemoRunner";
                       ^
/Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/../JuceLibraryCode/JuceHeader.h:57:24: note: previous definition is here
    const char* const  projectName    = "DemoRunner";
                       ^
In file included from /Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/Main.cpp:28:
In file included from /Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/../../Assets/DemoUtilities.h:22:
/Users/alain/dev/FRUT/generated/JUCE-5.4.5/examples/DemoRunner/build/JuceLibraryCode/../JuceLibraryCode/JuceHeader.h:49:24: error: redefinition of 'versionString'
    const char* const  versionString  = "5.4.5";
                       ^
/Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/../JuceLibraryCode/JuceHeader.h:59:24: note: previous definition is here
    const char* const  versionString  = "5.4.5";
                       ^
In file included from /Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/Main.cpp:28:
In file included from /Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/../../Assets/DemoUtilities.h:22:
/Users/alain/dev/FRUT/generated/JUCE-5.4.5/examples/DemoRunner/build/JuceLibraryCode/../JuceLibraryCode/JuceHeader.h:50:24: error: redefinition of 'versionNumber'
    const int          versionNumber  = 0x50405;
                       ^
/Users/alain/dev/FRUT/ci/tmp/JUCE-5.4.5/examples/DemoRunner/Source/../JuceLibraryCode/JuceHeader.h:60:24: note: previous definition is here
    const int          versionNumber  = 0x50405;
                       ^
3 errors generated.

What is happening in details:

  • DemoRunner/Source/Main.cpp:27 does #include "../JuceLibraryCode/JuceHeader.h". DemoRunner/JuceLibraryCode/JuceHeader.h is found by the compiler, relatively to Main.cpp itself, so the compiler includes it without considering the include search path.
  • DemoRunner/Source/Main.cpp:28 does #include "../../Assets/DemoUtilities.h". In the same way, the DemoUtilities.h header is found relatively to Main.cpp and included without using the include search path.
  • Assets/DemoUtilities.h:22 does #include "../JuceLibraryCode/JuceHeader.h". However, the compiler can't find a JuceHeader.h file at that relative path when starting from DemoUtilities.h, so the compiler uses the include search path. /Users/alain/dev/FRUT/generated/JUCE-5.4.5/examples/DemoRunner/build/JuceLibraryCode is in the include search path, and the compiler finds DemoRunner/build/JuceLibraryCode/JuceHeader.h as a viable candidate.

Projucer actually adds the JuceLibraryCode directory to the include search path in all exporters (Android, LinuxMakefile, MacOSX, VisualStudio2015, VisualStudio2017, VisualStudio2019, iOS), so there is no need to write #include "../JuceLibraryCode/JuceHeader.h" in any JUCE project. Replacing it with #include "JuceHeader.h" or #include <JuceHeader.h> will solve this problem.

I guess I should make a PR on JUCE to replace all existing #include "../JuceLibraryCode/*" statements and fix how Projucer generate stubs, but that won't solve the problem for existing projects... We might need a warning somewhere in FRUT as @danra suggested.

McMartin avatar Jan 13 '20 16:01 McMartin

I opened a pull request on JUCE to propose to always include JuceHeader.h using #include <JuceHeader.h>: https://github.com/WeAreROLI/JUCE/pull/658.

If these changes get merged into JUCE, I will make a pull request on FRUT to:

  • change #include "JuceHeader.h" to #include <JuceHeader.h> in Jucer2Reprojucer
  • make Jucer2Reprojucer scan all source files listed in the input .jucer file for #include "../JuceLibraryCode/JuceHeader.h" and output warnings to advise changing to #include <JuceHeader.h>.

McMartin avatar Jan 18 '20 16:01 McMartin