7

I'm trying to use ios-cmake to generate Xcode project targeting iOS. However, it cannot find Threads. Here's a simple CMake script for demonstration:

CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
PROJECT (MyCITest)

SET (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")

########################
# EDIT: I've also tried adding the lines below prior to posting this question, 
# but there doesn't seem to be any effect.
# (http://stackoverflow.com/questions/8386897)

SET (CMAKE_REQUIRED_INCLUDES ${CMAKE_IOS_SDK_ROOT}/usr ${CMAKE_IOS_SDK_ROOT}/usr/include)
SET (CMAKE_CXX_FLAGS "--sysroot=${CMAKE_IOS_SDK_ROOT} ${CMAKE_CXX_FLAGS}")
SET (CMAKE_C_FLAGS "--sysroot=${CMAKE_IOS_SDK_ROOT} ${CMAKE_C_FLAGS}")

########################

FIND_PACKAGE (ZLIB REQUIRED)
FIND_PACKAGE (LibXml2 REQUIRED)
FIND_PACKAGE (Threads REQUIRED)

Running CMake from the terminal:

cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/iOS.cmake -GXcode

This is the output I got:

-- Toolchain using default iOS SDK: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk
-- Found ZLIB: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/libz.dylib (found version "1.2.5") 
-- Found LibXml2: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/libxml2.dylib (found version "2.7.8") 
-- Looking for include file pthread.h
-- Looking for include file pthread.h - not found
CMake Error at cmake/modules/FindPackageHandleStandardArgs.cmake:97 (MESSAGE):
  Could NOT find Threads (missing: Threads_FOUND)
Call Stack (most recent call first):
  cmake/modules/FindPackageHandleStandardArgs.cmake:288 (_FPHSA_FAILURE_MESSAGE)
  cmake/modules/FindThreads.cmake:166 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:8 (FIND_PACKAGE)


-- Configuring incomplete, errors occurred!

I've already triple-checked that pthread.h is located in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/include, and besides, it located ZLib and LibXML2 without a problem, so I'm not sure what I'm doing wrong.

> cmake --version
cmake version 2.8.10.2
Hasyimi Bahrudin
  • 849
  • 1
  • 8
  • 12

7 Answers7

12

None of these solutions seem to work. I found the only thing that consistently worked for me was to set the variables that FindThreads.cmake sets. In other words, define the following in your toolchain file:

set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
ergosys
  • 47,835
  • 5
  • 49
  • 70
  • This will work, but it basically overrides the actual process of finding pthread: this is the equivalent of hardcoding it, which isn't inaccurate but maybe will cause problems with future updates and scaling. – agirault Aug 29 '19 at 13:13
2

The problem is indeed due to the call to try_compile failing in FindThreads.cmake. But for me setting CMAKE_CXX_COMPILER_WORKS was not enough. Instead, I changed the type of test performed by try_compile from trying to build an executable to trying to build a static library, by putting this in the toolchain file:

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
Samuel Peter
  • 4,136
  • 2
  • 34
  • 42
  • 1
    I think this deserves to be the accepted answer. The real issue is that `try_compile` compiles micro-tests as an iOS Application, which requires code signing. Static libraries do not. I didn't expect this to work, but I was pleasantly surprised! – Chris Watts Jun 11 '19 at 13:57
  • That's quite the hack, but the result of try_compile should be an executable, not a library. Using `XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED` to `NO` is more adequate here. – agirault Sep 25 '19 at 14:39
2

[Sept 2019] Fix for XCode 11 & iOS 13

As explained here.

Need to use XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED instead of CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED below to make this work:

set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES "XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED")
set(XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO")

find_package(Threads REQUIRED)

unset(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES)
unset(XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED)

[Aug 2019]: Info from CMake's issue tracker

The issue was discussed here and explained by @alcroito. It does not use the custom ios-cmake toolchain but the new native iOS toolchain (CMake 3.14+) but the issue is the same.

Source of the issue

When using the Xcode generator, it will try to sign applications by default. When looking for Threads, CMake calls FindThreads.cmake which will call a TRY_COMPILE test that Xcode will try to sign and fail at.

Proper solution:

Disable signing for the try_compile within FindThreads (seen here):

set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES "CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")

find_package(Threads REQUIRED)

unset(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES)
unset(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED)

Other solutions in this thread

  1. Make the binary of that try_compile static, which won't be signed (seen here). That's not great since it should be an executable and not a static lib.

  2. Pass proper information to be able to sign the try_compile executable (seen here). That actually would not work for me.

  3. Skip try_compile (seen here): not quite safe since you'll skip all your compiler tests. That would not work for me either.

  4. Hardcode Threads by overriding what FindThreads does (seen here): quite a dirty workaround.

agirault
  • 2,509
  • 20
  • 24
1

It turns out that the iOS toolchain currently doesn't support TRY_COMPILE, which is used by CheckIncludeFiles.cmake, which is in turn used by FindThreads.cmake. The toolchain is currently set to skip TRY_COMPILE by using:

set (CMAKE_CXX_COMPILER_WORKS TRUE)
set (CMAKE_C_COMPILER_WORKS TRUE)

Reference: http://code.google.com/p/ios-cmake/issues/detail?id=1&can=1

Hasyimi Bahrudin
  • 849
  • 1
  • 8
  • 12
  • This workaround will work, however, the fact that the toolchain "doesn't support" try_compile isn't quite accurate. The issue is with the xcode generator which will try to sign the try_compile project, which will fail, resulting in find threads missing. I'd say it's more try_compile that doesn't support the ios toolchain because of signing issues. – agirault Aug 29 '19 at 13:12
1

You can fix try_compile command using next variables in toolchain:

# toolchain.cmake    
set(CMAKE_MACOSX_BUNDLE YES)
set(CMAKE_OSX_SYSROOT "iphoneos")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.example")

And minimalistic example:

# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(Foo)

find_package(Threads REQUIRED)
add_executable(foo foo.cpp)

Generate output:

> cmake -H. -B_builds -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -GXcode
...    
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE
...
-1

Just to mention, I also encountered the same problem in my project. I commented out the find_package(Threads REQUIRED) line and generate the Xcode proejct. The codes compiled without errors. Maybe Xcode could automatically link with posix thread library.

nn0p
  • 1,189
  • 12
  • 28
-1

The solution for me was a combination of the 2 answers before me. Comment out the 2 lines that disable try_compile

# Skip the platform compiler checks for cross compiling
set (CMAKE_CXX_COMPILER_WORKS TRUE)
set (CMAKE_C_COMPILER_WORKS TRUE)

Then add this to the top of the IOS.cmake toolchain file.

set(MACOSX_BUNDLE_GUI_IDENTIFIER com.example)
set(CMAKE_MACOSX_BUNDLE YES)
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer")
aquawicket
  • 524
  • 1
  • 9
  • 27