Is it possible to convert CMakeLists.txt to Unix Makefile? - cmake

I'm trying to get rid of cmake in my project for some reasons. I need to create unix makefiles to build my project. If i use cmake to generate them for me, that makefiles would depend of cmake anyway. The only build tools that I can use is one from GNU toolchain.

cmake was invented to be a portable way to create makefiles. If you want to have a look at an alternative, take a look at bjam from boost. This tool works with a lot of toolchains (called toolset in the bjam terminology) and is quite simple to use as cmake is.
If you really want to get rid of cmake or bjam, then write your own makefiles taking the ones generated by cmake as a base for example... But this will limit the scope of systems and toolchains on which your code will compile. To be honest I would see rather that as a pain and encourage you to use bjam if you need better support for other toolsets.

Related

How exactly does CMake work?

I'm not asking this for just myself. I hope this question will be a reference for the many newbies who like me, found it utterly perplexing about what exactly what was going on behind the scenes when for such a small CMakeLists.txt file
cmake_minimum_required (VERSION 2.6)
project(Tutorial)
add_executable(Tutorial tutorial.cpp)
and such a small tutorial.cpp
int main() { return 0; }
there are so many files generated
CMakeCache.txt cmake_install.cmake Makefile
CMakeLists.txt tutorial.cpp
and a CMakeFiles folder with so many files and folders
CMakeCCompiler.cmake CMakeOutput.log Makefile.cmake
cmake.check_cache CMakeSystem.cmake progress.marks
CMakeCXXCompiler.cmake CMakeTmp TargetDirectories.txt
CMakeDetermineCompilerABI_C.bin CompilerIdC Tutorial.dir
CMakeDetermineCompilerABI_CXX.bin CompilerIdCXX
CMakeDirectoryInformation.cmake Makefile2
Not understanding what was going on behind the scenes (i.e: why so may files had to be generated and what their purpose was), was the biggest obstacle in being able to learn CMake.
If anyone knows, could you please explain it for the sake of posterity? What is the purpose of these files, and when I type cmake ., what exactly is cmake configuring and generating before it builds the project?
The secret is that you don't have to understand what the generated files do.
CMake introduces a lot of complexity into the build system, most of which only pays off if you use it for building complex software projects.
The good news is that CMake does a good job of keeping a lot of this messiness away from you: Use out-of-source builds and you don't even have to look at the generated files. If you didn't do this so far (which I guess is the case, since you wrote cmake .), please check them out before proceeding. Mixing the build and source directory is really painful with CMake and is not how the system is supposed to be used.
In a nutshell: Instead of
cd <source_dir>
cmake .
always use
cd <build_dir_different_from_source_dir>
cmake <source_dir>
I usually use an empty subfolder build inside my source directory as build directory.
To ease your pain, let me give a quick overview of the relevant files which CMake generates:
Project files/Makefiles - What you are actually interested in: The files required to build your project under the selected generator. This can be anything from a Unix Makefile to a Visual Studio solution.
CMakeCache.txt - This is a persistent key/value string storage which is used to cache value between runs. Values stored in here can be paths to library dependencies or whether an optional component is to be built at all. The list of variables is mostly identical to the one you see when running ccmake or cmake-gui. This can be useful to look at from time to time, but I would recommend to use the aforementioned tools for changing any of the values if possible.
Generated files - This can be anything from autogenerated source files to export macros that help you re-integrate your built project with other CMake projects. Most of these are only generated on demand and will not appear in a simple project such as the one from your question.
Anything else is pretty much noise to keep the build system happy. In particular, I never needed to care about anything that is going on inside the CMakeFiles subdirectory.
In general you should not mess with any of the files that CMake generates for you. All problems can be solved from within CMakeLists.txt in one way or the other. As long as the result builds your project as expected, you are probably fine. Do not worry too much about the gory details - as this is what CMake was trying to spare you of in the first place.
As stated on its website:
Cmake is cross-platform, open-source build system for managing the build process of software using a compiler-independent method
In most cases it is used to generate project/make files - in your example it has produced Makefile which are used to build your software (mostly on Linux/Unix platform).
Cmake allows to provide cross platform build files that would generate platform specific project/make files for particular compilation/platform.
For instance you may to try to compile your software on Windows with Visual Studio then with proper syntax in your CMakeLists.txt file you can launch
cmake .
inside your project's directory on Windows platform,Cmake will generate all the necessary project/solution files (.sln etc.).
If you would like to build your software on Linux/Unix platform you would simply go to source directory where you have your CMakeLists.txt file and trigger the same cmake . and it will generate all files necessary for you to build software via simple make or make all.
Here you have some very good presentation about key Cmake functionalities http://www.elpauer.org/stuff/learning_cmake.pdf
EDIT
If you'd like to make platform dependent library includes / variable definitions etc. you can use this syntax in CMakeLists.txt file
IF(WIN32)
...do something...
ELSE(WIN32)
...do something else...
ENDIF(WIN32)
There is also a lot of commands with use of which you are able to prevent the build from failing and in place Cmake will notify you that for instance you do not have boost libraries filesystem and regex installed on your system. To do that you can use the following syntax:
find_package(Boost 1.45.0 COMPONENTS filesystem regex)
Having checked that it will generate the makefiles for appropriate system/IDE/compiler.
Exactly how CMake works is a question for the developers, so this question can't be answered here.
However we can give a touch of useful guidance as far as when you should use CMake and when you therefore need to worry about how it works. I'm not a fan of "oh it just works" answers either - because, especially in software, NOTHING ever "just works" and you ALWAYS have to get into the nitty-gritty details at some point.
CMake is an industrial-strength tool. It automates several VERY complex process and takes into account many variables of which you may not be aware, especially as a fairly new developer, probably working with limited knowledge of all the operating systems and build tools CMake can handle. The reason so many files are generated and why things seem so complex is because all of those other systems are complex and must be accounted for and automated. Additionally there are the issues of "caching" and other time-saving features of the tool To understand everything in CMake would mean understanding everything in these build tools and OS's and all the possible combinations of these variables, which as you can imagine is impossible.
It's important to note that if you're not in charge of managing a large cross-platform build system, and your code base is a few KLOC, maybe up to 100KLOG, using CMake seems a little bit like using a 100,000 dollar forestry tree removal machine to remove weeds from your 2 foot by 2 foot flower garden. (By the way, if you've never seen such a machine, you should look for one on youtube, they're amazing)
If your build system is small and simple it's likely to be better to just write your own makefiles by hand or script them yourself. When your makefiles become unwieldy or you need to build a version of your system on another platform, then you can switch over to CMake. At that point, you'll have lots of problems to solve and you can ask more focused questions about it. In the meantime, check out some of the great books that have been written about CMake, or even better, write one yourself! 8)

