How do I convert an Autotools project to a CMake project? [closed] - build

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
So there seems to be a lot of writing on the subject of Autotools vs. CMake, but for the life of me I can't seem to find a good tutorial on how to convert a project from Autotools (Makefile.am and configure.ac files) to CMake (CMakeLists.txt files). How does one go about doing this?

There is no automated tool that will convert an arbitrary build system from autotools to cmake. I have converted a few moderately large projects manually. I like to create one CMakeLists.txt file for each set of configure.ac and/or Makefile.am file, to ease the conversion from autotools to cmake.
Sadly, this manual approach requires developing an expertise in two systems, no one of which should be inflicted on any innocent.
Capture a record of what autotools build actually does on your machine. This will help you verify that your CMake build system actually compiles every file, using the same compile flags, and creates every library and executable that autotools does; at least on your machine, with your options.
% ./configure [configure options] > configure_autotools.log
% make > make_autotools.log
% make install > make_install_autotools.log
In every directory that contains a configure.ac or Makefile.am file, including the project root directory, create a new empty CMakeLists.txt file. Add cmake add_subdirectory(...) commands to each non-leaf CMakeLists.txt file to link all the cmake files together in a tree structure. Add cmake project() and cmake_minimum_required() commands to the top of your top level CMakeLists.txt file.
project(MyProject)
cmake_minimum_required(VERSION 2.8)
add_subdirectory(foo)
You now have a consistent but useless cmake build system that does nothing. Temporarily add a few message(...) commands in the deeper CMakeLists.txt files to verify that everything is connected correctly. Remember that message() is your friend when debugging cmake configuration problems. Make sure your cmake infrastructure works by trying a build now. Nothing will get built or installed; but it is valuable to exercise the cmake infrastructure at this point.
% mkdir build_cmake
% cd build_cmake
% ccmake -i [your project root]
[configure, configure, generate]
% make VERBOSE=1
% make install
This is the hard part. One by one, populate your CMakeLists.txt files. Here are some guidelines:
Open two side-by-side editors, one with the CMakeLists.txt file, the other with the corresponding Makefile.am/configure.ac file.
Have your browser open to the cmake commands documentation.
Rather than starting from the very top, start off by creating cmake rules for building a small library or executable, if you can find one in the project (cmake add_library() or add_executable()). Using this approach you can build up your conversion one piece at a time.
Keep periodically testing your cmake build system as you add each target.
I like to use the cmake file(GLOB ...) command to compactly create lists of source files. Be aware that this is a controversial opinion.
Many common autotools stanzas have corresponding CMake commands. For example autoconf AC_TRY_COMPILE can be converted to cmake TRY_COMPILE. But mostly I find I have to understand what every little autotools stanza does and figure out how to write the corresponding cmake. Also, there is a series of CMake modules that help create autotools-like config.h files. Makefile.am files are often easier to convert, and can actually become more compact after translation to cmake.
Compare your cmake build results to the autotools logs you captured in step 1. Are the compile flags the same? Are all of the same targets built? Are the same files installed?
Unfortunately I have not converted autotools to cmake recently, so I am not in a position to write a comprehensive "if you see x in Makefile.am, write y in CMakeLists.txt". Can someone suggest a good location for a public wiki where folks who are actively converting from autotools to cmake can accumulate a comprehensive set of such guidelines? I'm not sure if this stackoverflow answer is the best place for such a list...
For extra credit, once you have it all working, tweak your cmake rules to be able to build and run your project from Windows Visual Studio. Try that with autotools!

This conversion is very project specific, and that makes writing a generally applicable tutorial difficult.
Here is the start of some tools that may give you some inspiration of what to do.
https://gitlab.kitware.com/cmake/community/-/wikis/Home#converters-from-other-buildsystems-to-cmake
=====
An interesting article related to this:
Why the KDE project switched to CMake -- and how (continued)
http://lwn.net/Articles/188693/

Related

Maintaining Makefiles and CMakeLists.txt

