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

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

Related

CMake Error: variable set to NOTFOUND even after defining it manually

I am new to cmake and attempting to build an existing repository that relies on GLEW. I have installed GLEW using Homebrew and am now trying to run cmake . The configuration step completes, but the generation step raises the following error:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
GLEW_LIBRARY
I have checked/tried the following:
CMakeLists.txt contains a line find_package(GLEW REQUIRED) which does not fail. I even added the line FIND_LIBRARY(GLEW_LIBRARY NAMES libGLEW.dylib PATHS /opt/local/lib /usr/local/lib /usr/lib REQUIRED) to explicitly tell cmake where to look for the library and it finds the correct path.
There is a file FindGlew.cmake that was placed in /usr/local/Cellar/cmake/3.25.2/share/cmake/Modules (I assume during the homebrew install of GLEW). It contains a line unset(GLEW_LIBRARY). I'm a bit hesitant to mess with the file (it shouldn't be necessary, right?) but I tried commenting that line out and running cmake again, but it didn't have any effect.
CMakeCache.txt contains the variables GLEW_LIBRARY_DEBUG and GLEW_LIBRARY_RELEASE which were set to GLEW_LIBRARY_DEBUG-NOTFOUND etc. I edited them manually to the path of the libGLEW.dylib file and added an additional path which I called GLEW_LIBRARY, but to no avail.
CMakeCache.txt also contains a variable GLEW_DIR which is defined. There is a GLEW_LIBRARY_DIR which is also NOTFOUND.
I passed the variable as an explicit command using cmake . -DGLEW_LIBRARY=/usr/local/lib/libGLEW.dylib. I tried this both with and without first deleting the cache.
Statically define the library using the approach in this answer.
brew reinstall glew.
I do have OpenGL installed as wel, but built from source (not via Homebrew). Could It have something to do with them not being linked correctly? OpenGL is found properly by CMakeLists.txt, so cmake must have access to its path somehow.
Edit: this is (a MWE of) the CMakeLists.txt file:
cmake_minimum_required (VERSION 3.15)
project ("ProjectName" LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(OpenGL REQUIRED)
include_directories( ${OPENGL_INCLUDE_DIRS} )
# set(CMAKE_FIND_DEBUG_MODE TRUE)
find_package(GLEW REQUIRED)
# set(CMAKE_FIND_DEBUG_MODE FALSE)
include_directories(${GLEW_INCLUDE_DIRS})
file(GLOB sources CONFIGURE_DEPENDS src/*.cpp src/*.hpp *src/.h)
add_executable(${PROJECT_NAME} ${sources})
target_link_libraries(${PROJECT_NAME} ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES})
file(COPY ${RESOURCE_FILES} DESTINATION ${CMAKE_BINARY_DIR}/Resources)
Edit: for completeness, here is the full output / error message:
-- The CXX compiler identification is AppleClang 14.0.0.14000029
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenGL: /Library/Developer/CommandLineTools/SDKs/MacOSX13.1.sdk/System/Library/Frameworks/OpenGL.framework
-- Found GLEW: /usr/local/lib/cmake/glew/glew-config.cmake
-- Configuring done
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
GLEW_LIBRARY
linked by target "ProjectName" in directory /Users/user1/dev/project
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
EDIT2: According to FindGLEW you should use one of the imported targets - GLEW::GLEW i.e.
target_link_libraries(your_target GLEW::GLEW ... )
I would also kindly ask you to post the new errors that you are getting related to the MRE you posted. I will update my answer accordingly.
EDIT: Because you mentioned that some people can compile it and some people can't. Look at this line right here:
find_package(GLEW CONFIG QUIET)
if(GLEW_FOUND)
#...
This line tries to find the actual GLEWConfig.cmake file to configure this. Meaning that if you've installed the package OR they have in a way that you have this GLEWConfig.cmake file then you will get different results.
My recommendation is: Figure out exactly how they installed their GLEW (or if they compiled it) and recreate the exact same environment.
Here is the link to FindGLEW.cmake. On Lines 41-58 you can see the variables that you can use in your project. There is NO GLEW_LIBRARY.
If you look down in the file you'll see why:
if(GLEW_FOUND)
find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_CONFIG)
get_target_property(GLEW_INCLUDE_DIRS GLEW::GLEW INTERFACE_INCLUDE_DIRECTORIES)
set(GLEW_INCLUDE_DIR ${GLEW_INCLUDE_DIRS})
get_target_property(_GLEW_DEFS GLEW::GLEW INTERFACE_COMPILE_DEFINITIONS)
if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC")
get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_LOCATION_DEBUG)
get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_LOCATION_RELEASE)
else()
get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_IMPLIB_DEBUG)
get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_IMPLIB_RELEASE)
endif()
get_target_property(_GLEW_LINK_INTERFACE GLEW::GLEW IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE) # same for debug and release
list(APPEND GLEW_LIBRARIES ${_GLEW_LINK_INTERFACE})
list(APPEND GLEW_LIBRARY ${_GLEW_LINK_INTERFACE})
select_library_configurations(GLEW)
if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC")
set(GLEW_STATIC_LIBRARIES ${GLEW_LIBRARIES})
else()
set(GLEW_SHARED_LIBRARIES ${GLEW_LIBRARIES})
endif()
unset(_GLEW_DEFS)
unset(_GLEW_LINK_INTERFACE)
unset(GLEW_LIBRARY) #<-- here the temporary variable is unset
unset(GLEW_LIBRARY_DEBUG)
unset(GLEW_LIBRARY_RELEASE)
return()
endif()
GLEW_LIBRARY is a temporary variable used to set other variables.
What instead you want to use is: GLEW_LIBRARIES

How to add icon to a Qt application on Windows using a .rc file on a CMake project?

I'm trying to add an application icon to an application I'm writing, following what is described in https://doc.qt.io/qt-5/appicon.html
I'm using Qt Desktop 5.15.2 (64) and 6.1.2 (64) for both MinGW and MSVC, on Windows 10 64 bits. They all compile without error or warnings, but the icon doesn't show up.
My CMakeFile.txt:
cmake_minimum_required(VERSION 3.14)
project(MyApp VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
# Check https://doc.qt.io/qt/deployment-android.html for more information.
# They need to be set before the find_package(...) calls below.
if(ANDROID)
set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
# if (ANDROID_ABI STREQUAL "armeabi-v7a")
# set(ANDROID_EXTRA_LIBS
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
# endif()
endif()
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick LinguistTools REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick LinguistTools REQUIRED)
set(TS_FILES _pt_BR.ts)
set(PROJECT_SOURCES
main.cpp
qml.qrc
${TS_FILES}
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/MyApp.rc")
qt_add_executable(MyApp
MANUAL_FINALIZATION
${PROJECT_SOURCES}
${APP_ICON_RESOURCE_WINDOWS}
)
qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
else()
if(ANDROID)
add_library(MyApp SHARED
${PROJECT_SOURCES}
)
elseif(WIN32)
set(APP_ICON_RESOURCE_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/windows/MyApp.rc")
add_executable(MyApp
${PROJECT_SOURCES}
${APP_ICON_RESOURCE_WINDOWS}
)
else()
add_executable(MyApp
${PROJECT_SOURCES}
)
endif()
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
endif()
target_compile_definitions(MyApp
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(MyApp
PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick)
set_target_properties(MyApp PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_import_qml_plugins(MyApp)
qt_finalize_executable(MyApp)
endif()
MyApp.rc:
MyAppIcon ICON "MyApp.ico"
The .ico contains a single 256x256 32-bit RGBA image.
For what matters, after so many failures I tried creating a test project using qmake, and added the icon using RC_ICONS = QtTest.ico the .pro file, which worked (got the correct icon). When I tried using the RC_FILE = QtTest.rc instead it used the default icon, but without any warnings or errors.
Just in case I generated the .res file using windres, but to no avail. Changed QtTestIco ICON "QtTest.ico" and regenerated the .res, the same result.
Substituting the CMakeList.txt for a .pro file and using the RC_ICONS is not an option, sadly.
Somebody could help me, please?
Thanks in advance.
In order to add a Microsoft resources (RC) file, you need to tell CMake to support the "RC" language by enabling Microsoft's RC language. This will kick in the resource compiler when it detects a file with the *.rc extension in your project.
Here is a sample code snippet:
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
enable_language("RC")
set (WIN32_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/windows/MyApp.rc)
endif()
add_executable(MyApp WIN32
${PROJECT_SOURCES}
${WIN32_RESOURCES}
)
Build your project and Microsoft Explorer will then see your icon.
Suppose you have (core and myapp just as an example):
core/
CMakeLists.txt
myapp.ico
myapp.rc
...other dirs with your sources...
Your myapp.rc contains:
IDI_ICON1 ICON DISCARDABLE "myapp.ico"
Suppose you have MS VC Build Tools installed and you have x64 Native Tools Command Prompt open. And you build your project using cmake, etc. It means that there you also have rc cmd program there. So in your prompt do:
C:\Users\MyName\myapprepo\core> rc myapp.rc
Then you get a binary file myapp.res:
core/
CMakeLists.txt
myapp.ico
myapp.rc
myapp.res
So now, you need to link this binary file to our lib/app. In my case it was a lib I called core and I would link it to my executable myapp. It does not matter. The point is that you should link the file:
# core/CMakeLists.txt
target_link_libraries(${CORE_LIBRARY_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/myapp.res
Qt5::Widgets)
The MS VC compiler knows what to do when linking the res file to your lib/exe. So don't worry about the strange entity. In general, the whole procedure is exactly as it is described in the docs https://doc.qt.io/archives/qt-4.8/appicon.html:
If you do not use qmake, the necessary steps are: first, run the rc program on the .rc file, then link your application with the resulting .res file.
If any question, ask in comments. Good luck!

missing .lib file when creating shared library with cmake and visual studio 2019 generator

I have created a personnal C++ library and I try to use it in an other program. To create and compile my library, I use the commands
cmake -G "Visual Studio 16 2019" -A x64 ..
cmake --build . --config Release --target INSTALL
I have no problem with te compilation and the installation, but in the Target-release.cmake install look like this :
#----------------------------------------------------------------
# Generated CMake target import file for configuration "Release".
#----------------------------------------------------------------
# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)
# Import target "containers" for configuration "Release"
set_property(TARGET containers APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(containers PROPERTIES
IMPORTED_IMPLIB_RELEASE "C:/Program Files (x86)/containers/lib/containers.lib"
IMPORTED_LOCATION_RELEASE "C:/Program Files (x86)/containers/bin/containers.dll"
)
list(APPEND _IMPORT_CHECK_TARGETS containers )
list(APPEND _IMPORT_CHECK_FILES_FOR_containers "C:/Program Files (x86)/containers/lib/containers.lib" "C:/Program Files (x86)/containers/bin/containers.dll" )
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
Nothing abnormal, as far as I can see. My problem is : I have no file C:/Program Files (x86)/containers/lib/containers.lib generated during the compilation and the installation. So every time I try to use a find package, I have an error. (It's only with visual studio generator, it works with mingw). Here is my CMakeLists.txt :
cmake_minimum_required(VERSION 3.1)
set(VERSION 1.0.0)
project (containers
VERSION ${VERSION}
DESCRIPTION "Library adding some features to containers of the stl."
LANGUAGES CXX)
option(BUILD_TESTING "Build test programs" OFF)
include(CTest)
# Set the possible values of build type for cmake-gui
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build.")
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
message( STATUS "Sources path : ${PROJECT_SOURCE_DIR}")
message( STATUS "Binary path : ${PROJECT_BINARY_DIR}")
message( STATUS "install path : ${CMAKE_INSTALL_PREFIX}")
message( STATUS "Version : ${PROJECT_VERSION}")
message( STATUS "Version : ${PROJECT_VERSION}")
message( STATUS "Compiler : ${CMAKE_CXX_COMPILER_ID}")
set(SOURCES ${PROJECT_SOURCE_DIR}/src/containers.cpp)
set(HEADERS ${PROJECT_SOURCE_DIR}/include/containers/containers_check.h
${PROJECT_SOURCE_DIR}/include/containers/containers.h
${PROJECT_SOURCE_DIR}/include/containers/append.h
${PROJECT_SOURCE_DIR}/include/containers/contains.h
${PROJECT_SOURCE_DIR}/include/containers/remove.h
${PROJECT_SOURCE_DIR}/include/containers/print.h
)
add_library(containers SHARED ${SOURCES} ${HEADERS})
#add_library(containers INTERFACE)
target_compile_features(containers PRIVATE cxx_std_17)
set_target_properties(containers
PROPERTIES
MSVC_RUNTIME_LIBRARY "MultiThreadedDLL"
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS OFF)
target_include_directories(containers
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_compile_options(containers PRIVATE
# g++
#$<$<CXX_COMPILER_ID:GNU>:$<BUILD_INTERFACE:-Wall>>
#$<$<CXX_COMPILER_ID:GNU>:$<BUILD_INTERFACE:-Wextra>>
#$<$<CXX_COMPILER_ID:GNU>:$<BUILD_INTERFACE:-pedantic>>
#$<$<CXX_COMPILER_ID:GNU>:$<BUILD_INTERFACE:-Werror>>
#$<$<CXX_COMPILER_ID:GNU>:-Wno-reorder>
## Clang
#$<$<CXX_COMPILER_ID:Clang>:$<BUILD_INTERFACE:-Wall>>
##TODO
## MSVC
#$<$<CXX_COMPILER_ID:MSVC>:$<BUILD_INTERFACE:/W4>>
#$<$<CXX_COMPILER_ID:MSVC>:$<BUILD_INTERFACE:/WX>>
)
install(TARGETS containers
EXPORT containersTarget
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/ COMPONENT Development
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/ COMPONENT Library NAMELINK_COMPONENT Development
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/ COMPONENT Runtimes
)
install(FILES ${HEADERS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/containers/
COMPONENT headers)
include(CMakePackageConfigHelpers)
# For moteur_de_calculConfig.cmake
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include CACHE PATH "install path for include files")
set(LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib CACHE PATH "install path for libraries")
#------------------------------------------------------------------------------
# Configure <export_config_name>ConfigVersion.cmake common to build and install tree
set(config_version_file ${PROJECT_BINARY_DIR}/containersConfigVersion.cmake)
write_basic_package_version_file(
${config_version_file}
VERSION "${CMAKE_PROJECT_VERSION}"
COMPATIBILITY ExactVersion
)
#------------------------------------------------------------------------------
# Export '<export_config_name>Target.cmake' for a build tree
export(TARGETS
containers
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Target.cmake"
)
#------------------------------------------------------------------------------
# Configure '<export_config_name>Config.cmake' for a build tree
set(build_config ${CMAKE_BINARY_DIR}/containersConfig.cmake)
configure_package_config_file(
"containersConfig.cmake.in"
${build_config}
INSTALL_DESTINATION "${PROJECT_BINARY_DIR}"
PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR VERSION
)
#------------------------------------------------------------------------------
# Export '<export_config_name>Target.cmake' for an install tree
install(EXPORT
containersTarget
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/${PROJECT_NAME}"
)
#------------------------------------------------------------------------------
# Configure '<export_config_name>Config.cmake' for a install tree
set(install_config ${PROJECT_BINARY_DIR}/CMakeFiles/containersConfig.cmake)
configure_package_config_file(
containersConfig.cmake.in
${install_config}
INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/${PROJECT_NAME}"
PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR VERSION
)
# Install config files
install(
FILES ${config_version_file} ${install_config}
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/${PROJECT_NAME}"
)
# test
if(BUILD_TESTING)
add_subdirectory(test)
endif()
# uninstall target
# use : make uninstall
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE #ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
My cmake version :
cmake version 3.18.0
What is missing in my CMakeLists.txt for generate the container.lib file ?
Faced the same problem, I found the solution here: for Visual Studio to export symbols in a .lib file besides the .dll library, you need to set this in your CMake (version>= 3.4) script:
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
Note that the .lib file created this way is a small size file and is not a static library.
CMake manual
I'd like to add to the accepted answer here, for others who might find it: although CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS will solve the problem, it could well be a sticking plaster masking a deeper issue going on with your code.
I'm not an expert on the Microsoft compilers, but I do know that if you build a shared library with MSVC, the .lib file should still be produced. However, rather than containing all of your compiled code as it would for a static library, it basically provides the compiler with information about the exported symbols in your shared library. This means that the compiler can automatically link any other targets to your shared library, without you needing to manually load the library from your code using the Windows API functions. If you link an executable to a shared library this way, the Microsoft C runtime will basically call LoadLibrary() for you automatically when your application starts. Useful, huh?
If the compiler does not produce a .lib alongside your shared library, this basically means that there are no exported symbols in the shared library. This is why CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS solves the problem - it forces all the symbols to be exported anyway, thereby causing the compiler to generate the .lib file detailing these exports. However, as you may be able to work out, this is very much the nuclear option. There's probably a lot of stuff in your shared library that really doesn't need to be visible from the outside! So the pertinent question becomes: why is nothing being exported from my library?
In the linked answer referred to previously, underneath all the CMake technicals, the issue was that the OP was not properly marking their symbols for export. It turns out that this was my issue too, but in a more round-about way: I had decided that for my particular library, which could previously be built in shared or static configurations, I now wanted to force it only to be built in a shared configuration. Because of this, I had removed a particular preprocessor definition from my project in CMake which specified whether the build mode was shared or static; this meant that all of the export annotations on my functions compiled down to nothing (as they should do under a static configuration where they are not needed). The upshot was that I accidentally ended up building the shared library with no exported symbols whatsoever, and MSVC just said "Well I guess there's no point building a .lib then", and didn't produce one. This caused the build issues stating that the .lib could not be found on disk.
When I encountered the answer above, I was suspicious as I wondered why I'd not had to set this value before, despite having used CMake to build Windows shared library projects for years. The correct solution in my case was not to switch CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS on - it was actually to remove the C++ preprocessor condition that checked for my "this is a shared build" preprocessor definition. This re-enabled all of the export annotations on my functions, and everything built as it should.
Before you use CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS, do check that there isn't some subtle bug in your scripts that is preventing your symbols from being exported!

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

How to get CMake to use existing 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.

Resources