CMake Roundtrip Workflow - build

I understand that CMake enables a project to be easily built in a variety of compiler/IDE environments. I have experienced this for myself and was amazed when CMake produced a working, buildable Xcode project for me from some open source project (cool!)
But what I don't understand is how you properly update the CMake system after you have made significant changes to the project that CMake created for you.
For example I am envisioning a workflow in which the project should be kept portable via CMake. So I create a clone of a github project, use CMake to create my XCode project, and then go to work implementing some new feature or bug fix. Perhaps these changes are non-trivial and affect build.
After these changes are complete I want to push the code base back to github. What happens now? Must all of the CMake files be updated by hand to reflect all of the work that I've done? Or is there some equally magical feature to update the CMake files with the changes that were implemented in XCode (or Visual Studio, or some other supported IDE/compiler combo)?
What is the general "Roundtrip" workflow with CMake and how efficient is it?

The point is that you change your project by changing the CMake configuration files themselves. It could be that you'll find some other tool which manages cmake projects, which will make changes to your cmake files. In the example you mention, you have to check if XCode is modifying your cmake files.
You have to commit all the necessary modifications you do to your cmake files, and your build program (make, ninja, or any other) will run cmake every time the cmake project files are touched.
Advanced note: if you use the command file with globbing instructions to get the list of your sources files, you might be interested to read Getting cmake to run before building after pulling from git

Related

How to setup complex project with Visual Studio 2022?

I have project that I was developing for years in Linux.
It depends on MKL, libxml++, GSL and armadillo library.
Its installation structure is done in CMake and project is formed by building a shared library and couple of executables that link to it. There are about 20 classes in the library.
Project structure is:
--src
--executable1.cpp
--executable2.cpp
--mysharedlib
--class1.h
--class1.cpp
--...
My question is how to install and run this code in Visual Studio in Windows.
I never used VS before and am still going through tutorials. I managed to run my code by installing Ubuntu on WSL, but I I'd like a VS solution as it'd be handy to pass to user not familiar with Linux.
I tried opening the project directory with VS, hoping CMAKE would do all the magic, but expectedly it cannot locate the dependent libraries, so I am now going through web looking how to integrate each to VS. I managed to find armadillo and mkl guide, but I am lost on how to link these libraries to my project codes and whether I should abandon its current cmake setup and start building the code structure differently in VS.
Any links to useful VS tutorials and advices how to this are greatly appreciated.
VS does have support for CMake, although I have no idea how well VS integrates CMake. If you're not set on using VS, you might want to look into an IDE that uses CMake at it's core, Clion comes to mind. That being said, when coming from Linux you don't have the (initial) luxury of simply installing all the dependencies via a preinstalled package manager.
In order for CMake to find your dependencies (assuming you've configured them by using find_package()) you should add the sources of your dependencies to your project in a thirdparty folder (name is up to you) and add these dependencies using add_subdirectory() instead. This will compile all your dependencies from source, so you might have to configure these dependencies yourself (look into the documentation of your dependencies on how to build them from source).
Another way is to use a package manager that is available on Windows to download, compile and provide your dependencies to your build tools. vcpkg comes to mind, claiming to integrate well with CMake by providing a toolchain file that you can pass to CMake when building your project. You might even be able to configure VS to automatically pass this toolchain to CMake whenever it's invoked.
From personal experience, there is no need to convert an existing project to the VS project structure. There's plenty of available solutions and tools available on Windows to work with CMake projects. Going with the cross-platform approach should be preferred unless you're only targeting Windows, using VS to it's fullest then might give you some additional quality of life.
If you have more specific questions regarding this, I suggest that you update your original post or to create separate, specific questions regarding the processes involved in setting up an existing CMake project on Windows.

CMake Zero Check fails to detect updates in CMakeLists.txt files for Xcode generator

Background
I have big project which builds runs on windows perfectly.
When some changes are applied in CMakeLists.txt and project is build, Visual Studio project is properly updated.
Xcode version: 10.0 (10A255) or 10.1 (10B61) (tested on different machines).
CMake version: 3.12.2 or 3.13.1
Problem
Problem appears when same project is build on Mac OS for Xcode.
After configuring CMake:
cmake .. -G Xcode
Generated project works fine, everything builds properly and test are passing.
Now when CMakeLists.txt files are modified (when developing project or when fetching new changes from repository) and ZERO_CHECK or BUILD_ALL are selected, build doesn't lead to Xcode project update.
Invoking cmake . doesn't detect changes too.
Workaround
The best workaround I've found is deleting everything two files: cmake_install.cmake and CMakeCache.txt. Then rerun command which generates project cmake .. -G Xcode.
In this scenario whole detection is redone from scratch, but at least build doesn't start from zero (unchanged files are not recompiled).
This is painful, since lots of manual stuff must be done, and project have to be recreated and this consumes time.
Hints
In some previous project I had similar problem, but it was happening only if maven was detecting updates for dependencies, so it happened quite rarely. When it happened I just called touch CMakeLists.txt and build again and this workaround was fine. This solution doesn't applies since every build has this issue.
I was suspecting that protobuf generation procedure has something with it, but when I've disabled it problem still persists.
I've tried to provide complete minimal example, by creating simple project file, but I was not able to reproduce the issue. For all other projects it just works, so system configuration is not the issue.
Questions
How can I debug project generation process when running cmake to find source of this problem?
Is this a known problem?
Is there a better workaround which will not lead to full rebuild regenerating project file (which also involves detecting system capabilities)?
Is this a known problem?
Over on the CMake Discourse, Craig Scott (one of the CMake maintainers) has commented on a variant of this bug as a known architectural limitation of Xcode:
With the Xcode generator, targets have a dependency on the ZERO_CHECK target, which is what re-runs cmake for you automatically if something changed. But the problem is that the rest of the build in that run still uses the old details from before cmake . gets run. If you build again, that rebuilds anything whose details changed, but explicitly re-running cmake . first if you know something about the project changed will be more robust and probably avoid more unnecessary rebuilds.
-- https://discourse.cmake.org/t/documented-criteria-for-build-correctness/3087/2?u=alex
Your comment that "invoking cmake . doesn't detect changes" is strange in light of this, but it could be that old CMake versions, like 3.12 and 3.13 which you were using when this question was asked, had a bug that has since been fixed. It could also be something project-specific that we can only guess at. Missing a CMAKE_CONFIGURE_DEPENDS directory property? Have a bad set(... CACHE ... FORCE) call? Can't say...

Build instructions when distributing C++ written in CLion

JetBrains has spoiled me. I'm familiar with the standard UNIX make file and the make, make install routine normally associated with installing software with traditional make files, but I'm not as familiar with cmake since CLion does it all for me.
I want to distribute my code to others and provide simple instructions for building it via cmake so that they have a binary they can execute. The official cmake tutorial shows writing install rules in the CMakeLists.txt file but it isn't clear if this is supported by CLion (or even if it needs to be).
For a simple, single-file (main.cpp) application, what would be an example of how to build it using cmake (assuming those it is distributed to don't have CLion nor use another IDE, they just want to build and use it)?
To build code that comes with a CMakeLists.txt file, you run cmake to generate a Makefile (or other build configuration file):
cmake <path_to_CMakeLists.txt>
Then you run
make;make install
as usual. (or as described in the comment, you can type cmake --build . instead of make - useful if you're on a platform with a different build system)
You don't want to check in the Makefile into your source control, though, as it needs to be generated on the computer that will actually be doing the building.

Import non-cmake GitHub project in CLion

Checking CLion help https://www.jetbrains.com/help/clion/2016.2/importing-existing-non-cmake-project.html I see how to import a non-CMake project into CLion.
And I'm also able to clone a project from GitHub https://www.jetbrains.com/help/clion/2016.2/cloning-a-repository-from-github.html
The project https://github.com/quickfix/quickfix uses ./bootstrap and ./configure to setup a makefile.
What I'd like to do is import that makefile into my CLion project and build and run from that. Is this possible?
While it is possible to "import a project" that's not CMake-based into your CLion project, CLion does not itself directly support using Makefiles as an origination point for a project yet. I know that this is something that has been wanted by many people, and as far as I know, the creators of CLion are at some point planning to integrate some support for this.
In the meantime, however, there is no handy way to do this directly. CMake is a build system configurator, in that it generates its own set of Makefiles to build everything, based on the things you write in your CMakeLists.txt file.
Your best bet, should you want to use the quickfix lib in a project of yours, is to learn the CMake process for building an external dependency, and then linking it to your project. A good blog post on such a thing can be found here. If you simply want to work on changes to it in CLion for your own convenience, but keep the original build files, you could just have CLion generate its own little CMakeLists.txt file for the purposes of importing and color-coding everything, and then set your debug config, etc to point to the binaries generated by running make in the command line.
Long story short, there's no easy way to do what you are talking about directly, but depending on your intended purpose, there are a couple of alternate paths to a similar end. Hope this helps!
Support for Makefiles has been added to CLion, however, the feature is (as of writing) still in early development.
This feature allows for a CLion project to be created by selecting File > Open from the main menu and then selecting the top level Makefile for the project.
More details of the feature can be found here: https://www.jetbrains.com/help/clion/makefiles-support.html

Is it possible to force CMake generate Visual Studio project on other project type generation?

I have a CMake project. It is a crossplatform project developed by a team of developers. Visual Studio and other make files are inside version control for library release and external developers.
Each time a file is added we need to recompile all project files for all platforms. How do I force CMake to generate new project files for all systems at once (if possible from inside CMakeLists.txt, not as command line arguments)?
I think it doesn't make sense for this to be possible within the CMakeLists.txt file. CMake is a makefile generator. Everything in the CMakeLists.txt file is configuring the makefile, and it can also be repurposed to make project files.
If the CMakeLists.txt file could also request to generate a different kind of makefile... it would be different from every other command in the CMakeLists.txt file in that it isn't describing the currently selected makefile.
If I were you I would just make a shell script, or a simple makefile, separate from CMake, which rebuilds each of the project files, by invoking CMake from command line with appropriate parameters.
Is the goal of the versioned CMake produced build scripts to not force developers to install CMake?
In any case: it's best to use the right tool for the right job. CMake is for producing build-files and the little scripting necessary to do so. Use a scripting environment (Bash, cmd.exe) to run CMake as necessary for all your platforms.
This keeps the CMake files clean (and readable, CMake scripting is hard to read) and provides clean separation of concerns.