Linking and UIC order in a CMake Qt project - c++

Talking about a Qt 5.3.2 project which is buildt using cmake.
This is a calling order problem between UIC execution and target_link_libraries... unfortunately not in that order.
Below this text you will find
1.) a (still functional) excerpt section of my CMakeLists.txt and
2.) an excerpt of the the output of the command 'cmake .'
3.) the output of a following call to 'make' without using the
generated headers like 'ui_main.h'.
If (in the source of my library libqt.a) I require 'ui_main.h' the
make process crashes not finding the header. Looking at the
non-crashing make output shows why:
[..]
Scanning dependencies of target qt
[ 29%] Building CXX object CMakeFiles/qt.dir/home/kochmn/projects/sentinel/src/qt/form_main.cpp.o
[ 35%] Building CXX object CMakeFiles/qt.dir/qt_automoc.cpp.o
Linking CXX static library libqt.a
[..]
[ 52%] Generating ui_main.h
[..]
Make would generate libqt.a before generating the required header file.
So I experimented using code like
target_link_libraries(sentinel
${Qt5Widgets_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Core_LIBRARIES})
add_library(optimization "${DIR_SRC}/optimization/linalg.cpp")
add_library(qt "${DIR_SRC}/qt/form_main.cpp")
target_link_libraries(sentinel qt optimization)
to no avail. The question: How can I motivate cmake to first run UIC generating the ui-header files and then compiling my libqt.a?
Appendix
# 2.8.11 instead of 2.8 required for automatic linking to the qtmain.lib
# library if this ever should expand to Windows.
# (http://doc.qt.io/qt-5/cmake-manual.html)
cmake_minimum_required(VERSION 2.8.11)
project(sentinel)
set( CMAKE_AUTOMOC ON )
# CMake uses uic in order to generate header files from .ui forms from designer.
set ( CMAKE AUTOUIC ON )
# Auto-generating functions write their headers into the build directory.
# Hence the build directory should be included.
set( CMAKE_INCLUDE_CURRENT_DIR ON )
#> Getting the Qt essentials. ----------------------------------------
# Widgets finds its own dependencies (QtGui and QtCore).
find_package(Qt5Widgets REQUIRED)
message ("Found Qt5Widgets Version ${Qt5Widgets_VERSION_STRING}")
# All those darling variables are explained here:
# http://doc.qt.io/qt-5/cmake-manual.html
message("Core FOUND: ${Qt5Core_FOUND}")
message("Gui FOUND: ${Qt5Gui_FOUND}")
message("Widgets FOUND: ${Qt5Widgets_FOUND}")
message("Core VERSION: ${Qt5Core_VERSION_STRING}")
message("Gui VERSION: ${Qt5Gui_VERSION_STRING}")
message("Widgets VERSION: ${Qt5Widgets_VERSION_STRING}")
message("Core INCLUDE: ${Qt5Core_INCLUDE_DIRS}")
message("Gui INCLUDE: ${Qt5Gui_INCLUDE_DIRS}")
message("Widgets INCLUDE: ${Qt5Widgets_INCLUDE_DIRS}")
message("Core LIBRARIES: ${Qt5Core_LIBRARIES}")
message("Gui LIBRARIES: ${Qt5Gui_LIBRARIES}")
message("Widgets LIBRARIES: ${Qt5Widgets_LIBRARIES}")
message("Core DEFINITIONS: ${Qt5Core_DEFINITIONS}")
message("Gui DEFINITIONS: ${Qt5Gui_DEFINITIONS}")
message("Widgets DEFINITIONS: ${Qt5Widgets_DEFINITIONS}")
message("Core COMPILE_DEFINITIONS: ${Qt5Core_COMPILE_DEFINITIONS}")
message("Gui COMPILE_DEFINITIONS: ${Qt5Gui_COMPILE_DEFINITIONS}")
message("Widgets COMPILE_DEFINITIONS: ${Qt5Widgets_COMPILE_DEFINITIONS}")
message("Core EXECUTABLE_COMPILE_FLAGS: ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
message("Gui EXECUTABLE_COMPILE_FLAGS: ${Qt5Gui_EXECUTABLE_COMPILE_FLAGS}")
message("Widgets EXECUTABLE_COMPILE_FLAGS: ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
include_directories(
${Qt5Widgets_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS})
add_definitions(${Qt5Widgets_DEFINITIONS})
#add_definitions(${Qt5Core_DEFINITIONS}) # Unnecessary. In Widgets.
#add_definitions(${Qt5Gui_DEFINITIONS}) # Unnecessary. In Widgets.
#< -------------------------------------------------------------------
set (DEBUG 1)
set (SENTINEL_NAME "Sentinel GL")
set (SENTINEL_VERSION_MAJOR "0")
set (SENTINEL_VERSION_MINOR "1")
set (SENTINEL_VERSION "${SENTINEL_VERSION_MAJOR}.${SENTINEL_VERSION_MINOR}")
## Compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
# ${Qt5Core_EXECUTABLE_COMPILE_FLAGS} ${Qt5Gui_EXECUTABLE_COMPILE_FLAGS} #<-- redundant.
if(CMAKE_COMPILER_IS_GNUCXX)
message("Using GnuCXX compiler.")
add_definitions("-O0 -std=c++0x -lSOIL -llapacke -lblas")
endif()
if (DEBUG MATCHES 1)
message("\nBuilding DEBUG build.")
add_definitions(-Wall)
set(CMAKE_BUILD_TYPE Debug)
endif()
set(DIR_BASE "${PROJECT_SOURCE_DIR}/..")
set(DIR_SRC "${PROJECT_SOURCE_DIR}/../src")
set(DIR_RES "${PROJECT_SOURCE_DIR}/../resources")
set(DIR_BUILD "${PROJECT_SOURCE_DIR}/../build")
# Generated using uic FormMain.ui > ui_FormMain.h
set(qt_H
"${DIR_BUILD}/ui_main.h" "${DIR_BUILD}/ui_dialog_setup_game.h")
# Generated using the trusty QtDesigner.
set(qt_UI
"${DIR_SRC}/ui/main.ui" "${DIR_SRC}/ui/dialog_setup_game.ui")
# My own hand-written XML describing the internal resources.
set(qt_QRC "${DIR_RES}/application.qrc")
# generate rules for building source files that moc generates
QT5_WRAP_CPP(qt_H_MOC ${qt_H})
# generate rules for building header files from the ui files
QT5_WRAP_UI(qt_UI_H ${qt_UI})
# Resource Handling. QRC: "Qt Resource Collection"
QT5_ADD_RESOURCES(qt_RCCS ${qt_QRC})
# btw.: rcc generates a C program from ./resources/application.qrc
# However, this is not needed. cmake sees to that. :-)
#< -------------------------------------------------------------------
include_directories("${DIR_SRC}/include" "${PROJECT_SOURCE_DIR}")
add_executable(sentinel "${DIR_SRC}/sentinel.cpp" ${qt_H_MOC} ${qt_UI_H} ${qt_RCCS})
# Available modules are listed here: http://doc.qt.io/qt-5/qtmodules.html
# find /usr/lib/x86_64-linux-gnu/cmake -iname "*.cmake*" | less
# Note: http://stackoverflow.com/questions/20266235/cmake-error-qglwidget-no-such-file-or-directory
qt5_use_modules(sentinel Widgets Gui Core)
add_library(optimization "${DIR_SRC}/optimization/linalg.cpp")
add_library(qt "${DIR_SRC}/qt/form_main.cpp")
target_link_libraries(sentinel
${Qt5Widgets_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Core_LIBRARIES}
qt optimization
)
kochmn#Ulyss:~/projects/sentinel/build$ cmake .
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- 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
-- 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
Found Qt5Widgets Version 5.3.2
Core FOUND: 1
Gui FOUND: 1
Widgets FOUND: 1
Core VERSION: 5.3.2
Gui VERSION: 5.3.2
Widgets VERSION: 5.3.2
Core INCLUDE: /usr/include/x86_64-linux-gnu/qt5/;/usr/include/x86_64-linux-gnu/qt5/QtCore;/usr/lib/x86_64-linux-gnu/qt5//mkspecs/linux-g++-64
Gui INCLUDE: /usr/include/x86_64-linux-gnu/qt5/;/usr/include/x86_64-linux-gnu/qt5/QtGui;/usr/include/x86_64-linux-gnu/qt5/QtCore;/usr/lib/x86_64-linux-gnu/qt5//mkspecs/linux-g++-64
Widgets INCLUDE: /usr/include/x86_64-linux-gnu/qt5/;/usr/include/x86_64-linux-gnu/qt5/QtWidgets;/usr/include/x86_64-linux-gnu/qt5/QtGui;/usr/include/x86_64-linux-gnu/qt5/QtCore;/usr/lib/x86_64-linux-gnu/qt5//mkspecs/linux-g++-64
Core LIBRARIES: Qt5::Core
Gui LIBRARIES: Qt5::Gui
Widgets LIBRARIES: Qt5::Widgets
Core DEFINITIONS: -DQT_CORE_LIB
Gui DEFINITIONS: -DQT_GUI_LIB;-DQT_CORE_LIB
Widgets DEFINITIONS: -DQT_WIDGETS_LIB;-DQT_GUI_LIB;-DQT_CORE_LIB
Core COMPILE_DEFINITIONS: QT_CORE_LIB
Gui COMPILE_DEFINITIONS: QT_GUI_LIB;QT_CORE_LIB
Widgets COMPILE_DEFINITIONS: QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB
Core EXECUTABLE_COMPILE_FLAGS: -fPIE
Gui EXECUTABLE_COMPILE_FLAGS: -fPIE
Widgets EXECUTABLE_COMPILE_FLAGS: -fPIE
Using GnuCXX compiler.
Building DEBUG build.
Sentinel GL -- C++ Project V 0.1.
(c) Markus-Hermann Koch, mhk#markuskoch.eu, 2015/04/28-?
Primary directory is /home/kochmn/projects/sentinel/build
System is Linux
Generating configuration header: "/home/kochmn/projects/sentinel/build/../build/mhk_cmake_config.h"
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kochmn/projects/sentinel/build
kochmn#Ulyss:~/projects/sentinel/build$ make
Scanning dependencies of target optimization_automoc
[ 5%] Automatic moc for target optimization
[ 5%] Built target optimization_automoc
Scanning dependencies of target optimization
[ 11%] Building CXX object CMakeFiles/optimization.dir/home/kochmn/projects/sentinel/src/optimization/linalg.cpp.o
[ 17%] Building CXX object CMakeFiles/optimization.dir/optimization_automoc.cpp.o
Linking CXX static library liboptimization.a
[ 17%] Built target optimization
Scanning dependencies of target qt_automoc
[ 23%] Automatic moc for target qt
[ 23%] Built target qt_automoc
Scanning dependencies of target qt
[ 29%] Building CXX object CMakeFiles/qt.dir/home/kochmn/projects/sentinel/src/qt/form_main.cpp.o
[ 35%] Building CXX object CMakeFiles/qt.dir/qt_automoc.cpp.o
Linking CXX static library libqt.a
[ 35%] Built target qt
Scanning dependencies of target sentinel_automoc
[ 41%] Automatic moc for target sentinel
[ 41%] Built target sentinel_automoc
[ 47%] Generating qrc_application.cpp
[ 52%] Generating ui_main.h
[ 58%] Generating moc_ui_main.cpp
/home/kochmn/projects/sentinel/build/ui_main.h:0: Note: No relevant classes found. No output generated.
[ 64%] Generating ui_dialog_setup_game.h
[ 70%] Generating moc_ui_dialog_setup_game.cpp
/home/kochmn/projects/sentinel/build/ui_dialog_setup_game.h:0: Note: No relevant classes found. No output generated.
Scanning dependencies of target sentinel
[ 76%] Building CXX object CMakeFiles/sentinel.dir/home/kochmn/projects/sentinel/src/sentinel.cpp.o
[ 82%] Building CXX object CMakeFiles/sentinel.dir/moc_ui_main.cpp.o
[ 88%] Building CXX object CMakeFiles/sentinel.dir/moc_ui_dialog_setup_game.cpp.o
[ 94%] Building CXX object CMakeFiles/sentinel.dir/qrc_application.cpp.o
[100%] Building CXX object CMakeFiles/sentinel.dir/sentinel_automoc.cpp.o
Linking CXX executable sentinel
[100%] Built target sentinel

CMake generation order is computed from dependencies between files and targets. If your qt library depends on headers generated from .ui files, then you have to add ${qt_UI_H} in inputs of target qt:
QT5_WRAP_UI(qt_UI_H ${qt_UI})
[...]
add_library(qt "${DIR_SRC}/qt/form_main.cpp" ${qt_UI_H})
And CMake should normally execute UIC on .ui files before compiling libqt
By the way using target_link_libraries only set dependencies between targets at link time. At compile time, the normal behavior is "All source files should be found". In your case, some headers are generated, so setting these headers as input of a target ensures that the macro which generates them (QT5_WRAP_UI) will be executed before the compilation of the target.

Related

GLM fails to build when using Clion

I am using the experimental GLM hash features in a CMake project.
Everything works fine unless the project is generated by Clion.
When building the Clion generated project GLM raises the error "GLM_GTX_hash requires C++11 standard library support" (see CMake logs) although C++11 is enabled.
Building the same, clion generated, project from a terminal fails with the same error.
However, when generating and building the project with cmake 'manually' (without Clion even knowing about it) everything works fine. As expected.
GLM is not directly included in the CMakeList. GLFW includes/imports it.
Example CMakeLists.txt
(...)
set(CMAKE_CXX_STANDARD 11)
add_executable(Test main.cpp)
(...)
add_subdirectory("glfw" ${CMAKE_CURRENT_BINARY_DIR}/glfw)
target_include_directories(Test PUBLIC ${GLFW_INCLUDE_DIRS})
target_link_libraries(Test ${GLFW_LIBRARIES} glfw)
Example main.cpp
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/hash.hpp>
int main() {
return 0;
}
Clion build output:
/usr/bin/cmake --build /home/lukas/Test/cmake-build-debug --target Test -- -j 2
[ 89%] Built target glfw
Scanning dependencies of target Test
[ 94%] Building CXX object CMakeFiles/Test.dir/main.cpp.o
In file included from /home/lukas/Test/main.cpp:8:
/usr/include/glm/gtx/hash.hpp:46:3: error: "GLM_GTX_hash requires C++11 standard library support"
# error "GLM_GTX_hash requires C++11 standard library support"
^
1 error generated.
make[3]: *** [CMakeFiles/Test.dir/build.make:63: CMakeFiles/Test.dir/main.cpp.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/Test.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/Test.dir/rule] Error 2
make: *** [Makefile:118: Test] Error 2
Terminal output (as expected)
$ cmake -H. -Bbuild -G "Unix Makefiles" && cmake --build build
Scanning dependencies of target glfw
[ 5%] Building C object glfw/src/CMakeFiles/glfw.dir/context.c.o
[ 10%] Building C object glfw/src/CMakeFiles/glfw.dir/init.c.o
[ 15%] Building C object glfw/src/CMakeFiles/glfw.dir/input.c.o
[ 21%] Building C object glfw/src/CMakeFiles/glfw.dir/monitor.c.o
[ 26%] Building C object glfw/src/CMakeFiles/glfw.dir/vulkan.c.o
[ 31%] Building C object glfw/src/CMakeFiles/glfw.dir/window.c.o
[ 36%] Building C object glfw/src/CMakeFiles/glfw.dir/x11_init.c.o
[ 42%] Building C object glfw/src/CMakeFiles/glfw.dir/x11_monitor.c.o
[ 47%] Building C object glfw/src/CMakeFiles/glfw.dir/x11_window.c.o
[ 52%] Building C object glfw/src/CMakeFiles/glfw.dir/xkb_unicode.c.o
[ 57%] Building C object glfw/src/CMakeFiles/glfw.dir/posix_time.c.o
[ 63%] Building C object glfw/src/CMakeFiles/glfw.dir/posix_thread.c.o
[ 68%] Building C object glfw/src/CMakeFiles/glfw.dir/glx_context.c.o
[ 73%] Building C object glfw/src/CMakeFiles/glfw.dir/egl_context.c.o
[ 78%] Building C object glfw/src/CMakeFiles/glfw.dir/osmesa_context.c.o
[ 84%] Building C object glfw/src/CMakeFiles/glfw.dir/linux_joystick.c.o
[ 89%] Linking C static library libglfw3.a
[ 89%] Built target glfw
Scanning dependencies of target Test
[ 94%] Building CXX object CMakeFiles/Test.dir/main.cpp.o
[100%] Linking CXX executable Test
[100%] Built target Test
Now I am actually curious about rather I messed up somewhere or if it is simply a bug. And if so, where should I report it?
[Clion/Jetbrains?, GLM?, GLFW?, CMake?]
Thanks in advance
Update
I am using the latest available (for me) builds:
CMake version: 3.14.4
Operating System: Arch Linux 5.0.18-1 x86_64 GNU/Linux
GLFW version/commit: d834f01c
GLM version/commit: fce2abd0
Clion: 2019.1.3
Clion EAP: 2019.2 EAP
Final update / 'Solution'
I just discovered that the problem is Clang, not Clion or anything else.
Clion simply defaulted to Clang (instead of GCC).
There are bug reports for GLM and Clang already existing (with potential fixes!):
https://github.com/g-truc/glm/issues/620
https://github.com/g-truc/glm/issues/646
Thank you very much everyone ~

Linking LLVM libraries on Windows with CMake and MinGW

I've been writing a compiler using LLVM as the backend. The CMake files I've written so far have worked on Linux, but I haven't had any luck on Windows. The project is split into a library and "driver" executable with their own CMakeLists.txt in separate subdirectories.
The top level CMakeLists.txt looks like this:
cmake_minimum_required (VERSION 3.7.0)
project (compiler)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CMAKE_CXX_EXTENSIONS OFF)
find_package (LLVM REQUIRED CONFIG)
message (STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message (STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
include_directories (${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
add_subdirectory (Compiler_Lib)
add_subdirectory (Compiler_exe)
The CMakeLists.txt for the library:
cmake_minimum_required (VERSION 3.7.0)
add_library (compiler_lib
AST.cpp
AST.h
parser.cpp
parser.h
scanner.cpp
scanner.h
token.cpp
token.h
visualizer.cpp
visualizer.h
codegen.cpp
codegen.h)
target_include_directories (compiler_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(compiler_lib LLVM)
And the CMakeLists.txt for the executable (which is where linking to the libraries fails):
cmake_minimum_required (VERSION 3.7.0)
project (compiler_exe)
add_executable (compiler_exe Compiler_exe.cpp getopt.h getopt.cpp)
target_link_libraries (compiler_exe LINK_PUBLIC LLVM compiler_lib)
I run the command "c:\Program Files\CMake\bin\cmake.exe" .. -G"MinGW Makefiles" -DCMAKE_PREFIX_PATH=C:\Users\James\llvm+clang-7.0.0-win64-msvc-release where C:\Users\James\llvm+clang-7.0.0-win64-msvc-release is the path to prebuilt LLVM libraries. However, running mingw32-make afterwards fails with the output
Scanning dependencies of target compiler_lib
[ 10%] Building CXX object Compiler_Lib/CMakeFiles/compiler_lib.dir/AST.cpp.obj
[ 20%] Building CXX object Compiler_Lib/CMakeFiles/compiler_lib.dir/parser.cpp.obj
[ 30%] Building CXX object Compiler_Lib/CMakeFiles/compiler_lib.dir/scanner.cpp.obj
[ 40%] Building CXX object Compiler_Lib/CMakeFiles/compiler_lib.dir/token.cpp.obj
[ 50%] Building CXX object Compiler_Lib/CMakeFiles/compiler_lib.dir/visualizer.cpp.obj
[ 60%] Building CXX object Compiler_Lib/CMakeFiles/compiler_lib.dir/codegen.cpp.obj
[ 70%] Linking CXX static library libcompiler_lib.a
[ 70%] Built target compiler_lib
Scanning dependencies of target compiler_exe
[ 80%] Building CXX object Compiler_exe/CMakeFiles/compiler_exe.dir/Compiler_exe.cpp.obj
[ 90%] Building CXX object Compiler_exe/CMakeFiles/compiler_exe.dir/getopt.cpp.obj
[100%] Linking CXX executable compiler_exe.exe
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: cannot find -lLLVM
collect2.exe: error: ld returned 1 exit status
Compiler_exe\CMakeFiles\compiler_exe.dir\build.make:102: recipe for target 'Compiler_exe/compiler_exe.exe' failed
mingw32-make[2]: *** [Compiler_exe/compiler_exe.exe] Error 1
CMakeFiles\Makefile2:176: recipe for target 'Compiler_exe/CMakeFiles/compiler_exe.dir/all' failed
mingw32-make[1]: *** [Compiler_exe/CMakeFiles/compiler_exe.dir/all] Error 2
Makefile:82: recipe for target 'all' failed
mingw32-make: *** [all] Error 2
This is the first time I've used CMake so I could have missed something obvious, but as I say it seems to work on Linux.
For the linking to succeed two things need to be true:
1) the file libLLVM.a needs to exist
2) that file has to be in a directory in the library search path
There should be a way to get cmake to tell you the list of places it searches for libraries, and you need to find a way to get wherever libLLVM.a exists into that list of dirs.
Apologies for the partial answer, but that's the troubleshooting path...

Can't locate c++ executable that g++ just created

This is a baffling issue for me, will be glad if someone has an insight.
I am tasked with converting an existing small c++ project that currently uses makefiles to one that is based on CMAKE. I am through the task, created CMakeLists.txt in all relevant folders and such. I then created a build folder inside the source tree and tried a build after running cmake. Everything builds correctly as it should (first builds 3 libs from other people's code, those are linked to this project's code etc.) and the status "make" command printed does show this. Finally, the command completes 100% with the last line saying [100%] Built target XXXXX
However, that target executable is nowhere to be found! I have tried explicitly setting CMAKE_ARCHIVE_OUTPUT_DIRECTORY to a directory in source (this is how we ideally want), some other folder, not setting it at all, etc. but to no avail. I create this executable using add_executable command and if I instead create a library from the same sources in the same location, the library (.a) gets created fine but I just cant seem to find this executable if I create it that make claims it built.
If it helps, the same project, if built on Windows, creates the EXE fine and I can see/run it in the folder inside source if I so specify.
(I am running g++/cmake on MacOS Sierra on the latest Macbook Pro that has SIP not turned off.)
Here is my minimal CMakeLists. The external libnames are replaced with LLLL. They are external libs in LLLL.a format in the lib directory.
cmake_minimum_required(VERSION 3.0)
project(my_exec C CXX)
cmake_policy(SET CMP0010 NEW)
set(CMAKE_MACOSX_RPATH TRUE)
SET(ENABLE_WARNINGS TRUE)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -c -std=c++11 -w")
#Includes
include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/inc/)
#External libs
set (EXT_LIBS LLLL LLLL LLLL)
#Where to find the libs above?
link_directories(${CMAKE_SOURCE_DIR}/lib/})
#Get all sources and headers
file(GLOB SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp)
#Finally!
add_executable(my_exec ${SOURCES})
target_link_libraries(my_exec ${EXT_LIBS})
message("Target path should be ${CMAKE_BINARY_DIR}")
Following is the cmake and build outputs and also find output which shows no exec
XXXX-MacBook-Pro:build XXXX$ rm -rf *
XXXX-MacBook-Pro:build XXXX$ cmake ..
-- The C compiler identification is AppleClang 9.0.0.9000037
-- The CXX compiler identification is AppleClang 9.0.0.9000037
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/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: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Target path should be /Users/XXXX/XXXX/XXXX/XXXX/build
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/XXXX/XXXX/XXXX/XXXX/build
XXXX-MacBook-Pro:build XXXX$ make -j34
Scanning dependencies of target my_exec
[ 9%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 18%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 27%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 36%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 45%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 54%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 72%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 72%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 81%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[ 90%] Building CXX object CMakeFiles/my_exec.dir/src/aaaa.cpp.o
[100%] Linking CXX executable my_exec
[100%] Built target my_exec
XXXX-MacBook-Pro:build XXXX$ cd ..
XXXX-MacBook-Pro:YYYY XXXX$ find . -name my*
./build/CMakeFiles/my_exec.dir
I think I have figured out the answer that took me VERY long time. The problem is the one little CMAKE_CXX_FLAG I had: "-c". It should not be there at all. CMake (for unknown reasons) passes that flag on to the "driver" c++/g++ even during the linking phase causing the underlying compiler to be invoked instead of a linker and then the compiler complains BUT ONLY AS WARNINGS that it is getting all this non-sense like *.o files and -l flags. Linking never happens as a result and so executable is never generated. And on top of this, all this drama is hidden and never shown to the user unless one does make VERBOSE=1 and actually reads the last command and then tries to use the last command by themselves with -Wall or -Werror to reveal these compiler warnings that it is getting all these linker flags.
I think this is a CMake bug but I am unsure.

Cmake error undefined symbols for x86_64

I am trying to compile the conv-net library in my mac osx yosemite with xcode. I even set the flags to libstdc++ still it is not linking properly.
i still get undefined symbols for architecture x86_64.
any help much appreciated.
sh-3.2# ./compile.sh
Building conv-net library
-- The C compiler identification is AppleClang 6.0.0.6000056
-- The CXX compiler identification is AppleClang 6.0.0.6000056
-- 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
-- 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
-- Configuring done
WARNING: Target "testimg" requests linking to directory "/usr/local/Cellar/opencv/2.4.9/lib". Targets may link only to libraries. CMake is dropping the item.
WARNING: Target "testimg" requests linking to directory "/usr/local/Cellar/opencv/2.4.9/lib". Targets may link only to libraries. CMake is dropping the item.
WARNING: Target "testmnist" requests linking to directory "/usr/local/Cellar/opencv/2.4.9/lib". Targets may link only to libraries. CMake is dropping the item.
WARNING: Target "testmnist" requests linking to directory "/usr/local/Cellar/opencv/2.4.9/lib". Targets may link only to libraries. CMake is dropping the item.
-- Generating done
-- Build files have been written to: /var/tmp/conv-net-0.1-prealpha_buildroot
Scanning dependencies of target cvconvnet
[ 11%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvsubsamplingplane.cpp.o
[ 22%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvconvolutionplane.cpp.o
[ 33%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvgenericplane.cpp.o
[ 44%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvsourceplane.cpp.o
[ 55%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvrbfplane.cpp.o
[ 66%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvmaxplane.cpp.o
[ 77%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvconvnetparser.cpp.o
[ 88%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvfastsigmoid.cpp.o
[100%] Building CXX object CMakeFiles/cvconvnet.dir/src/cvconvnet.cpp.o
/Users/prabhubalakrishnan/Desktop/conv-net/src/cvconvnet.cpp:169:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
1 warning generated.
Linking CXX static library libcvconvnet.a
[100%] Built target cvconvnet
Scanning dependencies of target testimg
Linking CXX executable testimg
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [testimg] Error 1
make[1]: *** [CMakeFiles/testimg.dir/all] Error 2
make: *** [all] Error 2
cp: testimg: No such file or directory
cp: testmnist: No such file or directory
ls: illegal option -- I
usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]
This is my make file
cmake_minimum_required(VERSION 3.0)
PROJECT (CvConvolutionalNet)
set (CMAKE_CXX_FLAGS " -stdlib=libstdc++")
# IF() ENDIF() statements
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
# Specify build-type as Debug if not specified already
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Debug)
ENDIF ()
# Produce verbose makefiles
# SET(CMAKE_VERBOSE_MAKEFILE ON)
# Sources for library
SET(CVCONVNET_SRCS
src/cvsubsamplingplane.cpp
src/cvconvolutionplane.cpp
src/cvgenericplane.cpp
src/cvsourceplane.cpp
src/cvrbfplane.cpp
src/cvmaxplane.cpp
src/cvconvnetparser.cpp
src/cvfastsigmoid.cpp
src/cvconvnet.cpp
)
# Sources for test files
SET(TESTIMG_SRCS tst/)
SET(TESTMNIST_SRCS tst/)
set (CV_H /usr/local/Cellar/opencv/2.4.9/include/opencv)
set (HIGHGUI_H src/include )
set (LIBCV /usr/local/Cellar/opencv/2.4.9/lib )
set (LIBHIGHGUI /usr/local/Cellar/opencv/2.4.9/lib )
# Here are common paths (in addition to default paths)
SET (INCLUDE_SEARCH_PATH
/usr/local/include /usr/include /usr/include/opencv/
/usr/include/opencv/ c:/program\ files/opencv/include
)
SET (LIBRARY_SEARCH_PATH
/usr/local/lib /usr/lib c:/program\ files/opencv/lib c:/windows/system32
)
# Find OpenCV and Expat
FIND_PATH(CV_H NAMES cv.h PATHS ${INCLUDE_SEARCH_PATH} )
FIND_PATH(HIGHGUI_H NAMES highgui.h PATHS ${INCLUDE_SEARCH_PATH} )
FIND_PATH(EXPAT_H NAMES expat.h PATHS ${INCLUDE_SEARCH_PATH} )
FIND_LIBRARY(LIBCV NAMES cv PATHS ${LIBRARY_SEARCH_PATH} )
FIND_LIBRARY(LIBHIGHGUI NAMES highgui PATHS ${LIBRARY_SEARCH_PATH} )
FIND_LIBRARY(LIBEXPAT NAMES expat PATHS ${LIBRARY_SEARCH_PATH} )
INCLUDE_DIRECTORIES(include/ ${CV_H} ${HIGHGUI_H} ${EXPAT_H})
# Here is out library
ADD_LIBRARY(cvconvnet STATIC ${CVCONVNET_SRCS})
# Here are our test programs
ADD_EXECUTABLE(testimg ${TESTIMG_SRCS})
ADD_EXECUTABLE(testmnist ${TESTMNIST_SRCS})
# Compiler options are different for Release and Debug
IF (CMAKE_BUILD_TYPE MATCHES Release)
# Highly optimized + cancel all assert()s
ADD_DEFINITIONS(-O3 -DNDEBUG)
ELSE ()
# Include debug info, profiling info, some text output
ADD_DEFINITIONS(-O -pg -g -DDEBUG)
# Set profiling for linker too
SET_TARGET_PROPERTIES(testmnist PROPERTIES LINK_FLAGS "-pg")
ENDIF ()
# We should link our test programs to libraries
TARGET_LINK_LIBRARIES(testimg cvconvnet ${LIBCV} ${LIBHIGHGUI} ${LIBEXPAT})
TARGET_LINK_LIBRARIES(testmnist cvconvnet ${LIBCV} ${LIBHIGHGUI} ${LIBEXPAT})
I fixed it by adding -c option in the compiler flags and it worked !!!!
The add_executable command takes a target name and a list of source files to be compiled. When you are creating a target for testimg you are passing it directory.
Use file(GLOB ...) command to gather all source files from directory into a list variable and pass it to add_executable call.

CppUnit and CMake: .cpp files get compiled twice

I'm currently using CMake to build my project and CppUnit to Test it. In my CMake file i create two executables. sample is the compiled source itself. And with sample_test I run the tests. If i r
Here a part of my CMakeLists.txt
SET(SAMPLE_ROOT_PATH ${PROJECT_BINARY_DIR})
SET(SAMPLE_SOURCE_PATH ${SAMPLE_ROOT_PATH}/src)
SET(SAMPLE_TEST_SOURCE_PATH ${SAMPLE_ROOT_PATH}/test)
SET(SAMPLE_BIN_PATH ${SAMPLE_ROOT_PATH}/bin)
SET(SAMPLE_EXEC_NAME sample)
SET(SAMPLE_TEST_EXEC_NAME sample_test)
SET(EXECUTABLE_OUTPUT_PATH ${SAMPLE_BIN_PATH})
FILE(GLOB_RECURSE SAMPLE_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/*.cpp)
FILE(GLOB_RECURSE SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_PATH}/*.cpp)
SET(SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_FILES} ${SAMPLE_SOURCE_FILES}
)
LIST(REMOVE_ITEM SAMPLE_TEST_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/main.cpp)
SET(CMAKE_CXX_FLAGS "-g -Wall")
ADD_EXECUTABLE(${SAMPLE_EXEC_NAME} ${SAMPLE_SOURCE_FILES})
ADD_EXECUTABLE(${SAMPLE_TEST_EXEC_NAME} ${SAMPLE_TEST_SOURCE_FILES})
this is the output of make
[ 8%] Building CXX object CMakeFiles/sample.dir/src/KeyBuffer.cpp.obj
[ 12%] Building CXX object CMakeFiles/sample.dir/src/main.cpp.obj
[ 20%] Building CXX object CMakeFiles/sample.dir/src/Object.cpp.obj
[ 45%] Building CXX object CMakeFiles/sample.dir/src/World.cpp.obj
Linking CXX executable bin/sample.exe
[ 45%] Built target sample
[ 50%] Building CXX object CMakeFiles/sample_test.dir/test/KeyBufferTest.cpp.obj
[ 54%] Building CXX object CMakeFiles/sample_test.dir/test/ObjectTest.cpp.obj
[ 66%] Building CXX object CMakeFiles/sample_test.dir/src/KeyBuffer.cpp.obj
[ 75%] Building CXX object CMakeFiles/sample_test.dir/src/Object.cpp.obj
[100%] Building CXX object CMakeFiles/sample_test.dir/src/World.cpp.obj
Linking CXX executable bin/sample_test.exe
As you can see Object.cpp, World.cpp and KeyBuffer.cpp get compiled twice! How can i prevent it? Or is there a better way to handle the CppUnit tests using CMake?
Each target may have different compiler flags configured, so if you add one source files to two targets, separate object files need to be produced from this one source file for both targets.
The usual solution is to compile the shared source files into a static library which is then linked into both application targets.
add_library(base STATIC ${shared_SOURCES}) # except e.g. foo_main.cpp
add_executable(foo ${foo_only_SOURCES})
target_link_libraries(foo base)
add_executable(bar ${bar_only_SOURCES})
target_link_libraries(bar base)
Conceptually CMake treats each target (i.e., executable or library) as a separate build unit. The generated build system will produce an object file for each source file belonging to the target. By default CMake does not avoid redundant compilations of source files that are used in multiple targets, even if the compilation settings (compilation flags, preprocessor definitions ...) are exactly the same.
CMake 2.8.8 introduced a new feature called OBJECT_LIBRARY target to address the problem of avoiding redundant compilations:
To generate an object library use add_library:
FILE(GLOB_RECURSE SAMPLE_SOURCE_FILES ${SAMPLE_SOURCE_PATH}/*.cpp)
ADD_LIBRARY(sample_objects OBJECT EXCLUDE_FROM_ALL ${SAMPLE_SOURCE_FILES})
Other targets created by add_library or add_executable may reference the objects using an expression of the form $<TARGET_OBJECTS:objlib>:
ADD_EXECUTABLE(${SAMPLE_EXEC_NAME} $<TARGET_OBJECTS:sample_objects>)
FILE(GLOB_RECURSE SAMPLE_TEST_SOURCE_FILES ${SAMPLE_TEST_SOURCE_PATH}/*.cpp)
ADD_EXECUTABLE(${SAMPLE_TEST_EXEC_NAME} $<TARGET_OBJECTS:sample_objects> ${SAMPLE_TEST_SOURCE_FILES})
Compared with using a regular static library to avoid redundant compilation, an object library has the advantage that it does not need to be linked. On top of that it cannot be imported, exported or installed.