# \[RFC\] Cross-platform CMake support

**URL:** <https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102>\
**Category:** Developing Cinder\
**Created:** [June 21, 2016, 1:29am UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102 "2016-06-21T01:29:13Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![gabor\_papp](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/gabor_papp/32/769_2.png) [@gabor\_papp](https://discourse.libcinder.org/u/gabor_papp)\
**Post date:** [August 14, 2016, 7:31am UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/21 "2016-08-14T07:31:24Z")

</div>

Hi,

Thanks for this. I tested #1560 with the SimplexNoise block and it works fine.

-Gabor

---

<div class="post-metadata">

**Author:** ![symbolix](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/symbolix/32/155_2.png) [@symbolix](https://discourse.libcinder.org/u/symbolix)\
**Post date:** [August 19, 2016, 4:44pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/22 "2016-08-19T16:44:43Z")

</div>

Hi,

I am excited to see that there has been some significant work done towards implementing CMake into the build workflow of Cinder. I have some previous experience with porting OpenFrameworks to CMake. Both on the lib side (static/shared) and on the examples side as I do not use any IDEs and like using CMake for project configuration.

So I am new to Cinder and I would like to give it a try under OSX. Thanks for the hard work.

Cheers,  
Milen

---

<div class="post-metadata">

**Author:** ![symbolix](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/symbolix/32/155_2.png) [@symbolix](https://discourse.libcinder.org/u/symbolix)\
**Post date:** [August 20, 2016, 2:18pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/23 "2016-08-20T14:18:49Z")

</div>

First Impression:

**_libcinder.a_** and **_libcinder\_d_** seems to be building fine with XCode under OSX. The examples are running. The only issue is that **_boost_** is missing in the original project structure and every project would fail at the `#include <boost/filesystem.hpp>` directive including the **_libcider_**. Once that problem is fixed, everything builds and runs.

With CMake, obviously the **_boost_** issue is there, however once that is fixed **_libcinder.a_** builds fine.

TODO:

1. Try building -DEBUG to get the **_libcinder\_d.a_** with CMake.
2. Try building one of the examples with CMake.

Thanks.

---

<div class="post-metadata">

**Author:** ![rich.e](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/rich.e/32/1025_2.png) [@rich.e](https://discourse.libcinder.org/u/rich.e)\
**Post date:** [August 20, 2016, 6:06pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/24 "2016-08-20T18:06:40Z")

</div>

boost headers are part of a submodule, make sure you do a `git submodule update --init` after any time you update your cinder repo.

---

<div class="post-metadata">

**Author:** ![symbolix](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/symbolix/32/155_2.png) [@symbolix](https://discourse.libcinder.org/u/symbolix)\
**Post date:** [August 21, 2016, 5:48pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/25 "2016-08-21T17:48:35Z")

</div>

Thanks rich.e,

That solved the boost issues. I would like to ask couple of questions:

1. Right now, I am running CMake from within `cinder-dev-0.9.1/build` by running `cmake ..` which seems to be working so far. Is this the intended approach?

2. To build an example, from within the build folder `cinder-dev-0.9.1/build` I would be running `cmake .. -DCINDER_BUILD_SAMPLE="BezierPathIteration"` which also seems to be working but partially. The sample application would be placed under `cinder-dev-0.9.1/build/Debug` however non of the assets would be placed under the package `Resources` folder. So the application would crash. Only after any dependent content such as `svn` assets or images are manually copied, the application will function as intended. Maybe because the `COPY` functionality has not been implemented yet?

3. What would be the ideal workflow to build a cinder project outside of the `samples` folder. Do you guys have a solution to that, or do you expect the user to come up with their own CMake scripts?

Let’s say, I have a project that is a clone of the the `BasicApp` sample but is inside `myDevFolder/cinder_projects/ci_MyCinderApp` folder. Should I be writing my own `CMakeLists.txt` or is there a way to invoke your CMake approach from with in my project?

Thanks.

---

<div class="post-metadata">

**Author:** ![petros](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/petros/32/26_2.png) [@petros](https://discourse.libcinder.org/u/petros)\
**Post date:** [August 22, 2016, 7:02am UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/26 "2016-08-22T07:02:15Z")

</div>

Hey @symbolix,

We have tried to keep Cinder’s CMake configuration aligned as much as possible with the way you would use any other CMake-based project. This means that for 1) this would be the ‘default’ way for building Cinder but there should be nothing that stops you to build Cinder from another directory. If you try a different dir structure and you hit any issues drop a line here so that we can have a look on it.

Your observations about 2) are correct. My personal opinion on that would be to have a custom post-build command that copies the assets to the binary directory from the source directory through [add\_custom\_command](https://cmake.org/cmake/help/v3.0/command/add_custom_command.html).

Regarding 3) we don’t have any template generator system at the moment in place so for using a custom dir or even for creating a new app under the samples folder you would need to copy one of the existing CMakeLists.txt files and modify it for your particular needs. This should be quite straightforward since the only thing that would need to be changed besides things like project name etc. would be the [CINDER\_PATH](https://github.com/cinder/Cinder/blob/android_linux/samples/BasicApp/proj/cmake/CMakeLists.txt#L6) variable which helps locate the exported config file of Cinder.

HTH,  
Petros

---

<div class="post-metadata">

**Author:** ![rich.e](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/rich.e/32/1025_2.png) [@rich.e](https://discourse.libcinder.org/u/rich.e)\
**Post date:** [August 22, 2016, 6:28pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/27 "2016-08-22T18:28:52Z")

</div>

1. Is indeed a problem that we’ve been trying to sort out. It came about when I addressed [#1505](https://github.com/cinder/Cinder/issues/1505), so that samples build into whatever folder you’re currently in (such as `build/Debug/SampleApp` or whatever), as this is the typical place where out-of-source cmake builds place the resulting binary. But yep, no assets can be found there because they live relative to the application directory. So lets discuss how to solve this. 🙂

The thing I don’t like about copying the assets folder to the build directory is that it will hinder the ability to update assets during runtime, whether with a filewatcher or just reloading your application. Either a) you’d mistakenly be modifying the assets that live in the sample’s directory, or b) you’d be modifying the assets in the build directory that aren’t versioned and will be overwritten during your next build.

What do people think about sym-linking the assets folder into the runtime output directory?

This isn’t just an issue for cinder’s samples and tests, by the way. I’m seeing the same thing in a personal project setup, which AFAICT is the recommended way to organize a project with many dependencies and executable targets. Basically this is the structure:

```bash
[root]
CMakeLists.txt # <- carries global flags and brings in all targets from sub-projects, including libcinder
app/ # main application
-- assets/
-- proj/cmake/CMakeLists.txt
-- src/
test/ # test suite for app's various components
-- assets/
-- proj/cmake/CMakeListst.txt
-- src/
common/ # shared library used by both app and test
-- proj/cmake/CMakeLists.txt
src/ # common source files
cinder/ # where cinder lives, as a dependency of common, test, and app
blocks/ # any cinderblocks live in here
-- OSC 
-- Cinder-View/
-- -- assets/

```

In the layout above, both the `app` and `test` targets have separate assets folders, and they live relative to their project folder. So if all build products end up somewhere in `[root]/build`, they won’t be automatically found.

It’s also a problem if you want to run a target from a sub-project that needs to find its own assets, such as [Cinder-View](https://github.com/richardeakin/Cinder-View) in this case. Its test suite is looking for some button images that live in `blocks/Cinder-View/assets/images/`, but the build product ends up in the root build dir.

---

<div class="post-metadata">

**Author:** ![symbolix](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/symbolix/32/155_2.png) [@symbolix](https://discourse.libcinder.org/u/symbolix)\
**Post date:** [August 22, 2016, 10:08pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/28 "2016-08-22T22:08:44Z")

</div>

Hi rich.e,

I can look into that. There are quite a few options that CMake provides. Just let me get up to speed with some of the aspects you guys have been working on 🙂

I have just managed to compile an independent cinder project, outside the cinder project structure using bits and pieces from your CMake scripts. I will create a case-study repo in a second. It will be messy but, for me, it should server as a good starting point, something I know that works.

---

<div class="post-metadata">

**Author:** ![symbolix](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/symbolix/32/155_2.png) [@symbolix](https://discourse.libcinder.org/u/symbolix)\
**Post date:** [August 22, 2016, 10:47pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/29 "2016-08-22T22:47:04Z")

</div>

Hello again,

This here is the initial repo:

> **[symbolix/ci\_bezierpathiteration](https://github.com/symbolix/ci_bezierpathiteration)**
>
> Demo cinder application. Contribute to symbolix/ci\_bezierpathiteration development by creating an account on GitHub.

Please let me know if there are any issues related to this. I have put this together as a case study to help myself understand the process of building a cinder application outside the cinder’s own project structure.

I have added verbose messages etc. only to get a better understanding of what is happening. The idea of building `libcinder` and preparing it to become an imported target is cool.

My initial question is, how can one make the build process of `libcinder` a dependency for the `ci_BezierPathIteration` application. Meaning, starting the build process for both `libcinder` (as a dependency) and as `ci_BezierPathIteration` from within the `ci_BezierPathIteration/build` folder.

Maybe something like this?

```auto
ExternalProject_Add(
        ci_static
        SOURCE_DIR ${CINDER_PATH}
        INSTALL_DIR ${cinder_install_dir}
        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
        CMAKE_CACHE_ARGS -DCINDER_VERBOSE=On -DCMAKE_BUILD_TYPE=Release
)

```

In that way, the build process of `libcinder` can be invoked within the project itself. Is this possible or is it a good idea?

Thanks.

---

<div class="post-metadata">

**Author:** ![gabor\_papp](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/gabor_papp/32/769_2.png) [@gabor\_papp](https://discourse.libcinder.org/u/gabor_papp)\
**Post date:** [August 25, 2016, 7:09am UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/30 "2016-08-25T07:09:59Z")

</div>

I’m trying to implement some post build action like supporting `make run` and post build copy.

This is what I managed to do for `make run`. It should use `CMAKE_RUNTIME_OUTPUT_DIRECTORY` instead of the `CMAKE_BUILD_TYPE` hack, but I could not access that variable.

```auto
add_custom_target( run
    COMMAND open ${CMAKE_BUILD_TYPE}/${APP_NAME}.app
    DEPENDS ${CMAKE_BUILD_TYPE}/${APP_NAME}.app/Contents/MacOS/${APP_NAME}
    WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}
)

```

I also have to define `CMAKE_BUILD_TYPE` in my CMake file to make this work.

It is also often necessary to copy a shared library from a block next to the application executable. It would be more elegant to do this from the block config cmake than hacking it into the application cmake. This is what I have for a block with Leap Motion dynamic libraries in the app cmake. I’m not sure if it is possible to put this in the block cmake.

```auto
if( CINDER_MAC )
    add_custom_command( TARGET ${APP_NAME} POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
            ${APP_DIR}/blocks/Cinder-Leap/lib/macosx/libLeap.dylib
            ${CMAKE_BUILD_TYPE}/${APP_NAME}.app/Contents/MacOS/
    )
elseif( CINDER_LINUX )
  ...
elseif( CINDER_MSW )
  ...
endif()

```

Do you have any suggestions to make these solutions simpler, more elegant? Or is it not possible to do this with the current cinder cmake system?

---

<div class="post-metadata">

**Author:** ![petros](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/petros/32/26_2.png) [@petros](https://discourse.libcinder.org/u/petros)\
**Post date:** [August 27, 2016, 11:00am UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/31 "2016-08-27T11:00:49Z")

</div>

Hi Gabor,

just looking into this…

For the first issue I think we could get away by making the `CMAKE_RUNTIME_OUTPUT_DIRECTORY` visible in the parent scope. Something like :

`set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} PARENT_SCOPE )` at [the end](https://github.com/cinder/Cinder/blob/android_linux/proj/cmake/modules/cinderMakeApp.cmake#L119) of `cinderMakeApp.cmake` should do the trick for this issue.

For your second issue I m not entirely sure yet what would be the best way to handle it – Right now personally I could imagine that the `BLOCKNAME_LIBRARIES` var that we introduced for non-target blocks could be of use and help here i.e we could check for this var even with blocks that define targets and if set copy these next to the binary.

Any other ideas are of course more than welcome!

---

<div class="post-metadata">

**Author:** ![petros](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/petros/32/26_2.png) [@petros](https://discourse.libcinder.org/u/petros)\
**Post date:** [August 27, 2016, 11:09am UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/32 "2016-08-27T11:09:37Z")

</div>

Hey Rich,

I haven’t encountered a symlink approach for handling assets on a CMake project before but this should not be something that stops us from trying it out and check how it works! From the top of my head I don’t see any obvious downsides with this approach and what you mention about copying assets definitely holds true i.e you have to be really aware of which directory you are actually watching/modifying etc.

Cheers,  
Petros

---

<div class="post-metadata">

**Author:** ![gabor\_papp](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/gabor_papp/32/769_2.png) [@gabor\_papp](https://discourse.libcinder.org/u/gabor_papp)\
**Post date:** [August 27, 2016, 4:55pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/33 "2016-08-27T16:55:55Z")

</div>

Hi Petros,

Thanks for the suggestions. It would be nice to have `CMAKE_RUNTIME_OUTPUT_DIRECTORY` available in parent scope if you think it is a valid use case. Would it make sense to do the same with `ARG_APP_NAME` as well? `CMAKE_RUNTIME_OUTPUT_DIRECTORY` only contains the directory, but the executable is placed in `${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${ARG_APP_NAME}.app/Contents/MacOS/` on OS X. The easiest path for the dynamic libraries is next to the executable, but from the block config file this path is not possible to guess I think. Additionally, if the app name was available it would be possible to use it as a target in `add_custom_command` in post build actions.

-Gabor

---

<div class="post-metadata">

**Author:** ![brucelane](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/brucelane/32/541_2.png) [@brucelane](https://discourse.libcinder.org/u/brucelane)\
**Post date:** [August 28, 2016, 7:50pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/34 "2016-08-28T19:50:42Z")

</div>

A warm thank you to all the team!  
Videodrömm now runs on Linux!!!  
I had to put some #if (defined( CINDER\_MSW) ) || (defined( CINDER\_MAC )) to compile it and avoid some segfaults, but this is very promising.  
Here is my [CMakeLists.txt](https://github.com/videodromm/videodromm-visualizer-cinder/blob/master/proj/cmake/CMakeLists.txt) file if you need, I’m glad to have imgui, warping, osc blocks compiling fine.

 ![](https://canada1.discourse-cdn.com/flex030/uploads/libcinder/original/1X/0a5023bcf49d4e04217152ed2dad949115f84073.png)

---

<div class="post-metadata">

**Author:** ![hurpyderpy](https://avatars.discourse-cdn.com/v4/letter/h/919ad9/32.png) [@hurpyderpy](https://discourse.libcinder.org/u/hurpyderpy)\
**Post date:** [September 15, 2016, 3:56pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/35 "2016-09-15T15:56:03Z")

</div>

Hi @rich.e and everyone. Thanks very much for bringing CMake into the mix. I’m pretty sure that this is the primary reason I’ve been able to get Cinder running on Linux now and it’s much appreciated.

I noticed that CLion support is made explicitly. As this is a RFC thread, I’d like to ask if [juCi++](https://github.com/cppit/jucipp) could possibly be supported as well? It also uses CMake as it’s build system and hopefully could be integrated into your system as well.

---

<div class="post-metadata">

**Author:** ![rich.e](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/rich.e/32/1025_2.png) [@rich.e](https://discourse.libcinder.org/u/rich.e)\
**Post date:** [September 15, 2016, 4:48pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/36 "2016-09-15T16:48:41Z")

</div>

Apologies for the silence, been working on totally unrelated things…

Re @petros exporting CMAKE\_RUNTIME\_OUTPUT\_DIRECTORY to parent scope - I’m slightly hesitant here, as subsequent targets are going to pick this build variable up. What about defining a new variable in the parent scope, ex. `CINDER_RUNTIME_OUTPUT_DIRECTORY`?

Re @gabor_papp copying dylib: yes perhaps if it is a dylib passed into `cinderMakeApp()`, we should copy it to the appropriate place for the current platform. Although I’m not sure how to distinguish when we need to copy a library to be local to the app executable and when the app should be using a shared lib at some global location (ex /usr/local/lib). Open to thoughts here, but if we can’t then perhaps cinderblocks can define a custom property like `CINDER_APP_COPY_LIBS` or something.

I think this weekend I will go ahead with trying out symlinking the assets folder. This will change the build folder layout slightly as on some platforms (linux) we need one extra folder with the app’s name, but I don’t think it will have any side effects.

---

<div class="post-metadata">

**Author:** ![rich.e](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/rich.e/32/1025_2.png) [@rich.e](https://discourse.libcinder.org/u/rich.e)\
**Post date:** [September 15, 2016, 5:26pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/37 "2016-09-15T17:26:24Z")

</div>

@hurpyderpy do we need to make changes to support juCi++? For CLion, it was necessary to make the cinder assets system work.

---

<div class="post-metadata">

**Author:** ![hurpyderpy](https://avatars.discourse-cdn.com/v4/letter/h/919ad9/32.png) [@hurpyderpy](https://discourse.libcinder.org/u/hurpyderpy)\
**Post date:** [September 15, 2016, 5:44pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/38 "2016-09-15T17:44:53Z")

</div>

> [@rich.e](#):
>
> do we need to make changes to support juCi++?

juCi++ expects a CMakeLists.txt file to be in the base folder of a project. Is it possible to accommodate this via the CMake

```auto
add_subdirectory()
```

command? I suppose this would mean 'add\_subdirectory()'ing the other folders needed in this base CMakeLists.txt file, and CMake will find them properly thereafter.

With this addition, Juci could then pick up the other CMakeLists.txt files automatically and it seems like this is a more general approach and would accommodate more development environments both now and in the future.

edit: Clarification

---

<div class="post-metadata">

**Author:** ![rich.e](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/rich.e/32/1025_2.png) [@rich.e](https://discourse.libcinder.org/u/rich.e)\
**Post date:** [September 17, 2016, 10:51am UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/39 "2016-09-17T10:51:42Z")

</div>

> juCi++ expects a CMakeLists.txt file to be in the base folder of a project.Is it possible to accommodate this via the CMake add\_subdirectory() command?

There’s a CMakeLists.txt file at the root of the repo that builds libcinder and optionally the samples. Does this work in juCi++?

After discussing, we decided for the samples themselves that they wouldn’t contain a CMakeLists.txt file in the their base folder (instead it is in proj/cmake/CMakeLists.txt) as we’re moving all build files into the proj folder to reduce clutter. This isn’t a problem in CLion at least, as you can tell it where the base directory of your project is. There’s no feature like this in your IDE?

Edit: I also [saw](https://github.com/cppit/jucipp/issues/250) that juC++ is planning to ditch cmake support in favor of Bazel (yet another build language from google)…

---

<div class="post-metadata">

**Author:** ![hurpyderpy](https://avatars.discourse-cdn.com/v4/letter/h/919ad9/32.png) [@hurpyderpy](https://discourse.libcinder.org/u/hurpyderpy)\
**Post date:** [September 18, 2016, 4:39pm UTC](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102/40 "2016-09-18T16:39:28Z")

</div>

> [@rich.e](#):
>
> Does this work in juCi++?

TBH, I don’t know enough about Cinder and building with it to be certain. But just now I was able to remove the previous ‘build’ dir inside the Cinder checkout dir, fire up Juci in the Cinder dir, and run a project build on that folder. As far as I can tell, it worked correctly. I included a capp of my desktop for you from after the fact, and if all the output obj files and the build output info text looks right to you, then it seems safe to assume the answer is yes.

 ![](https://canada1.discourse-cdn.com/flex030/uploads/libcinder/original/1X/aed2dfd6892f65f29ce6379b103c6eb59413081c.png)

> [@rich.e](#):
>
> There’s no feature like this in your IDE?

Not that I’m able to discern, no. However I wouldn’t be surprised to learn that I’m simply unaware of it.

> [@rich.e](#):
>
> Edit: I also saw that juC++ is planning to ditch cmake support in favor of Bazel (yet another build language from google)…

Haha you know Juci better than I do! 😃 I was unaware of that. To me, it’s a great editor with it’s auto-complete and syntax error analysis and I’ve quickly become rather attached to it (even though it’s still very early in it’s development cycle).

[Previous page](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102.md?page=1)

[Next page](https://discourse.libcinder.org/t/rfc-cross-platform-cmake-support/102.md?page=3)
