File in subfolder of module is not compiled when added manually to some target

Okay, this one is a bit complicated, but I’ll try my best to explain.

The directory structure of one of our projects looks like this

project
    ext <- Everything inside this folder is a git submodule
        juce
        specific_shared_code_for_excactly_two_plugins
            src
            test
                testFileA.cpp
                testFileB.cpp
                CMakeLists.txt <- generates a list variable holding all the cpp files above as absolute paths
            specific_shared_code_for_excactly_two_plugins.h <- JUCE module header
            specific_shared_code_for_excactly_two_plugins.cpp <- includes only files in src, not in test
    src
    CMakeLists.txt           

The content of ext/specific_shared_code_for_excactly_two_plugins/test/CMakeLists.txt is

set(TEST_SOURCES
        testFileA.cpp
        testFileB.cpp)

# Let's make absolute paths from these files
list (TRANSFORM TEST_SOURCES PREPEND ${CMAKE_CURRENT_LIST_DIR}/)

set(SHARED_TEST_SOURCES ${TEST_SOURCES} PARENT_SCOPE)

In the root CMakeLists.txt there is something like

add_subdirectory (ext/juce)

juce_add_module (ext/specific_shared_code_for_excactly_two_plugins)

add_subdirectory (ext/specific_shared_code_for_excactly_two_plugins/test)

add_executable (test_executable ${SHARED_TEST_SOURCES})

The problem:

Source files specified in SHARED_TEST_SOURCES are not compiled by the test_executable target. When I deliberately change a filename to something invalid, I get a cmake error, so obviously the file list gets passed correctly to add_executable and it is processed in some way, but then CMake decides that these files don’t need to be built by the target.

But as soon as I remove line juce_add_module (ext/specific_shared_code_for_excactly_two_plugins) the files will be compiled by the target. This leads me to the conclusion, that the juce call does something to the module folder that has side-effect on all files inside it, also files that are not actually compiled by the module.

Is this a bug or expected behaviour for some reason, and if so, could someone explain what’s going on here?

2 Likes

If you’re using JUCE_ENABLE_MODULE_SOURCE_GROUPS, then this will add all of the module sources to your build (the files need to be added to the module target in order to show up in the IDE). Then, to stop non-top-level files from building, the HEADER_FILE_ONLY property is set to true on all but the top level files. I suspect that your test sources are still marked as HEADER_FILE_ONLY when they are added to test_executable, which is why they don’t build.

I’d recommend using CMakePrintHelpers to debug the properties of the nested source files and see whether they are being treated as header files.

If this turns out to be the problem, then you could consider the following options:

  • Turn off JUCE_ENABLE_MODULE_SOURCE_GROUPS.
  • Rearrange your directory structure so that test lives next to the JUCE module, rather than inside it.
2 Likes

Yes, that did it! We actually had JUCE_ENABLE_MODULE_SOURCE_GROUPS activated – although we no longer work with IDEs that actually need this, so simply disabling it solved the issue.

Wow, how couldn’t I know about these helpers – would have saved me quite a bit of headache during previous CMake debugging tasks :exploding_head: Wasn’t even aware that there are optional CMake modules like that. Thanks a lot for that hint

Turns out that we still need the source-grouping in some cases, so another possible solution to this problem is to simply reset the HEADER_FILE_ONLY property of the test-sources before adding it to the executable:

add_subdirectory (ext/juce)
juce_add_module (ext/specific_shared_code_for_excactly_two_plugins)
add_subdirectory (ext/specific_shared_code_for_excactly_two_plugins/test)

set_source_files_properties(${SHARED_TEST_SOURCES} PROPERTIES HEADER_FILE_ONLY FALSE) # <---

add_executable (test_executable ${SHARED_TEST_SOURCES})

This could work, but also runs the risk of adding the source files to your non-test artefacts, depending on the order/directories in which you add targets and set the properties on your sources. It seems a bit dangerous, so I’d only recommend this if you’ve eliminated all other possibilities.

I get your point, but i dont see any other options with the current API.
Would it be an option to add a parameter to the juce_add_module call, such that processing of a folder is simply skipped?
To use the example from above i would imagine something like:

juce_add_module (ext/specific_shared_code_for_excactly_two_plugins IGNORED_FOLDERS test)

In this case, the ignored folders would not show up in the IDE’s tree view, which would defeat the point of enabling module source groups.

Is moving the nested folder to a location outside of the module out of the question?

Since the test sources will be added to the test-target, they would probably simply show up under the sources for this target i guess?

Moving the nested folder isn’t my preferred option. We’ve set up git submodules for different juce-modules that are shared across projects, and its very convenient to have have the juce-module structure starting at the root of the submodule… While this probably wouldn’t matter for the devs working with source groups, the other devs that simply work with the folder structure will be unhappy :slight_smile: