Qt Plugin with OpenMP Support on MinGW: Undefined reference? - c++

I am developing a "Qt Plugin" which uses OpenMP (OpenMP support can be enabled/disabled using CMake parameter). I use MinGW and CMake as development environment.
This is how I enable/disable OpenMP in the code:
#ifdef OPENMP_ENABLE
#pragma omp parallel for
#endif for(int i=0; i<volumeData->getZSize(); i++){ .
I have enabled OpenMP in CMake file as follows:
OPTION (OPENMP_SUPPORT "Build with OpenMP parallaization enabled")
IF (OPENMP_SUPPORT)
FIND_PACKAGE( OpenMP )
SET(CMAKE_CXX_FLAGS "${OpenMP_CXX_FLAGS}")
IF ( OpenMP_CXX_FLAGS )
MESSAGE("------- Adding compiler parameter for OpenMP")
ADD_DEFINITIONS(-DOPENMP_ENABLE)
ENDIF()
ENDIF()
and to build Qt plugin, I have configured CMake as follows:
ADD_DEFINITIONS(-DQT_PLUGIN)
ADD_DEFINITIONS(-DQT_SHARED)
This configuration compiles fine with Linux.
In Windows it compiles fine WITHOUT OpenMP support.
But when build with OpenMP support, it gives the error
c:/mingw4/bin/../lib/gcc/mingw32/4.5.0/../../../../mingw32/bin/ld.exe:
warning:auto-importing has been
activated without --enable-auto-import
specified on the command line. This
should work unless it involves
constant data structures referencing
symbol from auto-imported DLLs.
CMakeFiles\RinzoDLPluginIPThreshold.dir\ui\dialogthresholdconfig.cpp.obj:C:/svnosaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/imageprocplugins/thresholdPlgin/ui/dialogthresholdconfig.cpp:221:
undefined reference to
GOMP_parallel_stat'
CMakeFiles\RinzoDLPluginIPThreshold.dir\ui\dialogthresholdconfig.cpp.obj:C:/svnosaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/imageprocplugins/thresholdPlgin/ui/dialogthresholdconfig.cpp:221:
undefined reference to
GOMP_parallel_end
CMakeFiles\RinzoDLPluginIPThreshold.dir\ui\dialogthresholdconfig.cpp.obj:
In function
ZN21DialogThresholdConfig9slotApplyEv.omp_fn.0':
C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/imageprocplugins/threholdPlugin/ui/dialogthresholdconfig.cpp:223:
undefined reference to
omp_get_nu_threads'
C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/imageprocplugins/threholdPlugin/ui/dialogthresholdconfig.cpp:223:
undefined reference to
omp_get_thead_num'
C:/svn/osaka3d/trunk/osaka3d/rinzo-platform/src/dlplugins/imageprocplugins/threholdPlugin/ui/dialogthresholdconfig.cpp:233:
undefined reference to
omp_get_thead_num' collect2: ld
returned 1 exit status make[2]: *
[dist/plugins/libRinzoDLPluginIPThreshold.dll]
Error 1
Here is my complete CMake file:
http://www.keepandshare.com/doc/view.php?id=2552392&da=y
Any tip?

OpenMP requires a runtime library (called libgomp in case of gcc), which must be linked into the created executable. It is therefore not sufficient to add the OpenMP flags to the compilation flags, they must also be added to the link flags:
set_target_properties(<target_name> LINK_FLAGS "${OpenMP_CXX_FLAGS}")
Of course, you need to replace <target_name> with the actual name of your target.
And by the way, and extra definition like OPENMP_ENABLE is superfluous. If OpenMP is enabled, the macro _OPENMP is implicitly defined to contain the supported version of OpenMP (more precisely, the release date of the supported standard). You can use this macro to test for OpenMP support in the source code:
#if defined(_OPENMP)
// use openmp
#endif

Related

How can cmake_minimum_required required version impact generated files?

