Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/unittest_linux_32bit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: linux_32bit
on:
push:
paths-ignore:
- 'docs/**'
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
linux_32bit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: seanmiddleditch/gha-setup-ninja@master
- name: install 32-bit toolchain
run: sudo apt-get update && sudo apt-get install -y g++-multilib pkg-config
- name: make test
run: make -f makefile.dev test_atomic_32
30 changes: 30 additions & 0 deletions CMake/CheckAtomic.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Some 32-bit targets need libatomic for the library's 64-bit counters.
function(ixwebsocket_check_atomic)
include(CheckCXXSourceCompiles)
include(CMakePushCheckState)
cmake_push_check_state(RESET)
# A static-library try_compile would hide unresolved atomic runtime symbols.
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
set(atomic_test_source "
#include <atomic>
#include <cstdint>
int main(int argc, char**) {
std::atomic<std::uint64_t> counter(0);
counter.fetch_add(static_cast<std::uint64_t>(argc));
return static_cast<int>(counter.load());
}
")
check_cxx_source_compiles("${atomic_test_source}" IXWEBSOCKET_HAVE_BUILTIN_ATOMICS)
if (NOT IXWEBSOCKET_HAVE_BUILTIN_ATOMICS)
set(CMAKE_REQUIRED_LIBRARIES atomic)
check_cxx_source_compiles("${atomic_test_source}" IXWEBSOCKET_HAVE_LIBATOMIC)
if (NOT IXWEBSOCKET_HAVE_LIBATOMIC)
message(FATAL_ERROR "Unable to link 64-bit C++ atomics, even with libatomic. Install libatomic for the target toolchain.")
endif()
target_link_libraries(ixwebsocket PRIVATE atomic)
set(IXWEBSOCKET_PRIVATE_LIBS "-latomic" PARENT_SCOPE)
endif()
cmake_pop_check_state()
endfunction()

ixwebsocket_check_atomic()
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ else()
)
endif()

set(IXWEBSOCKET_PRIVATE_LIBS "")
include(CheckAtomic)

if (USE_TLS)
target_compile_definitions(ixwebsocket PUBLIC IXWEBSOCKET_USE_TLS)
if (USE_NETWORK_FRAMEWORK)
Expand Down
6 changes: 6 additions & 0 deletions docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ make install # will install to /usr/local on Unix, on macOS it is a good idea to
Headers and a static library will be installed to the target dir.
There is a unittest which can be executed by typing `make test`.

CMake checks whether 64-bit atomics need `libatomic` and links it when required,
including for consumers of the installed static library. Cross-compilation uses
a compile-and-link check without running target executables. On Linux with GCC
multilib installed, `make -f makefile.dev test_atomic_32` builds and runs the
32-bit installed-consumer checks.

Options for building:

* `-DBUILD_SHARED_LIBS=ON` will build the unittest as a shared libary instead of a static library, which is the default
Expand Down
1 change: 1 addition & 0 deletions ixwebsocket.pc.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ Name: ixwebsocket
Description: websocket and http client and server library, with TLS support and very few dependencies
Version: @CMAKE_PROJECT_VERSION@
Libs: -L${libdir} -lixwebsocket
Libs.private: @IXWEBSOCKET_PRIVATE_LIBS@
Cflags: -I${includedir}
Requires: @requires@
11 changes: 11 additions & 0 deletions makefile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ test:
(cd build ; ninja)
(cd build ; ninja -v test)

.PHONY: test_atomic_32
test_atomic_32:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_UNITY_BUILD=ON -DCMAKE_C_FLAGS="-m32 -march=i486" -DCMAKE_CXX_FLAGS="-m32 -march=i486" -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY -DUSE_TLS=OFF -DUSE_NETWORK_FRAMEWORK=OFF -DUSE_ZLIB=OFF -DUSE_TEST=OFF -DUSE_WS=OFF -DCMAKE_INSTALL_PREFIX="$(CURDIR)/build/atomic-install" -DCMAKE_INSTALL_LIBDIR=lib
cmake --build build --parallel
cmake --install build
cmake -S test/cmake/atomic -B build/atomic-consumer -DCMAKE_CXX_FLAGS="-m32 -march=i486" -DCMAKE_PREFIX_PATH="$(CURDIR)/build/atomic-install"
cmake --build build/atomic-consumer --parallel
./build/atomic-consumer/atomic_consumer
$(CXX) -std=c++11 -m32 -march=i486 test/cmake/atomic/main.cpp -o build/atomic-pkg-consumer $$(PKG_CONFIG_PATH="$(CURDIR)/build/atomic-install/lib/pkgconfig" pkg-config --cflags --libs --static ixwebsocket)
./build/atomic-pkg-consumer

test_asan:
mkdir -p build && (cd build ; cmake -GNinja -DCMAKE_INSTALL_MESSAGE=LAZY -DCMAKE_UNITY_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DUSE_TLS=1 -DUSE_TEST=1 .. -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer")
(cd build ; ninja)
Expand Down
12 changes: 12 additions & 0 deletions test/cmake/atomic/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.4.1...3.17.2)
project(ixwebsocket_atomic_consumer LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# The installed target also carries the library's existing thread dependency.
find_package(Threads REQUIRED)
find_package(ixwebsocket CONFIG REQUIRED)
add_executable(atomic_consumer main.cpp)
target_link_libraries(atomic_consumer PRIVATE ixwebsocket::ixwebsocket)
14 changes: 14 additions & 0 deletions test/cmake/atomic/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Check that installed consumers can link the library's 64-bit atomic users.
*/
#include <ixwebsocket/IXConnectionState.h>
#include <ixwebsocket/IXWebSocketTransport.h>

int main()
{
ix::ConnectionState first;
ix::ConnectionState second;
ix::WebSocketTransport transport;
return first.getId() == second.getId() ||
transport.getReadyState() != ix::WebSocketTransport::ReadyState::CLOSED;
}
Loading