What is the best way to integrate a CMake project into Buck? - c++

I am using Buck for my own C++ project, but I depend on a third-party library that is built using CMake. The CMake file is complex, so I do not think it is practical to recreate their CMake file in Buck. Instead, I would like to call CMake from Buck.
What is the best way to call CMake from Buck?
How should I structure my project to minimise headaches?

My suggestion is using genrule and prebuilt_cxx_library.
This is my Buck study project using Google Test:
https://github.com/ar90n/lab/tree/master/sandbox/buck-study/gtest
This project contains two Buck files. The one (./gtest/BUCK) is for fetching and building Google Test. The another (./BUCK) is for building and running test programs.
If you want to build and run this project, please execute the following commands,
$ buck fetch //gtest:googletest-src
$ buck build :sample1
$ buck run :sample1

Calling CMake will break reproducibility, so it isn't the best approach. Instead, try the following:
Fork the project that builds with CMake.
Call CMake to generate any header files.
Save the header files somewhere in the project (e.g. /cmake-generated).
Create a header-only library of the header files generated by CMake.
Build the rest of the project with Buck, depending on the CMake library.
Commit everything to Git.
Repeat step 2 for every target that you require.
This is not as good as a true port to Buck, but you get most of the benefits for a one-time manual step.

Related

Automate CMake build using C++ script

I would like to automate the build of CMake using an MSVC C++ script instead of using CMake-gui to generate the build or CMake terminal or using the CMake integrated on MSVC 2017 by right click on the CMakeLists.txt to build it manually. Assume we have a project (name it: initialize) that includes the CMakeLists.txt and initialize.cpp, so my question is how I can convert these commands into a C++ code, assume build_initialize.cpp:
mkdir build
cd build/
cmake ..
So, the requirement of this tiny C++ code is to
Set the path to this project
Create build folder
Run CMake
At the end if I execute build_initialize.exe, the job is just to build the initialize.cpp using CMake. The goal is to test if the build is success or not as a test case within another project that has several test cases.
You may ask, why I didnot include it to the top CMakelists.txt, and then build it from the beginning using CMake. If I am going to do that, I will get an executable file. As a result, by running the ctest of CMake, the initialize.exe will require a pace of hardware. This is not the goal. My goal is just to build it. If I run build_initialize.exe, just repeat the build using CMake without initialize.exe execution.
Sorry, it could be very simple, but I lack the good experience either in C++ or CMake. Two days have been lost without success.
Thanks to all of you for the comments. The answer has been given by #Fred. To run cmake from C++ script, simply the system() can be used such as: System(cmake -S path_to_src -B path_to_bld).
Useful link: https://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284392&answer=1044654269

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.

CMake Roundtrip Workflow

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

Framework for building and managing third-party libraries

I am working on a cross-platform project which uses a large number of third party libraries (currently 22 and counting, and I expect this number to increase significantly). My project is CMake-based, and keeps the ThirdParty/ directory organized like so:
ThirdParty/$libname/include/
ThirdParty/$libname/lib/$platform/$buildtype/
My CMakeLists.txt has logic to determine the appropriate values for $platform (mac-i386, mac-ia64, win32-i386, and so on) and $buildtype (debug/release).
The difficulty arises in keeping these libraries up-to-date for each platform. Currently I am doing this manually - when I update one library, I go and rebuild it for each platform. But this is a nightmare, and adding a new platform is a two day affair.
This would be easy to automate if the third party libraries were themselves CMake-based, but they use everything from CMake to autoconf to custom solutions to hand-rolled Makefiles. There is no consistency between them, and all require various hoops to be jumped through with regards to build platform (especially with regards to 32- vs. 64-bit builds).
Are there any tools (or CMake extensions) which would make this easier to manage? Is there even any reasonable common ground that can be reached between CMake and autoconf, for example?
The ideal solution would give me a single command to build everything that needs rebuilding for a given platform (cross-compilation is not necessary, as I have access to all necessary platforms), but anything that incrementally makes my life easier would be appreciated.
You can probably use ExternalProject for this.
Create custom targets to build projects in external trees.
The 'ExternalProject_Add' function creates a custom target to drive download, update/patch, configure, build, install and test steps of an external project.
If you already have the source in your project's file hierarchy, then you can use something like this (for zlib):
include(ExternalProject)
ExternalProject_Add(zlib URL ${CMAKE_CURRENT_SOURCE_DIR}/zlib-1.2.4/
CONFIGURE_COMMAND cd <SOURCE_DIR> && ./configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/zlib-build
BUILD_IN_SOURCE 1
BUILD_COMMAND make)
That will copy the zlib source code from your source tree into the build tree, run the configure step (after cd'ing into the copied directory), then run make on the configured directory. Finally the built version of zlib is installed into the current build directory, in a sub-directory called zlib-build.
You can tweak the setup, configure, and build steps however you like - zlib 1.2.4 for example doesn't like to have "configure" run out-of-source.
For a custom setup, you can skip the CONFIGURE step and just run the build command (for example). This requires a recent version of CMake to work (2.8+).