I'm experiencing a strange behaviour where changing cmake_minimum_required affects files generated by CMake targetting Visual Studio 2019. According to the doc of cmake_minimum_required:
If the running version of CMake is lower than the required version it will stop processing the project and report an error
So it's just supposed to interrupt project generation.
But, if I create:
main.cpp:
int main()
{
#ifndef _DEBUG
#error "DEBUG flag not set"
#endif
return 0;
}
and CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12)
project(hello_world)
set( CMAKE_CONFIGURATION_TYPES "Debug;Release;MyDebug" CACHE INTERNAL "" FORCE )
set( CMAKE_CXX_FLAGS_MYDEBUG "${CMAKE_CXX_FLAGS_DEBUG}" )
set( CMAKE_C_FLAGS_MYDEBUG "${CMAKE_C_FLAGS_DEBUG}" )
set( CMAKE_EXE_LINKER_FLAGS_MYDEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" )
set( CMAKE_SHARED_LINKER_FLAGS_MYDEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" )
set_property( GLOBAL PROPERTY DEBUG_CONFIGURATIONS "Debug;MyDebug" )
add_executable(app main.cpp)
If I generate this project with CMake 3.24.1 for Visual Studio 2019, then it builds correctly using MyDebug config as _DEBUG compilation flag is correctly set.
However, if I change cmake_minimum_required(VERSION 2.8.12) to cmake_minimum_required(VERSION 3.24.1), then it fails to build, reporting DEBUG flag not set, meaning _DEBUG compilation flag is not set anymore.
When I check vcproj file, I see that for MyDebug, <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> is changed to <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>.
Is this a CMake bug or am I doing something wrong?
So it's just supposed to interrupt project generation.
That's not the case at all!
cmake_minimum_required puts your project into a backwards compatibility mode consistent with the version specified. The "Policy Settings" section of that doc talks about this. There are a set of now over one hundred CMake policies that enable breaking improvements to the system. You can see the full list here: https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html
The relevant policy here is CMP0091 which was introduced in CMake 3.15.
CMake 3.15 and above prefer to leave the MSVC runtime library selection flags out of the default CMAKE_<LANG>_FLAGS_<CONFIG> values and instead offer a first-class abstraction. The CMAKE_MSVC_RUNTIME_LIBRARY variable and MSVC_RUNTIME_LIBRARY target property may be set to select the MSVC runtime library. If they are not set then CMake uses the default value MultiThreaded$<$<CONFIG:Debug>:Debug>DLL which is equivalent to the original flags.
So to upgrade your project to a version of CMake newer than 3.15, you'll just need to override the default CMAKE_MSVC_RUNTIME_LIBRARY close to the top of your CMakeLists.txt file:
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug,MyDebug>:Debug>DLL"
CACHE STRING "Rule for selecting MSVC runtime")
This uses the $<CONFIG> generator expression to enable the debug runtime for your custom MyDebug config.
Of course cmake can change behaviour with its evolution.
As CMake evolves it is sometimes necessary to change existing behavior in order to fix bugs or improve implementations of existing features. *
If it just changes some behaviour in a new version, it introduces a policy, that can explicitly switch cmake to use an old behaviour. The OLD behavior of a policy becomes deprecated by definition and may be removed in a future version of CMake.
See what is changed in the list cmake-policies(7).
Also you can set cmake_minimum_required incrementing the major version number by one at a time, run cmake and see what policies were introduced in cmake dump. One of them is changing the behaviour of RuntimeLibrary and _DEBUG.

How to use llvm target initialize function

My Host System
: Default target: x86_64-unknown-linux-gnu
: Host CPU: skylake
LLVM/Clang built with LLVM_TARGETS_TO_BUILD=all option.
How to Use another target's Initialize Function in My code?
I modifying klee (symbolic execution tool) to run cross-platform Target's IR.
#include "llvm/Support/TargetSelect.h"
int main () {
...
// llvm::InitializeAllTargets(); -> Error
llvm::InitializeNativeTargets(); -> Success
...
}
In this case, error
${LLVM}/build/include/llvm/Config/Targets.def:28: undefined reference to `LLVMInitializeARMTargetInfo'
${LLVM}/build/include/llvm/Config/Targets.def:29: undefined reference to `LLVMInitializeBPFTargetInfo'
...
The LLVMInitializexxxTargetInfo() functions are used by InitializeAllTargets(), and the error message implys that you didn't link the required LLVM libraries.
InitializeNativeTargets() succeeded, because you maybe did't include your native arch in -DLLVM_TARGETS_TO_BUILD.
You can add the following lines in your CMakeLists.txt to link LLVM Targets libraries:
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
)
# Build your .cpp with llvm macro to use LLVM_LINK_COMPONENTS
add_llvm_xxx_macro(YourOutputFile
...
)

Cannot set __cplusplus to C++17 standard with Visual Studio and CMake

I've a CMake project that's opened with Visual Studio 2019. I need c++17 features for my code, so I've set the corresponding flag in the CMakeLists.txt
cmake_minimum_required (VERSION 3.10.0)
project (datalog)
message (STATUS "Building project ${PROJECT_NAME}")
find_package(stxxl CONFIG REQUIRED)
include_directories (${CMAKE_SOURCE_DIR}/src)
set (PROJECT_SRC
main.cpp
)
add_executable (${PROJECT_NAME} ${PROJECT_SRC})
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
target_link_libraries(${PROJECT_NAME} stxxl)
When I build I obtain a lot of errors, because the library that I'm linking, stxxl, installed with vcpkg, has the following piece of code:
STXXL_BEGIN_NAMESPACE
template <class Type>
struct compat_unique_ptr {
#if __cplusplus >= 201103L && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40400)
typedef std::unique_ptr<Type> result;
#else
// auto_ptr is inherently broken and is deprecated by unique_ptr in c++0x
typedef std::auto_ptr<Type> result;
#endif
};
STXXL_END_NAMESPACE
The problem is that __cplusplus has value 199711L instead of the correct value 201703L, so code tries to use auto_ptr that's removed in C++17 standard.
I've also tried to set the flag manually in Visual Studio, adding this section in the CmakeLists.txt
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /Zc:__cplusplus")
endif()
But nothing changes. I'm also using some C++17 features, so going back at the moment is not an option.
I can manually update the stxxl header file to get rid of the macro, but it's a workaround, and every developer should create the same fix. Instead, I'd like to know why I'm getting the error and how to set the macro to the correct value with Visual Studio and CMake. Do you have any suggestion?
As far as i can tell from this, you need to add /Zc:__cplusplus manually (at least for now).
Your CMakeList snippet worked for me, are you sure, that __cplusplus is actually set incorrectly and it's not just the __GNUC__ Macro, that's missing?
That said, I'd recommend to test if the version of VisualStudio is actually new enough:
# /Zc:__cplusplus is required to make __cplusplus accurate
# /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7
# (according to https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus)
# That version is equivalent to _MSC_VER==1914
# (according to https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019)
# CMake's ${MSVC_VERSION} is equivalent to _MSC_VER
# (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
if ((MSVC) AND (MSVC_VERSION GREATER_EQUAL 1914))
target_compile_options(stxxl INTERFACE "/Zc:__cplusplus")
endif()
Note: I used target_compile_options to add the necessary option to the interface of your library target. This way all targets, that depend on that library (via target_link_libraries) will be compiled with that flag, but targets, that don't need it (and might be incompatible with it) won't get it.
If you want to add the flag to one of your own targets, you can use target_compile_options(stxxl PUBLIC "/Zc:__cplusplus") (PUBLIC instead of INTERFACE). INTERFACE means the option is used when other targets depend on that target, PRIVATE means the option is used for the target itself and PUBLIC means both. (IMHO this artical explains it well.)
Apart from that, you shouldn't set the c++ standard version via compile flags, but instead using target_compile_features if the newer version is required and using
set_target_properties(your_target_name PROPERTIES CXX_STANDARD 17) if you just wish to use the newer version if it is available.
In your case the latter is probably sufficient as your codesnippet has a fallback if the c++ version is older.
If changing the code of stxxl (via pull request, etc.) is an option, the code could test _MSVC_LANG and _MSC_VER. This way it would work without requiring /Zc:__cplusplus.
I think what you need is target_compile_definitions, where you can define arbitrary macros in CMake and pass to compiler.

