CMake depend.make file empty - cmake

I start using CMake to build my c++ source files, I see a strange comportament when I build inicially:
'cmake ../' will gerate the directory structure
'make' will build all
any successive make command will build nothing, as expected
'cmake ../' will apparent do nothing
'make' WILL REBUILD all
any successive make command will build nothing, as expected
There is my CMakelists.txt:
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_COMPILER "g++")
set(CMAKE_CXX_FLAGS "-Wall -pipe")
set(var_target CommonBase)
set(var_path_source base)
project(Prj_${var_target})
file(GLOB_RECURSE var_sources ${var_path_source}/*.cpp)
add_library(${var_target} SHARED ${var_sources})
install(TARGETS ${var_target} DESTINATION ${PROJECT_SOURCE_DIR}/install)
Looking better, at first 'cmake ../' command the file 'CMakeFiles/CommonBase.dir/depend.make' is empty, and the successive make command will insert the list of file dependencies
There is something wrong with my CMakelists.txt?
Thanks

There are a couple of issues here.
The actual cause of your problem is having the line set(CMAKE_CXX_FLAGS ...) before the project command.
The project command does quite a lot of work the first time it is run, and actually clears out this variable as a side-effect. So on your first run of CMake, the compiler flags are empty, and thereafter always contain what you set them to. (It's only the second time you run CMake which causes make to recompile all, not subsequent runs of CMake).
Try wrapping your project call with messages to see the effect:
message("CMAKE_CXX_FLAGS - ${CMAKE_CXX_FLAGS}")
project(Prj_${var_target})
message("CMAKE_CXX_FLAGS - ${CMAKE_CXX_FLAGS}")
Delete your CMakeCache.txt file (in your build root), then just run cmake .. repeatedly.
To fix this, move your set(CMAKE_CXX_FLAGS ...) to after the project command.
The second issue is that it's not recommended to set CMAKE_CXX_COMPILER in a CMakeLists.txt. Have a look at the comment below "Setting default compiler in CMake", and also the link there to CMake's FAQ entry How do I use a different compiler?

Related

Why CMake add_custom_command with DEPFILE reruns every time?

I'm trying to write my cmake script as follows:
set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/static_init/generated/${target}/static_init.cpp")
set(DEP_FILE "${CMAKE_BINARY_DIR}/static_init/input/${target}.d")
write_file(${DEP_FILE} "${OUTPUT_FILE}: ")
add_custom_command(
OUTPUT ${OUTPUT_FILE}
COMMAND ${Python3_EXECUTABLE} myscript.py
DEPFILE ${DEP_FILE}
VERBATIM)
I expect, that I will populate .d file during my script first launch and later custom command will be rerun only when one of files listed after colon will change.
Instead command is running during every compilation, even with empty dependencies list. Printing my own sources during cmake run also leads me to constant command rerunning. What am I doing (or understanding) wrong?
CMake 3.18.5
Ninja
Clang
Ninja removes depfiles by default after reading them. This would cause the behavior you are seeing.
Problem was that DEPFILE option and target name inside depfile must be relative to build dir, not absolute paths.
ninja -d explain helped me to find it.

CMake add_subdirectory() for SDL_image out of tree build

I cloned the SDL_image library and wish to build it using a simple add_subdirectory(...) command. My current directory structure is as follows.
├───lib
│ ├───sdl_image
| ├─── ...
├───build
I have a CMakeLists.txt which is as follows.
cmake_minimum_required(VERSION 3.13)
project(test)
add_subdirectory(lib/sdl_image)
Upon execution (For my environment, cmake . -G "MinGW Makefiles"), I get the following error.
CMake Error at lib/sdl_image/CMakeLists.txt:18 (message):
Prevented in-tree built. Please create a build directory outside of the
SDL_image source code and call cmake from there
In an attempt to fix this, I modified my CMakeLists.txt add_subdirectory(...) command as follows. If I understand correctly, this should specify the output directory to build/sdl_image, outside of the SDL_image source code.
...
add_subdirectory(lib/sdl_image build/sdl_image)
However, I still get the same error. The line that is giving me the error under lib/sdl_image/CMakeLists.txt is as follows.
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR ...)
endif()
I don't understand why this condition is getting triggered since I've specified the source_dir and binary_dir (parameters in add_subdirectory(...)) as very different paths. I also tried add_subdirectory(lib/sdl_image ../../build/sdl_image) in case it was treated as relative to the source_dir. This is still not working.
Any help is appreciated. Thanks.
This is about building in sources (calling cmake in your sources), not a path problem where to put sdl_image.
You probably call cmake from within your source directory which is considered a bad practice (same thing when using autotools, or any other build generator).
So you should have some kind of build tree like:
MyProjectWorkspace
|
\_ sources (tree in your case)
\_ build
and invoke cake with cmake ../build from the build directory.
The reason is that when building in sources, you somehow "pollute" your sources. Very likely you will need to add some .gitignore (if using git) and take special care not to commit thing that are built.
Moreover, when generating code, the generated code will appear in the source tree leading to some confusions at some point (you edit the generated file and see it deleted later).
It is also handy: to completely clear a build, you only need to remove the content of the build directory (would be much harder within the sources)
Last but not least, this also ease the packager's job as usually, the use off source builds.

build yaml-cpp lib with -m32 (32-bit) - on linux /w gcc or llvm

subject pretty much says it all:
I downloaded yaml-cpp version 0.6.3.
I need to compile on linux x86_64, target linux x86_32 (build on 64 bit, use result on 32-bit)
I have been trying to add a new "YAML_BUILD_32BIT" option - similar to the existing YAML_BUILD_SHARED_LIBS option.
When I detect YAML_BUILD_32BIT is set: I try to add "-m32" to a bunch of cmake variables.
My problem is that this list of variables seems endless or not well defined.
"yaml_cxx_flags" are passed to the compile and link steps for the yaml-cpp library code...but not to build the google 'mock' code. Similarly, I found other variables that I can also set, so that google-mock is compiled with -m32 as well...but then the yaml-cpp mock tests do not see the flag...and so on and so on.
I think I am missing something very fundamental. I expect that there will be a single variable I need to update...maybe 2 or 3. I don't expect to keep finding more and more.
--
Adding more specifics:
To CMakeLists.txt:
added line (immediately after the similar line which creates the YAML_BUILD_SHARED_LIBS flag)
option(YAML_BUILD_32BIT "Build with '-m32'" OFF)
then a bit later (immediately after the YAML_BUILD_SHARED_LIBS if/else):
if(YAML_BUILD_32BIT)
# seem to need this one for the shared lib link of yaml-cpp lib
# CXX_FLAGS passed to both compile and link
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
# seem to need this one, to get flag passed to gmock build
set(FLAG_TESTED "${FLAG_TESTED} -m32")
# this one passed to compile and link of testcase
set(yaml_cxx_flags "${yaml_cxx_flags} -m32")
endif()
and made "FLAG_TESTED" addive, on immediately following line:
set(FLAG_TESTED "-Wextra -Wshadow -Weffc++ -pedantic -pedantic-errors ${FLAG_TESTED}")
Given the above, then configuring with:
# using cmake/3.19.3
cmake -G "Unix Makefiles" -DYAML_BUILD_SHARED_LIBS=ON -DYAML_BUILD_32BIT=ON"
... and then building with 'make VERBOSE=1', I see that 'gmock-all.cc.o' did not receive the -m32 flag. (gmock-all.cc.o is only the first such file in my log..there are others.)
If I remove other of the lines in my CMakeLists.txt which attempted to add flags - then other compile commands or other link commands don't see -m32 and will fail.
As I said: I think there is something fundamental that I have misunderstood. I suspect that it is much easier to configure a 32-bit build than I am making it.
With some help from a coworker, I ended up doing the following:
top-level CMakeLists.txt file (near line 28, immediately following definition of YAML_BUILD_SHARED_LIBS variable):
option(YAML_BUILD_32BIT "Build with '-m32'" OFF)
if(YAML_BUILD_32BIT)
add_compile_options(-m32)
add_link_options(-m32)
endif()
in .../test/CMakeLists.txt (near line 10):
if(YAML_BUILD_32BIT)
set(GTEST_EXTRA_FLAGS "-DCMAKE_CXX_FLAGS=-m32")
endif()
then add new flag to "ExternalProject_Add(..." call (near line .../test/CMakeLists.txt:22):
ExternalProject_Add(
googletest_project
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.8.0"
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/prefix"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DBUILD_GMOCK=ON
-Dgtest_force_shared_crt=ON
${GTEST_EXTRA_FLAGS} # <- this line added
)
The above has the effect of passing the extra "-m32" flag the embedded gmocktest project.
Given the above changes, the cmake command line above generates something that will build successfully (at least on RHEL-7, with gcc/5.2.0)
Hope this can help somebody else.
Henry

Compiling a CMake project against libraries in a non-standard location

I have two projects using CMake.
The first is a shared library. It compiles and installs fine. Currently, it is still necessary to build 'debug' releases of it. So presently it is installed under ~/localdebug. That folder looks like the root of a filesystem with a 'include' and 'lib' directory. The same concept as '/usr/local'.
The second is a program. It needs to compile and link against my library in ~/localdebug. The CMakeLists.txt file for it looks like this:
cmake_minimum_required(VERSION 2.6)
set(CMAKE_C_FLAGS "-std=gnu99")
#add_definitions(-pg)
find_library(SANDGROUSE_LIB NAMES sandgrouse)
add_library(http_parser http_parser.c)
add_executable(rsva11001adapter main.c rsva11001.c)
target_link_libraries(rsva11001adapter http_parser ${SANDGROUSE_LIB})
I run the following to set up the make files:
cmake --debug-output -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH="/home/ericu/localdebug" ..
Based on the CMake wiki, setting DCMAKE_PREFIX_PATH does exactly what I want.
CMAKE_PREFIX_PATH
(since CMake 2.6.0) This is used when searching for include files, binaries, or libraries using either the FIND_PACKAGE(), FIND_PATH(), FIND_PROGRAM(), or FIND_LIBRARY() commands. For each path in the CMAKE_PREFIX_PATH list, CMake will check "PATH/include" and "PATH" when FIND_PATH() is called, "PATH/bin" and "PATH" when FIND_PROGRAM() is called, and "PATH/lib" and "PATH" when FIND_LIBRARY() is called. See the documentation for FIND_PACKAGE(), FIND_LIBRARY(), FIND_PATH(), and FIND_PROGRAM() for more details.
However, when I do a 'make VERBOSE=1' this is what I get:
cd /home/ericu/rsva11001adapter/build/src && /usr/bin/gcc -std=gnu99 -g -o CMakeFiles/rsva11001adapter.dir/main.c.o -c /home/ericu/rsva11001adapter/src/main.c
/home/ericu/rsva11001adapter/src/main.c:19:31: fatal error: sandgrouse/server.h: No such file or directory
compilation terminated.
So, it does not seem that CMake is finding things in CMAKE_PREFIX_PATH. It obviously is not adding -I variables to the compiler invocations either.
An inspection of CMakeCache.txt makes it seem as though it has no idea what the variable is:
// No help, variable specified on the command line.
CMAKE_PREFIX_PATH:UNINITIALIZED=/home/ericu/localdebug
I've been working on this for over an hour. I'm nearly at the point of giving up using CMake if it is this difficult to use a non-standard library with it.
You should instruct CMake to add -I flags when compiling your library:
find_path(SANDGROUSE_INCLUDE_DIR sandgrouse/server.h)
include_directories(${SANDGROUSE_INCLUDE_DIR}
Place these lines before add_library() invocation.

How do I view the CMake command line statement that Qt Creator executes?

I'm attempting to debug a command line CMake failure. The same CMake file works in Qt Creator, with the arguments in the Qt Creator window matching what I have entered on the command line.
This makes me think Qt Creator is adding some extra arguments, which makes sense since the generator drop down has several options that specify architecture and CMake version.
Is there a way to get the CMake command that Qt Creator executed to produce the desired result, specifically the arguments passed to the CMake executable?
I found one post that talks about viewing the CMakeCache files to do some forensics, but this only proves there are differences, it doesn't quickly show me what arguments to change.
Try adding the following block to the end of your CMakeLists.txt and running CMake from Qt Creator again. The CMake output should list all variables that have been passed via the -D command line argument.
get_cmake_property(CacheVars CACHE_VARIABLES)
foreach(CacheVar ${CacheVars})
get_property(CacheVarHelpString CACHE ${CacheVar} PROPERTY HELPSTRING)
if(CacheVarHelpString STREQUAL "No help, variable specified on the command line.")
get_property(CacheVarType CACHE ${CacheVar} PROPERTY TYPE)
if(CacheVarType STREQUAL "UNINITIALIZED")
set(CacheVarType)
else()
set(CacheVarType :${CacheVarType})
endif()
set(CMakeArgs "${CMakeArgs} -D${CacheVar}${CacheVarType}=\"${${CacheVar}}\"")
endif()
endforeach()
message("CMakeArgs: ${CMakeArgs}")
For more info, see this answer.
This won't show what generator was selected (if any) via the -G arg. To find that, you need to look for CMAKE_GENERATOR:INTERNAL=... in your CMakeCache.txt
If this doesn't help you identify the overall problem, you should probably heed #arrowdodger's advice and post more details about the errors you're getting and your two build environments. For example, an error could be caused simply by running CMake from a subdirectory of the source tree.