How to build and add a dependency library in CMake - 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)

Related

How to create CMakeLists for this make file [duplicate]

Work on Ubuntu 16
I used g++ main.cpp -lpq command for compiler my small project. Now I use Clion and wanna do same what I do with g++. But I can't add compiler flags in cmake file and get compile error.
cmake_minimum_required(VERSION 3.5.1)
project(day_g)
set(CMAKE_CXX_FLAGS "-lpq")
add_definitions(-lpq)
message("CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(day_g ${SOURCE_FILES})
Also I run only cmake file and get CMAKE_CXX_FLAGS with -lpq flag.
CMAKE_CXX_FLAGS is -lpq
-- Configuring done
-- Generating done
How properly add compiler flags to cmake file?
Flag -l is for linker, not for compiler. This flag is used for link with libraries. CMake has special command target_link_libraries for that purpose:
target_link_libraries(day_g pq)
-lq is not a compiler flag (CFLAGS) but a linker flag.
To pass a library in a CMake project you should use:
target_link_libraries(target_name libraries...)
Note that if you specify 'q' as library the project will link with libq.a or, if you are on windows q.dll.
... in your CMakeLists.txt the correct line to add is:
target_link_libraries(day_g pq)
Note also that when you add a CFLAG you should also "remember" the previous ones that may be added by libraries or by your platform, ie:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
To check the exact flags cmake is passing to compiler or linker you can always run, from the build directory, the following command:
make VERBOSE=1

Error with variables when invoking CMake from CMake

I need to invoke cmake from within cmake so that I can have binaries built before project files are generated. I have the following CmakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(StarEngine)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
#copy the other cmake file into where we'd like to invoke cmake
configure_file(deps-CMakeLists.txt deps/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
#eventually binaries will be built, for now this doesn't accomplish anything
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
And its friend, deps-CmakeLists.txt, a test script:
set(GENERATED_DIR "test")
MESSAGE( STATUS ${GENERATED_DIR} )
In the following file structure:
Project
build
Code
CmakeLists.txt
deps-CmakeLists.txt
No matter what I put in for the variable value, it is blank when displayed in MESSAGE. I imagine this is weird behavior resulting from invoking cmake from cmake. I had a bunch of other strange errors to, but I suspect if I can figure out this one that will help crack them all.
Thanks to #Florian, the problem was with variable replacement and I needed to add the COPYONLY option to configure_file

error while working with Makefile project

I am trying to debug my Makefile based project which I have imported in CLion. I created a simple CMake file as below
cmake_minimum_required(VERSION 2.8.4)
project(Project1)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ")
add_custom_target(myProject COMMAND make -j4 DEBUG=1
CLION_EXE_DIR=${PACKAGE_DIR})
CMake tool shows me error: CMake executable not specified. I tried adding add_executable(myProject ${SOURCE_FILES}) with correct source files, but still same error.
Where as on Edit Configurations page, I cannot select any Configuration. The drop down for Configuration is empty. At the bottom I get error Error: Configuration is not specified..
When I try to debug the program, I get a warning message Configuration is still incorrect. Do you want to edit it again? I click on Continue Anyway, which compiles the program as I expect and it generates the correct executable file as well. But it cannot run the executable because of the errors in the Configurations.
I assume "CMake executable" refers to the location of the executable cmake which is called to configure your project. Probably you have to search for a setting in CLion where you can define /usr/bin/cmake or whereever your cmake resides.
This solved the problem for me (Ubuntu):
sudo apt-get install cmake

cmake finds package, but does not add to include path

I am trying to compile (on FreeBSD, if that matters) a program that uses cmake. The CMakeLists.txt contains the lines
find_package(GLUT REQUIRED)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${OPENGL32_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS})
and cmake does not report any errors, but when I run make afterwards, I get
[…]
/usr/bin/c++ -fopenmp -I/path/build -o CMakeFiles/scriptbots.dir/GLView.cpp.o -c /path/GLView.cpp
[…]
In file included from /path/GLView.cpp:2:
/path/GLView.cpp:10:21: error: GL/glut.h: No such file or directory
[…]
GL/glut.h exists in /usr/local/include, which is not given as -I argument to /usr/bin/c++.
Compiling works when I explicitly add -I/usr/local/include to CMakeFiles/scriptbots.dir/flags.make. What do I need to change to make the project compile without manually changing the flags file?
As per its documentation, FindGLUT sets variable GLUT_INCLUDE_DIR, not GLUT_INCLUDE_DIRS. Change this in your CMakeList and it should work.

Using cmake with a custom file generator

I'd like to use CMake to generate obfuscated lua files for delivery. For the life of me I cannot get add_custom_command + add_custom_target to build these files for me. There's something I'm missing.
ADD_CUSTOM_TARGET(LUABIND_COMPILED_FILES ALL)
FOREACH(F ${LUA_SCRIPT_FILES})
ADD_CUSTOM_COMMAND(
OUTPUT ${LUA_COMPILED_SCRIPTS}/${F}
COMMAND ${LUAC} -o ${LUA_COMPILED_SCRIPTS}/${F}
COMMENT "Compiling ${F} to binary"
ADD_DEPENDENCIES(LUABIND_COMPILED_FILES ${LUA_COMPILED_SCRIPTS}/${F})
ENDFOREACH()
For some reason when I run cmake + make the output tells me there's nothing to be done for target LUABIND_COMPILED_FILES. Am I missing something here? Thanks in advance.
The ADD_DEPENDENCIES command can only be used to add dependencies between top-level targets. The ADD_CUSTOM_COMMAND command however generates output files, but does not add new targets.
To make a custom target depend on generated files, use the DEPENDS options of the add_custom_target command:
set (LUA_COMPILED_FILES "")
foreach(F ${LUA_SCRIPT_FILES})
add_custom_command(
OUTPUT "${LUA_COMPILED_SCRIPTS}/${F}"
COMMAND ${LUAC} -o "${LUA_COMPILED_SCRIPTS}/${F}"
COMMENT "Compiling ${F} to binary")
list (APPEND LUA_COMPILED_FILES "${LUA_COMPILED_SCRIPTS}/${F}")
endforeach()
add_custom_target(LUABIND ALL DEPENDS ${LUA_COMPILED_FILES})