this might be a duplicate, but I've already spent a couple of hours searching for an answer... without solution. First of all I know this problem might not exist if I'd use a Linux, but I am on Windows.
I am pretty new to c++ but already got some experience with java and gradle. I try to use cmake just like I am used to use gradle. I already read the cmake wiki, but I either do not find the correct pages or I just don't understand it. Here is my directory structure:
MyProject
-bin
-include
--header1.h
--header2.h
--header3.h
--header4.h
--header5.h
--header6.h
-src
--CMakeLists.txt
--MyProjectConfig.h.in
--impl1.cpp
--impl2.cpp
--impl3.cpp
--impl4.cpp
--impl5.cpp
--impl6.cpp
-main.cpp
-CMakeLists.txt
My CMakeLists.txt in my project folder looks like:
cmake_minimum_required (VERSION 3.14)
project (MyProject)
add_subdirectory(src)
file(GLOB_RECURSE sources src/*.cpp include/*.h)
# The version number.
set (Tutorial_VERSION_MAJOR 0)
set (Tutorial_VERSION_MINOR 1)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/MyProjectConfig.h.in"
"${PROJECT_BINARY_DIR}/MyProjectConfig.h"
)
# add the binary tree to the search path for include files
# so that we will find MyProjectConfig.h
include_directories("${PROJECT_BINARY_DIR}")
install (FILES "${PROJECT_BINARY_DIR}/MyProjectConfig.h"
DESTINATION include)
add_executable(MyProject main.cxx ${sources})
# add the install targets
install (TARGETS MyProject DESTINATION bin)
My CMakeLists.txt in the src folder looks like:
cmake_minimum_required (VERSION 3.14)
include_directories(${MyProject_SOURCE_DIR}/MyProject/include)
I use the command in the bin bin directory: cmake -G "MinGW Makefiles" -S ../src
I got 2 questions now:
(How do I tell cmake to always use MinGW? ( I don't want to use -G always)) solved
(The compiled file build\CMakeFiles\3.14.0-rc2\CompilerIdCXX\a.exe does not have the expected behavior. It should print "Hello world!" and "My Class", while "My Class" is printed from the attribute of a class created from impl1.cpp, however it does nothing.) needs clarification:
How do I build a windows .exe-file to ruin on the console?
Edit:
I have learned that I have to call cmake --build . in my bin directory after creating the cmake files. However I just don't get an exe-file. With flag -v I get this output:
"C:\Program Files\CMake\bin\cmake.exe" -SD:\git\MyProject\src -BD:\git\MyProject\bin --check-build-system CMakeFiles\Makefile.cmake 0
"C:\Program Files\CMake\bin\cmake.exe" -E cmake_progress_start D:\git\MyProject\bin\CMakeFiles D:\git\MyProject\bin\CMakeFiles\progress.marks
C:/MinGW/bin/mingw32-make.exe -f CMakeFiles\Makefile2 all
mingw32-make.exe[1]: Entering directory 'D:/git/MyProject/bin'
mingw32-make.exe[1]: Nothing to be done for 'all'.
mingw32-make.exe[1]: Leaving directory 'D:/git/MyProject/bin'
"C:\Program Files\CMake\bin\cmake.exe" -E cmake_progress_start D:\git\MyProject\bin\CMakeFiles 0 ```
Using the -G option is the standard way of doing it. It prevents you from having to put system-specific settings into your CMake config (like the hardcoded paths to MingW) and lets you use other compilers without having to change build scripts.
The a.exe you started is not your build output. It should be called MyProjectExec.exe. Also, you need to specify all source files in your call to add_executable. add_subdirectory does not automatically add any source files (to what build output should it add them?), it just executes the CMakeLists.txt.
Related
I have built a CERN's ROOT script which based on c++ and i write(edit an example) CMakeList.txt. I am so rokie at CMake btw.
When I command to compile with cmake .., it done correctly -i think- with no errors. But .exe file what i want to produce does not appear.
My directory orders
/Project
../TLV.cpp
../CMakeLists.txt
../build
There is my CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(TLV)
#Set CXX flags to compile with c++11 and error warnings quiet
set(CMAKE_CXX_FLAGS "-O3 -fPIC -Wall -Wextra -std=c++11 -m64")
#Load root
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} $ENV{ROOTSYS}/etc/cmake)
#print conf
message(STATUS "Environmental CMAKE_MODULE_PATH is $ENV{ROOTSYS}")
#find the package with extra libraries needed
find_package(ROOT MODULE REQUIRED Cling TreePlayer Tree Rint Postscript Matrix RIO Core Foam RooStats RooFit RooFitCore Gpad Graf3d Graf Hist Net TMVA XMLIO MLP)
#include ROOT stuff
include(${ROOT_USE_FILE})
message(STATUS "Environmental ROOTSYS is $ENV{ROOTSYS}")
message(STATUS "found root at: ${ROOT_USE_FILE}")
message(STATUS "ROOT_LIBRARIES=${ROOT_LIBRARIES}")
#produce executables in bin path
set(EXECUTABLE_OUTPUT_PATH bin)
#include_directories(./../Framework Headers)
#${FROM_OTHERS_INCLUDE})
#defines all .cpp support class with corresponding Headers
#file(GLOB SRCS Sources/*.cpp Headers/*.hpp )
#${FROM_OTHERS_HEADER} ${FROM_OTHERS_SOURCE})
#add executable
add_executable( TLV TLV.cpp )
#link the executable with the root libraries
target_link_libraries(TLV ${ROOT_LIBRARIES})
I do not get it where I am wrong.
A typical scenario on a project which uses cmake is
cd src_directory # for example cd ~/src/root-6.08.06/
mkdir build # skip this if dir build already exists
cd build
cmake .. # the .. just says your source home dir is up a dir
cmake-gui .. # (optional) skip this unless you need a GUI alternative to cmake where you can edit settings
cmake --build # if you have a quad core CPU could use: make -j8 ... or make -j $(nproc) # on linux
then launch binary and confirm its OK then if desired install it using
sudo make install
Currently, I have a CMakeLists.txt file in the main folder that has the following code in it:
cmake_minimum_required(VERSION 3.5)
SET(CMAKE_GENERATOR "MinGW Makefiles" CACHE INTERNAL "" FORCE)
SET(CMAKE_TOOLCHAIN_FILE ${PROJECT_SOURCE_DIR}/ToolChain.cmake)
project(Blinky)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
...
When I run it, it outputs first for Visual Studio to the source directory. When I run it the second time, it outputs the corresponding minGW makefiles but still to the source directory and not the bin folder. Is there any way to configure it to build for MinGW Makefile directly and to the correct output folder?
I'm running the script on a command line prompt with the following line of code from the source directory folder:
cmake CMakeLists.txt
Run cmake from the directory you want to use as your build directory, not from within your source tree. That will give you an out of source build (see here for some details about this).
You have to set the CMake generator and toolchain file you want to use on the command line, you don't do it within the CMakeLists.txt file. Also, you do not include the name of the CMakeLists.txt file on your cmake command line, but rather the directory it is in. For example:
cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=/path/to/source/dir/ToolChain.cmake /path/to/source/dir
Lastly, for specifying where your executables should go, make sure you use the correct CMake variables and make sure you put them in a place within your build directory, not your source tree:
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
You shouldn't run cmake from your source directory. It's definitely a bad practice
Indeed, that mixes your makefiles (or your Visual Studio files) with your source files and that can even corrupt your source directory (depending on what you've specified in your CMakeLists.txt).
What you have to do
First you need to create a separate build directory where you'll launch cmake.
Then, if you want to generate with MinGW makefiles, launch in the build directory the following command line:
cmake path_to_source_directory -G "MinGW Makefiles"
Further comments about your CMakeList.txt
As the command line above specifies the generator (option -G "…"), SET(CMAKE_GENERATOR "MinGW Makefiles" CACHE INTERNAL "" FORCE) is useless. Take a look on this SO post and its answers. It explains why you generate Visual Studio files on your first launch of CMake and MinGW makefiles on your second launch.
Then, as #Craig Scott said, you should replace SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) by SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin). Otherwise your executables will be put in your source directory.
I have the following CMake structure:
CMakelists.txt
toolchain.cmake
folder1
----CMakelists.txt
folder2
----CMakelists.txt
etc..
My first-level CMakelists.txt file includes the other subdirectories. Now I want to build my code for a different target.
The manual way is:
1.
mkdir hostBuild
cd hostBuild
cmake ..
make
2.
mkdir crossBuild
cd crossBuild
cmake .. --DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
make
Is it possible that this process can run automatically?
For example, I just have to run cmake . at my first level.
Is something like this is possible?
No. The recommendation would be to just put your manual steps into a shell script.
CMake can only handle one compiler/make environment at a time (if you switch the compiler you need a different binary output directory).
Especially a toolchain file that does contain SET(CMAKE_SYSTEM_NAME ...) does change the whole outcome of the configuration/generation process.
For details on what CMake does see: CMake: In which Order are Files parsed (Cache, Toolchain, …)?
And you could make use of some CMake command line options in your shell script:
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ..
fi
cmake --build hostBuild
...
I am quite new to linux and c++.. i have couple of cpp file and cmakefile.txt in my source folder. how can i compile in ubuntu with g++ (multiple cpp files)
I have this CMakeList.txt
project(Test)
# link_libraries($Nest_LIBRARIES})
subdirs(
#
engine
options
ui
# jni
)
#build the Test library
add_library(test STATIC
options/command_line_options.cpp
options/options_map.cpp
utility/timer.cpp
utility/generics/any.cpp
util/hdfs.cpp
logger/logger.cpp
logger/backtrace.cpp
)
requires_core_deps(test)
INSTALL(TARGETS
test ARCHIVE DESTINATION lib)
This is CMake (tutorial). Some say it simplifies build process.
Create makefiles from CMake metafiles: cmake . -G "Unix
Makefiles"
Run make: make -j2 install
I'd basically like to achieve the same as http://blog.alexrp.com/2013/09/26/clangs-static-analyzer-and-automake, but with CMake.
analyze_srcs = foo.c
analyze_plists = $(analyze_srcs:%.c=%.plist)
CLEANFILES = $(analyze_plists)
$(analyze_plists): %.plist: %.c
#echo " CCSA " $#
#$(COMPILE) --analyze $< -o $#
analyze: $(analyze_plists)
.PHONY: analyze
So you can run
make analyze
make clean
I guess I need to use add_custom_command/add_custom_target and somehow change the "object file" extension just for that target.
Afterwards get a list of the generated files to perhaps pass them to a script for combining them into 1 output file.
Can anyone point me in the right direction?
You can use scan-build when running cmake.
scan-build cmake /path/to/source
scan-build make
scan-build sets the CC and CXX environment variables which are picked up by cmake.
I found a way:
function(add_clang_static_analysis target)
get_target_property(SRCs ${target} SOURCES)
add_library(${target}_analyze OBJECT EXCLUDE_FROM_ALL ${SRCs})
set_target_properties(${target}_analyze PROPERTIES
COMPILE_OPTIONS "--analyze"
EXCLUDE_FROM_DEFAULT_BUILD true)
endfunction()
Combining clang's plist files (which get extension .o this way) into a report is still open ($<TARGET_OBJECTS:objlibtarget>?).
The following solution has the drawback of compiling and analyzing the entire project, not the specific targets.
set(on_side_build_path ${CMAKE_BINARY_DIR}/clang_static_analysis)
set(scan_build_path scan-build)
set(reports_path ${CMAKE_BINARY_DIR}/clang_static_analysis_reports)
# Creates clean directory where the analysis will be built.
add_custom_target(clang_static_analysis_prepare
COMMAND ${CMAKE_COMMAND} -E rm -rf ${on_side_build_path}
COMMAND ${CMAKE_COMMAND} -E make_directory ${on_side_build_path}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
# Runs the analysis from the path created specifically for that task. Use 'my own' project source directory as the source directory.
add_custom_target(clang_static_analysis
# scan-build wants Debug build, for better analysis.
COMMAND ${scan_build_path} ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} -DCMAKE_BUILD_TYPE=Debug
COMMAND ${scan_build_path}
-v -v -o ${reports_path}
${CMAKE_COMMAND} --build .
WORKING_DIRECTORY ${on_side_build_path}
)
# Run the *_prepare target always before the analysis
add_dependencies(clang_static_analysis clang_static_analysis_prepare)
Invoke it with:
cmake --build . --target clang_static_analysis
Bonus #1: Allowing custom toolchains to work
scan-build injects the CC and CXX environment variables to specify the replaced compilers, which are ccc-analyzer and c++-analyzer. When defining CMAKE_C_COMPILER and CMAKE_CXX_COMPILER the CC and CXX variables will be ignored. What you need to do to support scan-build is to point CMAKE_C*_COMPILER variables to use the one from environment, if defined. So having that in your toolchain file:
set(CMAKE_C_COMPILER some/path/to/c_compiler)
set(CMAKE_Cxx_COMPILER some/path/to/cxx_compiler)
Replace it with:
if(DEFINED ENV{CC})
set(CMAKE_C_COMPILER $ENV{CC})
else()
set(CMAKE_C_COMPILER some/path/to/c_compiler)
endif()
if(DEFINED ENV{CXX})
set(CMAKE_CXX_COMPILER $ENV{CXX})
else()
set(CMAKE_CXX_COMPILER some/path/to/cxx_compiler)
endif()
Bonus #2: Using scan-build from the LLVM toolchain
If your custom toolchain is LLVM, then most probably you want to use the scan-build command from the toolchain. To enable it, simply define the path to toolchain path using cmake's cache variables:
set(LLVM_TOOLCHAIN_PATH "some/path/here" CACHE PATH "Path to the LLVM toolchain")
or from the command line:
cmake -DLLVM_TOOLCHAIN_PATH=some/path/here ...
and then reuse the path from the custom target:
set(scan_build_path ${LLVM_TOOLCHAIN_PATH}/bin/scan-build)
Bonus #3: Adding test command
Note: enable_testing shall be called before add_test. enable_testing() must be called from the project's top level CMakeLists.txt for ctest to resolve paths to tests.
add_test(
NAME clang_static_analysis
COMMAND ${CMAKE_COMMAND} --build . --target clang_static_analysis
)
Run it like that:
# Fire configure and generate stages
cmake ../source/dir
ctest -R clang_static_analysis --verbose