Search code examples
objective-cxcodecmake

CMakeLists.txt for an Objective-C Project


I am working on simply creating a hello world executable on macOS using Objective-C and CMake. I understand that CMake does not natively support building Objective-C. You must first add the

set(CMAKE_C_FLAGS "-x objective-c")

or

set(CMAKE_CXX_FLAGS "-x objective-c++")

for the Makefile to even be created. The part where I'm getting stuck is how to appropriately link the existing frameworks. I've followed both the instructions in this post as well as the tutorial it's based off of: Can't link MacOS frameworks with CMake I've also tried linking the libraries with:

set(CMAKE_EXE_LINKER_FLAGS "-framework fm1-framework fm2…")

I can now get a successful CMake generated Xcode project, but when I open the project, none of the frameworks I specified in the CMakeLists.txt file are in the 'resources' folder. Using this Xcode project, I can get the project to compile, but when I run the executable I get the error:

"2014-01-06 18:02:35.859 HelloWorld[62641:303] No Info.plist file in application bundle or no NSPrincipalClass in the Info.plist file, exiting
Program ended with exit code: 1"

I also tried manually running the makefile made by CMake in the terminal and got many many warnings (during linking) all saying:

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:2252: warning: null character
ignored [-Wnull-character]
...

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:2263: warning: null character
ignored [-Wnull-character]
...

And 7 errors (during linking):

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:1:1: error: expected unqualified-id <U+0007>

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:90: error: expected unqualified-id ...H<89>uH<89>U]fffff.<U+000F><U+001F><84>

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:121: error: extraneous closing brace ('}') ...}H<89>uH<8B>uH<8B>=

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:122: error: expected unqualified-id ...H<89>uH<8B>uH<8B>=

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:169: error: extraneous closing brace ('}') ...}H<89>uH<89>UH<8B>uH<8B>=

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:170: error: expected unqualified-id ...H<89>uH<89>UH<8B>uH<8B>=

CMakeFiles/HelloWorld.dir/AppDelegate.m.o:3:2246: error: expected unqualified-id ...16@0:8

Any ideas on what I'm during wrong? I've spent the better portion of the day looking for answers and the post I referenced had the most useful information, but it still didn't fix my problem. Is it because the original program is also written in Xcode? And somehow that's messing up the CMake?

Here's the code for my HelloWorld app:

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[])
{
    return NSApplicationMain(argc, argv);
}

And the code for the CMakeLists.txt file:

cmake_minimum_required(VERSION 2.8)
project(HelloWorld)

set(src_files
   AppDelegate.h
   AppDelegate.m
   main.m
)

set(CMAKE_C_FLAGS "-x objective-c")
set(CMAKE_CXX_FLAGS "-x objective-c++")
set(CMAKE_EXE_LINKER_FLAGS "-framework Cocoa -framework AppKit -framework CoreData -     framework Foundation")

add_executable(HelloWorld 
   ${src_files}
)

Solution

  • Indirectly thanks to ruslo and the source code located here: https://github.com/forexample/cocoa-app I figured out the problem. It appears for CMake to work with a plist generated by Xcode, one MUST use the command line instructions specified in the README.md in the above mentioned repo. The GUI implementation of CMake will NOT work because the GUI has trouble interpreting the plist file. For clarity, I'll list them here:

    cd to the directory containing the CMakeLists.txt file.

    cmake -H. -B_OutputDirectory -GXcode

    cmake --build _OutputDirectory/

    open _OutputDirectory/HelloWorld.xcodeproj/

    The other issue I encountered was that my plist and MainWindow.xib weren't included in my original CMake file. After adding the MainWindow.xib and the HelloWorld-info.plist necessary code, I was able to generate a usable Xcode project. Here's the code for reference:

    cmake_minimum_required(VERSION 2.8)
    project(HelloWorld)
    set(NAME HelloWorld) 
    set(CMAKE_C_FLAGS "-x objective-c")
    
    set(HEADER_FILES 
        ./uhdplayerengine/HelloWorld/HelloWorld/AppDelegate.h
    )
    set(SOURCE_FILES 
        ./uhdplayerengine/HelloWorld/HelloWorld/AppDelegate.m
        ./uhdplayerengine/HelloWorld/HelloWorld/main.m
    )
    set(XIB_FILE
        ./uhdplayerengine/HelloWorld/HelloWorld/Base.lproj/MainMenu.xib
    )
    
    add_executable(
        ${NAME}
        MACOSX_BUNDLE
        ${HEADER_FILES}
        ${SOURCE_FILES}
        ${XIB_FILE}
    )
    
    set_source_files_properties(
        ${XIB_FILE}
        PROPERTIES
        MACOSX_PACKAGE_LOCATION
        Resources
    )
    
    set_target_properties(
        ${NAME}
        PROPERTIES
        MACOSX_BUNDLE_INFO_PLIST
        ./uhdplayerengine/HelloWorld/HelloWorld/HelloWorld-Info.plist
    )
    
    target_link_libraries(${NAME}
        "-framework Cocoa"
        "-framework AppKit"
        "-framework CoreData"
        "-framework Foundation"
    )
    

    I hope this saves someone else a headache! Thanks ruslo!