Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate libwebsockets into existing projects (based on CMake build method) #2965

Open
Alvazz opened this issue Sep 11, 2023 · 1 comment
Open

Comments

@Alvazz
Copy link

Alvazz commented Sep 11, 2023

Hi lws-team,
First of all thank you for sharing such great work.

My project is built based on cmake. It mainly runs on windows and macos platforms. I hope to integrate libwebsockets into the project through cmake in an elegant way. I hope to get help from lws-team.

I have read almost all the files in the READMEs directory. This may be the most attentive and serious work I have ever seen on any project. So much documentation, so awesome. It's a pity that there are no tips on how to integrate it into the cmake project :(

emm...since I don't understand libwebsockets, I thought of the simplest way, which is to show the cmake structure of my project so that lws-team can better guide me on how to integrate libwebsockets elegantly.

TL;DR

My project folder structure is roughly as follows:

my-app
   --cmake(this folder stores some .cmake files, such as Findjansson.cmake, or FindMbedTLS.cmake)
   --deps
       --w32-pthread
           CMakeLists.txt(in the w32-pthread directory)
       --jansson
       CMakeLists.txt(in the deps root directory)
   --libcore
   --libcat-win
   --libwasliy-win
   --plugins
   --UI
   CMakeLists.txt(in the my-app root directory)

I usually put third-party dependencies in the deps directory
This CMakeLists.txt is located in the root directory of my-app, and its content is as follows:

cmake_minimum_required(VERSION 3.16...3.25)

if(MYAPP_CMAKE_VERSION VERSION_GREATER_EQUAL 3.0.0)
  include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/common/bootstrap.cmake")

  project(my-app VERSION ${MYAPP_VERSION_CANONICAL})

  if(CMAKE_SIZEOF_VOID_P EQUAL 4)
    include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/32bit/projects.cmake")
    return()
  endif()


  option(ENABLE_RELEASE_BUILD "Enable all options for a release build" OFF)

  add_subdirectory(libcore)
  if(OS_WINDOWS)
    add_subdirectory(libcat-win)
    add_subdirectory(libwasliy-win)
  endif()
  add_subdirectory(plugins)
  add_subdirectory(UI)

  message_configuration()
  return()
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules")
include(VersionConfig)

# Prohibit in-source builds
if("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
  message(FATAL_ERROR "MYAPP: You cannot build in a source directory (or any directory with CMakeLists.txt file)."
                      "Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.")
endif()

project(my-app VERSION ${MYAPP_VERSION_CANONICAL})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# Use target folders for MSVC/Xcode/etc.
include(DeprecationHelpers)
# Set default compiler flags
include(CompilerConfig)

# Allow selection of common build types via UI
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE
      "RelWithDebInfo"
      CACHE STRING "MYAPP build type [Release, RelWithDebInfo, Debug, MinSizeRel]" FORCE)
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Release RelWithDebInfo Debug MinSizeRel)
endif()

# Global project options
option(BUILD_FOR_DISTRIBUTION "Build for distribution (enables optimizations)" OFF)
option(USE_LIBCXX "Use libc++ instead of libstdc++" ${APPLE})
option(BUILD_TESTS "Build test directory (includes test sources and possibly a platform test executable)" OFF)

if(OS_WINDOWS)
  option(INSTALLER_RUN
         "Build a multiarch installer (needs to run independently after both archs have compiled) (Windows)" OFF)
endif()

setup_myapp_project()
mark_as_advanced(BUILD_TESTS USE_LIBCXX)

if(INSTALLER_RUN)
  generate_multiarch_installer()
  return()
endif()

# MYAPP deps
add_subdirectory(deps)

# Tests
if(ENABLE_UNIT_TESTS)
  enable_testing()
endif()

if(BUILD_TESTS OR ENABLE_UNIT_TESTS)
  add_subdirectory(test)
endif()

Next is the content of the CMakeLists.txt file located in the deps root directory:

if(MYAPP_CMAKE_VERSION VERSION_GREATER_EQUAL 3.0.0)
  return()
endif()