Linker error when enabling Link Time Optimization in NDK

When I add the flag -flto to my NDK C++ project the linker emits the following error: "Optimization level must be between 0 and 3", even though my optimization level is explicitly set to 3 via -O3.
Does anyone know how to solve this?
The compiler flags are passed via Gradle which, as I understand it, should pass the flags to both the Clang compiler and linker. When I remove the -flto flag everything works fine.
Notes:
I'm using NDK 19.2 (latest version at the time I write this).
I also get the warning "clang++.exe: warning: argument unused during compilation: '-Wa,--noexecstack' [-Wunused-command-line-argument]" which I do not have if I compile without link time optimizations.
Two parts to the answer:
The error is caused by https://github.com/android-ndk/ndk/issues/721. Clang's LTO plugin just doesn't accept -Os or -Oz. This is a bug.
Okay, I might be really stupid, I suppose between 0 and 3 means 1 or 2 :)
It's actually because you can't use the generic cppFlags to set optimization levels. That corresponds to CMAKE_CXX_FLAGS, and you need to set these in CMAKE_CXX_FLAGS_DEBUG and CMAKE_CXX_FLAGS_RELEASE (and/or the C flavors of those). CMake has its own defaults in those variables and the command line is built as ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}, so your -O3 is being overridden by the default.
I also encounter this linking error but I fixed through a different way.
I had cross-compile a library for android with architectures of both arm64 and armv7. It's all OK for arm64 but encounter the linking error for armv7. And I found it can be fixed by commented out the following statements in my CMakeLists.txt:
if (${CMAKE_MAJOR_VERSION} GREATER_EQUAL 3 AND ${CMAKE_MINOR_VERSION} GREATER_EQUAL 9)
cmake_policy(SET CMP0069 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_supported OUTPUT ipo_supported_output)
if (ipo_supported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif ()
endif ()
The above CMake statements are related to the IPO setting and it seems cause the linking error when cross-compiling for android armv7.
I don't know why the IPO should not enabled for android armv7.

CLion and Crypto++ library

Some time ago I started coding my application in Visual Studio 2015, had no issues setting all of the library dependencies.
Now, I decided to move to CLion. However my application has a dependency of cryptopp library, which I need to link in my CLion project.
Currently, I'm facing tons of undefined reference errors
undefined reference to `CryptoPP::Integer::Integer(char const*)'
undefined reference to `CryptoPP::Integer::Integer(char const*)'
undefined reference to `CryptoPP::Integer::Integer(char const*)'
undefined reference to `CryptoPP::DH_Domain<CryptoPP::DL_GroupParameters_GFP_DefaultSafePrime, CryptoPP::EnumToType<CryptoPP::CofactorMultiplicationOption, 0> >::AccessGroupParameters()'
undefined reference to `CryptoPP::DH_Domain<CryptoPP::DL_GroupParameters_GFP_DefaultSafePrime, CryptoPP::EnumToType<CryptoPP::CofactorMultiplicationOption, 0> >::GetGroupParameters() const'
undefined reference to `CryptoPP::DH_Domain<CryptoPP::DL_GroupParameters_GFP_DefaultSafePrime, CryptoPP::EnumToType<CryptoPP::CofactorMultiplicationOption, 0> >::GetGroupParameters() const'
[..]
I have indeed set include directories in my CMakeLists:
set(EXTERN_LIBS E:/dev/libs)
include_directories(${EXTERN_LIBS} ${EXTERN_LIBS}/include)
link_directories(${EXTERN_LIBS})
However, I still cannot get it to work.
I'm using MinGW for my project. Here is a preview of settings and versions:
How can I properly add cryptopp library into my project in CLion?
I think we may have mostly cleared the MinGW/C++11 issue at Commit e4cef84883b2. You should work from Master or perform a git pull, and then uncomment the define for CRYPTOPP_NO_CXX11 in config.h : 65 (or so):
// Define CRYPTOPP_NO_CXX11 to avoid C++11 related features shown at the
// end of this file. Some compilers and standard C++ headers advertise C++11
// but they are really just C++03 with some additional C++11 headers and
// non-conforming classes. You might also consider `-std=c++03` or
// `-std=gnu++03`, but they are required options when building the library
// and all programs. CRYPTOPP_NO_CXX11 is probably easier to manage but it may
// cause -Wterminate warnings under GCC. MSVC++ has a similar warning.
// Also see https://github.com/weidai11/cryptopp/issues/529
// #define CRYPTOPP_NO_CXX11 1
I think the problems is, you are hitting issues related to Windows and its lack of proper C++11 support, but you are getting them indirectly. They are indirect because MinGW and GCC is layered on top. MinGW and GCC cannot possibly provide C++11 because the underlying platform cannot.
I think your best bet at this point is to define CRYPTOPP_NO_CXX11. I don't believe we can do it for you like we do on Windows because the defines we need access to are hidden behind MinGW and GCC. And we also have some MSVC++ bugs to workaround.
Here's how we do it on Windows, but we don't have access to these defines in MinGW (from config.h : 950):
// Dynamic Initialization and Destruction with Concurrency ("Magic Statics")
// MS at VS2015 with Vista (19.00); GCC at 4.3; LLVM Clang at 2.9; Apple Clang at 4.0; Intel 11.1; SunCC 5.13.
// Microsoft's implementation only works for Vista and above, so its further
// limited. http://connect.microsoft.com/VisualStudio/feedback/details/1789709
#if (CRYPTOPP_MSC_VERSION >= 1900) && ((WINVER >= 0x0600) || (_WIN32_WINNT >= 0x0600)) || \
(CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000) || \
(__INTEL_COMPILER >= 1110) || (CRYPTOPP_GCC_VERSION >= 40300) || (__SUNPRO_CC >= 0x5130)
# define CRYPTOPP_CXX11_DYNAMIC_INIT 1
#endif // Dynamic Initialization compilers
If you define CRYPTOPP_NO_CXX11, then the following will not be defined and you will avoid the problems: CRYPTOPP_CXX11_DYNAMIC_INIT, CRYPTOPP_CXX11_SYNCHRONIZATION, and CRYPTOPP_CXX11_ATOMICS.
The second issue, the one related to Clion and Cmake, was settled as follows. We setup a separate GitHub with our Autotools and Cmake files. The Autotools files are at cryptopp-autotools, and the Cmake files are at cryptopp-cmake.
The repositories are in my GiHub because this is the sort of administrivia that Wei Dai, who wrote the library and provides the Crypto++ GitHub, prefers to avoid. The logical separation also helps establish the logical boundary so folks know Autotools and CMake are not part of the official Crypto++ distribution.
The community is responsible for Autotools and Cmake, and we will work with the community on issues. If the community puts in the work, then Autotools and Cmake will improve. If either Autotools or CMake gets stable, then we will add a tarball with the files to the official distribution.
Currently Autotools and Cmake are in states that needs improvement. The problems with Cmake are detailed at CMake | Current Status on the wiki. The problems with Autotools are not really documented because I work with distro maintainers on them. Its kind of like we know what the prolems are, but most others do not.