cmake move build files in a subdirectory after configuring and building [duplicate] - cmake

I'm using cmake to compile a C++ project, and I want cmake to generate all the output files(metafiles like Makefile used to create binaries) in the build folder. I've checked all the answers in How do I make cmake output into a 'bin' dir?, none of them worked for me(suprisingly!). Files are generated in the root folder instead of in the build folder, what's wrong here? I guess I must have missed something.
Code Structure
➜ cmake-test tree .
.
├── CMakeLists.txt
└── hello.cpp
0 directories, 2 files
CMakeLists.txt
# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.11)
# Project's name
project(hello)
# Set the output folder where your program will be created
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# The following folder will be included
include_directories("${PROJECT_SOURCE_DIR}")
add_executable(hello ${PROJECT_SOURCE_DIR}/hello.cpp)
Build Commands and Outputs
➜ cmake-test cmake .
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/searene/CLionProjects/cmake-test
➜ cmake-test ls
bin CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt hello.cpp Makefile
cmake version
➜ cmake-test cmake --version
cmake version 3.11.4
CMake suite maintained and supported by Kitware (kitware.com/cmake).
OS
Linux

The usual way to do this, rather than changing variables to set the path, is simply to create the output directory, change to it, and run cmake from there. So instead of cmake . you usually have cmake .. or similar.
I understand the initial impulse to say "But I expect my build system to write output somewhere else." But CMake is not usually used in the way you were initially expecting, and other people who run your CMake build won't expect what you were expecting, so it's probably best to just use the built-in, default behavior, which is to put the output wherever cmake was run.
Put another way: You are fighting against the tool. Don't do that.

Disclaimer: I recommend going with #john-zwinck's answer.
By default, cmake uses the current working directory as build directory and whatever path you provide as source directory. So the normal way of achieving your goal is
create the build directory (mkdir build)
go there (cd build)
call cmake with the source dir as argument (cmake path/to/source)
BUT there is another way, as far as I know not documented in the cmake docs and only kept for compatibility reasons or internal usage, that some people are using. The -B and -H flags
cmake -Hpath/to/source -Bpath/to/build
or even from the source dir
cmake . -Bbuild
Important: no space after -B.

CMake 3.19.1 (not sure how about older ones) has following option (from docs):
cmake [<options>] -S <path-to-source> -B <path-to-build>
Uses as the build tree and as the
source tree. The specified paths may be absolute or relative to the
current working directory. The source tree must contain a
CMakeLists.txt file. The build tree will be created automatically if
it does not already exist. For example:
cmake -S src -B build

Related

cmake cannot find an existing directory on mingw64 (msys2)

I am trying to compile a project under MSYS2 and CLANG64 environment.
I have previously compiled dependencies in /usr/local.
$ ls /usr/local/include
boost compat-5.3.c cryptopp lauxlib.h libmongoc-1.0 lua.hpp luajit.h mongocxx yaml-cpp
bsoncxx compat-5.3.h gtest libbson-1.0 lua.h luaconf.h lualib.h tsl
$ ls /usr/local/lib
cmake libboost_filesystem-mt-s-x64.a libbson-static-1.0.a libmongoc-1.0.dll.a
libboost_atomic-mt-s-x64.a libboost_program_options-mt-s-x64.a libbsoncxx-static.a libmongoc-static-1.0.a
libboost_atomic-mt-x64.a libboost_regex-mt-s-x64.a libcryptopp.a libmongocxx-static.a
libboost_chrono-mt-s-x64.a libboost_system-mt-s-x64.a libgtest.a libyaml-cpp.a
libboost_container-mt-s-x64.a libboost_thread-mt-s-x64.a libgtest_main.a pkgconfig
libboost_context-mt-s-x64.a libbson-1.0.dll.a liblua-compat.a
But when I create the project, I explicitly set the location of binaries with interface libraries as I don't want to rely on the find mechanism that has hurt me badly in the past - linking to unintended, old system libraries.
project(test)
cmake_minimum_required( VERSION 3.0 )
add_library( cryptopp STATIC IMPORTED GLOBAL )
set_target_properties( cryptopp PROPERTIES
IMPORTED_LOCATION "/usr/local/lib/libcryptopp.a"
INTERFACE_INCLUDE_DIRECTORIES "/usr/local/include"
INTERFACE_COMPILE_DEFINITIONS "HAVE_CRYPTOPP"
)
add_executable( test test.cpp )
target_link_libraries( test cryptopp )
This works perfect under all Linux distros - Redhat, Ubuntu, etc but fails in MSYS2.
However when I run cmake, I get an error stating that /usr/local/include does not exist.
$ cmake ..
-- Building for: Ninja
-- The C compiler identification is Clang 14.0.4
-- The CXX compiler identification is Clang 14.0.4
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: G:/msys64/clang64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: G:/msys64/clang64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
CMake Error in CMakeLists.txt:
Imported target "cryptopp" includes non-existent path
"/usr/local/include"
in its INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:
* The path was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and references files it does not
provide.
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
I just cannot figure out why this is happening. Any clues?
Maybe it's a Windows path issue. Try replacing /usr/local with the output of cygpath -m /usr/local.

