Main() error with Cmake on OSX/Linux


#1

Hi all,

I have a project that works with Xcode that I need to port to Linux. The project compiles with both CMake on OSX and Linux but fails silently on launch. The samples seem fine. I have used both CLion on OSX and command line on OSX/Linux. By putting a break point in main using LLDB I can see that the main function used is different when created with CMake versus Xcode. It seems like the CINDER_APP macro is not working.

So I created another simpler project with the same dependancies to try and recreate the issue. Again this works in Xcode but this time it won’t compile with CMake. It throws the following error, also related to main:

Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

After some googling I tried adding the c flag with #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -c"). It then compiles and creates the app bundle but doesn’t create the binary inside it so there is nothing to launch.

Has anyone had similar issues or have any advice here? I can put a copy of the latter project up somewhere if someone wants to take a look.

Cheers,
nay.

EDIT - here is the CMake file:

cmake_minimum_required( VERSION 3.0 FATAL_ERROR )
set( CMAKE_VERBOSE_MAKEFILE ON )

project( PROJECT )

get_filename_component( CINDER_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../Cinder.git" ABSOLUTE )
get_filename_component( APP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../" ABSOLUTE )


list( APPEND PROJECT_LISTENER_SOURCES
    ${APP_PATH}/src/applets/PREFIXMainApp.cpp
    ${APP_PATH}/src/core/PREFIXAssets.cpp
    ${APP_PATH}/src/core/PREFIXComms.cpp
    ${APP_PATH}/src/core/PREFIXGlobals.cpp
    ${APP_PATH}/src/core/PREFIXModel.cpp
    ${APP_PATH}/src/core/PREFIXTimelineApp.cpp
    ${APP_PATH}/src/scene/PREFIXSceneBaseApp.cpp
    ${APP_PATH}/CoreCommon/core/TimelineApp.cpp
    ${APP_PATH}/CoreCommon/core/Globals.cpp
    ${APP_PATH}/CoreCommon/core/MainApp.cpp
    ${APP_PATH}/CoreCommon/core/BaseApp.cpp
    ${APP_PATH}/CoreCommon/core/BaseObject.cpp
    ${APP_PATH}/CoreCommon/core/SoundBase.cpp
    ${APP_PATH}/CoreCommon/core/Comms.cpp
    ${APP_PATH}/CoreCommon/core/ModelBase.cpp
    )

list( APPEND PROJECT_LISTENER_INCLUDES
    ${APP_PATH}/src/applets/
    ${APP_PATH}/src/core/
    ${APP_PATH}/src/scene/
    ${APP_PATH}/CoreCommon/core/
    )

include( "${CINDER_PATH}/proj/cmake/modules/cinderMakeApp.cmake" )

#pre-processor macros
add_definitions( -DCOC_CI )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -c")

#todo: HTTP and SQL blocks

ci_make_app(
    SOURCES     ${PROJECT_LISTENER_SOURCES}
    CINDER_PATH ${CINDER_PATH}
    BLOCKS ../../blocks/CoC-Assets
    BLOCKS ../../blocks/CoC-Core
    BLOCKS ../../blocks/CoC-Gui
    BLOCKS ../../blocks/CoC-Scene
    BLOCKS ../../blocks/CoC-SceneUI
    BLOCKS ../../blocks/CoC-UI
    BLOCKS ../../blocks/CoC-Utils
    INCLUDES ${PROJECT_LISTENER_INCLUDES}
    LIBRARIES ${BOOST_LIB}
    )

#2

Hi Nay,

from a first look your CMake file looks fine except that call to LIBRARIES ${BOOST_LIB} .

This variable seems nowhere defined in your CMake file and either way Boost should be pulled in by default when linking with Cinder so there should be no need to try and pull it in manually in this way except if you have something else in mind that I am missing now.

A basic project that reproduces the issue could be helpful in order to pinpoint what is happening here.

Cheers,
Petros

EDIT: Forgot to mention that the -c flag is definitely not what you want in this case since this way the compilation process just produces the object files and skips the linking stage thus no executable being produced.


#3

Hey Petros,

Thanks for clarifying the c flag and apologies I forgot to delete the boost lib reference, which was left over from when I thought I’d need boost date time for the project (now deleted but same error). I have made the stripped back project public. Would be awesome if able to take a look:

git clone -b cmake --recursive https://bitbucket.org/codeoncanvas/coc-boilerplate

Note that the main app is in src/PROJECTApp.h and src/PROJECTApp.cpp and inherits from multiple classes. Changing this to be a single file like a standard cinder project didn’t change anything for me.

Cheers,
nay.

EDIT - you will need to edit the CINDER_PATH in the cmake file as I keep my projects outside cinder


#4

Hey Nay,

just had a look on this – well, it seems that you were missing PROJECTApp.cpp from your CMake sources so it makes sense that no main was generated :slight_smile:

The updated file should look like this :

cmake_minimum_required( VERSION 3.0 FATAL_ERROR )
set( CMAKE_VERBOSE_MAKEFILE ON )

project( PROJECT ) #PETROS: maybe another name since PROJECT is a CMake keyword also would be nice :)

get_filename_component( CINDER_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../Cinder.git" ABSOLUTE )
get_filename_component( APP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../" ABSOLUTE )


list( APPEND PROJECT_LISTENER_SOURCES
    ${APP_PATH}/src/applets/PREFIXMainApp.cpp
    ${APP_PATH}/src/core/PREFIXAssets.cpp
    ${APP_PATH}/src/core/PREFIXComms.cpp
    ${APP_PATH}/src/core/PREFIXGlobals.cpp
    ${APP_PATH}/src/core/PREFIXModel.cpp
    ${APP_PATH}/src/core/PREFIXTimelineApp.cpp
    ${APP_PATH}/src/scene/PREFIXSceneBaseApp.cpp
    ${APP_PATH}/CoreCommon/core/TimelineApp.cpp
    ${APP_PATH}/CoreCommon/core/Globals.cpp
    ${APP_PATH}/CoreCommon/core/MainApp.cpp
    ${APP_PATH}/CoreCommon/core/BaseApp.cpp
    ${APP_PATH}/CoreCommon/core/BaseObject.cpp
    ${APP_PATH}/CoreCommon/core/SoundBase.cpp
    ${APP_PATH}/CoreCommon/core/Comms.cpp
    ${APP_PATH}/CoreCommon/core/ModelBase.cpp
    ${APP_PATH}/src/PROJECTApp.cpp #PETROS: This was missing so no main generated
    )

list( APPEND PROJECT_LISTENER_INCLUDES
    ${APP_PATH}/src/applets/
    ${APP_PATH}/src/core/
    ${APP_PATH}/src/scene/
    ${APP_PATH}/CoreCommon/core/
    )

include( "${CINDER_PATH}/proj/cmake/modules/cinderMakeApp.cmake" )

#pre-processor macros
add_definitions( -DCOC_CI )

#todo: HTTP, Scene-UI, SQL blocks

ci_make_app(
    SOURCES     ${PROJECT_LISTENER_SOURCES}
    CINDER_PATH ${CINDER_PATH}
    INCLUDES ${PROJECT_LISTENER_INCLUDES}
    BLOCKS ../../blocks/CoC-Assets 
     ../../blocks/CoC-Core
     ../../blocks/Cinder-ImGui #PETROS: This was also missing but nothing to do with the error.
     ../../blocks/CoC-Gui
     ../../blocks/CoC-Scene
     ../../blocks/CoC-UI
     ../../blocks/CoC-Utils
    )

Note also how I m passing the blocks without prefixing each one with the BLOCKS keyword. You should also do it like this since the ci_make_app macro internally considers BLOCKS as multi-value argument ( and the same goes for SOURCES, INCLUDES, LIBRARIES and RESOURCES ).

With the above I was able to build and run your application successfully on macOS ( didn’t try Linux ).

Cheers,
Petros


#5

Oh no, how embarrassing! Thanks Petros.
Now working for both projects on OSX, onto Linux next. I am surprised that the one project was even able to compile.
And thanks also for the other tips!