if(OS_WINDOWS)
  if(NOT MINGW)
    add_subdirectory(w32-pthreads)
  endif()
endif()

# Use bundled jansson version as fallback
find_package(Jansson 2.5 QUIET)
if(NOT TARGET Jansson::Jansson)
  myapp_status(STATUS "Jansson >=2.5 not found, building bundled version.")

  add_subdirectory(jansson)
  add_library(Jansson::Jansson ALIAS jansson)
else()
  myapp_status(STATUS "Using system Jansson library.")
endif()

The CMakeLists.txt in the win32-pthreads directory looks like this:

cmake_minimum_required(VERSION 3.24...3.25)

legacy_check()

add_library(w32-pthreads SHARED EXCLUDE_FROM_ALL )
add_library(MYAPP::w32-pthreads ALIAS w32-pthreads)

target_sources(w32-pthreads PRIVATE implement.h pthread.c pthread.h sched.h semaphore.h w32-pthreads.rc)
target_compile_definitions(w32-pthreads PRIVATE __CLEANUP_C PTW32_BUILD)
target_include_directories(w32-pthreads PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")

configure_file(cmake/windows/my-app.rc.in w32-pthreads.rc)

set_target_properties_myapp(w32-pthreads PROPERTIES FOLDER deps)

set_property(
  TARGET w32-pthreads
  APPEND
  PROPERTY PUBLIC_HEADER pthread.h sched.h)
target_export(w32-pthreads)

The above content and directory structure constitute the cmake function of my project. If I want to integrate libwebsockets into my project, how should I do it? Looking forward to your guidance.

Thanks, Best Wishes!

@dylanetaft
Copy link
Contributor

dylanetaft commented Oct 16, 2023

There's lots of ways to add LWS into a cmake file.

  • Build as a submodule, link statically
  • Link dynamically with an OS installed release
  • Link dynamically and have the library in the path of your executable so it is found before the OS's library
  • Cross compiling
  • Lots of other use cases

IMO your best bet is to break your cmake into a test case, and then try to port what you learned to your project's CMakeLists.txt. I am just a fan of minimal test cases when troubleshooting, though. It's usually the fastest way to figure things out.

I did so here
https://github.com/dylanetaft/lws_cmake_testcase

For an example of build as a submodule, link statically
You can pull LWS into your project path as a git submodule
https://chrisjean.com/git-submodules-adding-using-removing-and-updating/
Same thing you're doing with add_subdirectory in your existing CMakeLists.txt file

LWS's cmake files expose a handful of library targets and include targets, see the CMakeLists.txt in what I put on github there.

pkg_config also works if your environment has it, but that's for like OS installed libraries usually.
.....
find_package(PkgConfig)
pkg_check_modules(LIB_WEBSOCKETS REQUIRED libwebsockets)
......
target_link_libraries(
yourapp
${LIB_WEBSOCKETS_LIBRARIES}
)
target_include_directories(
yourapp PUBLIC
${LIB_WEBSOCKETS_DIRS}
)

target_compile_options(
test PUBLIC
${LIB_WEBSOCKETS_CFLAGS_OTHER}
)

Distros can have fairly out of date packages for LWS. Linking statically is sort of a safe bet and should provide for a reliable build process. Or having the dynamic library in the binary path. The MIT license is pretty permissive I think but I am not a lawyer.

I posted a similar question earlier, was closed as it is indeed more of a cmake question...butttt cmake doesn't dictate what you export as the cmake library name with add_library...or any helper things for linking, include paths, or cflags needed.

I ended up going to chatgpt and asked it generically, if I have a library B as a submodule in a git repo for project a, how do I link my application a to library b - and it informed me I needed to set stuff in the CMakeLists.txt file in library B with examples. It let me know what to look for at least, that I can't actually do it without knowing what B is making available as there isn't a standard.
Google sends you on a bad path with StackOverflow examples where AI is way more tailored with answers. Really good for learning stuff...usually.

I am using msys2 for compiling, no idea about Visual Studio, I'm guessing VS is super smart about cmake and importing third party libraries into a project though!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants