How to get CMake to use existing Makefile? - makefile

I have an existing project (wvdial) that has a working makefile. I'm trying to integrate it into our main build process which uses CMake. Can anyone advise on how to do this? I made an attempt below based on some of the other projects we build but the makefile is never called. All I want to do is call the makefile for wvdial and include the binary in the .deb package we build.
cmake_minimum_required(VERSION 2.6)
SET(COMPONENT_NAME roots-vendor-wvdial)
SET(DEBIAN_PACKAGE_VERSION 1.6.1)
SET(WVDIAL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
SET(WVDIAL_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET(WVDIAL_INSTALLED ${CMAKE_CURRENT_BINARY_DIR})
ADD_CUSTOM_TARGET(
wvdial ALL
DEPENDS ${WVDIAL_INSTALLED}
)
IF (${ROOTS_TARGET_ARCHITECTURE} STREQUAL "armhf")
SET(TARGET_FLAG "--host=arm-linux-gnueabihf")
ENDIF()
ADD_CUSTOM_COMMAND(
WORKING_DIRECTORY ${WVDIAL_BINARY_DIR}
OUTPUT ${WVDIAL_INSTALLED}
COMMAND env CXXFLAGS=${ROOTS_COMPILER_FLAGS} ./configure ${TARGET_FLAG} ${ROOTS_HOST_OPTION}
COMMAND make
COMMENT "Building wvdial"
VERBATIM
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/wvdial
DESTINATION usr/local/bin
COMPONENT ${COMPONENT_NAME}
PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
)
DEFINE_DEBIAN_PACKAGE(
NAME ${COMPONENT_NAME}
CONTROL_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/debian/control
CHANGELOG_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog
)

Take a look at the ExternalProject module.
This will add a dummy target to your CMake project that is responsible for building the dependency. The command is quite complex and supports a lot of stuff that you probably won't need in your case. Kitware (the company behind CMake) did a nice post called Building External Projects with CMake 2.8 a while back explaining the basic use of that command.

Related

How to add in a CMake project a global file extension (*.pde) to GCC which is treated like C++ code

I have a very simple CMake script. Unfortunately, the project uses a *.pde file which is plain C++ or C code.
CMake is working with any file ending, but I get a compiler error, because GCC does not know how to handle it. How can I add a global file extension to GCC, so that the *.pde file is compiled as a usual *.cpp file?
The -x c++ foo.pde command is nice if I want to use the console, but for CMake it is (I think) not applicable.
cmake_minimum_required(VERSION 2.8)
project(RPiCopter)
SET( RPiCopter
absdevice
containers
device
exceptions
navigation
frame
vehicle
receiver
scheduler
tinycopter.pde
)
message( STATUS "Include ArduPilot library directories" )
foreach( DIR ${AP_List} ${AP_List_Linux} ${AP_Headers} )
include_directories( "../libraries/${DIR}" )
endforeach()
include_directories( zserge-jsmn )
# ***************************************
# Build the firmware
# ***************************************
add_subdirectory ( zserge-jsmn )
#set(CMAKE_CXX_FLAGS "-x c++ *.pde")
ADD_EXECUTABLE ( RPiCopter ${RPiCopter} )
target_link_libraries ( RPiCopter -Wl,--start-group ${AP_List} ${AP_List_Linux} jsmn -Wl,--end-group )
You should be able to use set_source_files_properties along with the LANGUAGE property to mark the file(s) as C++ sources:
set_source_files_properties(${TheFiles} PROPERTIES LANGUAGE CXX)
As #steveire pointed out in his own answer, this bug will require something like the following workaround:
set_source_files_properties(${TheFiles} PROPERTIES LANGUAGE CXX)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_definitions("-x c++")
endif()
Normally you should be able to just extend CMAKE_CXX_SOURCE_FILE_EXTENSIONS. This would help, if you have a lot of files with unknown file extensions.
But this variable is not cached - as e.g. CMAKE_CXX_FLAGS is - so the following code in CMakeCXXCompiler.cmake.in will always overwrite/hide whatever you will set:
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP)
I consider this non-caching being a bug in CMake, but until this is going to be changed I searched for a workaround considering the following:
You normally don't want to change files in your CMake's installation
It won't have any effect if you change CMAKE_CXX_SOURCE_FILE_EXTENSIONS after project()/enable_language() (as discussed here).
I have successfully tested the following using one of the "hooks"/configuration variables inside CMakeCXXCompiler.cmake.in:
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_SYSROOT_FLAG_CODE "list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS pde)")
project(RPiCopter CXX)
message("CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")
add_executable(RPiCopter tinycopter.pde)
I decided to use this approach. I just remove the file ending by cmake in the temporary build directory.
So GCC is not confused anymore because of the strange Arduino *.pde file extension.
# Exchange the file ending of the Arduino project file
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tinycopter.pde ${CMAKE_CURRENT_BINARY_DIR}/tinycopter.cpp)
CMake doesn't do this for you:
http://public.kitware.com/Bug/view.php?id=14516

Using local makefile for CLion instead of CMake

Is there a way to configure CLion to use a local makefile to compile code, rather than CMake? I can't seem to find the way to do it from the build options.
Update: If you are using CLion 2020.2, then it already supports Makefiles. If you are using an older version, read on.
Even though currently only CMake is supported, you can instruct CMake to call make with your custom Makefile. Edit your CMakeLists.txt adding one of these two commands:
add_custom_target
add_custom_command
When you tell CLion to run your program, it will try to find an executable with the same name of the target in the directory pointed by PROJECT_BINARY_DIR. So as long as your make generates the file where CLion expects, there will be no problem.
Here is a working example:
Tell CLion to pass its $(PROJECT_BINARY_DIR) to make
This is the sample CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.4)
project(mytest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_custom_target(mytest COMMAND make -C ${mytest_SOURCE_DIR}
CLION_EXE_DIR=${PROJECT_BINARY_DIR})
Tell make to generate the executable in CLion's directory
This is the sample Makefile:
all:
echo Compiling $(CLION_EXE_DIR)/$# ...
g++ mytest.cpp -o $(CLION_EXE_DIR)/mytest
That is all, you may also want to change your program's working directory so it executes as it is when you run make from inside your directory. For this edit: Run -> Edit Configurations ... -> mytest -> Working directory
While this is one of the most voted feature requests, there is one plugin available, by Victor Kropp, that adds support to makefiles:
Makefile support plugin for IntelliJ IDEA
Install
You can install directly from the official repository:
Settings > Plugins > search for makefile > Search in repositories > Install > Restart
Use
There are at least three different ways to run:
Right click on a makefile and select Run
Have the makefile open in the editor, put the cursor over one target (anywhere on the line), hit alt + enter, then select make target
Hit ctrl/cmd + shift + F10 on a target (although this one didn't work for me on a mac).
It opens a pane named Run target with the output.
Newest version has better support literally for any generated Makefiles, through the compiledb
Three steps:
install compiledb
pip install compiledb
run a dry make
compiledb -n make
(do the autogen, configure if needed)
there will be a compile_commands.json file generated
open the project and you will see CLion will load info from the json file.
If you your CLion still try to find CMakeLists.txt and cannot read compile_commands.json, try to remove the entire folder, re-download the source files, and redo step 1,2,3
Orignal post: Working with Makefiles in CLion using Compilation DB
To totally avoid using CMAKE, you can simply:
Build your project as you normally with Make through the terminal.
Change your CLion configurations, go to (in top bar) :
Run -> Edit Configurations -> yourProjectFolder
Change the Executable to the one generated with Make
Change the Working directory to the folder holding your executable (if needed)
Remove the Build task in the Before launch:Activate tool window box
And you're all set! You can now use the debug button after your manual build.
Currently, only CMake is supported by CLion. Others build systems will be added in the future, but currently, you can only use CMake.
An importer tool has been implemented to help you to use CMake.
Edit:
Source : http://blog.jetbrains.com/clion/2014/09/clion-answers-frequently-asked-questions/
I am not very familiar with CMake and could not use Mondkin's solution directly.
Here is what I came up with in my CMakeLists.txt using the latest version of CLion (1.2.4) and MinGW on Windows (I guess you will just need to replace all:
g++ mytest.cpp -o bin/mytest by make if you are not using the same setup):
cmake_minimum_required(VERSION 3.3)
project(mytest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_custom_target(mytest ALL COMMAND mingw32-make WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
And the custom Makefile is like this (it is located at the root of my project and generates the executable in a bin directory):
all:
g++ mytest.cpp -o bin/mytest
I am able to build the executable and errors in the log window are clickable.
Hints in the IDE are quite limited through, which is a big limitation compared to pure CMake projects...

Add libraries Qt and LuaJIT / Lua51 with CMake

I am trying to use CMake with Qt and LuaJIT that will run on Visual Studio 2012. I managed somehow to run Qt, but i don't know how to add LuaJIT library to project. I am using source of LuaJIT cloned from http://luajit.org/git/luajit-2.0.git, which is build by running .bat file.
I dont care that LuaJIT will be build by CMake, i just need to link library and add headers to project.
I removed lib folder from my project... Is not worth troubles to have dependancies coupled with project whitout cmake file :D
My project hierarchy is:
+lib
-luajit-2.0
+src
-my sources
+ui
-ui files
-CMakeLists.txt
And CMakeLists.txt file looks like this:
cmake_minimum_required(VERSION 2.8.12)
set(PROJECT "Grapedit")
project(${PROJECT})
# Qt Stuff
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt5Widgets REQUIRED)
set(SOURCE_FILES
src/main.cpp
src/mainwindow.h
src/mainwindow.cpp
)
set(UI_FILES
ui/mainwindow.ui
)
source_group("UI Files" FILES ${UI_FILES})
qt5_wrap_ui(UI_HEADERS ${UI_FILES})
source_group("Generated UI Headers" FILES ${UI_HEADERS})
add_executable(${PROJECT} ${SOURCE_FILES} ${UI_HEADERS} ${UI_FILES})
qt5_use_modules(${PROJECT} Widgets)
My solution
So it is finally working and I made couple of newbie mistakes... :)
I will write them down for others:
didn't know what is find module... This will search environment and set up locations of libraries or flag that it didn't find them. Since LuaJIT is compatible with Lua51 you can use find_package(Lua51).
Your libraries must be some way visible to CMake. On Windows simplest way is to add them to PATH variable. Or you can add path of your libraries to CMake variable CMAKE_PREFIX_PATH. Open find module, for example FindLua51.cmake and you will see how must be your library organized. On windows I've must installed LuaJIT manualy - created LuaJIT folder and I've put *.h files to include subfolder, *.dll to bin subfolder and *.lib to lib subfolder. Then add bin folder to PATH and set LUA_DIR to LuaJIT folder.
use include_directories on include folder
then you must link libraries target_link_libraries, but after add_executable!
My CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8.12)
# Declare project variables...
set (PROJECT "Grapedit")
set (
SOURCE_FILES
src/main.cpp
src/mainwindow.h
src/mainwindow.cpp
)
set(UI_FILES
ui/mainwindow.ui
)
# Set project name
project(${PROJECT})
# Include Lua directories
include_directories(${LUA_INCLUDE_DIR})
# Qt Stuff
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
# Find packages...
# Will find also LuaJIT, but must be named same as Lua51 and installed into directories
find_package(Lua51)
# Find Qt modules, every module separately
find_package(Qt5Widgets REQUIRED)
# Create nice groups in IDEs
source_group("UI Files" FILES ${UI_FILES})
source_group("Generated UI Headers" FILES ${UI_HEADERS})
# Use Qt UI files
qt5_wrap_ui(UI_HEADERS ${UI_FILES})
# Create executable
add_executable (
${PROJECT}
${SOURCE_FILES}
${UI_HEADERS}
${UI_FILES}
)
# Link libraries...
# Must be after executable is created!
# Link Qt modules
qt5_use_modules (
${PROJECT}
Widgets
)
# Link Lua
target_link_libraries(${PROJECT} ${LUA_LIBRARIES})
# Will not show new windows prompt when running program
if (MSVC)
set_target_properties(${PROJECT} PROPERTIES
WIN32_EXECUTABLE YES
LINK_FLAGS "/ENTRY:mainCRTStartup"
)
endif ()
You are missing the actual linkage which you can amend with the following statement:
target_link_libraries(${PROJECT} luajit-5.1)
For sure, it would be even better if this lua jit could have a cmake find module, or config/version file depending on its exact build system.
You could grab the find module from here:
https://github.com/brimworks/lua-zlib/blob/master/cmake/Modules/FindLuaJIT.cmake
Then you could link against it as follows:
target_link_libraries(${PROJECT} ${LUA_LIBRARIES})
You can see that it would become more dynamic this way rather than hard-coding the exact name. The details for figuring out that would be left with the find module.
Note that you would probably need to use the corresponding variables for the header inclusion then as follows:
include_directories(${LUA_INCLUDE_DIR})
This will take care of automatically finding the include directory, respectively, without you hard-coding it.
You would also need to add the following line into your CMakeLists.txt:
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
and you need to place the downloaded find module into a "cmake" subfolder.
Please refer to the following page for further details about this topic in general:
CMake:How To Find Libraries

CMAKE: Build library and link against it

I'm trying to use cmake (on Linux with GNU make and g++) to build a project with two sub-directories: MyLib and MyApp. MyLib contains source for a static library; MyApp needs to link against that library. I'm trying to build on Linux with generated makefiles using the following CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (MyProj)
include_directories (MyLib)
file(GLOB MyLibSrc MyLib/*.cpp)
add_library(MyLibrary STATIC ${MyLibSrc})
file(GLOB MyAppSrc MyApp/*.cpp)
add_executable(MyApplication ${MyAppSrc})
target_link_libraries(MyApplication MyLibrary)
This 'almost' works. It fails at link time because while it generates libMyLibrary.a - it is in the root. When I add:
link_directories(${MyProj_BINARY_DIR})
it makes no difference.
I've got a few (inter-linked) questions:
What's the best way to coerce cmake into building my library and executable into a 'staging directory' — say MyStage — to keep targets separate from source?
How do I convince cmake to link the application against the library?
If I wanted to build a debug and a release version, what's the best way to extend my cmake scripts to do this — making sure that the debug application links against the debug library and the release application against the release library?
I'm a relative newcomer to cmake. I've read what I can find on the web, but find myself struggling to get my library to link with my executable. This sort of a configuration, to my mind, should be quite common. An example from which to crib would be very helpful, but I've not found one.
Well, it is better to read this example and do exactly as suggested.
cmake_minimum_required (VERSION 2.6)
project (MyProj CXX)
add_subdirectory(MyLib)
add_subdirectory(MyApp)
Then for each subdirectory specified, CMakeLists.txt files are created
MyLib\CMakeLists.txt
file(GLOB SRC_FILES *.cpp)
add_library(MyLib ${SRC_FILES})
MyApp\CMakeLists.txt
file(GLOB SRC_FILES *.cpp)
add_executable(MyApp ${SRC_FILES})
target_link_libraries(MyApp MyLib)
Use "out of the source build". Make a directory used only for build and while in it, call
cmake <path to the sources, it may be relative>
Either use
link_directories(${MyProj_BINARY_DIR}/MyLib)
or make CMakeLists.txt in each subdirectory - that would be better for project larger than very small.
This is a bit tricky, check out CMAKE_BUILD_TYPE in the docs (you can set it and/or "if" by it). You can also set it from command line:
cmake -DCMAKE_BUILD_TYPE=Debug
I've discovered the 'optimal' solution to (1)... so, thought I should post it here:
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY MyStage)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY MyStage)
The thing that confused me previously is that static libraries are not considered a LIBRARY by Cmake - they're considered to be ARCHIVEs.
Do not add libraries and executables in the root Cmakelists.txt. Add these libraries and executables in Cmakelists.txt of subdirectories.

install(TARGETS ...) and add_subdirectory

Is it possible to use install(TARGETS ...) with targets that are defined in directories added with add_subdirectory?
My use case is, that I want to build e.gg an rpm for gtest. the gtest project happens to have a CMakeLists.txt without any install statements. I want to build the package without adding those statements to the CMakeLists.txt of gtest.
I have this resulting directory structure:
+ gtest-1.5.0/...
+ CMakeLists.txt
The CMakeLists of gtest-1.5.0 defines libraries like this:
cxx_static_library(gtest "${cxx_strict}" src/gtest-all.cc)
cxx_static_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
target_link_libraries(gtest_main gtest)
now i want to add something like this to my CMakeLists.txt:
add_subdirectory(gtest-1.5.0)
install(TARGETS gtest gtest_main ARCHIVE DESTINATION lib)
but cmake correctly states:
CMake Error at CMakeLists.txt:10 (install):
install TARGETS given target "gtest" which does not exist in this
directory.
Is there a way to do this without patching gtest-1.5.0?
You could try using file install rather than install targets. The downside is that you will have to handle shared and static builds.
install(FILES gtest-1.5.0/gtest_main.so DESTINATION lib)

Resources