When you're working to very big projects with a large amount of people, maintaining both Makefiles and CMakeLists.txt could be very difficult. I know that CMakeLists.txt could generate Makefiles, but suppose that I want to compile my code by using make and in the same time, use an IDE to have a kind of intellisense. How can I achieve it?
In the scenario that I'm describing, CMakeLists.txt files will disappear, so I won't have the chance to generate solutions with them.
CMake is not a build manager!
It is a generator of files for other build managers!
So you can generate project for IDEs (Visual Studio, Xcode, CodeBlocks, ..) or generate MakeFile, or whatever you prefer and CMake supports. So I do not understand why do you maintain CMakeLists.txt and Makefiles at the same time.
Just maintain CMakeLists.txt and then generate respective Makefiles from it.
For details see CMake Documentation - generators:
Command-Line Build Tool Generators
These generators support command-line build tools. In order to use them, one must launch CMake from a command-line prompt whose environment is already configured for the chosen compiler and build tool.
Borland Makefiles
MSYS Makefiles
MinGW Makefiles
NMake Makefiles
NMake Makefiles JOM
Ninja
Unix Makefiles
Watcom WMake
Bottom line you should be able to generate files for IDE or Makefile for you favorite build manager without any complications.
In the scenario that I'm describing, CMakeLists.txt files will disappear, so I won't have the chance to generate solutions with them.
WAT? You are doing something very strange and most probably wrong and you didn't provide any details abut that.
Concerning intellisense I would say:
Visual Studio 2017 as built-in support for CMake, see announcement
CMake can generate a json file with all commands see CMAKE_EXPORT_COMPILE_COMMANDS
so you can use it to have smart clang based completion in vim
QtCreator as built-in support for CMake so you'll have completion too.
Extra tip at first: Do not try to mix both handmade make files and CMake over the whole time of the project.
The normal way is to create the make files using cmake. The extra of cmake is the cross platform and in your case the nativ support by some IDEs, eg. QtCreator, CLion(awaik). For a wide range of other IDE cmake can generate the project files.
Example Workflow using QtCreator:
Create a simple CMakeLists.txt, at least with the name of the project
Load this into QtCreator
Add source files, update the CMakeLists.txt from within QtCreator
Build from within QtCreator, repeat
But the same CMakeLists.txt will be used to create the make file on command line. Or on your build server or CI system.

How to improve my script and copy program resources on build?

