Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building guidance #214

Open
TheVitya opened this issue Aug 20, 2024 · 7 comments
Open

Building guidance #214

TheVitya opened this issue Aug 20, 2024 · 7 comments

Comments

@TheVitya
Copy link

TheVitya commented Aug 20, 2024

Hello everyone!

I am about to build a simple 2 file test c++ library and than use it as a Cocoa Pod. The library does some basic logging.

I am struggling to find the right resources to what and how should I approach this problem. I am confused whether I should build a framework or build always from source.

I would be really really grateful if you could give me some advice or some examples what should I check or read. Also this might be also helpful for others.

What I do:

  • Build the framework with the following command and it gives me the framework as expected:
cmake -B build -G Xcode -DCMAKE_TOOLCHAIN_FILE=./toolchain/ios.toolchain.cmake -DPLATFORM=SIMULATORARM64
cmake --build build --config Release
  • In an example application I install the pod by its path, but when building the application the module can not be found in a Swift file.

The file structure looks like this:

build/
--- MyFramework.framework
include/
--- MyClass.hpp
--- module.modulemap
src/
--- MyClass.cpp
CMakeLists.txt
MyFramework.podspec

The CMake file looks like this:

CMAKE_MINIMUM_REQUIRED(VERSION 3.15)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

PROJECT(MyFramework)

set(SOURCES
  src/MyClass.cpp
)

set(HEADERS
  include/MyClass.hpp
  include/module.modulemap
)

add_library(MyFramework STATIC ${HEADERS} ${SOURCES})

target_include_directories(MyFramework
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/include
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src
)

set_target_properties(MyFramework PROPERTIES
  FRAMEWORK TRUE
  VERSION 1.0.0
  SOVERSION 1.0.0
  PUBLIC_HEADER "${HEADERS}"
  FRAMEWORK_VERSION A
  XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET 13.0
  XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym"
)

The podspec looks like this:

Pod::Spec.new do |s|
  s.name         = "MyFramework"
  s.version      = "1.0.0"
  s.summary      = "Core"
  s.homepage     = "Core"
  s.license      = "MIT"
  s.authors      = "Author"
  s.source       = { :git => 'https://example.com/MyFramework.git', :tag => s.version.to_s }

  s.platform     = :ios, '13.0'

  s.module_map = 'include/module.modulemap'

  s.vendored_frameworks = 'build/MyFramework.framework'
  s.public_header_files = 'build/MyFramework.framework/Headers/*'
  s.source_files = 'build/MyFramework.framework/Headers/*'

  s.libraries = 'c++'

end

Thank you in advance!

@kambala-decapitator
Copy link

if your C++ library doesn't require to use cmake, then you could describe it using podspec only, i.e. like you'd normally do for objc/swift libraries. And that'd build from source, of course.

what is your exact goal? Are you going to distribute this C++ library/framework in a binary form to other users?

@TheVitya
Copy link
Author

Thank you for your reply!

Makes sense.

My end goal would be to create a library for general utilities for applications. For example, I would like to use a thirdparty HTTP client in C++ and link it with CMake using FetchContent. I know there are libraries that cannot be built for iOS, but lets assume that I want to link such a library.

So the general idea would be to have a library that holds some public APIs that I can import in Swift, ObjC or Java. Those APIs are defined by me, something like ApplicationUtils.postRequest, but that uses under the hood some other C++ library that is being linked by CMake.

Yes, I would like to distribute to others via Cocoa Pods if it is possible.

@kambala-decapitator
Copy link

I wouldn't recommend using FetchContent to get a dependency on popular libraries, rather use package manager like Conan or vcpkg (if that library doesn't provide Package.swift / podspec file) and use the standard find_package calls. BTW Conan can generate integration files for Xcode directly (xcconfig), so you might not even need CMake.

Yes, I would like to distribute to others via Cocoa Pods if it is possible.

I still wonder if you're going to distribute in binary or source form. Also you might want to add objc/swift wrappers right into your library to make lives of library users easier.

P.S. This project (ios-cmake toolchain) doesn't really have much to do with your question. It can be used to build CMake library / simplify generation of Xcode project from CMake, but everything else is really out of scope and more belongs to some CMake chat. Also maybe this example will help you: https://github.com/kambala-decapitator/cmake-ios-rpath-example

@TheVitya
Copy link
Author

Thank you for your reply!

Conan absolutely makes sense, I would take a look at it. Also thank you for the example.

Please correct me if I am wrong, so basically what I would need are private C++ source files, a public header file for the library/framework, and some additional wrappers for easier usage.

Let's say, I would like distribute the pod in binary form using a framework, then I will use the ios-toolchain to create the framework, than I will add the built framework to my podspec. If the framework itself builds in Xcode, than that should be it.

Am I wrong?

@kambala-decapitator
Copy link

Please correct me if I am wrong, so basically what I would need are private C++ source files, a public header file for the library/framework, and some additional wrappers for easier usage.

yes, correct. Wrapper sources can also be made private if you wish so.

then I will use the ios-toolchain to create the framework

if you decide to use just cmake to describe/build your framework, then yes. But you could also create your C++ framework as Xcode project and use Conan to generate xcconfig files for dependencies, no cmake involved. Basically it's up to you / your requirements.

After that you'd simply vendor the built framework in your podspec like in your example. (btw in such case you don't need to specify source_files property iirc)

@TheVitya
Copy link
Author

Thank you for your reply!

I've read a few articles since last week about how it might be done.

Mainly this one: chuck

As far as I correctly understood everything, this example should compile for iOS. Here is a quick example that I have just made to demonstrate what I am about to do. I would really appreciate if you could take a look at it: repo

Am I on a completely wrong path?

P.S.
Sorry for the delay!

@kambala-decapitator
Copy link

Mainly this one: chuck

looks quite good. But I have a couple of recommendations where you shouldn't follow those articles:

  1. use Conan v2 and read Conan docs, ignore most of the info in that article as it's quite old
  2. most probably you don't need to create C API for iOS app:
  • if you go with objc wrappers, there's objc++ mode that can work with C++ directly
  • if you go with Swift, since Swift 5.9 there's interoperability with C++. Although it might look rather crippled as it currently lacks a lot of useful features, for simple cases it should be sufficient.

Here is a quick example that I have just made to demonstrate what I am about to do.

looks good to me. For distribution you'll probably need to adjust podspec to point to some remote location.

You can also check this Russian article that describes something similar, although it's a bit more advanced as it also needs bazel to build a dependency: https://habr.com/ru/companies/ru_mts/articles/838926/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants