Add support for AppleClang and iOS cross compilation
authorCharles Giessen <charles@lunarg.com>
Thu, 17 Aug 2023 22:12:26 +0000 (16:12 -0600)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Fri, 18 Aug 2023 16:05:18 +0000 (10:05 -0600)
Compiling for iOS on an intel mac failed due to not handling the locations of
gen_defines.asm and asm_offset.s when running under AppleClang. This solution
works for the toolchain file used during development but may not work in other
situations.

iOS does not support secure_getenv, which is fine, except that the cmake
code check_function_exists seems to think it is supported, causing compilation
to fail. Just hardcoding secure_getenv to not be supported is enough for
the unix shim logic to compile.

The compilation revelaed a few issues in the test code, like not using
[[maybe_unused]] and a signed/unsigned comparison.

CMakeLists.txt
loader/CMakeLists.txt
scripts/parse_asm_values.py
tests/framework/icd/test_icd.cpp
tests/framework/shim/unix_shim.cpp

index 52e33d1e162197c21c067960e8b744ca05933500..c113d55dcadf79225919dbde8e96569ee46cdad2 100644 (file)
@@ -164,7 +164,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Cl
         target_compile_options(loader_common_options INTERFACE /WX)
     endif()
     target_compile_options(loader_common_options INTERFACE /W4)
-elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
     # using GCC or Clang with the regular front end
     if (ENABLE_WERROR)
         target_compile_options(loader_common_options INTERFACE -Werror)
@@ -172,7 +172,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "C
     target_compile_options(loader_common_options INTERFACE -Wall -Wextra)
 endif()
 
-if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
     target_compile_options(loader_common_options INTERFACE -Wno-missing-field-initializers)
 
     # need to prepend /clang: to compiler arguments when using clang-cl
index 2b3b6c274c9555ad7fe4fc0aa7a7e7c99a48a74f..394ce22018bae99fd9d9741bf3fb3df1c3d2d678 100644 (file)
@@ -216,15 +216,23 @@ elseif(UNIX) # i.e.: Linux & Apple
             # Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it.
             target_compile_options(asm_offset PRIVATE -save-temps=obj)
             if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+                set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm")
                 set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.c.s")
             elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+                set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm")
                 set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.s")
+            elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+            # Need to use the current binary dir since the asm_offset.s file is in that folder rather than the bundle
+                set(ASM_OFFSET_EXECUTABLE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm")
+                set(ASM_OFFSET_INTERMEDIATE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/asm_offset.dir/asm_offset.s")
+            else()
+                message(FATAL_ERROR "CXX_COMPILER_ID not supported!")
             endif()
 
             find_package(Python3 REQUIRED QUIET)
             # Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on
             add_custom_command(TARGET asm_offset POST_BUILD
-                COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm"
+                COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${ASM_OFFSET_EXECUTABLE_LOCATION}"
                     "${ASM_OFFSET_INTERMEDIATE_LOCATION}" "GAS" "${CMAKE_CXX_COMPILER_ID}" "${ASM_OFFSET_SYSTEM_PROCESSOR}"
                 BYPRODUCTS gen_defines.asm
             )
index df7a0460c20c2fcade4fec8a8a895f32ded9d8aa..e6ae90f5f056ead4515da26266185d6e242d8b32 100644 (file)
@@ -39,6 +39,8 @@ compiler = sys.argv[4]
 # Only used with GAS - MASM doesn't need this, as it has its own way to determine x86 vs x64
 arch = sys.argv[5]
 
+POSIX_COMPILERS = ["GNU", "Clang", "AppleClang"]
+
 if destination_file is None or source_asm_file is None or assembler_type is None or compiler is None or arch is None:
     print("Required command line arguments were not provided")
     sys.exit(1)
@@ -80,13 +82,13 @@ with open(destination_file, "w", encoding="utf-8") as dest:
             if d == "VULKAN_LOADER_ERROR_BIT":
                 continue # skip due to special case
             match = re.search(d + " DD [ ]*([0-9a-f]+)H", asm_intermediate_file)
-        elif compiler == "Clang" or compiler == "GNU":
+        elif compiler in POSIX_COMPILERS:
             match = re.search(d + " = ([0-9]+)", asm_intermediate_file)
 
         if match:
             if compiler == "MSVC":
                 value = str(int(match.group(1), 16))
-            elif compiler == "Clang" or compiler == "GNU":
+            elif compiler in POSIX_COMPILERS:
                 value = match.group(1)
             if assembler_type == "MASM":
             # MASM uses hex values, decode them here
index f620f1ddc5c0ef3993394e6341e6caefb5faacd0..a2c475743b28fb06402fc78bd61efef88eb18dcd 100644 (file)
@@ -606,16 +606,20 @@ VKAPI_ATTR VkBool32 VKAPI_CALL test_vkGetPhysicalDeviceDirectFBPresentationSuppo
 #endif  // VK_USE_PLATFORM_DIRECTFB_EXT
 
 #if defined(VK_USE_PLATFORM_MACOS_MVK)
-VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
-                                                            const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateMacOSSurfaceMVK([[maybe_unused]] VkInstance instance,
+                                                            [[maybe_unused]] const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
+                                                            [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
+                                                            VkSurfaceKHR* pSurface) {
     common_nondispatch_handle_creation(icd.surface_handles, pSurface);
     return VK_SUCCESS;
 }
 #endif  // VK_USE_PLATFORM_MACOS_MVK
 
 #if defined(VK_USE_PLATFORM_IOS_MVK)
-VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
-                                                          const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateIOSSurfaceMVK([[maybe_unused]] VkInstance instance,
+                                                          [[maybe_unused]] const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
+                                                          [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
+                                                          VkSurfaceKHR* pSurface) {
     common_nondispatch_handle_creation(icd.surface_handles, pSurface);
     return VK_SUCCESS;
 }
@@ -632,8 +636,10 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateStreamDescriptorSurfaceGGP(VkInstanc
 #endif  // VK_USE_PLATFORM_GGP
 
 #if defined(VK_USE_PLATFORM_METAL_EXT)
-VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
-                                                            const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateMetalSurfaceEXT([[maybe_unused]] VkInstance instance,
+                                                            [[maybe_unused]] const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
+                                                            [[maybe_unused]] const VkAllocationCallbacks* pAllocator,
+                                                            VkSurfaceKHR* pSurface) {
     common_nondispatch_handle_creation(icd.surface_handles, pSurface);
     return VK_SUCCESS;
 }
index 16bd73ad0006b52ec565e551a9686f21f4633b2c..12b3bfa56fbb1a6bc4f2291e1359df8c672eb36c 100644 (file)
@@ -72,6 +72,7 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>*
 #define DLOPEN_FUNC_NAME my_dlopen
 #define GETEUID_FUNC_NAME my_geteuid
 #define GETEGID_FUNC_NAME my_getegid
+#if !defined(TARGET_OS_IPHONE)
 #if defined(HAVE_SECURE_GETENV)
 #define SECURE_GETENV_FUNC_NAME my_secure_getenv
 #endif
@@ -79,6 +80,7 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>*
 #define __SECURE_GETENV_FUNC_NAME my__secure_getenv
 #endif
 #endif
+#endif
 
 using PFN_OPENDIR = DIR* (*)(const char* path_name);
 using PFN_READDIR = struct dirent* (*)(DIR* dir_stream);
@@ -102,7 +104,7 @@ using PFN_SEC_GETENV = char* (*)(const char* name);
 #define real_geteuid geteuid
 #define real_getegid getegid
 #if defined(HAVE_SECURE_GETENV)
-#define real_secure_getenv _secure_getenv
+#define real_secure_getenv secure_getenv
 #endif
 #if defined(HAVE___SECURE_GETENV)
 #define real__secure_getenv __secure_getenv
@@ -281,6 +283,7 @@ FRAMEWORK_EXPORT gid_t GETEGID_FUNC_NAME(void) {
     }
 }
 
+#if !defined(TARGET_OS_IPHONE)
 #if defined(HAVE_SECURE_GETENV)
 FRAMEWORK_EXPORT char* SECURE_GETENV_FUNC_NAME(const char* name) {
 #if !defined(__APPLE__)
@@ -306,20 +309,21 @@ FRAMEWORK_EXPORT char* __SECURE_GETENV_FUNC_NAME(const char* name) {
     }
 }
 #endif
-
+#endif
 #if defined(__APPLE__)
 FRAMEWORK_EXPORT CFBundleRef my_CFBundleGetMainBundle() {
     static CFBundleRef global_bundle{};
     return reinterpret_cast<CFBundleRef>(&global_bundle);
 }
-FRAMEWORK_EXPORT CFURLRef my_CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) {
+FRAMEWORK_EXPORT CFURLRef my_CFBundleCopyResourcesDirectoryURL([[maybe_unused]] CFBundleRef bundle) {
     static CFURLRef global_url{};
     return reinterpret_cast<CFURLRef>(&global_url);
 }
-FRAMEWORK_EXPORT Boolean my_CFURLGetFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, UInt8* buffer,
+FRAMEWORK_EXPORT Boolean my_CFURLGetFileSystemRepresentation([[maybe_unused]] CFURLRef url,
+                                                             [[maybe_unused]] Boolean resolveAgainstBase, UInt8* buffer,
                                                              CFIndex maxBufLen) {
     if (!platform_shim.bundle_contents.empty()) {
-        size_t copy_len = platform_shim.bundle_contents.size();
+        CFIndex copy_len = (CFIndex)platform_shim.bundle_contents.size();
         if (copy_len > maxBufLen) {
             copy_len = maxBufLen;
         }
@@ -352,6 +356,7 @@ __attribute__((used)) static Interposer _interpose_fopen MACOS_ATTRIB = {VOIDP_C
 __attribute__((used)) static Interposer _interpose_dlopen MACOS_ATTRIB = {VOIDP_CAST(my_dlopen), VOIDP_CAST(dlopen)};
 __attribute__((used)) static Interposer _interpose_euid MACOS_ATTRIB = {VOIDP_CAST(my_geteuid), VOIDP_CAST(geteuid)};
 __attribute__((used)) static Interposer _interpose_egid MACOS_ATTRIB = {VOIDP_CAST(my_getegid), VOIDP_CAST(getegid)};
+#if !defined(TARGET_OS_IPHONE)
 #if defined(HAVE_SECURE_GETENV)
 __attribute__((used)) static Interposer _interpose_secure_getenv MACOS_ATTRIB = {VOIDP_CAST(my_secure_getenv),
                                                                                  VOIDP_CAST(secure_getenv)};
@@ -360,6 +365,7 @@ __attribute__((used)) static Interposer _interpose_secure_getenv MACOS_ATTRIB =
 __attribute__((used)) static Interposer _interpose__secure_getenv MACOS_ATTRIB = {VOIDP_CAST(my__secure_getenv),
                                                                                   VOIDP_CAST(__secure_getenv)};
 #endif
+#endif
 __attribute__((used)) static Interposer _interpose_CFBundleGetMainBundle MACOS_ATTRIB = {VOIDP_CAST(my_CFBundleGetMainBundle),
                                                                                          VOIDP_CAST(CFBundleGetMainBundle)};
 __attribute__((used)) static Interposer _interpose_CFBundleCopyResourcesDirectoryURL MACOS_ATTRIB = {