atsushieno / android-juce-cmake

experimental CMake-based JUCE audio plugin project for Android
5 stars 1 forks source link

Versions of Android Studio, Gradle plugin, Cmake required to make this work? #2

Open christofmuc opened 3 years ago

christofmuc commented 3 years ago

Hi and thanks for doing this! I thinkg we might have spoken on ADC 2020 on this topic?

I am trying to reproduce what you did, but I don't get very far as my versions seem to mismatch - if I checkout your code and try to open with Android Studio 4.1.2 (current release), I get the following error:

This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) cannot open this project, please retry with version 4.3 or newer.

But AFAIK the latest Android Studio in beta is 4.2? I hope I don't need Canary?

 classpath 'com.android.tools.build:gradle:4.1.0'

When downgrading gradle plugin to 4.1.0 to get by this problem, I get a CMake mismatch, as the NDK obviously still ships with the very old CMake 3.10.

> Task :prepareKotlinBuildScriptModel UP-TO-DATE
D:\Development\others\android-juce-cmake\app\CMakeLists.txt : C/C++ debug|x86 : CMake Error at D:\Development\others\android-juce-cmake\app\CMakeLists.txt:4 (cmake_minimum_required):
CMake 3.15 or higher is required.  You are running version 3.10.2

I have to set the local.properties to make it use my CMake 3.18.1:

cmake.dir=c\:program files\\cmake

I get past this problem but then run into the next CMake depreciation warning:

D:\Development\others\android-juce-cmake\app\CMakeLists.txt : C/C++ debug|x86 : CMake Deprecation Warning:
The 'cmake-server(7)' is deprecated.  Please port clients to use the
 'cmake-file-api(7)' instead.

Affected Modules: app

So I think the whole combination of Android Studio, NDK, Gradle and Gradle.plugin, CMake and JUCE is highly fragile. Can you list the versions of the component you used to successfully build this?

Thank you!

atsushieno commented 3 years ago

Hi and yes, that was me!

Thanks for your attempt and feedback. Since it seems there are more interested people than I thought, I would try to make it more general and make it to target stable version (AS 4.1).

These are the related facts:

atsushieno commented 3 years ago

It is now based on stable versions.

christofmuc commented 3 years ago

Awesome! The new version does no longer have the gradle version problem, and the CMake problem I can solve with the variable as above.

Still it seems the external CMake might have some problem. I now get the following error from a JUCE CMake file:

    D:\Development\others\android-juce-cmake\app\CMakeLists.txt : C/C++ debug|armeabi-v7a : CMake Error at D:/Development/others/android-juce-cmake/JUCE/extras/Build/juceaide/CMakeLists.txt:73 (message):
      Failed to configure juceaide

      -- The C compiler identification is unknown

      -- The CXX compiler identification is unknown

      CMake Error at D:\Development\others\android-juce-cmake\app\CMakeLists.txt:26 (project):

        No CMAKE_C_COMPILER could be found.

      CMake Error at D:\Development\others\android-juce-cmake\app\CMakeLists.txt:26 (project):

        No CMAKE_CXX_COMPILER could be found.

The part of the Juceaide CMake file is commented like this:

        # If we're building using the NDK, the gradle wrapper will try to inject its own compiler using
        # environment variables, which is unfortunate because we really don't want to cross-compile
        # juceaide. If you really want to set the compilers for juceaide, pass the appropriate
        # CMAKE_<lang>_COMPILER flags when configuring CMake.
        unset(ENV{ASM})
        unset(ENV{CC})
        unset(ENV{CXX})

That seems to be some wrong assumption, or this code should actually not be executed.

On what OS are you? I'm on Windows 10.

I will install the Canary Android Studio and try again.

atsushieno commented 3 years ago

Interesting. I'm on Ubuntu 20.04, so as the GitHub Actions setup on this repo (which shows green build now). I haven't booted Windows machine for a while... Maybe there's something that blocks Android+CMake on Windows 10 that JUCE team did not want to deal with yet. As the comment says, what if you add -DCMAKE_CXX_COMPILER clang++ to externalNativeBuild { cmake { arguments ... } list in app/build.gradle ?

christofmuc commented 3 years ago

Setting this is ignored, or maybe not because if I set both CXX and C compiler variables, I'm back to square one at

D:\Development\others\android-juce-cmake\app\CMakeLists.txt : C/C++ debug|x86 : CMake Deprecation Warning:
    The 'cmake-server(7)' is deprecated.  Please port clients to use the
     'cmake-file-api(7)' instead.

But I don't think that's a proper message, I think the problem is rather the toolchain is not invoked correctly. I am trying to reproduce the build behavior without gradle, but then I get stuck in that there is no ninja.build file.

Google and their build systems, it is always such a mess.

Did the JUCE guys say anything about Windows not being supported? I would be surprised, that'd be the first time.

I will look further to see if I can somehow figure out how the original CMake call should be, because I think gradle gobbles up the real error messages (it likes to do that).

christofmuc commented 3 years ago

I am one step further. The following command - to record it - will configure the app without gradle but with a direct usage of CMake. The big advantage is that gradle does not swallow any error messages then:

D:\Development\others\android-juce-cmake>cmake -DCMAKE_TOOLCHAIN_FILE=%NDK%\build\cmake\android.toolchain.cmake -DANDROID_ABI=armeabi-v7a  -DANDROID_PLATFORM=android-21 -S app -B app\.cxx\cmake\debug\armeabi-v7a -G Ninja

