PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label clang. Show all posts
Showing posts with label clang. Show all posts

Sunday, November 13, 2022

[FIXED] How to compile memcached from github sources?

 November 13, 2022     clang, memcached     No comments   

Issue

GitHub has no configure file. Only configure.am. No idea, how to handle it.


Solution

Memcached use Autotools to build source, as you got configure.ac and Makefile.am, follow these steps to build the source:

./autogen.sh
./configure
make

The binary is generated now, find the location by running find * -name memcached.



Answered By - sel-fish
Answer Checked By - Mary Flores (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Monday, October 31, 2022

[FIXED] Why is this seemingly slower C loop actually twice as fast as the other way?

 October 31, 2022     c, clang, compiler-optimization, performance     No comments   

Issue

I'm an R developer that uses C for algorithmic purposes and have a question about why a C loop that seems like it would be slow is actually faster than the alternative approach.

In R, our boolean type can actually have 3 values, true, false, and na, and we represent this using an int at the C level.

I'm looking into a vectorized && operation (yes we have this in R already, but bear with me) that also handles the na case. The scalar results would look like this:

 F && F == F
 F && T == F
 F && N == F

 T && F == F
 T && T == T
 T && N == N

 N && F == F
 N && T == N
 N && N == N

Note that it works like && in C except that na values propagate when combined with anything except false, in which case we "know" that && can never be true, so we return false.

Now to the implementation, assume we have two vectors v_out and v_x, and we'd like to perform the vectorized && on them. We are allowed to overwrite v_out with the result. One option is:

// Option 1
for (int i = 0; i < size; ++i) {
  int elt_out = v_out[i];
  int elt_x = v_x[i];

  if (elt_out == 0) {
    // Done
  } else if (elt_x == 0) {
    v_out[i] = 0;
  } else if (elt_out == na) {
    // Done
  } else if (elt_x == na) {
    v_out[i] = na;
  }
}

and another option is:

// Option 2
for (int i = 0; i < size; ++i) {
  int elt_out = v_out[i];

  if (elt_out == 0) {
    continue;
  }

  int elt_x = v_x[i];

  if (elt_x == 0) {
    v_out[i] = 0;
  } else if (elt_out == na) {
    // Done
  } else if (elt_x == na) {
    v_out[i] = na;
  }
}

I sort of expected the second option to be faster because it avoids accessing v_x[i] when it isn't required. But in fact it was twice as slow when compiled with -O2!

In the following script, I get the following timing results. Note that I am on a Mac and compile with clang.

Seems reasonable with O0, they are about the same.
2x faster with O2 with Option 1!

Option 1, `clang -O0`
0.110560

Option 2, `clang -O0`
0.107710

Option 1, `clang -O2`
0.032223

Option 2, `clang -O2`
0.070557

Can anyone explain what is going on here? My best guess is that it has something to do with the fact that in Option 1 v_x[i] is always being accessed linearly, which is extremely fast. But in Option 2, v_x[i] is essentially being accessed randomly (sort of) because it might access v_x[10] but then not need another element from v_x until v_x[120], and because that access isn't linear, it is probably much slower.

Reproducible script:

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <time.h>

int main() {
  srand(123);

  int size = 1e7;
  int na = INT_MIN;

  int* v_out = (int*) malloc(size * sizeof(int));
  int* v_x = (int*) malloc(size * sizeof(int));

  // Generate random numbers between 1-3
  // 1 -> false
  // 2 -> true
  // 3 -> na
  for (int i = 0; i < size; ++i) {
    int elt_out = rand() % 3 + 1;

    if (elt_out == 1) {
      v_out[i] = 0;
    } else if (elt_out == 2) {
      v_out[i] = 1;
    } else {
      v_out[i] = na;
    }

    int elt_x = rand() % 3 + 1;

    if (elt_x == 1) {
      v_x[i] = 0;
    } else if (elt_x == 2) {
      v_x[i] = 1;
    } else {
      v_x[i] = na;
    }
  }

  clock_t start = clock();

  // Option 1
  for (int i = 0; i < size; ++i) {
    int elt_out = v_out[i];
    int elt_x = v_x[i];

    if (elt_out == 0) {
      // Done
    } else if (elt_x == 0) {
      v_out[i] = 0;
    } else if (elt_out == na) {
      // Done
    } else if (elt_x == na) {
      v_out[i] = na;
    }
  }

  // // Option 2
  // for (int i = 0; i < size; ++i) {
  //   int elt_out = v_out[i];
  //
  //   if (elt_out == 0) {
  //     continue;
  //   }
  //
  //   int elt_x = v_x[i];
  //
  //   if (elt_x == 0) {
  //     v_out[i] = 0;
  //   } else if (elt_out == na) {
  //     // Done
  //   } else if (elt_x == na) {
  //     v_out[i] = na;
  //   }
  // }

  clock_t end = clock();
  double time = (double) (end - start) / CLOCKS_PER_SEC;

  free(v_out);
  free(v_x);

  printf("%f\n", time);
  return 0;
}

Updates: Based on a few questions in the comments, here are a few points of clarifications for future readers:

  • I am on a 2018 15-inch Macbook Pro with a 2.9 GHz 6-Core Intel i9-8950HK (6 core Coffee Lake.)

  • My particular clang version that I tested with is Apple clang version 13.1.6 (clang-1316.0.21.2.5) with Target: x86_64-apple-darwin21.6.0

  • I am restricted by R to use int as the data type (even though there are more efficient options) and the following coding: false = 0, true = 1, na = INT_MIN. The reproducible example that I provided respects this.

  • The original question was not actually a request to make the code run faster, I just wanted to get an idea of what the difference was between my two if/else approaches. That said, some answers have shown that branchless approaches can be much faster, and I really appreciate the explanations that those users have provided! That has greatly influenced the final version of the implementation I am working on.


Solution

Why is this seemingly slower C loop actually twice as fast as the other way?

At a high level, it is a quirk of the compiler and execution environment you are using. Unless array v_x is declared volatile, the compiler is free to interpret the two variations on your code exactly the same way.

I sort of expected the second option to be faster because it avoids accessing v_x[i] when it isn't required.

And if the compiler's optimizer judged that to be true, then it could make use of that judgement to conditionally avoid reading v_x[i] in conjunction with the first code.


But at a lower level, if the compiler generates code that indeed does conditionally avoid reading v_x[i] in option 2 but not in option 1, then you are probably observing the effects of branch misprediction in the option 2 case. It is entirely plausible that it is cheaper on average to read v_x[i] unconditionally than to suffer large numbers of branch misprediction penalties involving whether it should be read.

One of the takeaways is that on modern hardware, branches can be a lot more expensive than one might expect, especially when the branch is difficult for the CPU to predict. Where the same computation can be performed via a branchless approach, that may yield a performance win in practice, at, usually, a cost in source code clarity. @KarlKnechtel's answer presents a possible branchless (but for testing the for loop condition, which is pretty predictable) variation on the computation you are trying to perform.



Answered By - John Bollinger
Answer Checked By - Pedro (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Thursday, September 29, 2022

[FIXED] How to fix my build: .framework file with CocoaPods dependencies and 2 targets (iOS and tvOS)

 September 29, 2022     clang, ios, tvos, xamarin, xcode     No comments   

Issue

I have a project with a slightly complex requirement, so let's start with the desired goal:

  • The project is an SDK for interfacing with our back-end services (not an app)
  • The project must output a .framework file that can be included in a Xamarin app (all of our internal apps are built with Xamarin)
  • The project must be a proper CocoaPod with a .podspec file so that third parties can include the SDK in their own apps (customer request)
  • The project depends on three third-party dependencies, one of which is delivered differently from the others:
    • CocoaLumberjack and JSONModel, when listed as dependencies in the Podfile or .podspec, will download their respective projects and include them in your own workspace as sub-projects, to be built
    • GoogleInterativeMediaAds, when listed as a dependency in the Podfile or .podspec, will download a .framework file and is completely closed-source
  • The project must be able to build for both iOS and tvOS (we have apps and clients for both)
    • Note that while JSONModel and CocoaLumberjack both advertise that they have iOS and tvOS support, there are separate CocoaPods for the GoogleInteractiveMediaAds (GoogleAds-IMA-iOS-SDK ~> 3.9 and GoogleAds-IMA-tvOS-SDK ~> 4.0)
  • Any .framework file output by the project must contain both embedded bitcode and be a fat binary
  • The project has several static assets (PNG files and XIB files) that need to be included as a .bundle within the .framework

Now, then: I have all of this working. It took a long time and a lot of experimenting but I have a project that meets all of the above requirements. My Podfile looks like so:

Podfile

use_frameworks!

def common()
    pod 'CocoaLumberjack', '~> 3.5'
    pod 'JSONModel', '~> 1.8'
end

target 'MyFramework-iOS' do
    platform :ios, '9.0'
    common()
    pod 'GoogleAds-IMA-iOS-SDK', '~> 3.9'
end

target 'MyFramework-tvOS' do
    platform :tvos, '9.1'
    common()
    pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.0'
end

And my .podspec looks like so:

MyFramework.podspec

Pod::Spec.new do |spec|
  spec.name         = "MyFramework"
  spec.version      = "1.0.0"
  spec.summary      = "A framework for interfacing with our back-end"

  spec.description  = <<-DESC
    A longer description
  DESC

  spec.homepage     = "https://example.com/"
  spec.license      = "MIT"

  spec.authors             = {
    "Steven Barnett" => "xxx@example.com"
  }

  spec.ios.deployment_target = "9.0"
  spec.tvos.deployment_target = "9.1"

  spec.source       = { :git => "https://bitbucket.org/xxx/MyFramework.git", :tag => "#{spec.version}" }

  spec.source_files  = "Sources/Common/**/*.{h,m}", "Sources/MyFramework.h"
  spec.ios.source_files  = "Sources/iOS/**/*.{h,m}"
  spec.tvos.source_files = "Sources/tvOS/**/*.{h,m}"

  spec.ios.resource_bundles = {
    "MyFramework" => ["Assets.xcassets", "Sources/iOS/**/*.{xib}"]
  }
  spec.tvos.resource_bundles = {
    "MyFramework" => ["Assets.xcassets", "Sources/tvOS/**/*.{xib}"]
  }

  spec.frameworks = "Foundation", "UIKit", "AVKit"

  spec.requires_arc = true

  spec.dependency "CocoaLumberjack", "~> 3.5"
  spec.dependency "JSONModel", "~> 1.8"
  spec.ios.dependency "GoogleAds-IMA-iOS-SDK", "~> 3.9"
  spec.tvos.dependency "GoogleAds-IMA-tvOS-SDK", "~> 4.0"
end

My source code is divided into three folders:

  • ./Sources/Common contains 99% of our code and is common among iOS and tvOS
  • ./Sources/iOS contains a handful of features that are only available on iOS. Specifically, iOS grants more flexibility in customizing the layout of a video player, so we have custom controls
  • ./Sources/tvOS contains a handful of features that are only available on tvOS. Specifically, a paired-down collections of XIBs and .m files for the player controls

Within my project's Build Phases, I added a Run Script phase with the following script:

Run Script

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal

if [ "true" == ${ALREADYINVOKED:-false} ]; then
    echo "RECURSION: Detected, stopping"
else
    export ALREADYINVOKED="true"

    # make sure the output directory exists
    mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"

    # Step "0". Build our project twice
    echo "Building for AppleTV Device (redundantly... sigh)"
    xcodebuild -workspace "${PROJECT_DIR}/${PROJECT}.xcworkspace" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk appletvos ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" OBJROOT="${OBJROOT}/DependentBuilds" OTHER_CFLAGS="-fembed-bitcode"

    echo "Building for AppleTV Simulator"
    xcodebuild -workspace "${PROJECT_DIR}/${PROJECT}.xcworkspace" -scheme "${TARGET_NAME}" -configuration ${CONFIGURATION} -sdk appletvsimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" OBJROOT="${OBJROOT}/DependentBuilds" OTHER_CFLAGS="-fembed-bitcode"

    # Step 1. Copy the framework structure (from iphoneos build) to the universal folder
    echo "Copying to output folder"
    cp -R "${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}" "${UNIVERSAL_OUTPUTFOLDER}/"

    # Step 2. Create universal binary file using lipo and place the combined executable in the copied framework directory
    echo "Combining executables"
    lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${EXECUTABLE_PATH}" "${BUILD_DIR}/${CONFIGURATION}-appletvsimulator/${EXECUTABLE_PATH}" "${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}"

    # Step 3. Create universal binaries for embedded frameworks
    for FRAMEWORK in $( find "${TARGET_BUILD_DIR}" -type d -name "*.framework" ); do
        FRAMEWORK_PATH="${FRAMEWORK##$TARGET_BUILD_DIR}"
        BINARY_NAME="${FRAMEWORK##*/}"
        BINARY_NAME="${BINARY_NAME%.*}"
        # I don't know how to do "if not" in Bash. Sue me.
        if [[ $BINARY_NAME == Pods_* ]] || [[ $BINARY_NAME == $TARGET_NAME ]]; then
            echo "Skipping framework: $FRAMEWORK_PATH"
        else
            echo "Creating fat binary for framework: $FRAMEWORK_PATH"
            cp -r "${FRAMEWORK}" "${UNIVERSAL_OUTPUTFOLDER}/"
            lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${BINARY_NAME}.framework/${BINARY_NAME}" "${BUILD_DIR}/${CONFIGURATION}-appletvsimulator/${FRAMEWORK_PATH}/${BINARY_NAME}" "${TARGET_BUILD_DIR}/${FRAMEWORK_PATH}/${BINARY_NAME}"
        fi
    done

    # Step 4. Manually copy some files to the output dir
    cp -r "${SOURCE_ROOT}/Pods/GoogleAds-IMA-tvOS-SDK/GoogleInteractiveMediaAds.framework" "${UNIVERSAL_OUTPUTFOLDER}"
    cp "${SOURCE_ROOT}/generate-xamarin-bindings.py" "${UNIVERSAL_OUTPUTFOLDER}"

    # Step 5. Convenience step
    open "${UNIVERSAL_OUTPUTFOLDER}"
fi

This script is a modification of a similar script I found online. It basically does the following:

  1. Build my project for a device (ARM processor) with bitcode embedded
  2. Build my project for the simulator (x86 processor) with bitcode embedded
  3. Use lipo to create a fat binary for my project
  4. Iteratively use lipo to create fat binaries for all frameworks I depend on
  5. Copy my framework and all frameworks I depend on to a "universal" output directory

You may also notice the generate-xamarin-bindings.py file. This can be pretty much ignored for my purposes. It just uses Objective Sharpie to automate the creation of Xamarin bindings, then fixes a handful of known bugs with JSONModel (variables defined as @property (retain, nonatomic, nullable) NSString <Optional> *test; will get pulled into the bindings as Optional test { get; set; } instead of string test { get; set; })

Beyond that, I can't recall what additional configurations and tweaks had to be made to all of the scripts, build settings, and config files - but if any questions arise I can look through the code and answer them.

I have a test project that uses CocoaPods to pull in my SDK like so:

Examples/tvOS/Podfile

use_frameworks!
platform :tvos, '9.1'

target 'MyFramework Example tvOS App' do
    pod 'MyFramework', :path => '../../'
end

This test project builds perfectly, and I can run it on the simulator or on a real device. Several weeks ago I was also able to deploy my test project to the Apple Store (TestFlight) however since then I have made a few changes (including switching from standard build to a fat binary) and so I don't know for certain that it still works (I will test this)

Furthermore, when we build for profiling and create the Xamarin bindings, we can embed all four frameworks (MyFramework.framework, CocoaLumberjack.framework, JSONModel.framework, and GoogleInteractiveMediaAds.framework) into our Xamarin apps and they will build and run on both the simulator and on a real device.

The problem we ran into was when we tried to push one of these Xamarin-based apps to the Apple Store (TestFlight). We received 11 errors:

  • ERROR ITMS-90166: "Missing Code Signing Entitlements. No entitlements found in bundle 'com.xxx.MyFramework' for executable 'Payload/InternalApp.app/Frameworks/MyFramework-tvOS.framework/MyFramework.bundle/MyFramework'."
  • ERROR ITMS-90668: "Invalid Bundle Executable. The executable file 'InternalApp.app/Frameworks/MyFramework-tvOS.framework/MyFramework-tvOS' contains incomplete bitcode. To compile binaries with complete bitcode, open Xcode and choose Archive in the Product menu"
  • ERROR ITMS-90668: "Invalid Bundle Executable. The executable file 'InternalApp.app/Frameworks/CocoaLumberjack.framework/CocoaLumberjack' contains incomplete bitcode. To compile binaries with complete bitcode, open Xcode and choose Archive in the Product menu"
  • ERROR ITMS-90668: "Invalid Bundle Executable. The executable file 'InternalApp.app/Frameworks/JSONModel.framework/JSONModel' contains incomplete bitcode. To compile binaries with complete bitcode, open Xcode and choose Archive in the Product menu"
  • ERROR ITMS-90635: "Invalid Mach-O Format. The Mach-O in bundle "InternalApp.app/Frameworks/CocoaLumberjack.framework" isn't consistent with the Mach-O in the main bundle. The main bundle Mach-O contains arm64(bitcode), while the nested bundle Mach-O contains arm64(machine code). Verify that all of the targets for a platform have a consistent value for the ENABLE_BITCODE build setting."
  • ERROR ITMS-90635: "Invalid Mach-O Format. The Mach-O in bundle "InternalApp.app/Frameworks/MyFramework-tvOS.framework" isn't consistent with the Mach-O in the main bundle. The main bundle Mach-O contains arm64(bitcode), while the nested bundle Mach-O contains arm64(machine code). Verify that all of the targets for a platform have a consistent value for the ENABLE_BITCODE build setting."
  • ERROR ITMS-90635: "Invalid Mach-O Format. The Mach-O in bundle "InternalApp.app/Frameworks/JSONModel.framework" isn't consistent with the Mach-O in the main bundle. The main bundle Mach-O contains arm64(bitcode), while the nested bundle Mach-O contains arm64(machine code). Verify that all of the targets for a platform have a consistent value for the ENABLE_BITCODE build setting."
  • ERROR ITMS-90171: "Invalid Bundle Structure - The binary file 'InternalApp.app/Frameworks/MyFramework-tvOS.framework/MyFramework.bundle/MyFramework' is not permitted. Your app can't contain standalone executables or libraries, other than a valid CFBundleExecutable of supported bundles. Refer to the Bundle Programming Guide at https://developer.apple.com/go/?id=bundle-structure for information on the tvOS app bundle structure."
  • ERROR ITMS-90209: "Invalid Segment Alignment. The app binary at 'InternalApp.app/Frameworks/MyFramework-tvOS.framework/MyFramework-tvOS' does not have proper segment alignment. Try rebuilding the app with the latest Xcode version."
  • ERROR ITMS-90209: "Invalid Segment Alignment. The app binary at 'InternalApp.app/Frameworks/CocoaLumberjack.framework/CocoaLumberjack' does not have proper segment alignment. Try rebuilding the app with the latest Xcode version."
  • ERROR ITMS-90209: "Invalid Segment Alignment. The app binary at 'InternalApp.app/Frameworks/JSONModel.framework/JSONModel' does not have proper segment alignment. Try rebuilding the app with the latest Xcode version."

So I started trying to trace the build process manually to figure out where or what went wrong. I'm already using the latest Xcode, and we've tried both Product > Archive and Product > Build For > Profiling, so I don't think that the suggested solutions for ITMS-90668 or ITMS-90209 are accurate.

While looking into the build process manually, I noticed a few things that were strange:

  1. When I build the tvOS version of my app, in ~/Library/Developer/Xcode/DerivedData/MyFramework-xxxxxx/Build/Products (henceforth: ${BUILD_ROOT}) the iOS and tvOS versions of my dependencies were being built:
    • ${BUILD_ROOT}/Release-appletvos/JSONModel-iOS.framework
    • ${BUILD_ROOT}/Release-appletvos/JSONModel-tvOS.framework
    • ${BUILD_ROOT}/Release-appletvsimulator/JSONModel-iOS.framework
    • ${BUILD_ROOT}/Release-appletvsimulator/JSONModel-tvOS.framework
    • etc. (same for CocoaLumberjack)
  2. Sure enough, if I looked inside of ${BUILD_ROOT}/Release-universal/MyFramework-tvOS.framework/MyFramework.bundle, there was an executable file in there titled MyFramework. I have no idea who or what is creating this executable, where it's coming from, or why it's getting included in my bundle. There is no reference to it in any of the Build Phases, but this seems to be the cause for ITMS-90171
  3. The GoogleInteractiveMediaAds framework was the only one that didn't have bitcode enabled, which leads me to suspect that bitcode isn't necessary to submit an app to the store since it's also the only framework that didn't throw any errors (despite what I was told before that you need to include bitcode)

What I'm trying to do doesn't sound like it should be that hard. I'm just creating a library (like CocoaLumberjack) which can be run on iOS or tvOS (like CocoaLumberjack) but which has dependencies (unlike CocoaLumberjack) and which can be delivered as a .framework file instead of just as a CocoaPod (not sure if CocoaLumberjack has this?). But I can't find any answers to the problems I'm encountering or any explanation for some of the weird build behavior.

Specifically:

  • Why is an executable file showing up in my .bundle?
  • Why is it building the iOS versions of dependent frameworks when I try to build a tvOS version of mine?
  • Do I need bitcode? Or should I disable it?

Update

  • The Google Interactive Media Ads framework does have bitcode, it just doesn't have an __LLVM segment
  • Deleting the binary from my .bundle replaced ITMS-90171 with a new error (I forget the ITMS-X code) about the Info.plist referencing a CFBundleExecutable that did not exist. Deleting this binary also handled ITMS-90166
  • By going to the resource bundle's target and selecting "Info" I could remove the "Executable file" key to remove this line in the output Info.plist, however it did not fix the executable being created in the first place. It DID prevent the new error when the binary was deleted manually

So by modifying the Info.plist and removing that executable (manually for now, since I don't know what's generating it), 2 of the 11 errors went away, leaving 3 instances of 3 errors (total of 9):

  • CocoaLumberjack (ITMS-90668, ITMS-90635, and ITMS-90209)
  • JSONModel (ITMS-90668, ITMS-90635, and ITMS-90209)
  • MyFramework (ITMS-90668, ITMS-90635, and ITMS-90209)

Update 2

  • Adding the BITCODE_GENERATION_MODE=bitcode flag to my xcodebuild command seemed to improve things. My output binary went from 1.2 MB to 3.4 MB (presumably containing "complete" bitcode). However something weird happened. Instead of the three instances of ITMS-90668 going away, all three errors (ITMS-90668, ITMS-90635, and ITMS-90209) went away for a single framework: JSONModel

I'm now seeing 6 errors (CocoaLumberjack and MyFramework each throwing 3 errosr). But I can't comprehend how or why JSONModel was fixed and the other issues weren't

One other addendum: When I added the bitcode generation mode flag, I started getting a linker error for the executable in my bundle (which shouldn't exist and I still don't know what's creating it). I noticed that the OTHER_CFLAGS was being passed to EVERY invocation of clang and not just the relevant ones, so I removed OTHER_CFLAGS="-fembed-bitcode" and this fixed the linker error

One final addendum: I noticed that when I don't use my Run Script to produce a fat binary, only the *-tvOS versions of my dependencies are built. My Run Script is building the *-iOS versions. This seems to have no impact on the errors I'm seeing from the Apple Store, but it slows down my builds, creates extra files, and emits several warnings about implicit dependency detection finding two candidates. I don't know how to fix this.

Update 3

I've solved one of my issues!

So the strange binary that was appearing inside of my bundle was due to the VERSIONING_SYSTEM build setting being defaulted to apple-generic. The Apple Generic Versioning system creates a source file calls <ProjectName>_vers.c, compiles it, and then links this file against some libraries (I guess system libraries?)

It was this file which was causing my linker errors when I had OTHER_CFLAGS="-fembed-bitcode", since this binary was setting -bundle which is incompatible. By setting the versioning system to None I was able to bring back this flag without any linker errors!

I just compiled and tried to push to the Apple store once more and everything worked this time!

Summary

  • To fix ITMS-90166 and ITMS-90171 I had to set Versioning System to None for any resource bundle targets
  • After this is fixed, you must ensure that the info.plist for the resource bundles does not contain an Executable File key (delete it if present)
  • To fix ITMS-90668, ITMS-90635, and ITMS-90209 I had to add the flags BITCODE_GENERATION_MODE=bitcode and ENABLE_BITCODE=YES to my xcodebuild command (along with the existing OTHER_CFLAGS="-fembed-bitcode")

After all of this there's still a weird quirk of my build system, but it only throws warnings (not errors) and I can live with it for the short-term. That is the fact that it's building iOS versions of my dependencies when I run xcodebuild instead of just building the tvOS versions.


Solution

I don't know how useful this question / answer will be to others who stumble across it, since I had a huge number of issues and a very specific setup. But I wanted to go ahead and post that I did find a solution to my issues.

First and foremost, I needed to set the ENABLE_BITCODE=YES and BITCODE_GENERATION_MODE=bitcode flags. However settings these two flags prevented my code from building with a linker error. This error was caused because my Resource Bundle target was using Apple Generic Versioning -- which is not supported for Resource Bundles

By setting the Versioning System build setting to "None", it fixed everything



Answered By - stevendesu
Answer Checked By - Clifford M. (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Saturday, September 10, 2022

[FIXED] How to list supported target architectures in clang?

 September 10, 2022     architecture, clang, cross-platform, llvm     No comments   

Issue

Currently I am interested in ARM in general and specifically iPhone/Android targets. But I just want to know more about clang, since it feels to play important role in the years to come.

I tried

clang -cc1 --help|grep -i list
clang -cc1 --help|grep arch|grep -v search
clang -cc1 --help|grep target

 -triple <value>         Specify target triple (e.g. i686-apple-darwin9)

I know clang has -triplet parameter, but how can I list all possible values for it?

I found that clang is very different to gcc in respect to cross compiling, in GCC world you should have separate binary for everything, like PLATFORM_make or PLATFORM_ld (i*86-pc-cygwin i*86-*-linux-gnu etc. http://git.savannah.gnu.org/cgit/libtool.git/tree/doc/PLATFORMS)

In clang world, it's only one binary (as I read on some forums). But how do I get the list of supported targets? And if my target it not supported on my distro (Linux/Windows/macOS/whatever) how can I get the one that supports more platform?

If I SVN latest clang like this:

svn co http://llvm.org/svn/llvm-project/cfe/trunk clang

will I get most of platforms?

It looks like Clang was not built with cross compiling in mind right away, but since it's LLVM-based it should be very cross-friendly in theory?


Solution

Starting Clang 11 (trunk), the list of supported target architectures could be handily printed using the newly added -print-targets flag:

$ clang-11 -print-targets
  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    amdgcn     - AMD GCN GPUs
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    avr        - Atmel AVR Microcontroller
    bpf        - BPF (host endian)
    bpfeb      - BPF (big endian)
    bpfel      - BPF (little endian)
    hexagon    - Hexagon
    lanai      - Lanai
    mips       - MIPS (32-bit big endian)
    mips64     - MIPS (64-bit big endian)
    mips64el   - MIPS (64-bit little endian)
    mipsel     - MIPS (32-bit little endian)
    msp430     - MSP430 [experimental]
    nvptx      - NVIDIA PTX 32-bit
    nvptx64    - NVIDIA PTX 64-bit
    ppc32      - PowerPC 32
    ppc64      - PowerPC 64
    ppc64le    - PowerPC 64 LE
    r600       - AMD GPUs HD2XXX-HD6XXX
    riscv32    - 32-bit RISC-V
    riscv64    - 64-bit RISC-V
    sparc      - Sparc
    sparcel    - Sparc LE
    sparcv9    - Sparc V9
    systemz    - SystemZ
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    wasm32     - WebAssembly 32-bit
    wasm64     - WebAssembly 64-bit
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64
    xcore      - XCore

References: LLVM PR, LLVM commit, Clang 11 documentation.



Answered By - valiano
Answer Checked By - Timothy Miller (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Saturday, July 16, 2022

[FIXED] Why is there no warning from -Wfloat-equal when comparing containers of doubles?

 July 16, 2022     c++, clang, floating-point, gcc-warning, warnings     No comments   

Issue

If I use the compiler option -Wfloat-equal with GCC or Clang, equality comparisons of float/double values cause a warning. However, when comparing containers (like std::vector or std::tuple) of float or double values, no such warning is raised.

Example code (also at https://godbolt.org/z/YP8v8hTs3):

#include <tuple>
#include <vector>
#include <assert.h>

int main() {
    double d = 1.2;

    std::tuple<double, double> t_d{1.2, 3.14};
    std::tuple<double, double> t_d_2{1.2, 3.14};

    std::vector<double> v_d{1.2, 3.14};
    std::vector<double> v_d_2{1.2, 3.14};

    // this causes a warning, like "warning: comparing floating-point with '==' or '!=' is unsafe [-Wfloat-equal]":
    assert(d == 1.2);
    // but why no warning from -Wfloat-equal here?
    assert(t_d == t_d_2);
    // no warning here either:
    assert(v_d == v_d_2);

    // all of these cause warnings as expected:
    assert(std::get<0>(t_d) == 1.2);
    assert(std::get<0>(t_d) == std::get<0>(t_d_2));
    assert(v_d[0] == 1.2);
    assert(v_d[0] == v_d_2[0]);

    return 0;
}

Why are the warnings omitted for these container comparisons? And more importantly, what can I do to actually get these warnings as well?


Solution

GCC doesn't report warnings for system headers by default. The desired behavior may be obtained by adding -Wsystem-header compiler flag.

Quotation from the documentation:

-Wsystem-headers

Print warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on the assumption that they usually do not indicate real problems and would only make the compiler output harder to read. Using this command-line option tells GCC to emit warnings from system headers as if they occurred in user code...

Live demo: https://godbolt.org/z/s6rExszj6

Clang seemingly adopted the same approach, see https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-in-system-headers and https://clang.llvm.org/docs/UsersManual.html#options-to-control-error-and-warning-messages.

Live demo: https://godbolt.org/z/n9xY8rcM8



Answered By - Daniel Langr
Answer Checked By - Katrina (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Sunday, July 10, 2022

[FIXED] What is __ext_vector_type__ and simd?

 July 10, 2022     c, c++, clang, reference, simd     No comments   

Issue

I'm playing with Apple Metal API along with so called simd library. There's such code in a header:

typedef __attribute__((__ext_vector_type__(3))) float vector_float3;

And I'm curious what it actually does and why the compiler doesn't allow references to vector_float3 in a function's argument or in the next manner:

vector_float3  v;
vector_float3& ref = v;

Solution

It appears to be a clang extension to GNU C vector extensions, where something like this would be normal:

typedef int v4si __attribute__ ((vector_size (16)));

Googling for ext_vector_type without the leading/trailing underscores found the Clang docs. (The underscores version is usable in headers even if some program had used #define on the non-underscores version of the token. But names with leading underscores in the global namespace are reserved for the implementation.)

My best guess is that it's a way to let the compiler know you only care about the value of the first 3 elements of a 4 element SIMD register. So it can potentially do optimizations that leave different garbage in the high element than the source would have.


why the compiler doesn't allow references to vector_float3

Works for me with clang3.8. Try a different compiler.

typedef __attribute__((__ext_vector_type__(3))) float vector_float3;

int foo(vector_float3 &arg) {
  vector_float3  v;
  vector_float3& ref = v;  // unused, but syntactically valid
  return arg[0];           // return the low element of the vector, converted to an integer.  GNU C vector-extensions syntax.
}

compiles to the following asm on the Godbolt compiler explorer

    # targeting x86-64 SystemV ABI (so the first integer/pointer arg is in rdi)
    cvttss2si       eax, dword ptr [rdi]
    ret


Answered By - Peter Cordes
Answer Checked By - Mary Flores (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Sunday, June 26, 2022

[FIXED] How to force Werror=declaration-after-statement with -std=c99 in clang

 June 26, 2022     c, c99, clang, compiler-errors, gcc     No comments   

Issue

I would like to have compiler throw an error every time there is a declaration after statement because that is the coding style I want to enforce, but I also want to compile with -std=c99 since I use some of the specific c99 features.

The problem is that in c99 declarations are allowed anywhere in the code, not just at the beginning of a block.

Take a look at the following program:

// prog.c
#include <stdio.h>

int main(void)
{
    printf("hello world\n");
    int i = 0;

    return 0;
}

If I compile this code with gcc like this:

gcc -std=c99 -Werror=declaration-after-statement prog.c

it throws the following error:

prog.c: In function ‘main’:
prog.c:6:9: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
    6 |         int i = 0;
      |         ^~~
cc1: some warnings being treated as errors

This is the behavior I would like to have when compiling with clang, but clang behaves differently.

If I compile the same code with clang like this:

clang -std=c99 -Werror=declaration-after-statement prog.c

it throws no errors.

Only if I compile the code with clang like this it throws the error I want:

clang -std=c90 -Werror=declaration-after-statement prog.c

prog.c:6:6: error: ISO C90 forbids mixing declarations and code [-Werror,-Wdeclaration-after-statement]
        int i = 0;
            ^
1 error generated.

But this is not good for me because I need to use -std=c99.

Is it possible to force -Werror=declaration-after-statement along with -std=c99 when compiling with clang?


Solution

Looking at the source code of clang it seems like not supported.

The diagnostic is defined in clang/include/clang/Basic/DiagnosticSemaKind.td

def ext_mixed_decls_code : Extension<
  "ISO C90 forbids mixing declarations and code">,
  InGroup<DiagGroup<"declaration-after-statement">>;

And its only usage is in clang/lib/Sema/SemaStmt.cpp

StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
                                   ArrayRef<Stmt *> Elts, bool isStmtExpr) {
  const unsigned NumElts = Elts.size();

  // If we're in C89 mode, check that we don't have any decls after stmts.  If
  // so, emit an extension diagnostic.
  if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {
    // Note that __extension__ can be around a decl.
    unsigned i = 0;
    // Skip over all declarations.
    for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i)
      /*empty*/;

    // We found the end of the list or a statement.  Scan for another declstmt.
    for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i)
      /*empty*/;

    if (i != NumElts) {
      Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin();
      Diag(D->getLocation(), diag::ext_mixed_decls_code); // <-- here
    }
  }
  ...

Note the !getLangOpts().C99 in the if. The diagnose code will never execute with a standard above c90.

Well one thing you can surely try is build clang by yourself and delete that part of the if so end up with if (!getLangOpts().CPlusPlus).

I tried and it worked for me.

You can configure the clang build with cmake -G "Ninja" -DCMAKE_BUILD_TYPE="Release" -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_C_COMPILER="/usr/bin/gcc" -DCMAKE_CXX_COMPILER="/usr/bin/g++" -DLLVM_PARALLEL_LINK_JOBS=2 -DLLVM_OPTIMIZED_TABLEGEN=ON path/to/llvm-project/llvm



Answered By - Eraklon
Answer Checked By - Dawn Plyler (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How does Clang's "did you mean ...?" variable name correction algorithm work?

 June 26, 2022     c++, clang, compiler-errors     No comments   

Issue

I am compiling C++ code with Clang. (Apple clang version 12.0.5 (clang-1205.0.22.11)).

Clang can give tips in case you misspell a variable:

#include <iostream>

int main() {
    int my_int;
    std::cout << my_it << std::endl;
}
spellcheck-test.cpp:5:18: error: use of undeclared identifier 'my_it'; did you mean 'my_int'?
    std::cout << my_it << std::endl;
                 ^~~~~
                 my_int
spellcheck-test.cpp:4:9: note: 'my_int' declared here
    int my_int;
        ^
1 error generated.

My question is:

What is the criterion Clang uses to determine when to suggest another variable?

My experimentation suggests it is quite sophisticated:

  • If there is another similarly named variable that you might have meant (e.g. int my_in;) it does not give a suggestion
  • If the suggested variable has the wrong type for the operation (e.g. by trying to print my_it.size() instead) it does not give a suggestion
  • Whether or not it gives the suggestion depends on a non-trivial comparison of variable names: it allows for both deletions and insertions of characters, and longer variable names allow for more insertion/deletions to be considered "similar".

Solution

You will not likely find it documented, but as Clang is open-source you can turn to the source to try to figure it out.

Clangd?

The particular diagnostic (from DiagnosticSemaKinds.td):

def err_undeclared_var_use_suggest : Error<
  "use of undeclared identifier %0; did you mean %1?">;

is ever only referred to from clang-tools-extra/clangd/IncludeFixer.cpp:

  // Try to fix unresolved name caused by missing declaration.
  // E.g.
  //   clang::SourceManager SM;
  //          ~~~~~~~~~~~~~
  //          UnresolvedName
  //   or
  //   namespace clang {  SourceManager SM; }
  //                      ~~~~~~~~~~~~~
  //                      UnresolvedName
  // We only attempt to recover a diagnostic if it has the same location as
  // the last seen unresolved name.
  if (DiagLevel >= DiagnosticsEngine::Error &&
      LastUnresolvedName->Loc == Info.getLocation())
    return fixUnresolvedName();

Now, clangd is a language server and t.b.h. I don't know how whether this is actually used by the Clang compiler frontend to yield certain diagnostics, but you're free to continue down the rabbit hole to tie together these details. The fixUnresolvedName above eventually performs a fuzzy search:

if (llvm::Optional<const SymbolSlab *> Syms = fuzzyFindCached(Req))
    return fixesForSymbols(**Syms);

If you want to dig into the details, I would recommend starting with the fuzzyFindCached function:

llvm::Optional<const SymbolSlab *>
IncludeFixer::fuzzyFindCached(const FuzzyFindRequest &Req) const {
  auto ReqStr = llvm::formatv("{0}", toJSON(Req)).str();
  auto I = FuzzyFindCache.find(ReqStr);
  if (I != FuzzyFindCache.end())
    return &I->second;

  if (IndexRequestCount >= IndexRequestLimit)
    return llvm::None;
  IndexRequestCount++;

  SymbolSlab::Builder Matches;
  Index.fuzzyFind(Req, [&](const Symbol &Sym) {
    if (Sym.Name != Req.Query)
      return;
    if (!Sym.IncludeHeaders.empty())
      Matches.insert(Sym);
  });
  auto Syms = std::move(Matches).build();
  auto E = FuzzyFindCache.try_emplace(ReqStr, std::move(Syms));
  return &E.first->second;
}

along with the type of its single function parameter, FuzzyFindRequest in clang/index/Index.h:

struct FuzzyFindRequest {
  /// A query string for the fuzzy find. This is matched against symbols'
  /// un-qualified identifiers and should not contain qualifiers like "::".
  std::string Query;
  /// If this is non-empty, symbols must be in at least one of the scopes
  /// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz::"
  /// is provided, the matched symbols must be defined in namespace xyz but not
  /// namespace xyz::abc.
  ///
  /// The global scope is "", a top level scope is "foo::", etc.
  std::vector<std::string> Scopes;
  /// If set to true, allow symbols from any scope. Scopes explicitly listed
  /// above will be ranked higher.
  bool AnyScope = false;
  /// The number of top candidates to return. The index may choose to
  /// return more than this, e.g. if it doesn't know which candidates are best.
  llvm::Optional<uint32_t> Limit;
  /// If set to true, only symbols for completion support will be considered.
  bool RestrictForCodeCompletion = false;
  /// Contextually relevant files (e.g. the file we're code-completing in).
  /// Paths should be absolute.
  std::vector<std::string> ProximityPaths;
  /// Preferred types of symbols. These are raw representation of `OpaqueType`.
  std::vector<std::string> PreferredTypes;

  bool operator==(const FuzzyFindRequest &Req) const {
    return std::tie(Query, Scopes, Limit, RestrictForCodeCompletion,
                    ProximityPaths, PreferredTypes) ==
           std::tie(Req.Query, Req.Scopes, Req.Limit,
                    Req.RestrictForCodeCompletion, Req.ProximityPaths,
                    Req.PreferredTypes);
  }
  bool operator!=(const FuzzyFindRequest &Req) const { return !(*this == Req); }
};

Other rabbit holes?

The following commit may be another leg to start from:

[Frontend] Allow attaching an external sema source to compiler instance and extra diags to TypoCorrections

This can be used to append alternative typo corrections to an existing diag. include-fixer can use it to suggest includes to be added.

Differential Revision: https://reviews.llvm.org/D26745

from which we may end up in clang/include/clang/Sema/TypoCorrection.h, which sounds like a more reasonably used feature by the compiler frontend than that of the (clang extra tool) clangd. E.g.:

  /// Gets the "edit distance" of the typo correction from the typo.
  /// If Normalized is true, scale the distance down by the CharDistanceWeight
  /// to return the edit distance in terms of single-character edits.
  unsigned getEditDistance(bool Normalized = true) const {
    if (CharDistance > MaximumDistance || QualifierDistance > MaximumDistance ||
        CallbackDistance > MaximumDistance)
      return InvalidDistance;
    unsigned ED =
        CharDistance * CharDistanceWeight +
        QualifierDistance * QualifierDistanceWeight +
        CallbackDistance * CallbackDistanceWeight;
    if (ED > MaximumDistance)
      return InvalidDistance;
    // Half the CharDistanceWeight is added to ED to simulate rounding since
    // integer division truncates the value (i.e. round-to-nearest-int instead
    // of round-to-zero).
    return Normalized ? NormalizeEditDistance(ED) : ED;
  }

used in clang/lib/Sema/SemaDecl.cpp:

// Callback to only accept typo corrections that have a non-zero edit distance.
// Also only accept corrections that have the same parent decl.
class DifferentNameValidatorCCC final : public CorrectionCandidateCallback {
 public:
  DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD,
                            CXXRecordDecl *Parent)
      : Context(Context), OriginalFD(TypoFD),
        ExpectedParent(Parent ? Parent->getCanonicalDecl() : nullptr) {}

  bool ValidateCandidate(const TypoCorrection &candidate) override {
    if (candidate.getEditDistance() == 0)
      return false;
     // ...
  }
  // ...
};


Answered By - dfrib
Answer Checked By - Robin (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Thursday, April 28, 2022

[FIXED] How can I make GCC/Clang warn about the use of uninitialized members?

 April 28, 2022     c++, clang, gcc, warnings     No comments   

Issue

I am compiling the code behind

class Test {
public:
    Test() {}

    int k;
};

int main() {
  Test t;
  std::cout << t.k << "\n";
}

like

g/clang++ main.cpp -Wall -Wextra --std=c++14 -o exe; ./exe

Why neither of the compilers does not warn me about indeterminate value of the integer is not it a very serious potential bug? How to enable a warning for indeterminate initializations?


Solution

For this example, GCC gives me the desired warning when I give it -O1 (or higher).

Presumably whatever mechanism it uses to detect this is tied into the optimisation effort level somehow. It's a notoriously hard thing to do.

Ensure that you heed your release-build warnings as well as debug-build warnings.



Answered By - Lightness Races in Orbit
Answer Checked By - Timothy Miller (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How can I ignore all warnings from included headers in clang/gcc?

 April 28, 2022     clang, gcc, warnings     No comments   

Issue

I want to use #pragma clang diagnostic push to ignore warnings from some included header files. So I write this:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wall"
#include "SpinGenApi/SpinnakerGenApi.h"
#include "Spinnaker.h"
#pragma clang diagnostic pop

But still the compiler prints warnings when compiling the file with this code. What do I need to change so that all warnings are ignored for these headers?


Solution

The answer seems to be in this case that -Wall contrary to its name did not include the warnings which I wanted to suppress. I added #pragma clang diagnostic ignored "-Weverything" as well and they went away.



Answered By - oarfish
Answer Checked By - Katrina (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Wednesday, April 27, 2022

[FIXED] How to deal with "exit-time destructor" warning in clang?

 April 27, 2022     c++, c++11, clang, destructor, warnings     No comments   

Issue

In my C++11 code I get the clang warning "Declaration requires an exit-time destructor" in the following case:

static const std::map<int, const someStruct> mymap = {
    {1, {
        "A",
        "B",
        "C"
    }},
    {2, {
        "D",
        "E",
        "F"
    }}
};

As far as I understand Google an "exit-time destructor" is required to destroy main() and statics in a deterministic way to prevent crashes on exit due to "already released variables". Is that right? Can someone explain it better?

Plus: What can I do about it (I don't want to disable the warning)? The code above is used within context of one thread only.

Looks like this is the way Chromium deals with these cases; would that be the right way for my case as well?

#define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \
  static type& name = *new type arguments

(Source: https://chromium.googlesource.com/chromium/src/+/32352ad08ee673a4d43e8593ce988b224f6482d3/base/basictypes.h)


Solution

Global and function static objects will get their destructors called when your application is exiting. these destructors are "exit time destructors". and are called in the reverse order that they were constructed in.

As you said, if some of these destructors touch already destroyed objects, your program could crash. Also, destructors running at exit time will make the program exit slower, and most of the time they are not necessary for the correctness of the program (since when the program exits, it'll release all its memory anyway).

The warning is simply pointing out that you have destructors that'll be run at exit time.

The fix you proposed will heap allocate the object, which will not cause it to be automatically destroyed at program exit. For your case, this is probably good enough.



Answered By - yiding
Answer Checked By - Katrina (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How can -Wgnu-zero-variadic-macro-arguments warning be turned off with Clang?

 April 27, 2022     clang, suppress-warnings, warnings     No comments   

Issue

Context

I read Clang's "Controlling Diagnostics via Pragmas" section about turning off particular warnings. It works well in general for all warnings except for -Wgnu-zero-variadic-macro-arguments.

The code is:

MyHeader.hpp

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"

#import "header generating -Wgnu-zero-variadic-macro-arguments warning"

#pragma clang diagnostic pop

Problem

Clang generates -Wgnu-zero-variadic-macro-arguments warnings while compiling translation units importing MyHeader.hpp.

Env

Clang Version: Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn) Target: x86_64-apple-darwin13.4.0 Thread model: posix

OS: Mac OS X 10.9.5


Solution

This seems to be working in Xcode 6.4 (6E35b). The pragma suppresses the warning now.

I have -Weverything in build settings. Without the diagnostic ignore I definitely get the warning:

Token pasting of ',' and __VA_ARGS__ is a GNU extension

Output from Terminal to match your Env section:

$ clang --version
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
Thread model: posix

Using the following code:

#define DEBUG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#import "Macros.h"
#pragma clang diagnostic pop

In which Macros.h contains:

#ifdef DEBUG
#define AssLog(condition, message, ...) NSAssert(condition, message, ##__VA_ARGS__)
#else
#define AssLog(condition, message, ...) if (!condition) NSLog((@"%@ [Line %d] " message), [NSString stringWithUTF8String:__PRETTY_FUNCTION__], __LINE__, ##__VA_ARGS__)
#endif


Answered By - Jeff
Answer Checked By - Marie Seifert (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing