Skip to content

Commit

Permalink
[CMakeToolchain] Adding Xcode flags (#10985)
Browse files Browse the repository at this point in the history
* Added xcode flags

* Added test and refactored xcode flags addition

* Initializing common variables

* Improved coverage

* Added one more functional test and simplified logic in Jinja template

* Improved test and docs. Removed default bitcode value

* Improved tests docstrings
  • Loading branch information
franramirez688 authored Apr 26, 2022
1 parent 39b0c0b commit d383bb2
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 4 deletions.
1 change: 0 additions & 1 deletion conan/tools/apple/apple.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os

from conans.util.runners import check_output_runner

Expand Down
61 changes: 58 additions & 3 deletions conan/tools/cmake/toolchain/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,47 @@ class AppleSystemBlock(Block):
# Setting CMAKE_OSX_DEPLOYMENT_TARGET if "os.version" is defined by the used conan profile
set(CMAKE_OSX_DEPLOYMENT_TARGET "{{ cmake_osx_deployment_target }}" CACHE STRING "")
{% endif %}
set(BITCODE "")
set(FOBJC_ARC "")
set(VISIBILITY "")
{% if enable_bitcode %}
# Bitcode ON
set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")
set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")
{% if enable_bitcode_marker %}
set(BITCODE "-fembed-bitcode-marker")
{% else %}
set(BITCODE "-fembed-bitcode")
{% endif %}
{% elif enable_bitcode is not none %}
# Bitcode OFF
set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
{% endif %}
{% if enable_arc %}
# ARC ON
set(FOBJC_ARC "-fobjc-arc")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES")
{% elif enable_arc is not none %}
# ARC OFF
set(FOBJC_ARC "-fno-objc-arc")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO")
{% endif %}
{% if enable_visibility %}
# Visibility ON
set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO")
set(VISIBILITY "-fvisibility=default")
{% elif enable_visibility is not none %}
# Visibility OFF
set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden")
set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES")
{% endif %}
#Check if Xcode generator is used, since that will handle these flags automagically
if(CMAKE_GENERATOR MATCHES "Xcode")
message(DEBUG "Not setting any manual command-line buildflags, since Xcode is selected as generator.")
else()
string(APPEND CONAN_C_FLAGS " ${BITCODE} ${FOBJC_ARC}")
string(APPEND CONAN_CXX_FLAGS " ${BITCODE} ${VISIBILITY} ${FOBJC_ARC}")
endif()
""")

def _apple_sdk_name(self):
Expand Down Expand Up @@ -357,15 +398,28 @@ def _apple_sdk_name(self):

def context(self):
os_ = self._conanfile.settings.get_safe("os")
if os_ not in ['Macos', 'iOS', 'watchOS', 'tvOS']:
if not is_apple_os(os_):
return None

arch = self._conanfile.settings.get_safe("arch")
host_architecture = to_apple_arch(arch)
host_os_version = self._conanfile.settings.get_safe("os.version")
host_sdk_name = self._apple_sdk_name()
is_debug = self._conanfile.settings.get_safe('build_type') == "Debug"

# Reading some configurations to enable or disable some Xcode toolchain flags and variables
# Issue related: https://github.com/conan-io/conan/issues/9448
# Based on https://github.com/leetal/ios-cmake repository
enable_bitcode = self._conanfile.conf.get("tools.apple:enable_bitcode", check_type=bool)
enable_arc = self._conanfile.conf.get("tools.apple:enable_arc", check_type=bool)
enable_visibility = self._conanfile.conf.get("tools.apple:enable_visibility", check_type=bool)

ctxt_toolchain = {}
ctxt_toolchain = {
"enable_bitcode": enable_bitcode,
"enable_bitcode_marker": all([enable_bitcode, is_debug]),
"enable_arc": enable_arc,
"enable_visibility": enable_visibility
}
if host_sdk_name:
ctxt_toolchain["cmake_osx_sysroot"] = host_sdk_name
# this is used to initialize the OSX_ARCHITECTURES property on each target as it is created
Expand Down Expand Up @@ -724,7 +778,8 @@ def _is_apple_cross_building(self):
os_host = self._conanfile.settings.get_safe("os")
arch_host = self._conanfile.settings.get_safe("arch")
arch_build = self._conanfile.settings_build.get_safe("arch")
return os_host in ('iOS', 'watchOS', 'tvOS') or (os_host == 'Macos' and arch_host != arch_build)
return os_host in ('iOS', 'watchOS', 'tvOS') or (
os_host == 'Macos' and arch_host != arch_build)

def _get_cross_build(self):
user_toolchain = self._conanfile.conf.get("tools.cmake.cmaketoolchain:user_toolchain")
Expand Down
3 changes: 3 additions & 0 deletions conans/model/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
"tools.system.package_manager:sudo": "Use 'sudo' when invoking the package manager tools in Linux (False by default)",
"tools.system.package_manager:sudo_askpass": "Use the '-A' argument if using sudo in Linux to invoke the system package manager (False by default)",
"tools.apple.xcodebuild:verbosity": "Verbosity level for xcodebuild: 'verbose' or 'quiet",
"tools.apple:enable_bitcode": "(boolean) Enable/Disable Bitcode Apple Clang flags",
"tools.apple:enable_arc": "(boolean) Enable/Disable ARC Apple Clang flags",
"tools.apple:enable_visibility": "(boolean) Enable/Disable Visibility Apple Clang flags",
# Flags configuration
"tools.build:cxxflags": "List of extra CXX flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
"tools.build:cflags": "List of extra C flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import textwrap
import platform
import os

import pytest

from conans.test.utils.tools import TestClient


def _add_message_status_flags(client):
cmakelists_path = os.path.join(client.current_folder, "CMakeLists.txt")
with open(cmakelists_path, "a") as cmakelists_file:
cmakelists_file.write('message(STATUS "CONAN_C_FLAGS: ${CONAN_C_FLAGS}")\n')
cmakelists_file.write('message(STATUS "CONAN_CXX_FLAGS: ${CONAN_CXX_FLAGS}")\n')


@pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
@pytest.mark.parametrize("op_system,os_version,sdk,arch", [
("watchOS", "8.1", "watchos", "armv7k"),
("tvOS", "13.2", "appletvos", "armv8")
])
def test_cmake_apple_bitcode_arc_and_visibility_flags_enabled(op_system, os_version, sdk, arch):
profile = textwrap.dedent("""
include(default)
[settings]
os={}
os.version={}
os.sdk={}
arch={}
[conf]
tools.apple:enable_bitcode=True
tools.apple:enable_arc=True
tools.apple:enable_visibility=True
""".format(op_system, os_version, sdk, arch))

client = TestClient(path_with_spaces=False)
client.save({"host": profile}, clean_first=True)
client.run("new hello/0.1 --template=cmake_lib")
_add_message_status_flags(client)
client.run("install . --profile:build=default --profile:host=host")
toolchain = client.load(os.path.join("cmake-build-release", "conan", "conan_toolchain.cmake"))
# bitcode
assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")' in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")' in toolchain
assert 'set(BITCODE "-fembed-bitcode")' in toolchain
# arc
assert 'set(FOBJC_ARC "-fobjc-arc")' in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES")' in toolchain
# visibility
assert 'set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO")' in toolchain
assert 'set(VISIBILITY "-fvisibility=default")' in toolchain

client.run("create . --profile:build=default --profile:host=host -tf None")
# flags
assert "-- CONAN_C_FLAGS: -fembed-bitcode -fobjc-arc" in client.out
assert "-- CONAN_CXX_FLAGS: -fembed-bitcode -fvisibility=default -fobjc-arc" in client.out
assert "[100%] Built target hello" in client.out


@pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
@pytest.mark.parametrize("op_system,os_version,sdk,arch", [
("watchOS", "8.1", "watchos", "armv7k"),
("tvOS", "13.2", "appletvos", "armv8")
])
def test_cmake_apple_bitcode_arc_and_visibility_flags_enabled_and_xcode_generator(op_system, os_version, sdk, arch):
"""
Testing when all the Bitcode, ARC and Visibility are enabled, and Xcode as generator.
Note: When using CMake and Xcode as generator, the C/CXX flags do not need to be appended.
"""
profile = textwrap.dedent("""
include(default)
[settings]
os={}
os.version={}
os.sdk={}
arch={}
[conf]
tools.apple:enable_bitcode=True
tools.apple:enable_arc=True
tools.apple:enable_visibility=True
""".format(op_system, os_version, sdk, arch))

client = TestClient(path_with_spaces=False)
client.save({"host": profile}, clean_first=True)
client.run("new hello/0.1 --template=cmake_lib")
_add_message_status_flags(client)
client.run("create . --profile:build=default --profile:host=host -tf None "
"-c tools.cmake.cmaketoolchain:generator=Xcode")
assert "** BUILD SUCCEEDED **" in client.out
# flags are not appended when Xcode generator is used
for line in str(client.out).splitlines():
if "CONAN_C_FLAGS:" in line:
assert "-- CONAN_C_FLAGS:" == line.strip()
if "CONAN_CXX_FLAGS:" in line:
assert "-- CONAN_CXX_FLAGS: -stdlib=libc++" == line.strip()
break


@pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
@pytest.mark.parametrize("op_system,os_version,sdk,arch", [
("watchOS", "8.1", "watchos", "armv7k"),
("tvOS", "13.2", "appletvos", "armv8")
])
def test_cmake_apple_bitcode_arc_and_visibility_flags_disabled(op_system, os_version, sdk, arch):
profile = textwrap.dedent("""
include(default)
[settings]
os={}
os.version={}
os.sdk={}
arch={}
[conf]
tools.apple:enable_bitcode=False
tools.apple:enable_arc=False
tools.apple:enable_visibility=False
""".format(op_system, os_version, sdk, arch))

client = TestClient(path_with_spaces=False)
client.save({"host": profile}, clean_first=True)
client.run("new hello/0.1 --template=cmake_lib")
_add_message_status_flags(client)
client.run("install . --profile:build=default --profile:host=host")
toolchain = client.load(os.path.join("cmake-build-release", "conan", "conan_toolchain.cmake"))
# bitcode
assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")' in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")' not in toolchain
assert 'set(BITCODE "-fembed-bitcode")' not in toolchain
# arc
assert 'set(FOBJC_ARC "-fno-objc-arc")' in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO")' in toolchain
# visibility
assert 'set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES")' in toolchain
assert 'set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden")' in toolchain

client.run("create . --profile:build=default --profile:host=host -tf None")
# flags
assert "-- CONAN_C_FLAGS: -fno-objc-arc" in client.out
assert "-- CONAN_CXX_FLAGS: -fvisibility=hidden -fvisibility-inlines-hidden -fno-objc-arc" in client.out
assert "[100%] Built target hello" in client.out


@pytest.mark.skipif(platform.system() != "Darwin", reason="Only OSX")
@pytest.mark.parametrize("op_system,os_version,sdk,arch", [
("watchOS", "8.1", "watchos", "armv7k"),
("tvOS", "13.2", "appletvos", "armv8")
])
def test_cmake_apple_bitcode_arc_and_visibility_flags_are_none(op_system, os_version, sdk, arch):
"""
Testing what happens when any of the Bitcode, ARC or Visibility configurations are not defined.
"""
profile = textwrap.dedent("""
include(default)
[settings]
os={}
os.version={}
os.sdk={}
arch={}
""".format(op_system, os_version, sdk, arch))

client = TestClient(path_with_spaces=False)
client.save({"host": profile}, clean_first=True)
client.run("new hello/0.1 --template=cmake_lib")
_add_message_status_flags(client)
client.run("install . --profile:build=default --profile:host=host")
toolchain = client.load(os.path.join("cmake-build-release", "conan", "conan_toolchain.cmake"))
# bitcode
assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")' not in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode")' not in toolchain
assert 'set(BITCODE "-fembed-bitcode")' not in toolchain
# arc
assert 'set(FOBJC_ARC "-' not in toolchain
assert 'set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC' not in toolchain
# visibility
assert 'set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN' not in toolchain
assert 'set(VISIBILITY "-' not in toolchain

client.run("create . --profile:build=default --profile:host=host -tf None")
# flags are not appended
for flag in ["-fembed-bitcode", "-fno-objc-arc", "-fobjc-arc", "-fvisibility"]:
assert flag not in client.out
assert "[100%] Built target hello" in client.out

0 comments on commit d383bb2

Please sign in to comment.