How to make intermediate object file not a library using qmake? - qt5

Filesystem layout:
MyProject
|_ myproject.pro
|_ FuncA
|_ core.cpp
|_ core.h
|_ core.pro
|_ app
|_ main.cpp
|_ app.pro
I want just to compile "core.cpp" in FuncA to make a object file not a library. That is "gcc -c core.cpp". And in app I want to make main program linking core.o created previously.
In this case how do I make core.pro? Which TEMPLATE should I use?

Use can use generic app template for core.pro. It will create intermediate core.o anyway, which you can link later in app.pro like so:
LIBS += $$PWD/../FuncA/core.o

I solved this problem with "static library config" so that it will not make ".so" libs and then link that static library with main program.
TEMPLATE = lib
CONFIG += staticlib

Related

How to build and deploy an external library with CMake [duplicate]

This question already has answers here:
CMake link to external library
(6 answers)
Closed 6 months ago.
I would like to use and deploy an external library in my program.
My project's structure is as follow (simplified):
ProjectDir
|_ _build
|_ CMakeLists.txt
|_ Src
| |_ CMakeLists.txt
| |_ .h and .cpp files
|_ ThirdParty
|_ CMakeLists.txt
|_ ExternalLib
|_ includes
| |_ .h files
|_ lib
|_ Windows
| |_ .dll files
|_ Linux
|_ .so files
For this library, I've only the include files and the binaries for Windows and Linux.
I'm able to find the includes files by using target_include_directories() in the CMakeLists.txt of the ThirdParty directory but I cannot build my program even by declaring the libraries with :
target_link_libraries(${CMAKE_PROJECT_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/ExternalLib/lib/Windows/extLib)
Note: this command is also in the CMakeLists.txt of ThirdParty directory.
I get the following error:
'../../../ThirdParty/ExternalLib/lib/Windows/extLib', needed by 'program' missing and no known rule to make it
I develop on a Windows platform with VS2022 and my program will be build and installed on a Linux server.
On Windows I've the latest version of CMake but on Linux the version is 3.16.
Can somebody help me in fixing this error?
You should import library as a target of you project.
For instance something like
add_library(your_lib SHARED IMPORTED)
set_property(TARGET your_lib PROPERTY
IMPORTED_LOCATION
"${CMAKE_SOURCE_DIR}/ThirdParty/ExternalLib/lib/Linux/extLib.so") # to be adapted for windows
target_include_directories(your_lib
PUBLIC
${CMAKE_SOURCE_DIR}/ThirdParty/ExternalLib/include)
then you should be able to use it as any other library in cmake:
target_link_libraries(yourExecutable PRIVATE your_lib)
see doc in details here:
https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html

CMake fix_bundle how to ignore embedded dll

My system has some dlls that are linked in other embedded executables, like commands from MSYS.
Directories structure:
MySystem/
|_ mysystem.exe
|_ CMakeLists.txt
|_ embedded system/
|_ msys_command1.exe
|_ msys_command2.exe
|_ msys-1.0.dll
When it is running fixup_bundle from CMake, this warning is showed:
EXEC : warning : cannot resolve item 'msys-1.0.dll'
possible problems:
need more directories?
need to use InstallRequiredSystemLibraries?
run in install tree instead of build tree?
EXEC : -- warning : gp_resolved_file_type non-absolute file 'msys-1.0.dll' returning type 'other' -- possibly incorrect
--
EXEC : warning : cannot resolve item 'msys-1.0.dll'
possible problems:
need more directories?
need to use InstallRequiredSystemLibraries?
run in install tree instead of build tree?
The MSYS commands are within the software embedded directory.
If I put the embedded directory on fixup_bundle paths, the dlls are copied to my executable directory, but I don't want that behavior.
Is there a way to ignore that dlls?
I've tried with fixup_bundle macro IGNORE_ITEM, but it didn't work.
Besides that, the problem propagates to CPack:
CPack: Create package using NSIS
CPack: Install projects
CPack: - Install project: MySystem
Error copying file "msys-1.0.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/msys-1.0.dll".
Error copying file "msys-intl-8.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/msys-intl-8.dll".
Error copying file "Qt5Core.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/Qt5Core.dll".
Error copying file "Qt5Gui.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/Qt5Gui.dll".
Error copying file "Qt5Network.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/Qt5Network.dll".
Error copying file "Qt5Widgets.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/Qt5Widgets.dll".
Error copying file "libprotobuf.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/libprotobuf.dll".
Error copying file "lua.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/lua.dll".
Error copying file "qwt.dll" to "D:/mysystem/solution/build/_CPack_Packages/win64/NSIS/MySystem/qwt.dll".
CPack: Create package
Not sure if this is what you need but I made a custom fixup_bundle function which also uses the IGNORE_ITEM key to skip libraries.
I call fixup_bundle2 as follows:
install(CODE "
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/dist/cmake)
include(InstallRequiredSystemLibraries)
include(BundleUtilities)
include(FixUp)
fixup_bundle2(\"\${CMAKE_INSTALL_PREFIX}/${APPS}\" \"${LIBS}\" \"${DIRS}\" IGNORE_ITEM \"exe_with_z64;exe_with_zip;libopenvr_api_so\")"
)
Note the set(CMAKE_MODULE_PATH... line which is there to include my own provided fixup_bundle2 from my FixUp.cmake file. Also note that I need to specify libopenvr_api_so while in reality it is libopenvr_api.so.
fixup_bundle2 is a copy of fixup_bundle with the following added in the foreach(key ${keys}) loop:
# also ignore libs in INGORE_ITEM
if(key IN_LIST CFG_IGNORE_ITEM)
message(STATUS "skipping ${key}")
continue()
endif()
You'll also need to set
cmake_policy(SET CMP0057 NEW)
in the FixUp.cmake file apparently.

How do I structure an ear file in JBoss AS 7 to avoid class cast exception?

Currently we are using JBoss AS 5 and using single ear file with the deployment structure as follows
company.ear
|_ webapp1.war
|_ webapp2.war
|_ lib
| |_ ejb1.jar
| |_ ejb2.jar
|_ META-INF
| |_application.xml
|_ thirdparty1.jar
|_ thirdparty2.jar
All ejb which are common to web application are kept in lib and thirdparty jars are kept in ear root path. This is working fine.
Now, we are migrating the same to JBoss 7.1.1. and we have tried with following deployment structures.
1. company.ear
|_ webapp1.war
|_ webapp2.war
|_ lib
| |_ thirdparty1.jar
| |_ thirdparty2.jar
|_ META-INF
| |_application.xml
| |_jboss-deployment-structure.xml
|_ ejb1.jar
|_ ejb2.jar
2. company.ear
|_ webapp1.war
|_ webapp2.war
|_ lib
| |_ ejb1.jar
| |_ ejb2.jar
|_ META-INF
|_application.xml
|_jboss-deployment-structure.xml
In the second deployment structure, we have defined thirdparty jars in modules folder and added global dependency in the stanalone.xml.
Though we are following JBoss AS 7 migration document and some work-around, we are getting ClassCastExceptions during deployment.
how do I keep from getting these exceptions in my deployment file?
Or how can we force JBoss SA to load all EJB jars by a single class loader.

How to add source files in another folder

I'm using cmake to build my project in C++. Assume I have the following directories on my Source folder
Source
|_Dir1
| |_Class.cpp
| |_Class.hpp
|
|_Dir2
|_Main.cpp
In Dir1 there's a class with its header and implementation files (Class.cpp and Class.hpp).
In Dir2 there's the main application which uses the class in Dir1
What is the good way to tell the CMakeLists in Dir2 to build the executable with Dir1/Class.cpp file?
EDIT: To be more specific, I want to define that the source file for Class.cpp has to be used in Dir1's CMakeLists.txt, and not in Dir2's. Doing it the other way feels plain wrong to me and it's hard to use, so if there's a reason they're enforcing me to do this some clarification on the topic would be nice.
What I'm currently doing is hard-coding the Class.cpp file location in Dir2/CMakeLists.txt but that just doesn't scale when I've got a bunch of classes interacting together.
Supposed you have a single CMakeLists.txt file at the Source directory, you'll create two variables using different file() commands
file(GLOB Dir1_Sources RELATIVE "Dir1" "*.cpp")
file(GLOB Dir2_Sources RELATIVE "Dir2" "*.cpp")
and add both sets generated by the file() commands to your target's source list:
add_executable(MyProgram ${Dir1_Sources} ${Dir2_Sources})
Alternatively you can place a CMakeLists.txt file under Dir1 and Dir2 (Main) looking as follows
Source
|
|_ CMakeLists.txt
| > project(MyProgram)
| > cmake_minimum_required(VERSION 3.8)
| > add_subdirectory("Dir1")
| > add_subdirectory("Dir2")
|
|_ Dir1
| |_ CMakeLists.txt
| > file(GLOB Sources "*.cpp")
| > add_library(Dir1 STATIC ${Sources})
|_ Dir2
|_ CMakeLists.txt
> file(GLOB Sources "*.cpp")
> add_executable(MyProgram ${Sources})
> target_link_libraries(MyProgram Dir1)
to add subdirectories as further (static) libraries linked to your main target.

CMake exclude tests in subdirectories

I have a c++ project which includes libevent library. Project structure:
.
|_ CMakeLists.txt
|_ Makefile
|_ src
| |_ my_lib.cpp
|_ test
| |_ my_lib_test.cpp
|_ lib
|_ libevent
|_ CMakeLists.txt
|_ ...
When I build and run my tests, libevent tests are also executed. How can I exclude them and run only my own tests?
There is also a more general way to do it. Add a file named CTestCustom.cmake to your source tree and add a list of tests that you want CTest not to run:
set(CTEST_CUSTOM_TESTS_IGNORE
test1
....
testN
)
Then copy this file to the build directory where tests are executed:
configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_BINARY_DIR})
This will make CTest ignore the listed tests. See this for more info.
Looking at the available options in libevent's CMakeLists.txt file, it appears that you can disable these pretty easily by setting EVENT__DISABLE_TESTS to ON.
You can either do this in your own CMakeLists.txt before libevent is included:
set(EVENT__DISABLE_TESTS ON)
...
add_subdirectory(lib/libevent)
or when you invoke CMake on the command line:
cmake . -DEVENT__DISABLE_TESTS=ON
I've found another (better) way to solve the actual question.
TL;DR
Add to your CMakeLists.txt file:
configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_BINARY_DIR} #ONLY)
Add do your CTestCustom.cmake file in your source code:
file (STRINGS "#CMAKE_BINARY_DIR#/CTestTestfile.cmake" LINES)
# overwrite the file....
file(WRITE "#CMAKE_BINARY_DIR#/CTestTestfile.cmake" "")
# loop through the lines,
foreach(LINE IN LISTS LINES)
# remove unwanted parts
string(REGEX REPLACE ".*directory_to_remove.*" "" STRIPPED "${LINE}")
# and write the (changed) line ...
file(APPEND "#CMAKE_BINARY_DIR#/CTestTestfile.cmake" "${STRIPPED}\n")
endforeach()
(See https://stackoverflow.com/a/59506088/4166604 for a function form of removing a line)
Explanation:
The excluding per test method has many downsides, including dynamically (via a macro) added tests, wasted time, etc...
This was tested on CMake 3.x: When a CMake project with tests enabled is built, a CTestTestfile.cmake file is generate in the CMAKE_BINARY_DIR. Essentially every time add_subdirectory is called, an equivalent subdirs command is added to the CTestTestfile.cmake file. The CTestTestfile.cmake files will mimic an equivalent directory structure as the CMakeLists.txt files. (So if you need to remove a sub directory in another directory, that's the CTestTestfile.cmake you need to edit).
The CTestCustom.cmake is executed before the CTestTestfile.cmake, so all CTestCustom.cmake needs to do is remove the offending line from the CTestTestfile.cmake file. This could be done with a sed, but in the spirit of cross compatibility, it's all pure CMake now. The CTestCustom.cmake does not have CMAKE_BINARY_DIR set, so we use # substitution to get the value of CMAKE_BINARY_DIR at CMake generate time, and replace the values that will be in the CTestCustom.cmake copy in the build directory, using #ONLY replacement, to leave the other variables $ alone.
I agree with #Ivan Baidakou.
I'm not sure this is much better, but here's a non-portable hack (won't work on Windows by default) to get it done.
execute_process(COMMAND sh -c "echo 'set(CTEST_CUSTOM_TESTS_IGNORE'; find '${CMAKE_SOURCE_DIR}/relative_paths' -path '*tests/CMakeLists.txt' -exec sed -nE '/add_test.*NAME/{s|.*NAME *([^ ]+).*|\\1|; p}' {} +; echo ')'"
OUTPUT_FILE ${CMAKE_BINARY_DIR}/CTestCustom.cmake)
Where ${CMAKE_SOURCE_DIR}/relative_paths can be multiple paths for multiple libraries if you want.