MinGW on Windows: cmake arguments to find wxWidgets?

Similar questions already exist but I haven't found an answer that works.
I need to build a wxWidgets project in Windows using MinGW, I would like to use the cmake command from the command line (I installed mingw, cmake and bash using chocolatey)
I would like to avoid compiling wxWidgets so I am using the pre-built binaries MinGW-w64 10.2 (Headers + Dev x64 + Release x64), I unpack them to C:\wxWidgets-3.1.5
I've tried a number of combinations of arguments for cmake but haven't found one that works on the first run, I say first run because I've found one that works on the second:
cmake .. -G "MinGW Makefiles" \
-DwxWidgets_ROOT_DIR=/c/wxWidgets-3.1.5/ \
-DwxWidgets_LIB_DIR=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/
I am not a cmake expert but I imagine that by specifying these arguments in the first run they are cached and in the second run they are used, bypassing the search.
What I would like to know is what arguments I have to give to get them to be found correctly, _CONFIGURATION, _ROOT_DIR, _LIBRARIES, _INCLUDE_DIRS don't seem to have any effect.
↓ edit ↓
CMakelists.txt:
cmake_minimum_required(VERSION 3.18)
project(Test)
set(wxWidgets_USE_LIBS)
find_package(wxWidgets REQUIRED)
if(wxWidgets_FOUND)
include(${wxWidgets_USE_FILE})
add_executable(MyTest WIN32 main.cpp)
target_link_libraries(MyTest ${wxWidgets_LIBRARIES})
else(wxWidgets_FOUND)
message("wxWidgets not found!")
endif(wxWidgets_FOUND)
command line used:
cmake .. -G "MinGW Makefiles" -DwxWidgets_ROOT_DIR=/c/wxWidgets-3.1.5/ -DwxWidgets_LIB_DIR=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/ -DwxWidgets_wxrc_EXECUTABLE=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/wxrc.exe -DCMAKE_BUILD_TYPE=Release -DwxWidgets_LIBRARIES=/c/wxWidgets-3.1.5/lib/gcc1020_x64_dll/ -DwxWidgets_INCLUDE_DIRS=/c/wxWidgets-3.1.5/include/
first run:
-- The C compiler identification is GNU 10.2.0
-- The CXX compiler identification is GNU 10.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/ProgramData/chocolatey/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/ProgramData/chocolatey/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find wxWidgets (missing: wxWidgets_LIBRARIES wxWidgets_INCLUDE_DIRS core base)
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Alex/Documents/Progetti/wx-test/build
wxWidgets not found!
second run:
-- Found wxWidgets: debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxmsw31ud_core.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxmsw31u_core.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31ud.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31u.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31ud_net.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxbase31u_net.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxpngd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxpng.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxtiffd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxtiff.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxjpegd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxjpeg.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxzlibd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxzlib.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxregexud.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxregexu.a;debug;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxexpatd.a;optimized;C:/wxWidgets-3.1.5/lib/gcc1020_x64_dll/libwxexpat.a;winmm;comctl32;uuid;oleacc;uxtheme;rpcrt4;shlwapi;version;wsock32 (found version "3.1.5") found components: core base net png tiff jpeg zlib regex expat
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Alex/Documents/Progetti/wx-test/build
if I use find_package(wxWidgets REQUIRED):
CMake Error at C:/Program Files/CMake/share/cmake-3.21/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find wxWidgets (missing: wxWidgets_LIBRARIES
wxWidgets_INCLUDE_DIRS)
Call Stack (most recent call first):
C:/Program Files/CMake/share/cmake-3.21/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
C:/Program Files/CMake/share/cmake-3.21/Modules/FindwxWidgets.cmake:1025 (find_package_handle_standard_args)
CMakeLists.txt:24 (find_package)
Thanks to Process Monitor I noticed that FindwxWidgets.cmake looks for libraries in gcc_dll/ (not gcc2010_x64_dll/), once the directory was renamed cmake -G "MinGW Makefiles" -DwxWidgets_ROOT_DIR=/c/wxWidgets-3.1.5 was enough to find the directory on the first run.

why can't wsl be called from cmake scripts?

I have bash scripts that generate c++ files and I would like to call them from an add_custom_command() in cmake. On windows, I'd like to call the bash script through wsl (windows subsytem for linux). cmake configures fine (finding wsl.exe), but on build it complains that:
'C:\Windows\System32\wsl.exe' is not recognized as an internal or external command,
Here is a simple cmake script to recreate. It succeeds in a linux environment (including wsl), but fails in the native windows environment.
cmake_minimum_required(VERSION 3.7)
project(WhyNotWSL)
set(source ${CMAKE_SOURCE_DIR}/Input/main.cpp)
set(target generated.cpp )
if (WIN32)
find_program(WSL wsl)
message("WSL is ${WSL}")
set (command ${WSL} cp ${source} ${target})
else()
set (command cp ${source} ${target})
endif()
message("command is ${command}")
add_custom_target( ${target} )
add_custom_command(
OUTPUT ${target}
COMMAND ${command}
DEPENDS ${source}
COMMENT "Generated ${target}"
)
add_custom_target(p ALL
DEPENDS ${target}
)
add_executable(hello ${target})
The following output is from cmake configure:
-- Building for: Visual Studio 16 2019
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.18363.
-- The C compiler identification is MSVC 19.27.29110.0
-- The CXX compiler identification is MSVC 19.27.29110.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/MSVC/14.27.29110/
bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/VC/Tools/MSVC/14.27.2911
0/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
**WSL is C:/Windows/System32/wsl.exe**
**command is C:/Windows/System32/wsl.exe;cp;D:/Development/CMakeWSLTest/Input/main.cpp;generated.cpp**
-- Configuring done
-- Generating done
-- Build files have been written to: D:/Development/CMakeWSLTest/BUILD
And the following is the output from cmake build
Microsoft (R) Build Engine version 16.7.0+b89cb5fde for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Checking Build System
Building Custom Rule D:/Development/CMakeWSLTest/CMakeLists.txt
Building Custom Rule D:/Development/CMakeWSLTest/CMakeLists.txt
Generated generated.cpp
'C:\Windows\System32\wsl.exe' is not recognized as an internal or external command,
operable program or batch file.
For the record, the following works from a DOS shell:
>C:\Windows\System32\wsl.exe cp ../Input/main.cpp generated.cpp
Try giving HINTS to find_program() and point to C:\Windows\Sysnative
Something like this:
if (WIN32)
find_program(WSL wsl HINTS C:/Windows/Sysnative)
message("WSL is ${WSL}")
set (command ${WSL} cp ${source} ${target})
else()
set (command cp ${source} ${target})
endif()
Rationale here: https://superuser.com/a/1528297/2201 but basicly, this could be caused by your cmake buil. find_program() finds executable with absolute path that then should be different when it actually gets called during the build, it should actually point the binary from another location due to inherited build type of parent process of your build.
Maybe..

Create Portable CMake/MingGW(G++) [duplicate]

