Having trouble understanding xcode build parameter: "${BUILD_DIR%Build/*}"

Viewed 242

I'm integrating the WireGuardKit, according to its README file, I need to create an external build system target to build wireguard-go-bridge library.

In the external build system target's info tab. The documentation says I should use this location: ${BUILD_DIR%Build/*}SourcePackages/checkouts/wireguard-apple/Sources/WireGuardKitGo The build for the external build system target failed. As the path can't be resolved. If I change the path with a correct, absolute path, the build will succeed.

Can anyone tell me what's the meaning of this ${BUILD_DIR%Build/*}, looks firebase is also using this magic variable, see Firebase Crashlytics | Swift Package Manager (SPM) Run Script?

1 Answers

After some googling, I figured it out: Quote SuperUser contributor Marek Rost's Post:

When the percent sign (%) is used in the pattern ${variable%substring}, it will return content of the variable with the shortest occurrence of substring deleted from the back of the variable.

This function supports wildcard patterns, that is why it accepts an asterisk (star) as a substitute for zero or more characters. It should be mentioned that this is Bash specific. Other Linux shells do not necessarily contain this function.

If you want to learn more about string manipulation in Bash, then I highly suggest reading the following page, Advanced Bash-Scripting Guide: Chapter 10. Manipulating Variables. Among many other handy functions, it explains what a double percent sign (%%) does, for example.

I forgot to mention that when it is used in the pattern $((variable%number)) or $((variable1%$variable2)), the percent sign (%) character will function as a modulo operator.

When the percent sign (%) is used in different contexts, it should be recognized as a regular character only.

So suppose ${BUILD_DIR} is

~/Library/Developer/Xcode/DerivedData/wgShowcase-dejirdnsktlwtagdrhljeefdnxvi/Build/Products

What ${BUILD_DIR%Build/*} mean is delete the shortest occurrence of substring Build/*(the star sign is a wildcard) from the back of ${BUILD_DIR} variable. In this case, the Build/Products will be removed. then we have the result:

~/Library/Developer/Xcode/DerivedData/wgShowcase-dejirdnsktlwtagdrhljeefdnxvi/

So since all the SPM packages used by this project checks out at a child directory at ~/Library/Developer/Xcode/DerivedData/wgShowcase-dejirdnsktlwtagdrhljeefdnxvi/, the final resolved path should be:

~/Library/Developer/Xcode/DerivedData/wgShowcase-dejirdnsktlwtagdrhljeefdnxvi/SourcePackages/checkouts/wireguard-apple/Sources/WireGuardKitGo

As for why the build is not succeed, I think it's a Xcode bug. I have reported a bug to apple. For anyone who is trying to build. Use below as a workaround:

${BUILD_DIR}/../../SourcePackages/checkouts/wireguard-apple/Sources/WireGuardKitGo

Update: Here is the response from Apple regarding to this 'issue'

After reviewing your feedback, we have some additional information for you, or some additional information, or action is necessary for this issue:

The Directory field here is not evaluated as a bash variable, it’s evaluated as an Xcode build setting, which does not support bash operators such as %.

You would likely need to set the working directory to a known directory with a makefile, and then have that makefile use makefiles from the ultimate target directory.

We noticed that when we clone the repo it comes with macOS and iOS targets whose directories are set to $(PROJECT_DIR)/Sources/WireGuardKitGo, so we're wondering if the project owner has updated the project to fix this issue, but hasn’t updated the documentation.

In any event, this is behaving correctly.

Related