with NDK e.g.

set NDK=c:\users\Christof\AppData\Local\Android\sdk\ndk\22.0.7026061    

The error is caused by the attempt of the juceaide CMake file to abort the platform build for Arm Android and launch back into building for the x86, as the juceaide is really a build helper tool that will not run on the Android target, but rather on the Windows build machine. I am now trying to understand why the mechanism built into JUCE does not work...

atsushieno commented 3 years ago

Hmm, okay. Thanks for trying the suggestion.

The 'cmake-server(7)' is deprecated.

This warnings also occurs on Linux. It is at least not a build blocker.

Did the JUCE guys say anything about Windows not being supported?

I haven't even asked, as JUCE+CMake+Android is not supported in any platform at all, not just to Windows.

D:\Development\others\android-juce-cmake>cmake -DCMAKE_TOOLCHAIN_FILE=%NDK%\build\cmake\android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DANDROID_PLATFORM=android-21 -S app -B app.cxx\cmake\debug\armeabi-v7a -G Ninja

Yes, it in general matches my understanding on how cmake is used by AGP. You would have already had a look at app/.cxx/cmake/debug/[arch](or release), but in case you haven't the logs are there.

I believe that "juceaide" targeting host is the right and expected behaviour. I will also set up Windows environment and see if I can find some solution.

christofmuc commented 3 years ago

It works now! The correct call, if I should ever need it again, is this one (don't forget the build type):

D:\Development\others\android-juce-cmake>cmake -DCMAKE_TOOLCHAIN_FILE=%NDK%\build\cmake\android.toolchain.cmake -DANDROID_ABI=armeabi-v7a  -DANDROID_PLATFORM=android-21 -DCMAKE_BUILD_TYPE=Debug -S app -B app\.cxx\cmake\debug\armeabi-v7a -G Ninja

The problem on Windows comes from the fact that on Windows, you do not have a C compiler in the path. Normally. Because there are too many different ones, and you would always launch a Visual Studio developer prompt. But Ninja will not find the compiler when it is not on the path, you need to run the above command from a Visual Studio Developer prompt (because otherwise compiling the juceaide fails, you don't need Visual Studio to compile the Android target obviously).

And now to the fun part - when running this from Android Studio 4, you need to launch Android Studio from the Developer Command prompt, so it will get all the paths and environment variables for the selected Visual Studio and inherits them. This is highly counter-intuitive and the wrong way around, as you would expect to set the compiler environment somewhere in the gradle file (for the non-target build), but I have no idea where.

For posterity, I got it to work with:

atsushieno commented 3 years ago

Ohh, thanks for the detailed reports. I guess some tricks mentioned here would be needed to get it working on Android Studio without that VS DevEnv trick. Especially if VS CMake integration automatically sets up C/C++ compiler, that would be useful to build juceaide maybe separately.

christofmuc commented 3 years ago

Not sure. This is what happens:

  1. You start Android Studio
  2. Android Studio launches gradle
  3. gradle launches CMake to cross-compile, with the Ninja generator
  4. CMake generates makefiles for Ninja and launches Ninja
  5. Ninja starts building (via the NDK's bundles make program)
  6. Ninja wants to build the juceaide, but that wasn't meant to be build for the Arm Android target and shells out to CMake
  7. CMake runs again in a command shell and wants to build juceaide, but doesn't find a compiler.

Step 7 is JUCE-specific, and fails because it depends on the CMake generator which compiler is used (at least on Windows). If you want to use Visual Studio 2017, you specify the generator "Visual Studio 15 2017 Win64". If you want Visual Studio 2019 you specify "Visual Studio 16 2019", you can also specify Mingw, Clang, etc. But you have to specify the compiler in advance.

This indicates the solution with the developer prompt might be correct: https://stackoverflow.com/questions/31262342/cmake-g-ninja-on-windows-specify-x64.

Alternatively, in the JUCE CMakeLists instead of just unsetting the compiler, they could detect that they are on Windows and specify the correct flags to the sub-CMake call. It would be something like "-DCMAKE_C_COMPILER="cl.exe" -DCMAKE_CXX_COMPILER="cl.exe" -DMSVC_TOOLSET_VERSION=140", but then again selecting which revision of Visual C++ would need some hand down of a property from gradle into the CMakeLists, I guess.

Maybe another way to look at it would be that building juceaide and other host tools should be a separate compile step and not a side effect of building the JUCE library for the target. Or even just assuming that juceaide.exe is on the path on not try to relaunch the CMake build... Have to think about this.

christofmuc commented 3 years ago

Ninja Generator's behavior detailed and modified here: https://gitlab.kitware.com/cmake/cmake/-/issues/20585

christofmuc commented 3 years ago

I did crosspost to JUCE forum to see if they have more suggestions: https://forum.juce.com/t/native-built-in-cmake-support-in-juce/38700/193?u=christofr

atsushieno commented 3 years ago

Thanks for the further feedback and sharing on forums.

I've been in the long process of recovering my Windows laptop that randomly loses primary partition :/ but at this state I also think building juceaide aside JUCE modules for Android ABIs would be better, if possible.

atsushieno commented 3 years ago

I'm slowly getting things working. I just added Windows CI build that installs ninja via choco. It works on GitHub Actions only because it has those environment variables set on the runner powershell. To get equivalent results, probably juceaide builds need to pull in those environment variables (via vsdevcmd.bat etc.), maybe by patching its CMakeLists.txt.