I have a problem with this CMakeLists.txt file:
cmake_minimum_required(VERSION 2.6)
SET(CMAKE_C_COMPILER C:/MinGW/bin/gcc)
SET(CMAKE_CXX_COMPILER C:/MinGW/bin/g++)
project(cmake_test)
add_executable(a.exe test.cpp)
Calling cmake with: cmake -G "MinGW Makefiles" , it fails with the following output:
c:\Users\pietro.mele\projects\tests\buildSystem_test\cmake_test>cmake -G "MinGW Makefiles" .
-- The C compiler identification is GNU 4.6.1
-- The CXX compiler identification is GNU 4.6.1
-- Check for working C compiler: C:/MinGW/bin/gcc
CMake Error: your C compiler: "C:/MinGW/bin/gcc" was not found. Please set CMAKE_C_COMPILER to a valid compiler path or name.
CMake Error: Internal CMake error, TryCompile configure of cmake failed
-- Check for working C compiler: C:/MinGW/bin/gcc -- broken
CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake:52 (MESSAGE):
The C compiler "C:/MinGW/bin/gcc" is not able to compile a simple test
program.
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:10 (project)
CMake Error: your C compiler: "C:/MinGW/bin/gcc" was not found. Please set CMAKE_C_COMPILER to a valid compiler path or name.
CMake Error: your CXX compiler: "C:/MinGW/bin/g++" was not found. Please set CMAKE_CXX_COMPILER to a valid compiler path or name.
-- Configuring incomplete, errors occurred!
However the gcc compiler is in C:/MinGW/bin/ and it works.
Any idea?
Platform:
Windows 7
MinGW/GCC 4.6
Never try to set the compiler in the CMakeLists.txt file.
See the CMake FAQ about how to use a different compiler:
https://gitlab.kitware.com/cmake/community/wikis/FAQ#how-do-i-use-a-different-compiler
(Note that you are attempting method #3 and the FAQ says "(avoid)"...)
We recommend avoiding the "in the CMakeLists" technique because there are problems with it when a different compiler was used for a first configure, and then the CMakeLists file changes to try setting a different compiler... And because the intent of a CMakeLists file should be to work with multiple compilers, according to the preference of the developer running CMake.
The best method is to set the environment variables CC and CXX before calling CMake for the very first time in a build tree.
After CMake detects what compilers to use, it saves them in the CMakeCache.txt file so that it can still generate proper build systems even if those variables disappear from the environment...
If you ever need to change compilers, you need to start with a fresh build tree.
I had similar problem as Pietro,
I am on Window 10 and using "Git Bash".
I tried to execute >>cmake -G "MinGW Makefiles", but I got the same error as Pietro.
Then, I tried >>cmake -G "MSYS Makefiles", but realized that I need to set my environment correctly.
Make sure set a path to C:\MinGW\msys\1.0\bin and check if you have gcc.exe there. If gcc.exe is not there then you have to run C:/MinGW/bin/mingw-get.exe and install gcc from MSYS.
After that it works fine for me
Using with FILEPATH option might work:
set(CMAKE_CXX_COMPILER:FILEPATH C:/MinGW/bin/gcc.exe)
I had the same issue. And in my case the fix was pretty simple. The trick is to simply add the ".exe" to your compilers path. So, instead of :
SET(CMAKE_C_COMPILER C:/MinGW/bin/gcc)
It should be
SET(CMAKE_C_COMPILER C:/MinGW/bin/gcc.exe)
The same applies for g++.

Specify CMake generator unless explicitly passed as command argument by user

In all of the following, I'm using Windows, so WIN32 is always defined in CMake.
I have a CMakeLists.txt file which does its job fine, and I'm using a Preload.CMake file to specify a bunch of stuff, including a certain generator depending on circumstances:
if( WIN32 )
message( "Current generator: ${CMAKE_GENERATOR}" ) # For debugging purposes
if( NOT COMMAND cl OR NOT COMMAND nmake )
set( CMAKE_CXX_COMPILER "g++" )
set( CMAKE_GENERATOR "MinGW Makefiles" CACHE STRING "" FORCE )
set( CMAKE_MAKE_PROGRAM "make" )
message( "MSVC compiler could not be found, attempting with g++ and MinGW makefiles." )
endif( )
endif( )
This allows a Windows user with no Visual Studio to run cmake .. instead of a whole cmake .. -G "MinGW Makefiles".
It works pretty well, here is the output when cmake .. is run from an empty directory (no cache, no nothing):
Current generator:
MSVC compiler could not be found, attempting with g++ and MinGW makefiles.
Windows detected, forcing static libs.
-- The CXX compiler identification is GNU 8.2.0
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/SAYENS/Desktop/picross/build
The problem with this is when I want to specify a generator through the command line. Here is what happens when I run cmake .. -G "MSYS Makefiles" from a MSYS terminal (empty directory, no cache):
Current generator:
MSVC compiler could not be found, attempting with g++ and MinGW makefiles.
CMake Error: Error: generator : MSYS Makefiles
Does not match the generator used previously: MinGW Makefiles
Either remove the CMakeCache.txt file and CMakeFiles directory or choose a different binary directory.
(There is no such file as CMakeCache.txt or a CMakeFiles directory, but explicitly specifying a generator in the command line, that is different from the one specified in Preload.CMake, seems to be enough of a source of confusion to print out this message.)
I thought I'd be able to work around the issue by "catching" the value of the -G argument with CMAKE_GENERATOR, but it turns out I can't, as per the first output line Current generator:.
How can I work this out? I tried looking for a way to parse command line arguments, but found none that doesn't involve using a wrapper script, which I'd like to avoid resorting to.
Set the generator name in the environment variable CMAKE_GENERATOR. The documentation says:
Specifies the CMake default generator to use when no generator is
supplied with -G. If the provided value doesn’t name a generator known
by CMake, the internal default is used. Either way the resulting
generator selection is stored in the CMAKE_GENERATOR variable.
Some generators may be additionally configured using the environment
variables:
CMAKE_GENERATOR_PLATFORM
CMAKE_GENERATOR_TOOLSET
CMAKE_GENERATOR_INSTANCE