So I got into a problem where I needed to use linux for a while instead of windows, and figured linux doesn't have Visual Studio. I then also realized that I made my project Visual Studio only, which I don't want.
So I looked up some CMake tutorials and try'ed creating some examples that could be loaded in both Visual Studio and CodeBlocks. When I got that to work, I went and code a CMake script for my actual program by piecing together what I learned and what I found in tutorials.
See here:
cmake_minimum_required(VERSION 2.8.9)
add_subdirectory(libraries/glfw)
project (OpenGLEngine3D)
include_directories(libraries/glfw/include)
include_directories(libraries/glm)
include_directories(libraries/glad/include)
include_directories(libraries/whereami/src)
include_directories(libraries/stb)
file(GLOB SOURCES "src/*.cpp" "src/*.h" "libraries/whereami/src/whereami.c" "libraries/glad/src/glad.c")
add_executable(OpenGLEngine3D ${SOURCES})
target_link_libraries(OpenGLEngine3D glfw)
Its dirty(I think) but it works.
So now my first question is, how to improve my CMake script? What is redundant or done in a poor way?
Now my program also requires some resources(like shaders, textures) which I have stored in a directory along with my CMake script, libraries and c++ files.
So my second question is, how would I tell CMake to the ide/compiler to copy the files in a certain directory to the program build directory(where the compiled binaries are) after compiling?(And have it only do it when the files aren't there ofc.)
Thanks!
I recently came across this article, which might be help you with CMake.
Here are a couple suggestions from me:
You're safe to use newer version of CMake. Currently, it's 3.11. There's no point in sticking to old versions.
Consider listing all your sources in a variable (using set command) instead of using file(GLOB). file(GLOB) will be evaluated only once, when generating build files. If you add new sources, you'll have to re-generate it manually, so it doesn't help too much, and is harder to debug (and really, debugging more complex CMake projects can be painful).
Avoid using include_directories (and link_libraries). Prefer using target_include_directories which works per-target. It allows to express dependencies between targets (when you have more than one - which might happen as your project grows)
You might consider using find_package(GLFW), instead of including GLFW in your project. Edit: actually, CMake doesn't came with find module for GLFW, but you can use an external module for this (e. g. this one) as described here.
Edit:
Example below illustrates the idea behind point 2), assuming that sources are placed in "src/" directory on the same level as CMakeLists.txt file:
set(engine_sources
"src/header_1.hpp"
"src/source_1.cpp"
# and so on for reset of files...
)
add_executable(OpenGLEngine3D ${engine_sources})
As for the second question: that's what file(COPY) command is for. Alternatively, you could just leave assets in source directory, and set working directory in IDE.
Side note: if you choose the second options, there appears to be a way to set this from CMake for Visual Studio, by setting VS_DEBUGGER_WORKING_DIRECTORY property:
set_target_properties(OpenGLEngine3D PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
(I haven't checked if this works as expected, as I rarely use VS. I remember looking for something like that in the past, and just recently came across it.)

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.

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

Can CMake generate build scripts which do *not* use cmake?

Question: Can CMake generate build scripts that do not, in any way, use CMake? If not, how hard is it to gut a CMake generated automake script to not make any checks against CMake?
I am a big fan of CMake to the point where I am championing the idea that we transition to it in my current work environment. One thing that could ease this transition from our current build system to CMake would be if I could demonstrate that CMake can generate automake files that do not require cmake themselves.
Clearly, I would never want to do this for day to day use, but having the ability to easily create a branch of our code that can be built from source without requiring cmake would go a long way in helping me make my case.
The ability to do this depends on your OS, I'm presuming Unix/Makefile or Windows/MSVC. If you're using MSVC, the cmake dependency should be eliminated by declaring the CMAKE_SUPPRESS_REGENERATION option at the start of your cmake script.
SET(CMAKE_SUPPRESS_REGENERATION TRUE)
On Unix-based systems, however, the Makefiles are tied explicitly to the cmake build files (CMakeFiles, etc). I suspect that this dependency could be bypassed by the strategic commenting out of Makefile directives although, I cannot say what they might be.
No, CMake cannot do this. It doesn't really make sense, either, since without any CMake-support at build-time, there would be no way to check or update the makefiles/project-files themselves when the CMakeLists.txt files have changed.
If you are moving from Visual Studio to CMake, you may want to take a look at vcproj2cmake.
CMake generated files depend on cmake for various commands such as create / remove / etc... not just to regenerate the makefiles on a change so removing cmake is not going to work.
As someone who has taken a large complex piece of software and recently pulled out its existing build system, installing a new build system in its place. I can tell you that it's not easy, but I would definitely not want shell scripts as part of my build process, if they can be avoided. More and more systems will find themselves with CMake on them anyway, as more big name software packages like LLVM and KDE start using it—This is an area where it really accels, large projects.
One of the nice things about CMake is it builds things quicker. Resorting to have to fork shell instances to interpret a script really slows down the build process.
What about the 'atomic solution' ?
EX- auto-generate a "QT moc" file from CMakeLists.txt, then build project that depends on the .cpp file being generated
# inside project level CMakeLists.txt
# run shell script to create the "moc_GUICreator.cpp" auto-generated source file
if(UNIX)
execute_process(COMMAND "sh" ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_moc.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts )
endif(UNIX)
Where the .sh file contains:
# generate_moc.sh
echo "generating moc file: moc ../include/GUICreator.h -o ../src/moc_GUICreator.cpp "
moc ../include/GUICreator.h -o ../src/moc_GUICreator.cpp
Equivalent windows batch file, "moc_creator_win.bat":
moc "GUICreator.h" -o "moc_GUICreator.cpp"
Haven't tried this last bit in windows, but it or something very close should work, just after the if(UNIX) block in CMakeLists.txt:
if(WIN32)
execute_process(COMMAND "cmd" ${CMAKE_CURRENT_SOURCE_DIR}/scripts/moc_creator_win.bat WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts )
endif(WIN32)
So, basically if you're clever you can do whatever you want from a script and use CMake variables as args to it, I'm not sure if you can ask for more...
the point is to avoid 'non-portable build types' unless you really need to hack it into a specialized compiler, or don't feel like using QT Designer to place the widgets ;-)