使用 CMake (make) 和 GCC 构建和编译 gSOAP 项目
Build and compile gSOAP project with CMake (make) and GCC
我有一个关于 CMake 的非常基本的问题,我将不胜感激任何帮助。
问题:
当我尝试使用纯 GCC 编译 gSOAP 时一切正常,但是当我使用 CMake 生成 Makefile 并构建它时,出现链接错误。
这是有效的 gcc 命令(但这不是一个好的解决方案):
c++ -o vms_server -Wall -fpermissive -DWITH_OPENSSL -DWITH_DOM -DWITH_ZLIB \
-I. -I gen -I libs/gsoap-2.8/gsoap/plugin -I libs/gsoap-2.8/gsoap/custom -I libs/gsoap-2.8/gsoap \
main.cpp \
gen/soapC.cpp \
gen/wsddClient.cpp \
gen/wsddServer.cpp \
gen/soapAdvancedSecurityServiceBindingProxy.cpp \
gen/soapDeviceBindingProxy.cpp \
gen/soapDeviceIOBindingProxy.cpp \
gen/soapImagingBindingProxy.cpp \
gen/soapMediaBindingProxy.cpp \
gen/soapPTZBindingProxy.cpp \
gen/soapPullPointSubscriptionBindingProxy.cpp \
gen/soapRemoteDiscoveryBindingProxy.cpp \
libs/gsoap-2.8/gsoap/stdsoap2.cpp \
libs/gsoap-2.8/gsoap/dom.cpp \
libs/gsoap-2.8/gsoap/plugin/smdevp.c \
libs/gsoap-2.8/gsoap/plugin/mecevp.c \
libs/gsoap-2.8/gsoap/plugin/wsaapi.c \
libs/gsoap-2.8/gsoap/plugin/wsseapi.c \
libs/gsoap-2.8/gsoap/plugin/wsddapi.c \
-lcrypto -lssl -lz
这是有问题的 CMakeLists.txt 文件:
cmake_minimum_required(VERSION 3.10.2)
project(vms_server LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-Wall -fpermissive -DWITH_OPENSSL -DWITH_DOM -DWITH_ZLIB)
find_package(OpenSSL REQUIRED)
find_package(ZLIB)
SET(SRC_FILES main.cpp)
SET(GSOAP_DEP_FILES
libs/gsoap-2.8/gsoap/stdsoap2.cpp
libs/gsoap-2.8/gsoap/dom.cpp
libs/gsoap-2.8/gsoap/plugin/smdevp.c
libs/gsoap-2.8/gsoap/plugin/mecevp.c
libs/gsoap-2.8/gsoap/plugin/wsse2api.c
libs/gsoap-2.8/gsoap/plugin/wsaapi.c
libs/gsoap-2.8/gsoap/plugin/wsseapi.c
libs/gsoap-2.8/gsoap/plugin/wsddapi.c
)
SET(GEN_FILES
gen/soapC.cpp
gen/wsddClient.cpp
gen/wsddServer.cpp
gen/soapAdvancedSecurityServiceBindingProxy.cpp
gen/soapDeviceBindingProxy.cpp
gen/soapDeviceIOBindingProxy.cpp
gen/soapImagingBindingProxy.cpp
gen/soapMediaBindingProxy.cpp
gen/soapPTZBindingProxy.cpp
gen/soapPullPointSubscriptionBindingProxy.cpp
gen/soapRemoteDiscoveryBindingProxy.cpp
)
include_directories(
libs/gsoap-2.8/gsoap/plugin
libs/gsoap-2.8/gsoap/custom
libs/gsoap-2.8/gsoap
gen
)
add_executable(vms ${SRC_FILES} ${GSOAP_DEP_FILES} ${GEN_FILES})
target_link_libraries(vms OpenSSL::Crypto OpenSSL::SSL ${ZLIB_LIBRARIES})
cmake .
命令运行时没有警告或问题,但随后 make
输出错误:
Scanning dependencies of target vms
[ 6%] Building CXX object CMakeFiles/vms.dir/main.cpp.o
/home/guy/Desktop/vms_server-c++/main.cpp: In function ‘int main()’:
/home/guy/Desktop/vms_server-c++/main.cpp:194:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<tt__Profile*>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
194 | for (int i = 0; i < GetProfilesResponse.Profiles.size(); ++i)
| ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/guy/Desktop/vms_server-c++/main.cpp: At global scope:
/home/guy/Desktop/vms_server-c++/main.cpp:308:13: warning: ‘void dyn_destroy_function(CRYPTO_dynlock_value*, const char*, int)’ defined but not used [-Wunused-function]
308 | static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line)
| ^~~~~~~~~~~~~~~~~~~~
/home/guy/Desktop/vms_server-c++/main.cpp:300:13: warning: ‘void dyn_lock_function(int, CRYPTO_dynlock_value*, const char*, int)’ defined but not used [-Wunused-function]
300 | static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
| ^~~~~~~~~~~~~~~~~
/home/guy/Desktop/vms_server-c++/main.cpp:291:37: warning: ‘CRYPTO_dynlock_value* dyn_create_function(const char*, int)’ defined but not used [-Wunused-function]
291 | static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line)
| ^~~~~~~~~~~~~~~~~~~
[ 13%] Building CXX object CMakeFiles/vms.dir/libs/gsoap-2.8/gsoap/stdsoap2.cpp.o
[ 20%] Building CXX object CMakeFiles/vms.dir/libs/gsoap-2.8/gsoap/dom.cpp.o
[ 26%] Building CXX object CMakeFiles/vms.dir/gen/soapC.cpp.o
[ 33%] Building CXX object CMakeFiles/vms.dir/gen/wsddClient.cpp.o
[ 40%] Building CXX object CMakeFiles/vms.dir/gen/wsddServer.cpp.o
[ 46%] Building CXX object CMakeFiles/vms.dir/gen/soapAdvancedSecurityServiceBindingProxy.cpp.o
[ 53%] Building CXX object CMakeFiles/vms.dir/gen/soapDeviceBindingProxy.cpp.o
[ 60%] Building CXX object CMakeFiles/vms.dir/gen/soapDeviceIOBindingProxy.cpp.o
[ 66%] Building CXX object CMakeFiles/vms.dir/gen/soapImagingBindingProxy.cpp.o
[ 73%] Building CXX object CMakeFiles/vms.dir/gen/soapMediaBindingProxy.cpp.o
[ 80%] Building CXX object CMakeFiles/vms.dir/gen/soapPTZBindingProxy.cpp.o
[ 86%] Building CXX object CMakeFiles/vms.dir/gen/soapPullPointSubscriptionBindingProxy.cpp.o
[ 93%] Building CXX object CMakeFiles/vms.dir/gen/soapRemoteDiscoveryBindingProxy.cpp.o
[100%] Linking CXX executable vms
CMakeFiles/vms.dir/main.cpp.o: In function `set_credentials(soap*)':
main.cpp:(.text+0x65): undefined reference to `soap_wsse_delete_Security'
main.cpp:(.text+0x7d): undefined reference to `soap_wsse_add_Timestamp'
main.cpp:(.text+0xa2): undefined reference to `soap_wsse_add_UsernameTokenDigest'
CMakeFiles/vms.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x3ec): undefined reference to `soap_wsse'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Hello(soap*)':
wsddServer.cpp:(.text+0x63c): undefined reference to `__wsdd__Hello(soap*, wsdd__HelloType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Bye(soap*)':
wsddServer.cpp:(.text+0x751): undefined reference to `__wsdd__Bye(soap*, wsdd__ByeType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Probe(soap*)':
wsddServer.cpp:(.text+0x866): undefined reference to `__wsdd__Probe(soap*, wsdd__ProbeType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__ProbeMatches(soap*)':
wsddServer.cpp:(.text+0x97b): undefined reference to `__wsdd__ProbeMatches(soap*, wsdd__ProbeMatchesType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Resolve(soap*)':
wsddServer.cpp:(.text+0xa90): undefined reference to `__wsdd__Resolve(soap*, wsdd__ResolveType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__ResolveMatches(soap*)':
wsddServer.cpp:(.text+0xba5): undefined reference to `__wsdd__ResolveMatches(soap*, wsdd__ResolveMatchesType*)'
collect2: error: ld returned 1 exit status
CMakeFiles/vms.dir/build.make:436: recipe for target 'vms' failed
make[2]: *** [vms] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/vms.dir/all' failed
make[1]: *** [CMakeFiles/vms.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
我发现当您使用 CMake 生成的 Makefile 进行编译时,您的 .c
文件没有被构建;这是导致 link 错误。因为您正在编译 C++ 项目 (CXX
),CMake 将忽略 .c
文件。您可以尝试通过将 c
文件扩展名附加到 CMAKE_LANG_SOURCE_FILE_EXTENSIONS
列表来告诉 CMake 将 .c
视为 C++ 文件:
list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)
这是一个过激的举动,您可能不希望将其应用于您的所有 C++ 项目。更细粒度的方法是使用 set_source_files_properties()
:
为每个 .c
源文件将 LANGUAGE
属性 设置为 C++
# Split up the GSOAP_DEP_FILES variable based on the file extension (.c or .cpp).
SET(GSOAP_DEP_CPP_FILES
libs/gsoap-2.8/gsoap/stdsoap2.cpp
libs/gsoap-2.8/gsoap/dom.cpp
)
SET(GSOAP_DEP_C_FILES
libs/gsoap-2.8/gsoap/plugin/smdevp.c
libs/gsoap-2.8/gsoap/plugin/mecevp.c
libs/gsoap-2.8/gsoap/plugin/wsaapi.c
libs/gsoap-2.8/gsoap/plugin/wsseapi.c
libs/gsoap-2.8/gsoap/plugin/wsddapi.c
)
...
# Set the language for the .c files to C++, so CMake includes them for compilation.
set_source_files_properties(${GSOAP_DEP_C_FILES} PROPERTIES LANGUAGE CXX)
add_executable(vms ${SRC_FILES} ${GSOAP_DEP_CPP_FILES} ${GSOAP_DEP_C_FILES} ${GEN_FILES})
我有一个关于 CMake 的非常基本的问题,我将不胜感激任何帮助。
问题: 当我尝试使用纯 GCC 编译 gSOAP 时一切正常,但是当我使用 CMake 生成 Makefile 并构建它时,出现链接错误。
这是有效的 gcc 命令(但这不是一个好的解决方案):
c++ -o vms_server -Wall -fpermissive -DWITH_OPENSSL -DWITH_DOM -DWITH_ZLIB \
-I. -I gen -I libs/gsoap-2.8/gsoap/plugin -I libs/gsoap-2.8/gsoap/custom -I libs/gsoap-2.8/gsoap \
main.cpp \
gen/soapC.cpp \
gen/wsddClient.cpp \
gen/wsddServer.cpp \
gen/soapAdvancedSecurityServiceBindingProxy.cpp \
gen/soapDeviceBindingProxy.cpp \
gen/soapDeviceIOBindingProxy.cpp \
gen/soapImagingBindingProxy.cpp \
gen/soapMediaBindingProxy.cpp \
gen/soapPTZBindingProxy.cpp \
gen/soapPullPointSubscriptionBindingProxy.cpp \
gen/soapRemoteDiscoveryBindingProxy.cpp \
libs/gsoap-2.8/gsoap/stdsoap2.cpp \
libs/gsoap-2.8/gsoap/dom.cpp \
libs/gsoap-2.8/gsoap/plugin/smdevp.c \
libs/gsoap-2.8/gsoap/plugin/mecevp.c \
libs/gsoap-2.8/gsoap/plugin/wsaapi.c \
libs/gsoap-2.8/gsoap/plugin/wsseapi.c \
libs/gsoap-2.8/gsoap/plugin/wsddapi.c \
-lcrypto -lssl -lz
这是有问题的 CMakeLists.txt 文件:
cmake_minimum_required(VERSION 3.10.2)
project(vms_server LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-Wall -fpermissive -DWITH_OPENSSL -DWITH_DOM -DWITH_ZLIB)
find_package(OpenSSL REQUIRED)
find_package(ZLIB)
SET(SRC_FILES main.cpp)
SET(GSOAP_DEP_FILES
libs/gsoap-2.8/gsoap/stdsoap2.cpp
libs/gsoap-2.8/gsoap/dom.cpp
libs/gsoap-2.8/gsoap/plugin/smdevp.c
libs/gsoap-2.8/gsoap/plugin/mecevp.c
libs/gsoap-2.8/gsoap/plugin/wsse2api.c
libs/gsoap-2.8/gsoap/plugin/wsaapi.c
libs/gsoap-2.8/gsoap/plugin/wsseapi.c
libs/gsoap-2.8/gsoap/plugin/wsddapi.c
)
SET(GEN_FILES
gen/soapC.cpp
gen/wsddClient.cpp
gen/wsddServer.cpp
gen/soapAdvancedSecurityServiceBindingProxy.cpp
gen/soapDeviceBindingProxy.cpp
gen/soapDeviceIOBindingProxy.cpp
gen/soapImagingBindingProxy.cpp
gen/soapMediaBindingProxy.cpp
gen/soapPTZBindingProxy.cpp
gen/soapPullPointSubscriptionBindingProxy.cpp
gen/soapRemoteDiscoveryBindingProxy.cpp
)
include_directories(
libs/gsoap-2.8/gsoap/plugin
libs/gsoap-2.8/gsoap/custom
libs/gsoap-2.8/gsoap
gen
)
add_executable(vms ${SRC_FILES} ${GSOAP_DEP_FILES} ${GEN_FILES})
target_link_libraries(vms OpenSSL::Crypto OpenSSL::SSL ${ZLIB_LIBRARIES})
cmake .
命令运行时没有警告或问题,但随后 make
输出错误:
Scanning dependencies of target vms
[ 6%] Building CXX object CMakeFiles/vms.dir/main.cpp.o
/home/guy/Desktop/vms_server-c++/main.cpp: In function ‘int main()’:
/home/guy/Desktop/vms_server-c++/main.cpp:194:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<tt__Profile*>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
194 | for (int i = 0; i < GetProfilesResponse.Profiles.size(); ++i)
| ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/guy/Desktop/vms_server-c++/main.cpp: At global scope:
/home/guy/Desktop/vms_server-c++/main.cpp:308:13: warning: ‘void dyn_destroy_function(CRYPTO_dynlock_value*, const char*, int)’ defined but not used [-Wunused-function]
308 | static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line)
| ^~~~~~~~~~~~~~~~~~~~
/home/guy/Desktop/vms_server-c++/main.cpp:300:13: warning: ‘void dyn_lock_function(int, CRYPTO_dynlock_value*, const char*, int)’ defined but not used [-Wunused-function]
300 | static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
| ^~~~~~~~~~~~~~~~~
/home/guy/Desktop/vms_server-c++/main.cpp:291:37: warning: ‘CRYPTO_dynlock_value* dyn_create_function(const char*, int)’ defined but not used [-Wunused-function]
291 | static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line)
| ^~~~~~~~~~~~~~~~~~~
[ 13%] Building CXX object CMakeFiles/vms.dir/libs/gsoap-2.8/gsoap/stdsoap2.cpp.o
[ 20%] Building CXX object CMakeFiles/vms.dir/libs/gsoap-2.8/gsoap/dom.cpp.o
[ 26%] Building CXX object CMakeFiles/vms.dir/gen/soapC.cpp.o
[ 33%] Building CXX object CMakeFiles/vms.dir/gen/wsddClient.cpp.o
[ 40%] Building CXX object CMakeFiles/vms.dir/gen/wsddServer.cpp.o
[ 46%] Building CXX object CMakeFiles/vms.dir/gen/soapAdvancedSecurityServiceBindingProxy.cpp.o
[ 53%] Building CXX object CMakeFiles/vms.dir/gen/soapDeviceBindingProxy.cpp.o
[ 60%] Building CXX object CMakeFiles/vms.dir/gen/soapDeviceIOBindingProxy.cpp.o
[ 66%] Building CXX object CMakeFiles/vms.dir/gen/soapImagingBindingProxy.cpp.o
[ 73%] Building CXX object CMakeFiles/vms.dir/gen/soapMediaBindingProxy.cpp.o
[ 80%] Building CXX object CMakeFiles/vms.dir/gen/soapPTZBindingProxy.cpp.o
[ 86%] Building CXX object CMakeFiles/vms.dir/gen/soapPullPointSubscriptionBindingProxy.cpp.o
[ 93%] Building CXX object CMakeFiles/vms.dir/gen/soapRemoteDiscoveryBindingProxy.cpp.o
[100%] Linking CXX executable vms
CMakeFiles/vms.dir/main.cpp.o: In function `set_credentials(soap*)':
main.cpp:(.text+0x65): undefined reference to `soap_wsse_delete_Security'
main.cpp:(.text+0x7d): undefined reference to `soap_wsse_add_Timestamp'
main.cpp:(.text+0xa2): undefined reference to `soap_wsse_add_UsernameTokenDigest'
CMakeFiles/vms.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x3ec): undefined reference to `soap_wsse'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Hello(soap*)':
wsddServer.cpp:(.text+0x63c): undefined reference to `__wsdd__Hello(soap*, wsdd__HelloType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Bye(soap*)':
wsddServer.cpp:(.text+0x751): undefined reference to `__wsdd__Bye(soap*, wsdd__ByeType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Probe(soap*)':
wsddServer.cpp:(.text+0x866): undefined reference to `__wsdd__Probe(soap*, wsdd__ProbeType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__ProbeMatches(soap*)':
wsddServer.cpp:(.text+0x97b): undefined reference to `__wsdd__ProbeMatches(soap*, wsdd__ProbeMatchesType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__Resolve(soap*)':
wsddServer.cpp:(.text+0xa90): undefined reference to `__wsdd__Resolve(soap*, wsdd__ResolveType*)'
CMakeFiles/vms.dir/gen/wsddServer.cpp.o: In function `soap_serve___wsdd__ResolveMatches(soap*)':
wsddServer.cpp:(.text+0xba5): undefined reference to `__wsdd__ResolveMatches(soap*, wsdd__ResolveMatchesType*)'
collect2: error: ld returned 1 exit status
CMakeFiles/vms.dir/build.make:436: recipe for target 'vms' failed
make[2]: *** [vms] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/vms.dir/all' failed
make[1]: *** [CMakeFiles/vms.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
我发现当您使用 CMake 生成的 Makefile 进行编译时,您的 .c
文件没有被构建;这是导致 link 错误。因为您正在编译 C++ 项目 (CXX
),CMake 将忽略 .c
文件。您可以尝试通过将 c
文件扩展名附加到 CMAKE_LANG_SOURCE_FILE_EXTENSIONS
列表来告诉 CMake 将 .c
视为 C++ 文件:
list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)
这是一个过激的举动,您可能不希望将其应用于您的所有 C++ 项目。更细粒度的方法是使用 set_source_files_properties()
:
.c
源文件将 LANGUAGE
属性 设置为 C++
# Split up the GSOAP_DEP_FILES variable based on the file extension (.c or .cpp).
SET(GSOAP_DEP_CPP_FILES
libs/gsoap-2.8/gsoap/stdsoap2.cpp
libs/gsoap-2.8/gsoap/dom.cpp
)
SET(GSOAP_DEP_C_FILES
libs/gsoap-2.8/gsoap/plugin/smdevp.c
libs/gsoap-2.8/gsoap/plugin/mecevp.c
libs/gsoap-2.8/gsoap/plugin/wsaapi.c
libs/gsoap-2.8/gsoap/plugin/wsseapi.c
libs/gsoap-2.8/gsoap/plugin/wsddapi.c
)
...
# Set the language for the .c files to C++, so CMake includes them for compilation.
set_source_files_properties(${GSOAP_DEP_C_FILES} PROPERTIES LANGUAGE CXX)
add_executable(vms ${SRC_FILES} ${GSOAP_DEP_CPP_FILES} ${GSOAP_DEP_C_FILES} ${GEN_FILES})