configure script calling cmake

I'm thinking to write a simple configure script (similar to autoconf one) which execs cmake. But before doing that I want to check if anyone knows of such an effort already. I wasn't able to find anything on google.
It should be able to support the basic autoconf configure flags (prefix, exec-prefix, bindir mostly).
Reason to do it is of course that there's a certain user expectancy to be able to do ./configure && make
Also not really an answer but too long for a comment:
After reading up about cmake / cpack, I can at least tell you this. Cmake expects to be present on the platform. Therefore CPack cannot generate the same type of ./configure scripts as autotools. The Autotools expect some shell to be present, which is essentially the same as cmake to be present. However since cmake also targets the Win environment, it cannot rely on a shell. That being said, CPack can provide source packages, which need to be installed with cmake in the usual manner.
Also this does not solve your problem, I do not recommend to write a tool for cmake. Cmake is able to use all these type of prefixes you are interested in. If the user wants to compile your program from scratch, he has to know at least the basics (e.g. setting variables) of your build system. This is also true for autotools. If you want to spare him the pain, you can provide binary .sh, .deb or .rpm packages, which can be easily built with cmake / cpack.

Call external programs with CMake

I tried to search the CMake documentation, but I couldn't figure out how to call external programs from CMake.
There are few things I want to do.
Compile other third-party dependencies that uses a makefile
Compile Thrift definition files to C++ / Python stubs.
Compile Cython definition files.
Another question is, what is a good way to handle those cases anyway? It feels like calling a shell script directly from CMake doesn't feel so clean, when "C" in CMake stands for Cross Platform.
EDIT: I have few extra questions. Before, in my build, I prebuilt my dependencies, and the project itself used FIND_PACKAGE(...) to find the header / libraries for the dependencies.
Now, I'm ExternalProject_Add() to compile the dependencies, but the problem is, all my FindXYZ() functions fails when I run cmake ., because the dependencies aren't present when CMake gets executed.
How should I include the third-party libraries in my project in this case?
http://www.kitware.com/media/html/BuildingExternalProjectsWithCMake2.8.html
2+3. can be hacked with CONFIGURE_COMMAND/BUILD_COMMAND/INSTALL_COMMAND

