"makefile:1: *** missing separator" in one-line makefile - cmake

My makefile consists of one line
cmake_minimum_required(VERSION 3.6)
There are no leading spaces, line ending is UNIX-style. I'm out of ideas.

You cannot run input files for cmake with make.
A makefile is input for make command.
A CMakeLists.txt is input for cmake command.
CMake is a build system generator, i.e. it will create a makefile from a CMakeLists.txt for you, that can later be run with make.

Related

How do I make makefile generatedby cmake output the last command when error occur? [duplicate]

I use CMake with GNU Make and would like to see all commands exactly (for example how the compiler is executed, all the flags etc.).
GNU make has --debug, but it does not seem to be that helpful are there any other options? Does CMake provide additional flags in the generated Makefile for debugging purpose?
When you run make, add VERBOSE=1 to see the full command output. For example:
cmake .
make VERBOSE=1
Or you can add -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON to the cmake command for permanent verbose command output from the generated Makefiles.
cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON .
make
To reduce some possibly less-interesting output you might like to use the following options. The option CMAKE_RULE_MESSAGES=OFF removes lines like [ 33%] Building C object..., while --no-print-directory tells make to not print out the current directory filtering out lines like make[1]: Entering directory and make[1]: Leaving directory.
cmake -DCMAKE_RULE_MESSAGES:BOOL=OFF -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON .
make --no-print-directory
It is convenient to set the option in the CMakeLists.txt file as:
set(CMAKE_VERBOSE_MAKEFILE ON)
Or simply export VERBOSE environment variable on the shell like this:
export VERBOSE=1
cmake --build . --verbose
On Linux and with Makefile generation, this is likely just calling make VERBOSE=1 under the hood, but cmake --build can be more portable for your build system, e.g. working across OSes or if you decide to do e.g. Ninja builds later on:
mkdir build
cd build
cmake ..
cmake --build . --verbose
Its documentation also suggests that it is equivalent to VERBOSE=1:
--verbose, -v
Enable verbose output - if supported - including the build commands to be executed.
This option can be omitted if VERBOSE environment variable or CMAKE_VERBOSE_MAKEFILE cached variable is set.
Tested on Cmake 3.22.1, Ubuntu 22.04.
If you use the CMake GUI then swap to the advanced view and then the option is called CMAKE_VERBOSE_MAKEFILE.
I was trying something similar to ensure the -ggdb flag was present.
Call make in a clean directory and grep the flag you are looking for. Looking for debug rather than ggdb I would just write.
make VERBOSE=1 | grep debug
The -ggdb flag was obscure enough that only the compile commands popped up.
CMake 3.14+
CMake now has --verbose to specify verbose build output. This works regardless of your generator.
cd project
cmake -B build/
cmake --build build --verbose
It's worth noting however Xcode may not work with --verbose
Some generators such as Xcode don't support this option currently.
Another option it to use the VERBOSE environment variable.
New in version 3.14.
Activates verbose output from CMake and your build tools of choice when you start to actually build your project.
Note that any given value is ignored. It's just checked for existence.
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=TRUE will generate a file with all compilation commands.
This file is required by some LSP to know how to compile a source file out of the box, but it could also help for debugging compilation problems.
The output file is named ${CMAKE_BINARY_DIR}/compile_commands.json.

CMake - customize 'make help' output

I introduced CMake to my project it replaced Make's makefiles. Anyhow I'm not able to find how to customize 'make help' output. This target is created automagically anyhow I would like to add some descriptions for particular targets. It is anyhow possible?
Overwriting help with add_custom_target results in:
See also "/tmp/20/CMakeFiles/CMakeOutput.log".
CMake Error at CMakeLists.txt:5 (add_custom_target):
The target name "help" is reserved or not valid for certain CMake features,
such as generator expressions, and may result in undefined behavior.
Instead of overwriting what cmake generates, write your own make wrapper one directory above the cmake one. Like so:
$ cd /your/project
$ ls
_build CMakeLists.txt source_file.c Makefile
$ cmake -S. -B./_build
... configure the project in ./_build builddir ...
$ make
cmake --build _build --target all
<builds the project>
$ make help
This is your help
With Makefile:
all:
cmake --build _build --target all
configure_for_some_configuration:
cmake -S. -B_build -DSOME_OPTION=true
help:
#echo 'This is your help'
.PHONY: help configure_for_some_configuration all
Remember that make is one of several of supported generators. I recommend Ninja for faster builds. Use cmake --build <the build dir> to abstractly build the project independently of the used generator.

How to build and add a dependency library in CMake

