I have a C++17 application using nothing but STL and boost 1.71.0. The application needs to run on Windows, Linux and BSD. On Windows I use GCC 9.2 provided by MinGW-w64. I use the distribution that comes with MSYS2.
I need to have the ability to create a system process (launching an external application from within my C++ application).
In the past I used QProcess of the Qt libraries for this. However, this application doesn't have any Qt dependencies and I'd like to prevent adding Qt dependencies just for this one feature.
Looking for solutions I came across boost::process. On first glance this seems like a very suitable alternative to QProcess.
I started by creating a minimal application using C++17, cmake and boost:
#include <iostream>
#include <boost/process.hpp>
int main() {
int result = boost::process::system("g++ main.cpp");
return 0;
}
Unfortunately, I ran into compilation errors straight away:
====================[ Build | boost_process_test | Debug ]======================
C:\Users\joel\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\193.5233.103\bin\cmake\win\bin\cmake.exe --build C:\Users\joel\Documents\projects\boost_process_test\cmake-build-debug --target boost_process_test -- -j 6
Scanning dependencies of target boost_process_test
[ 50%] Building CXX object CMakeFiles/boost_process_test.dir/main.cpp.obj
In file included from C:/msys64/mingw64/include/boost/process/detail/windows/handles.hpp:11,
from C:/msys64/mingw64/include/boost/process/detail/used_handles.hpp:17,
from C:/msys64/mingw64/include/boost/process/detail/windows/async_in.hpp:20,
from C:/msys64/mingw64/include/boost/process/async.hpp:49,
from C:/msys64/mingw64/include/boost/process.hpp:23,
from C:\Users\joel\Documents\projects\boost_process_test\main.cpp:2:
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp:208:51: error: expected ')' before '*' token
208 | typedef ::boost::winapi::NTSTATUS_ (__kernel_entry *nt_system_query_information_p )(
| ~ ^~
| )
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp:223:51: error: expected ')' before '*' token
223 | typedef ::boost::winapi::NTSTATUS_ (__kernel_entry *nt_query_object_p )(
| ~ ^~
| )
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp: In function 'boost::winapi::NTSTATUS_ boost::process::detail::windows::workaround::nt_system_query_information(boost::process::detail::windows::workaround::SYSTEM_INFORMATION_CLASS_, void*, boost::winapi::ULONG_, boost::winapi::PULONG_)':
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp:239:12: error: 'nt_system_query_information_p' does not name a type; did you mean 'nt_system_query_information'?
239 | static nt_system_query_information_p f = reinterpret_cast<nt_system_query_information_p>(::boost::winapi::get_proc_address(h, "NtQuerySystemInformation"));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| nt_system_query_information
In file included from C:/msys64/mingw64/include/boost/process/detail/windows/handles.hpp:11,
from C:/msys64/mingw64/include/boost/process/detail/used_handles.hpp:17,
from C:/msys64/mingw64/include/boost/process/detail/windows/async_in.hpp:20,
from C:/msys64/mingw64/include/boost/process/async.hpp:49,
from C:/msys64/mingw64/include/boost/process.hpp:23,
from C:\Users\joel\Documents\projects\boost_process_test\main.cpp:2:
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp:241:14: error: 'f' was not declared in this scope
241 | return (*f)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
| ^
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp: In function 'boost::winapi::BOOL_ boost::process::detail::windows::workaround::nt_query_object(boost::winapi::HANDLE_, boost::process::detail::windows::workaround::OBJECT_INFORMATION_CLASS_, void*, boost::winapi::ULONG_, boost::winapi::PULONG_)':
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp:253:12: error: 'nt_query_object_p' does not name a type; did you mean 'nt_query_object'?
253 | static nt_query_object_p f = reinterpret_cast<nt_query_object_p>(::boost::winapi::get_proc_address(h, "NtQueryObject"));
| ^~~~~~~~~~~~~~~~~
| nt_query_object
C:/msys64/mingw64/include/boost/process/detail/windows/handle_workaround.hpp:255:14: error: 'f' was not declared in this scope
255 | return (*f)(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
| ^
mingw32-make.exe[3]: *** [CMakeFiles\boost_process_test.dir\build.make:62: CMakeFiles/boost_process_test.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:75: CMakeFiles/boost_process_test.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/boost_process_test.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:117: boost_process_test] Error 2
Here is my corresponding CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(boost_process_test)
set(CMAKE_CXX_STANDARD 17)
find_package(Boost 1.71.0 REQUIRED)
add_executable(boost_process_test main.cpp)
I consulted the boost.process documentation to figure out what kind of dependencies & compatibilities there are. Unfortunately, I couldn't find much info on this.
Before I start getting too deep into actually debugging this - Does somebody know whether boost.process as of version 1.71.0 actually runs on Windows and if so - whether it works with GCC / MinGW and not just MSVC? And if MinGW/GCC is supported - does it rely on posix or win32api?
Solution
I've come across this github issue on the boost::process repository where the OP mentions the same issue. It appears to be a MinGW issue. A workaround was presented in the issue which involves defining the __kernel_entry pre-processor symbol before including the boost/process.hpp header.
Applying this to my code looks like this:
// Workaround for a boost/mingw bug.
// This must occur before the inclusion of the boost/process.hpp header.
// Taken from https://github.com/boostorg/process/issues/96
#ifndef __kernel_entry
#define __kernel_entry
#endif
#include <boost/process.hpp>
int main() {
int result = boost::process::system("g++ main.cpp");
return 0;
}
This made the compilation error(s) go away and resulted in correctly working program binary.
Further steps
After applying the fix the initial compiler error shown in the question didn't appear anymore. However, the program still didn't compile & link properly as I didn't include the boost libraries correctly.
My CMakeLists.txt for the working example looks like this:
cmake_minimum_required(VERSION 3.15)
project(boost_process_test)
set(CMAKE_CXX_STANDARD 17)
find_package(Boost 1.71.0 REQUIRED
COMPONENTS
filesystem
system
)
add_executable(boost_process_test main.cpp)
target_link_libraries(boost_process_test
PRIVATE
$<$<BOOL:${WIN32}>:ws2_32>
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
)
Note the linking towards the ws2_32 library on Windows platforms.
Credits
Thank you # mrjj from the Qt community for pointing me towards the github issue that helped me solving this compilation issue.
Related
I would like to use Open3d in LAMMPS. Open3D details how to find the pre-installed Open3D package using cmake.
Using the above, I have written a cmake file that I believe LAMMPS uses during its build stage to find packages and link them. Curiously, the line
target_link_libraries(lammps PRIVATE Open3D::Open3D)
appears to cause the compiler to find errors in the LAMMPS src code, i.e.,
/home/USER/lammps/src/fmtlib_format.cpp:58:51: error: duplicate explicit instantiation of ‘struct fmt::v7_lmp::detail::basic_data<void>’ [-fpermissive]
58 | template struct FMT_INSTANTIATION_DEF_API detail::basic_data<void>;
If I comment the target_link_libraries statement, the code compiles just fine (but doesn't link to Open3D). Apologies for being unable to provide a MWE as I do not know how to replicate this behaviour in a simple manner. Could you please explain to me why the target_link_libraries command causes the compiler to find errors in the LAMMPS src code and provide a solution to prevent this from occuring? If relevant I am using Clion 2021.1.2 and
CMAKE_CXX_COMPILER_VERSION = 9.3.0
CMAKE_CXX_STANDARD = 11
CMAKE_VERSION = 3.19.2
CMake is giving me a real hard time, here. I checked out llvm, clang, and extras, and I created a custom driver folder, added it to the llvm\tools\clang\tools\extra\CMakeLists.txt and created my own CMakeLists.txt:
cmake_minimum_required(VERSION 3.8)
set(LLVM_LINK_COMPONENTS
Support
)
set(CMAKE_CXX_FLAGS ${LLVM_CONFIG})
set(CMAKE_CXX_COMPILER "clang++")
add_clang_executable(mydriver
main.cpp
)
set(CLANG_LIBS clangFrontend clangDriver clangSerialization clangParse
clangCodeGen clangSema clangAnalysis clangEdit clangAST clangLex
clangBasic )
target_link_libraries(mydriver ${CLANG_LIBS})
target_link_libraries(mydriver ${LLVM_LIBS})
CMake works fine. I target VS2017 and build the mydriver project with msbuild
λ msbuild tools\clang\tools\extra\mydriver\mydriver.vcxproj
This results in the following error:
"C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj" (default target) (1) ->
(ClCompile target) ->
C:\dev\llvm\tools\clang\tools\extra\mydriver\main.cpp(45): error C2027: use of undefined type 'clang::Preprocessor Options' [C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj]
C:\dev\llvm\tools\clang\tools\extra\mydriver\main.cpp(45): error C2228: left of '.addRemappedFile' must have class /struct/union [C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj]
C:\dev\llvm\tools\clang\tools\extra\mydriver\main.cpp(50): error C2664: 'void clang::CompilerInstance::setInvocati on(std::shared_ptr<clang::CompilerInvocation>)': cannot convert argument 1 from 'clang::CompilerInvocation *' to 'st d::shared_ptr<clang::CompilerInvocation>' [C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj]
However, clangLex is clearly included in the CLANG_LIBS variable in my CMakeLists.txt. The documentation of the clang::PreprocessorOptions class seems to indicate that I have the right libs included.
Any ideas?
Please note that this question is closely related to this one:
Generate assembly from C code in memory using libclang
In classic SO fashion, the problem was that the include file had migrated since the example was posted. The clang documentation requires a new header file, that is, in fact, in the include path. All I needed was:
#include <clang/Lex/PreprocessorOptions.h>
Sorry folks, nothing to see here.
I'm trying to compile some C++/OpenGL source codes in FreeBSD-10.2-RELEASE.
To be specific, I'm following the instruction below:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-1-opening-a-window/#Building_on_Linux
In step 6, I got an error message says:
In file included from /home/(my username)/Downloads/OpenGL-tutorial_v0014_33/external/glew-1.9.0/src/glew.c:32:
/home/(my username)/Downloads/OpenGL-tutorial_v0014_33/external/glew-1.9.0/include/GL/glew.h:1180:14: fatal error:
'GL/glu.h' file not found
# include <GL/glu.h>
^
1 error generated.
*** Error code 1
Stop.
I installed some packages such as graphics/glew, graphics/glfw, math/glm, graphics/libGL, graphics/libGLU, etc, but it still fails.
What should I do to make them work?
Thank you.
In FreeBSD OpenGL includes are located in /usr/local/include, so you need -I/usr/local/include flag.
To make tutorials link properly, you'd also need to replace
set(ALL_LIBS
${OPENGL_LIBRARY}
GLFW_303
GLEW_190
)
with
set(ALL_LIBS
${OPENGL_LIBRARY}
glfw3
GLEW
)
Note that you seemingly using headers from older libraries, this might cause more problems.
I am currently trying to build a 3rd party project (qt 5.0.1) for Solaris and am currently stuck with the following error:
io/qtemporarydir.cpp: In member function 'void QTemporaryDirPrivate::create(const QString&)':
io/qtemporarydir.cpp:150:30: error: 'mkdtemp' was not declared in this scope
gmake[3]: *** [.obj/release-shared/qtemporarydir.o] Error 1
From what I have found out, mkdtemp should be found in stdlib.h which is in /usr/include. However looking in stdlib.h on my solaris system it soes not define the mkdtemp method.
Does anyone know of a workaround for this? (Or how I can compile Qt for Solaris...)
I have since found that there was an additional function in the Qt source which replaced mkdtemp for systems which did not define it themselves. However it was wrapped in an #ifdef statement which did not account for Solaris builds. Uncommenting the #ifdef wrapper fixed that buil
Has anyone successfully compiled the performance test application for boost::math library?
link: http://www.boost.org/doc/libs/1_50_0/libs/math/doc/sf_and_dist/html/math_toolkit/perf/perf_test_app.html
I tried compiling by running b2 in the directory and there were lots of errors (over 222000 lines).
First few lines of errors:
../test/erf_data.ipp:6:74: error: wrong number of template arguments (1, should be 2)
In file included from ../../../boost/math/tools/rational.hpp:13:0,
from ../../../boost/math/special_functions/log1p.hpp:18,
from ../../../boost/math/special_functions/gamma.hpp:35,
from test_erf.cpp:9:
../../../boost/array.hpp:60:11: error: provided for ‘template<class T, long unsigned int N> class boost::array’
In file included from test_erf.cpp:13:0:
../test/erf_data.ipp:6:80: error: template argument 1 is invalid
../test/erf_data.ipp:6:91: error: invalid type in declaration before ‘=’ token
../test/erf_data.ipp:7:38: error: ‘SC_’ was not declared in this scope
../test/erf_data.ipp:7:88: error: ‘SC_’ was not declared in this scope
In file included from test_erf.cpp:13:0:
../test/erf_data.ipp:7:136: error: ‘SC_’ was not declared in this scope
Alright, I got it to compile and link properly but it was not with b2. I know the OP asked for b2 but im not familiar with it so i am providing an alternative. This solution assumes you have Cmake installed. (easy to do, just ask dr google.)
If you go to the math tests location:
~/pathToBoost/libs/math/performance
and you add a file called:
CMakeLists.txt
with the following Contents:
cmake_minimum_required(VERSION 2.8)
find_package(Boost COMPONENTS REQUIRED)
include_directories(${DEPENDENCY_DIR}/libboost/lib)
add_executable(main main.cpp test_reference.cpp)
target_link_libraries (main ${Boost_LIBRARIES} boost_regex)
Then you make a folder called build:
mkdir build
And build it.
cd build
cmake ..
make
Doing this got me successful compilation and building. I get a program called main out of it.
Hope this helps.