How to configure cmake to compile informix *.ec files?

I'm just found cmake and I want to use it to create make files for a little project that uses the esql compiler.
I've not used cmake yet (it is on my list of things that I need to look at - round about the time some spare tuits become available), but...
I do have several sets of rules for compiling ESQL/C to object code etc for regular make.
You can find one set of those rules online at the IIUG Software Archive in the SQLCMD package. Or you can contact me directly to discuss the niceties in detail (and/or the differences between cmake stuff and regular make stuff). You can also find Informix-related autoconf macros in the SQLCMD package - file acinformix.m4.
You will probably need to use the cmake ADD_CUSTOM_COMMAND command to create the rule for compiling each source file with the esql compiler.

Build System and portability

I'm wondering how i can make a portable build system (step-by-step), i currently use cmake because it was easy to set up in the first place, with only one arch target, but now that i have to package the library I'm developing I'm wondering how is the best way to make it portable for arch I'm testing.
I know I need a config.h to define things depending on the arch but I don't know how automatic this can be.
Any other way to have a build system are warmly welcome!
You can just use CMake, it's pretty straightforward.
You need these things:
First, means to find out the configuration specifics. For example, if you know that some function is named differently on some platform, you can use TRY_COMPILE to discover that:
TRY_COMPILE(HAVE_ALTERNATIVE_FUNC
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/alternative_function_test.cpp
CMAKE_FLAGS -DINCLUDE_DIRECTORIES=xxx
)
where alternative_function_test.cpp is a file in your source directory that compiles only with the alternative definition.
This will define variable HAVE_ALTERNATIVE_FUNC if the compile succeeds.
Second, you need to make this definition affect your sources. Either you can add it to compile flags
IF(HAVE_TR1_RANDOM)
ADD_DEFINITIONS(-DHAVE_TR1_RANDOM)
ENDIF(HAVE_TR1_RANDOM)
or you can make a config.h file. Create config.h.in with the following line
#cmakedefine HAVE_ALTERNATIVE_FUNCS
and create a config.h file by this line in CMakeLists.txt (see CONFIGURE_FILE)
CONFIGURE_FILE(config.h.in config.h #ONLY)
the #cmakedefine will be translated to #define or #undef depending on the CMake variable.
BTW, for testing edianness, see this mail
I have been using the GNU autoconf/automake toolchain which has worked well for me so far. I am only really focussed on Linux/x86 (and 64bit) and the Mac, which is important if you are building on a PowerPC, due to endian issues.
With autoconf you can check the host platform with the macro:
AC_CANONICAL_HOST
And check the endianness using:
AC_C_BIGENDIAN
Autoconf will then add definitions to config.h which you can use in your code.
I am not certain (have never tried) how well the GNU autotools work on Windows, so if Windows is one of your targets then you may be better off finding similar functionality with your existing cmake build system.
For a good primer on the autotools, have a look here:
http://www.freesoftwaremagazine.com/books/autotools_a_guide_to_autoconf_automake_libtool