Cocos2d-x 3.17.1 CMake issues

I’ve just updated my project to Cocos2d-x 3.17.1, and now I’m getting strange build errors that were not present with 3.17, and it has something to do with the changes made to the CMake related files. This is using Visual Studio 2017, where I’m trying to create a debug Win32 build.

For instance, I’ve disabled the built-in spine runtime, and I’m using the latest version from the Esoteric github repository.

I’ve put this runtime into [game root folder]/external/spine/

The error is:

Error C1083 Cannot open include file: 'GL/glew.h': No such file or directory

In the game root folder, CMakeLists.txt, I have this entry:

set(GAME_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

set(spine_INCLUDE_DIRS ${GAME_ROOT_PATH}/external/spine/src)
add_subdirectory(${GAME_ROOT_PATH}/external/spine ${PROJECT_BINARY_DIR}/spine)

then further below:

target_link_libraries(${APP_NAME} spine-static)
# the following was not required prior to 3.17.1, but is now needed to make sure it finds "cocos2d.h"
target_include_directories(spine-static
	PRIVATE ${COCOS2DX_ROOT_PATH}/cocos
)

So, now it finds cocos2d.h, but has issues including GL/glew.h, since it can’t locate it. I’ve tried everything I could think of to fix this, but I can’t seem to find how to make sure that path exists in the include list.

This all worked in 3.17, but it’s completely broken in 3.17.1.

There are other issues too, like not being able to disable the UNICODE flags that are forcefully added to the target in the file CocosConfigDefines.cmake, method use_cocos2dx_compile_define():

...
    target_compile_definitions(${target} 
        PUBLIC WIN32
        PUBLIC _WIN32
        PUBLIC _WINDOWS
        PUBLIC UNICODE
        PUBLIC _UNICODE
        PUBLIC _CRT_SECURE_NO_WARNINGS
        PUBLIC _SCL_SECURE_NO_WARNINGS
    )
...

Which is called from cocos/CMakeLists.txt:

use_cocos2dx_compile_define(cocos2d)

Why are UNICODE and _UNICODE being added in such a way, since it’s literally not being used anywhere in the Cocos2d-x code for Windows builds? This should be left up to the game CMakeLists.txt to define it if necessary, or at least have a way to remove/disable those definitions. The reason I am mentioning this is that certain 3rd party libraries I am using in my game actually check for UNICODE, but the code they output for Windows with UNICODE enabled is based on std::wstring, which breaks any calls to them from the Cocos2d-x game code (because it’s all std::string etc). For the time being I’ve had to go into the header files and un-define “UNICODE” and “_UNICODE” before it affects anything, and that seems to be working.

Anyhow, I would really appreciate it if someone with experience in CMake could explain how to fix the compilation issue, where an external library can’t find headers in Cocos2d-x.

EDIT:

In cocos2d/external/win32-specific/gles/CMakeLists.txt, I noticed this:

set_target_properties(${target_name} PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/include/OGLES
)

then in another CMakeLists.txt further up the chain, there is this:

if(WINDOWS)
    # sqlite3 prebuilt only existed at windows
    add_subdirectory(sqlite3)
    add_subdirectory(win32-specific/gles)
    add_subdirectory(win32-specific/icon)
    add_subdirectory(win32-specific/MP3Decoder)
    add_subdirectory(win32-specific/OggDecoder)
    add_subdirectory(win32-specific/OpenalSoft)
    target_link_libraries(external 
        ext_sqlite3
        ext_gles
        ext_icon
        ext_MP3Decoder
        ext_OggDecoder
        ext_OpenalSoft
    )
endif()

Notice the ext_gles library being linked to “external”, and then “external” is linked to cocos2d via:

target_link_libraries(cocos2d external)

Now, the reason the spine code that is included in the Cocos2d folder works is because it’s compiled as part of the cocos2d library, and not as a separate library that is linked, as you can see here:

set(COCOS_SRC cocos2d.cpp
    ${COCOS_2D_SRC}
    ${COCOS_3D_SRC}
    ....
    ${COCOS_EDITOR_SUPPORT_SRC}
    ....
    )

Where COCOS_EDITOR_SUPPORT_SRC contains the source for spine.

@drelaptop can help us. I know the CMAKE process was improved in 3.17.1.

I found a way around the issue that allows me to build my application. In the CMakeLists.txt file of the spine runtime folder, I added this at the end:

target_link_libraries(spine-static PRIVATE cocos2d)

Now, that makes sense since the Cocos2d-x spine runtime does have a dependency on the cocos2d library, but is this the correct way of fixing this issue, or is there a better way?

Edit: Removed reference to PDB linker error, since it’s a completely separate issue, and can be fixed by placing the /Z7 switch in the game side CMakeLists.txt

Correct way is add here https://github.com/cocos2d/cocos2d-x-external all dependencies, remove current prebuilds (with hacks and tricks inside) and use modern CMake everywhere

add_subdirectory(
target_link_libraries(

Currently If you want to use other dependencies, change configuration etc. you have to do what you are doing right now (hack and try …).

p.s.
By the way, why you have to use latest spine?

I don’t agree that the correct way is to add new entries in cocos2d-x-external, because such a library isn’t even being used by the Cocos2d engine (Spine isn’t being used internally by the engine, so it shouldn’t even be there). I’m assuming it was added as part of the cocos2d default build for convenience, but other than that, it being there is besides the point.

The add_subdirectory and target_link_library aren’t really hacks, they are literally what is required to get things working, and I’m simply asking if the way I did it, which is linking the cocos2d library to the Spine runtime (since it’s a dependency), is in fact the right way to do so or not.

I’m not sure why that would be relevant, but if you must know, it’s because the artist working on the animations is using new functionality that is only available in Spine V3.7+.

I mentioned the Spine runtime because it was just an example, but in reality the compilation issues I faced could happen to any library that included references to cocos2d code.

Best way I think.

the difference in headers is cocos2d-x 3.17.1 use modern cmake style, that means when you link a library, you will auto include the public headers of that library. but cocos2d-x 3.17 use old style all headers set is global.

Thank you for verifying that. I’m still trying to wrap my head around CMake and the multitude of ways to do things, but at least it’s all working now. :slight_smile:

Congratulations, and two docs in 18717#issuecomment-373539533 will help you understand cmake changes in 3.17.1 release.


That’s

Please see below two documents (there are also videos on youtube)
https://github.com/boostcon/cppnow_presentations_2017/blob/master/05-19-2017_friday/effective_cmake__daniel_pfeifer__cppnow_05-19-2017.pdf

https://github.com/CppCon/CppCon2017/blob/master/Tutorials/Using%20Modern%20CMake%20Patterns%20to%20Enforce%20a%20Good%20Modular%20Design/Using%20Modern%20CMake%20Patterns%20to%20Enforce%20a%20Good%20Modular%20Design%20-%20Mathieu%20Ropert%20-%20CppCon%202017.pdf

1 Like