# CMAKE plugin and OS 11 Universal Binary

**URL:** <https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997>\
**Category:** Audio Plugins\
**Created:** [October 1, 2020, 1:31pm UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997 "2020-10-01T13:31:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![kunz](https://avatars.discourse-cdn.com/v4/letter/k/f19dbf/32.png) [@kunz](https://forum.juce.com/u/kunz)\
**Post date:** [October 1, 2020, 1:31pm UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/1 "2020-10-01T13:31:31Z")

</div>

We want to build our first Universal Binary 2 for OS 11 ARM. We are using the new JCUE 6 CMAKE infrastructure and i started to think how we can build the plugins as Universal Binary without time consuming manual steps.

There are some problems i see:

- The deployment target may has to be different for the ARM and Intel builds.
- We may can’t build the AAX plugin because the library does not compile for ARM and is not supported?
- Other problems that may occur?

Can this be configured within the CMAKE file and does juce already offer a way to build universal binaries 2 with CMAKE where we can keep our low deployment targets for the intel builds and also don’t have to care about AAX (maybe it can be excluded for this architecture as long as it’s not supported)?

Any help welcome!

---

<div class="post-metadata">

**Author:** ![reuk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/reuk/32/21494_2.png) [@reuk](https://forum.juce.com/u/reuk)\
**Post date:** [October 1, 2020, 2:14pm UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/2 "2020-10-01T14:14:47Z")

</div>

I’ve successfully built universal JUCE targets by configuring the CMake project with

```auto
cmake -D CMAKE_OSX_ARCHITECTURES="arm64;x86_64"

```

To disable arm builds for specific targets, you should be able to use the `OSX_ARCHITECTURES` property:

```auto
set_target_properties(my_plugin_AAX PROPERTIES OSX_ARCHITECTURES x86_64)

```

---

<div class="post-metadata">

**Author:** ![kunz](https://avatars.discourse-cdn.com/v4/letter/k/f19dbf/32.png) [@kunz](https://forum.juce.com/u/kunz)\
**Post date:** [October 1, 2020, 2:34pm UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/3 "2020-10-01T14:34:30Z")

</div>

Thanks for the fast answer. That looks pretty easy. I will try it asap. For the moment it looks like it was a good decision to switch to CMAKE builds 🙂

---

<div class="post-metadata">

**Author:** ![aleFX](https://avatars.discourse-cdn.com/v4/letter/a/aca169/32.png) [@aleFX](https://forum.juce.com/u/aleFX)\
**Post date:** [April 18, 2022, 10:21am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/4 "2022-04-18T10:21:26Z")

</div>

> [@reuk](#):
>
> I’ve successfully built universal JUCE targets by configuring the CMake project with
> 
> ```auto
> cmake -D CMAKE_OSX_ARCHITECTURES="arm64;x86_64"
> 
> ```

Sorry, could you explain more in detail how to do that? I’m using CMAKE on an Intel Macbook and I’m compiling with the CMAKE extensions of Visual Studio Code. Basically my question is: how can I add that compilation flag inside the CMakeList.txt?

---

<div class="post-metadata">

**Author:** ![pflugshaupt](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pflugshaupt/32/13206_2.png) [@pflugshaupt](https://forum.juce.com/u/pflugshaupt)\
**Post date:** [April 18, 2022, 10:24am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/5 "2022-04-18T10:24:05Z")

</div>

Add this to the project CMakeLists.txt somewhere before juce\_add\_\*

```auto
if (APPLE)
    set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
endif()

```

---

<div class="post-metadata">

**Author:** ![aleFX](https://avatars.discourse-cdn.com/v4/letter/a/aca169/32.png) [@aleFX](https://forum.juce.com/u/aleFX)\
**Post date:** [April 18, 2022, 10:35am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/6 "2022-04-18T10:35:51Z")

</div>

> [@pflugshaupt](#):
>
> ```auto
> if (APPLE)
> set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
> endif()
> 
> ```

Awesome! thank you!

---

<div class="post-metadata">

**Author:** ![adamwilson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/adamwilson/32/1387_2.png) [@adamwilson](https://forum.juce.com/u/adamwilson)\
**Post date:** [April 18, 2022, 9:16pm UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/7 "2022-04-18T21:16:06Z")

</div>

I was having some issues with my build server not producing a universal binary. I also wanted to support users on OSX 10.9.

First I tried exporting an Xcode project after adding these lines to my CMakeLists.txt:

```auto
if(APPLE)
    set (CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version" FORCE)
    set (CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "Architectures" FORCE)
    set (CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET[arch=arm64] "11.0" CACHE STRING "arm 64 minimum deployment target" FORCE)
endif()

```

This worked, producing different minimum targets for each architecture. I then tried exporting to Ninja - this works even better as it integrates nicely into CMake and detects the number of available processors for parallel builds.

---

<div class="post-metadata">

**Author:** ![PluginPenguin](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pluginpenguin/32/10203_2.png) [@PluginPenguin](https://forum.juce.com/u/PluginPenguin)\
**Post date:** [April 19, 2022, 8:57am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/8 "2022-04-19T08:57:03Z")

</div>

Interesting, I didn’t know setting individual deployment targets for each architecture slice works. And I would expect that `CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET` is ignored when using Ninja, as it’s an Xcode specific attribute.

In any case, we successfully only set a single deployment target for universal binary builds which seems to work fine in general, even if the target predates 11.0. I don’t quite see the benefit of using a different deployment target for the ARM slice since the shared code cannot use any features introduced in later macOS versions anyway. Am I overlooking something here?

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [April 19, 2022, 9:42am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/9 "2022-04-19T09:42:32Z")

</div>

> [@PluginPenguin](#):
>
> And I would expect that `CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET` is ignored when using Ninja, as it’s an Xcode specific attribute.

I think despite this called “XCODE…” this is a global mac setting, I’m using those xcode attributes with Ninja and Unix Makefiles successfully.

> [@PluginPenguin](#):
>
> In any case, we successfully only set a single deployment target for universal binary builds which seems to work fine in general, even if the target predates 11.0.

Yeah, that works for me as well. I set 10.9 as the minimum and it ‘does the right thing’ on ARM.

---

<div class="post-metadata">

**Author:** ![reuk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/reuk/32/21494_2.png) [@reuk](https://forum.juce.com/u/reuk)\
**Post date:** [April 19, 2022, 10:46am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/10 "2022-04-19T10:46:36Z")

</div>

> [@eyalamir](#):
>
> I think despite this called “XCODE…” this is a global mac setting, I’m using those xcode attributes with Ninja and Unix Makefiles successfully.

According to the docs, these variables only have an effect on the Xcode generator. It sounds like these settings are ignored in all other generators.

[https://cmake.org/cmake/help/latest/variable/CMAKE\_XCODE\_ATTRIBUTE\_an-attribute.html](https://cmake.org/cmake/help/latest/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.html)

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [April 19, 2022, 11:26am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/11 "2022-04-19T11:26:27Z")

</div>

> [@reuk](#):
>
> According to the docs, these variables only have an effect on the Xcode generator. It sounds like these settings are ignored in all other generators.

Yes, I’ve read that too, but the docs are wrong.  
I set those constantly on all my different computers and CI and they’re always accepted on all Mac generators that I’ve used.

---

<div class="post-metadata">

**Author:** ![reuk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/reuk/32/21494_2.png) [@reuk](https://forum.juce.com/u/reuk)\
**Post date:** [April 19, 2022, 11:36am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/12 "2022-04-19T11:36:01Z")

</div>

My point is that it’s a bad idea to rely on behaviour that contradicts the documentation. Failing to ignore these variables in non-Xcode generators is arguably a bug in CMake, and this might be fixed in the future.

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [April 19, 2022, 11:37am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/13 "2022-04-19T11:37:44Z")

</div>

Actually I can’t imagine this would even change - without that feature the other Mac generators have no way of doing code sign, OS target, etc, so breaking that would make any other generator completely useless on Mac.

It would probably only change if the syntax of the call itself will modernize to not explicitly mention xcode.

---

<div class="post-metadata">

**Author:** ![reuk](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/reuk/32/21494_2.png) [@reuk](https://forum.juce.com/u/reuk)\
**Post date:** [April 19, 2022, 11:40am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/14 "2022-04-19T11:40:37Z")

</div>

- `CMAKE_OSX_ARCHITECTURES` for universal builds
- `CMAKE_OSX_DEPLOYMENT_TARGET` for deployment target

Note that these are _not_ `CMAKE_XCODE_ATTRIBUTE` variables, will work for generators other than Xcode, and will work for targets other than macOS (iOS, watchOS etc.).

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [April 19, 2022, 11:41am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/15 "2022-04-19T11:41:52Z")

</div>

> [@reuk](#):
>
> - `CMAKE_OSX_ARCHITECTURES` for universal builds
> - `CMAKE_OSX_DEPLOYMENT_TARGET` for deployment target

Ah yes, my mistake. You’re absolutely right.

---

<div class="post-metadata">

**Author:** ![pflugshaupt](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pflugshaupt/32/13206_2.png) [@pflugshaupt](https://forum.juce.com/u/pflugshaupt)\
**Post date:** [November 13, 2022, 9:27pm UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/16 "2022-11-13T21:27:36Z")

</div>

> [@](#):
>
> ```auto
> if (APPLE)
> set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
> endif()
> 
> ```

I’m pulling my hair out over this: Has anyone managed to create juce universal-binary-2 XCode projects using CMake that only build the native architecture (arm64 in my case) for the Debug scheme, but are universal-2 for Release? I tried all kinds of stuff with [variant=…] and various cmake flags but only end up with a non-working mess or the Debug builds always being universal and taking twice as long as necessary.  
Using google I also found that this has been a problem with CMake in the past and maybe it’s still unsolved? Any help would be very welcome.

this almost worked, but only affects the main “project”, not the single targets:

```auto
   set(CMAKE_XCODE_ATTRIBUTE_ARCHS[variant=Debug] "$(NATIVE_ARCH_ACTUAL)")
   set(CMAKE_XCODE_ATTRIBUTE_ARCHS[variant=MinSizeRel] "arm64;x86_64")
   set(CMAKE_XCODE_ATTRIBUTE_ARCHS[variant=RelWithDebInfo] "arm64;x86_64")
   set(CMAKE_XCODE_ATTRIBUTE_ARCHS[variant=Release] "arm64;x86_64")

```

---

<div class="post-metadata">

**Author:** ![benvining](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/benvining/32/9922_2.png) [@benvining](https://forum.juce.com/u/benvining)\
**Post date:** [November 13, 2022, 9:41pm UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/17 "2022-11-13T21:41:55Z")

</div>

I would do this using generator expressions to set target properties:

```nohighlight
function(set_univ_bin target)

    if(NOT APPLE)
        return()
    endif()

    execute_process (COMMAND uname -m OUTPUT_VARIABLE osx_native_arch
                     OUTPUT_STRIP_TRAILING_WHITESPACE)

    message (VERBOSE "Mac native arch: ${osx_native_arch}")

    get_property (debug_configs GLOBAL PROPERTY DEBUG_CONFIGURATIONS)

    if (NOT debug_configs)
        set (debug_configs Debug)
    endif ()

    set (config_is_debug "$<IN_LIST:$<CONFIG>,${debug_configs}>")
    set (config_is_release "$<NOT:${config_is_debug}>")

    set_target_properties ("${target}" PROPERTIES 
        OSX_ARCHITECTURES
        "$<${config_is_debug}:${osx_native_arch}>"
        "$<${config_is_release}:x86_64$<SEMICOLON>arm64>"
        )
endfunction()

```

---

<div class="post-metadata">

**Author:** ![pflugshaupt](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pflugshaupt/32/13206_2.png) [@pflugshaupt](https://forum.juce.com/u/pflugshaupt)\
**Post date:** [November 14, 2022, 8:32am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/18 "2022-11-14T08:32:59Z")

</div>

Thank you for the help!  
Unfortunately, I couldn’t make your script work. It seems generator expressions are not supported inside set\_target\_properties().

Luckily, playing around with your code led me to a solution that works for me for now. I realized that CMake by default sets the architectures to “arm64”, so all I need is to make the Release config/variant universal on both the project and all targets as unfortunately the project setting is overridden for each target by CMake.

On top of my CMakeLists.txt I configure the project:

```auto
if (APPLE)   
    set(CMAKE_XCODE_ATTRIBUTE_ARCHS[variant=Release] "$(STANDARD_ARCHS)")

```

After setting up the targets I iterate through the formats and some extra targets (this is a juce plugin build):

```auto
if (APPLE)
    foreach(t ${FORMATS} "BinaryData" "All" "")
        set(tgt ${CMAKE_PROJECT_NAME})
        if(NOT t STREQUAL "") 
            set(tgt ${tgt}_${t})
        endif()
        if(TARGET ${tgt})
            set_target_properties(${tgt} PROPERTIES 
                XCODE_ATTRIBUTE_ARCHS[variant=Release] "$(STANDARD_ARCHS)"
            )
        endif()
    endforeach()
endif()

```

That sets everything the way I need it for now (still using Xcode 13.2 on 12.3)

---

<div class="post-metadata">

**Author:** ![eyalamir](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/eyalamir/32/2978_2.png) [@eyalamir](https://forum.juce.com/u/eyalamir)\
**Post date:** [November 14, 2022, 9:26am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/19 "2022-11-14T09:26:27Z")

</div>

You probably don’t want to globally build universal binary for release builds, as you also probably test release builds locally, and the 2x built times are just a waste of your dev time. Also, scripting that would create complication in your build script that isn’t gonna be easy to get rid of when you don’t want it.

Instead, just pass the universal binary argument to CMake when you’re actually deploying.  
Something like:

```auto
#dev build:
cmake -G Xcode -B build

#deployment build:
cmake -G Xcode -B build-deploy -D CMAKE_OSX_ARCHITECTURES "x86_64;arm64"

```

Edit: Also universal binaries are useful for debug builds too, as sometimes you need to test on Rosetta-based hosts, so that’s another reason to be able to manually enable universal builds/intel only arch when you need it, and not have too much deployment logic in your build script.

---

<div class="post-metadata">

**Author:** ![pflugshaupt](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/pflugshaupt/32/13206_2.png) [@pflugshaupt](https://forum.juce.com/u/pflugshaupt)\
**Post date:** [November 14, 2022, 10:37am UTC](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997/20 "2022-11-14T10:37:12Z")

</div>

> [@eyalamir](#):
>
> You probably don’t want to globally build universal binary for release builds, as you also probably test release builds locally, and the 2x built times are just a waste of your dev time.

I certainly want it, but it’s of course a matter of taste and workflow. To each his own.  
What I wanted is the default way XCode works without CMake and I frankly find it quite weird this isn’t much easier to achieve. I use Debug builds for development and Release builds for testing on multiple machines and sometimes making sure the other arch still builds correctly, so this makes perfect sense to me.

[Next page](https://forum.juce.com/t/cmake-plugin-and-os-11-universal-binary/41997.md?page=2)