For my project, I need to build and include another library, https://github.com/t-dillon/tdoku/, as my dependency.
Toku is also built using CMake, and there's a build script I can run by doing:
$ cd lib/toku
$ ./BUILD.sh
This puts the library file in ./lib/tdoku/build/libtdoku.a.
I'm trying to build the Toku library inside CMake, and use it as a dependency. How can I do this?
I tried using add_custom_target, add_custom_command, add_dependencies, add_subdirectory to no avail.
My current CMakeLists.txt looks like:
cmake_minimum_required(VERSION 3.17)
project(project_1_cpp)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion")
set(CMAKE_CXX_FLAGS_DEBUG_INIT "")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3")
add_custom_target(toku)
add_custom_command(
TARGET toku
COMMAND ${CMAKE_SOURCE_DIR}/lib/tdoku/BUILD.sh
WORKING_DIR ${CMAKE_SOURCE_DIR}/lib/tdoku
)
file(GLOB project_1_src "*.cpp")
add_executable(project_1_cpp ${project_1_src})
add_dependencies(tdoku project_1_cpp)
target_link_libraries(project_1_cpp ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a)
From some help of #Tsyvarev, I first changed my CMakeLists.txt to include:
add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a
COMMAND ${CMAKE_SOURCE_DIR}/lib/tdoku/BUILD.sh tdoku
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/lib/tdoku
)
add_custom_target(project DEPENDS ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a)
The key is that WORKING_DIR does not work, and I need to instead have WORKING_DIRECTORY. I figured this part out by trying to modify the build.sh script, and having it print things to a file, so I can know if it's being run at all, and what's breaking inside the script. I realized that the script's working directory was wrong.
In fact, I believe I did all this before posting the question, but I got the following errors after, which lead me to think that the tdoku library wasn't compiling properly. It was, but it was linking incorrectly to my project:
/usr/bin/ld: /usr/bin/ld: DWARF error: could not find variable specification at offset 223f
/usr/bin/ld: DWARF error: could not find variable specification at offset 22ba
I googled "DWARF error: could not find variable specification", which led me to ld.exe: DWARF error: could not find variable specification at offset 101cee. Googling cmake flto led me to How do I enable link time optimization (LTO) with CMake?.
This finally allowed me to compile my project.
The entire list of changes include:
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a
COMMAND ${CMAKE_SOURCE_DIR}/lib/tdoku/BUILD.sh tdoku
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/lib/tdoku
)
add_custom_target(project DEPENDS ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a)

How to setup make options with cmake

I would like to setup commands like make debug, make test, etc... What is the best way to do this with cmake, so that I run cmake .. one time (it takes a while) and then be able to choose the build type with make?
I couldn't find any resources on this.
As #Tsyvarev has commented this needs a little extra work for single-configuration environments (respectively CMake's Makefile generators) since the build type is chosen during CMake's configuration and finalized during the build environment generation step.
So here is what I've done:
First you run - e.g. in a script - CMake for all configurations you want to support and choose respective sub-folders for the output:
> cmake -H"." -B"Debug" -DCMAKE_BUILD_TYPE=Debug
> cmake -H"." -B"Release" -DCMAKE_BUILD_TYPE=Release
Note: -H (for "home directory") and -B (for "binary output directory") are undocumented options, but very useful in those cases. And they work with all CMake releases so far. Just be careful not to put spaces between the option and the their values.
Then you can use again CMake to build from/in those sub-folders:
> cmake --build "Debug"
> cmake --build "Release"
And if you want to run the tests you can:
> cmake --build "Debug" --target "test"
> cmake --build "Release" --target "test"
References
Changing CMake files standard location
Does CMake always generate configurations for all possible project configurations?
cmake build multiple targets in different build directories
CMAKE_BUILD_TYPE not being used in CMakeLists.txt

cmake: Selecting a generator within CMakeLists.txt

I would like to force CMake to use the "Unix Makefiles" generator from within CMakeLists.txt.
This is the command I use now.
cmake -G "Unix Makefiles" .
I would like it to be this.
cmake .
When running on windows with VC installed and a custom tool-chain.
I would expect to be-able to set the generator in the CMakeLists.txt file.
Maybe something like this.
set(CMAKE_GENERATOR "Unix Makefiles")
Here is what worked for me - create a file called PreLoad.cmake in your project dir containing this:
set (CMAKE_GENERATOR "Unix Makefiles" CACHE INTERNAL "" FORCE)
It seems to me that the variable CMAKE_GENERATOR is set too late if set in the CMakeLists.txt. If you use (even at the beginning of CMakeLists.txt)
set(CMAKE_GENERATOR "Ninja")
message("generator is set to ${CMAKE_GENERATOR}")
you can see in the output something like
% cmake ../source
-- The C compiler identification is GNU 4.9.2
...
-- Detecting CXX compile features - done
generator is set to Ninja
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/build
So the variable is only set at the very end of the generation procedure. If you use something like
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "" FORCE)
in CMakeLists.txt, then in the very first run of cmake ../source (without -G) the default generator is used. The variable CMAKE_GENERATOR is stored in the cache, though. So if you rerun cmake ../source afterwards, it will use the generator as specified in the CMAKE_GENERATOR variable in the cache.
This is surely not the most elegant solution, though ;-) Maybe use a batch file that will actually execute the cmake -G generator for the user...
This is not what I get, when I run the same command, cmake will look for a gcc compiler / make utility. If the PATH is not set up correctly it will fail with something like:
D:\Development\build>cmake -G "Unix Makefiles" ..\source
CMake Error: CMake was unable to find a build program corresponding to "Unix Makefiles". CMAKE_MAKE_PROGRAM is not set.
You probably need to select a different build tool.
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_C_COMPILER_ENV_VAR
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_C_COMPILER
CMake Error: Could not find cmake module file:D:/Development/build/CMakeFiles/CMakeCCompiler.cmake
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_CXX_COMPILER_ENV_VAR
CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
Missing variable is:
CMAKE_CXX_COMPILER
CMake Error: Could not find cmake module file:D:/Development/build/CMakeFiles/CMakeCXXCompiler.cmake
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
-- Configuring incomplete, errors occurred!
when gcc / mingw is in the path then everything works fine. So could you provide more information as to your PATH variable or CMAKE version?
You need to set the generator at the Generate stage so it is written into the cache.
You only need to run this command once for the first configuration
cmake .. -DCMAKE_GENERATOR:INTERNAL=Ninja
This will configure Ninja as the default generator.
Later you can simply run
cmake ..
And it would use the Ninja generator as default
You can read more about it under Running CMake from the command line
When running cmake from the command line, it is possible to specify command line options to cmake that will set values in the cache. This is done with a -DVARIABLE:TYPE=VALUE syntax on the command line. This is useful for non-interactive nightly test builds.
CMake 3.19 introduces a new feature - presets. So, to select proper generator automatically, you can specify it name in CMakePresets.json.
Full description for these files available here: https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html