vector-of-bool / cmrc

A Resource Compiler in a Single CMake Script
MIT License
674 stars 74 forks source link

empty resources in android project #2

Closed Scindix closed 6 years ago

Scindix commented 6 years ago

I'm currently writing a C++ app for android and accessing assets from native code is far from trivial in Android. On my search for alternatives I stumbled upon your resource compiler. It looks fantastic and would solve a lot of problems for me. However when I try to access resources it just returns null pointers as iterators. Have a look at the following: Inside CMakeLists.txt:

cmrc_add_resource_library(shaderFiles src/main/assets/shader/standard.fs src/main/assets/shader/standard.vs)

Inside C++:

CMRC_INIT(shaderFiles);
auto stdVertexShader = cmrc::open("src/main/assets/shader/standard.vs");
auto stdFragShader = cmrc::open("src/main/assets/shader/standard.fs");
LOGI("%d", stdVertexShader.end()-stdVertexShader.begin()); // prints "0"
LOGI("%d", (int)stdVertexShader.begin()); // prints "0"

The code compiles without errors and prints two zeros when executed. However the vertex shader file definitely contains data. In order to get behind this I added the following line to the cmake script:

function(_cmrc_generate_intermediate_cpp libname symbol outfile infile)
    message(STATUS "infile: ${infile}")  # <--
    add_custom_command(

This prints "infile: /home/<...>/ProjectPath/app/src/main/assets/shader/standard.vs" (and respectively "*.fs") which are the valid paths to my files I want to include. (Tested using "cat") The table entries in "/home/<...>/ProjectPath/app/shaderFiles/lib_.cpp" are the following:

// Table entry for src/main/assets/shader/standard.fs
table.emplace("src/main/assets/shader/standard.fs", resource{res_chars::f_be11_src_main_assets_shader_standard_fs_begin, res_chars::f_be11_src_main_assets_shader_standard_fs_end});
// Table entry for src/main/assets/shader/standard.vs
table.emplace("src/main/assets/shader/standard.vs", resource{res_chars::f_6947_src_main_assets_shader_standard_vs_begin, res_chars::f_6947_src_main_assets_shader_standard_vs_end});

So I'm using the correct keys and the script uses the correct file paths. What could have gone wrong? How can I further investigate this problem? I'm not exactly a CMake expert...

vector-of-bool commented 6 years ago

CMRC uses a global table (unforuntate. I've thought about changing this approach) to store the resource file pointers. The CMRC_INIT call initializes the table entries for the named resource library so that cmrc::open will load them correctly.

There are a few potential problems, and I'd be curious to see what's gone wrong. My biggest hypothesis: There isn't a single global table that it is using. If the table in table.emplace is not the same table used in cmrc::open, they won't be able to see each other. This might happen if the linker is doing something unexpected.

Might you be able to attach a debugger and break into the CMRC_INIT call?

In the future, a better approach might involve not using a global table.

Scindix commented 6 years ago

I found the source of the error.

Android Studio uses gradle scripts to compile an app. However these scripts don't output any messages from CMake (which is extremely annoying). If you want to see messages and warnings you have to invoke "cmake ." and "make" by hand in a terminal. Which is what I did and which created mentioned files that are totally correct. However if I want to create an executable apk for android I need to run the gradle scripts and they are using their own copy of cmake. It seems that "3.6.0-rc2" is the maximum allowed version. However that version of cmake doesn't support the "PARSE_ARGV" signature of "cmake_parse_arguments". (See cmake documentation)

So changing this line:

cmake_parse_arguments(PARSE_ARGV 1 ARG "${options}" "${args}" "${list_args}")

to

cmake_parse_arguments(ARG "${options}" "${args}" "${list_args}" "${ARGN}")

fixed it for me.

vector-of-bool commented 6 years ago

Interesting...

I'll keep this issue open so that I can go back and commit the fix, and also set cmake_minimum_required to a reasonable version so that this can be avoided in the future.

vector-of-bool commented 6 years ago

It's been a while, but this should work now in older CMake versions. I've added a cmake_minimum_required() to enforce a minimum version.