Add standalone CMake build for mars-libowfat

This commit is contained in:
OpenAI
2026-06-03 08:26:24 +00:00
committed by Mario Fetka
parent 8fc74a2d57
commit 4ed6d195c4
8 changed files with 310 additions and 6 deletions

252
CMakeLists.txt Normal file
View File

@@ -0,0 +1,252 @@
cmake_minimum_required(VERSION 3.16)
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES" _libowfat_changes LIMIT_COUNT 1)
string(REGEX REPLACE ":.*$" "" LIBOWFAT_VERSION "${_libowfat_changes}")
if(NOT LIBOWFAT_VERSION MATCHES "^[0-9]+(\\.[0-9]+)*$")
message(FATAL_ERROR "Could not read libowfat version from first line of CHANGES")
endif()
project(mars-libowfat
VERSION ${LIBOWFAT_VERSION}
DESCRIPTION "mars-nwe libowfat build"
LANGUAGES C)
include(CheckCSourceCompiles)
include(CheckIncludeFile)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
option(MARS_LIBOWFAT_BUILD_STATIC "Build static libowfat/nwowfat library" ON)
option(MARS_LIBOWFAT_BUILD_SHARED "Build shared libowfat/nwowfat library" ON)
set(MARS_LIBOWFAT_OUTPUT_NAME "owfat" CACHE STRING "Library output basename: owfat or nwowfat")
set_property(CACHE MARS_LIBOWFAT_OUTPUT_NAME PROPERTY STRINGS owfat nwowfat)
option(MARS_LIBOWFAT_INSTALL "Install libraries and headers" ON)
option(MARS_LIBOWFAT_GLIBC_COMPAT "Enable glibc-compatible feature-test defines" ON)
if(NOT MARS_LIBOWFAT_BUILD_STATIC AND NOT MARS_LIBOWFAT_BUILD_SHARED)
message(FATAL_ERROR "At least one of MARS_LIBOWFAT_BUILD_STATIC or MARS_LIBOWFAT_BUILD_SHARED must be ON")
endif()
# Keep this CMake build close to the existing GNUmakefile, but make the checks
# out-of-tree friendly and avoid dietlibc-specific defaults. glibc builds get
# _GNU_SOURCE so Linux/glibc extension declarations stay visible.
set(LIBOWFAT_FEATURE_DEFINES _REENTRANT)
if(MARS_LIBOWFAT_GLIBC_COMPAT AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND LIBOWFAT_FEATURE_DEFINES _GNU_SOURCE)
endif()
set(CMAKE_REQUIRED_DEFINITIONS "")
foreach(_def IN LISTS LIBOWFAT_FEATURE_DEFINES)
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D${_def}")
endforeach()
set(CMAKE_REQUIRED_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}")
check_c_source_compiles("#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\nint main(void) { struct sockaddr_in6 x; (void)x; return 0; }" LIBC_HAS_IP6)
check_c_source_compiles("#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\nint main(void) { struct sockaddr_in6 x; x.sin6_scope_id = 0; return 0; }" LIBC_HAS_SCOPE_ID)
check_c_source_compiles("#include <sys/socket.h>\nint main(void) { socklen_t x = 0; return (int)x; }" HAVE_SOCKLEN_T)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/tryn2i.c" _tryn2i_source)
check_c_source_compiles("${_tryn2i_source}" HAVE_N2I)
check_c_source_compiles("static inline int f(void) { return 0; }\nint main(void) { return f(); }" HAVE_INLINE)
check_c_source_compiles("#include <sys/types.h>\n#include <sys/event.h>\nint main(void) { return kqueue(); }" HAVE_KQUEUE)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/trybsdsf.c" _trybsdsf_source)
check_c_source_compiles("${_trybsdsf_source}" HAVE_BSDSENDFILE)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/trysendfile.c" _trysendfile_source)
check_c_source_compiles("${_trysendfile_source}" HAVE_SENDFILE)
check_c_source_compiles("#include <sys/epoll.h>\nint main(void) { return epoll_create(1) < 0; }" HAVE_EPOLL)
check_c_source_compiles("#include <sys/devpoll.h>\nint main(void) { return 0; }" HAVE_DEVPOLL)
check_c_source_compiles("#include <signal.h>\n#include <fcntl.h>\nint main(void) { int x = F_SETSIG; return x == 0; }" HAVE_SIGIO)
check_c_source_compiles("int main(void) { unsigned __int128 x = 0; return (int)x; }" HAVE_UINT128)
check_c_source_compiles("#include <unistd.h>\nint main(void) { char c; return pread(0, &c, 1, 0) < 0; }" HAVE_PREAD)
check_c_source_compiles("#include <fcntl.h>\n#include <sys/socket.h>\nint main(void) { return accept4(-1, 0, 0, SOCK_CLOEXEC); }" HAVE_ACCEPT4)
check_c_source_compiles("#include <poll.h>\nint main(void) { struct pollfd p; return poll(&p, 0, 0); }" HAVE_POLL)
check_c_source_compiles("#include <sys/select.h>\nint main(void) { fd_set fds; FD_ZERO(&fds); return 0; }" HAVE_SYS_SELECT_H)
check_c_source_compiles("#include <stdlib.h>\n#include <alloca.h>\nint main(void) { void *p = alloca(1); return p == 0; }" HAVE_ALLOCA_H)
check_c_source_compiles("#include <stdlib.h>\n#include <malloc.h>\nint main(void) { return 0; }" HAVE_MALLOC_H)
set(_generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
set(_generated_libowfat_dir "${_generated_dir}/libowfat")
file(MAKE_DIRECTORY "${_generated_libowfat_dir}")
function(_write_feature_header name content_if_true)
if(${ARGV2})
file(WRITE "${_generated_dir}/${name}" "${content_if_true}\n")
else()
file(WRITE "${_generated_dir}/${name}" "")
endif()
endfunction()
_write_feature_header(haveip6.h "#define LIBC_HAS_IP6" LIBC_HAS_IP6)
_write_feature_header(havescope.h "#define LIBC_HAS_SCOPE_ID" LIBC_HAS_SCOPE_ID)
_write_feature_header(haven2i.h "#define HAVE_N2I" HAVE_N2I)
_write_feature_header(haveinline.h "#define inline" NOT_HAVE_INLINE)
if(HAVE_INLINE)
file(WRITE "${_generated_dir}/haveinline.h" "")
endif()
_write_feature_header(havekqueue.h "#define HAVE_KQUEUE" HAVE_KQUEUE)
_write_feature_header(havebsdsf.h "#define HAVE_BSDSENDFILE" HAVE_BSDSENDFILE)
_write_feature_header(havesendfile.h "#define HAVE_SENDFILE" HAVE_SENDFILE)
if(HAVE_EPOLL)
file(WRITE "${_generated_dir}/haveepoll.h" "#define HAVE_EPOLL 1\n")
else()
file(WRITE "${_generated_dir}/haveepoll.h" "")
endif()
_write_feature_header(havedevpoll.h "#define HAVE_DEVPOLL" HAVE_DEVPOLL)
_write_feature_header(havesigio.h "#define HAVE_SIGIO" HAVE_SIGIO)
_write_feature_header(haveuint128.h "#define HAVE_UINT128" HAVE_UINT128)
_write_feature_header(havepread.h "#define HAVE_PREAD" HAVE_PREAD)
_write_feature_header(haveaccept4.h "#define HAVE_ACCEPT4" HAVE_ACCEPT4)
if(HAVE_SOCKLEN_T)
file(WRITE "${_generated_dir}/havesl.h" "")
else()
file(WRITE "${_generated_dir}/havesl.h" "typedef int socklen_t;\n")
endif()
file(WRITE "${_generated_dir}/havealloca.h" "#include <stdlib.h>\n")
if(HAVE_ALLOCA_H)
file(APPEND "${_generated_dir}/havealloca.h" "#include <alloca.h>\n")
endif()
if(HAVE_MALLOC_H)
file(APPEND "${_generated_dir}/havealloca.h" "#include <malloc.h>\n")
endif()
if(HAVE_POLL)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/iopause.h2" "${_generated_dir}/iopause.h" COPYONLY)
else()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/iopause.h1" "${_generated_dir}/iopause.h" COPYONLY)
endif()
if(HAVE_SYS_SELECT_H)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/select.h2" "${_generated_dir}/select.h" COPYONLY)
else()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/select.h1" "${_generated_dir}/select.h" COPYONLY)
endif()
add_executable(libowfat_ent EXCLUDE_FROM_ALL "${CMAKE_CURRENT_SOURCE_DIR}/ent.c")
target_include_directories(libowfat_ent PRIVATE "${_generated_dir}" "${CMAKE_CURRENT_SOURCE_DIR}")
target_compile_definitions(libowfat_ent PRIVATE _REENTRANT)
add_custom_command(
OUTPUT "${_generated_dir}/entities.h"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/entities.json" "${_generated_dir}/entities.json"
COMMAND libowfat_ent
WORKING_DIRECTORY "${_generated_dir}"
DEPENDS libowfat_ent "${CMAKE_CURRENT_SOURCE_DIR}/entities.json"
COMMENT "Generating entities.h"
VERBATIM)
add_custom_target(libowfat_entities DEPENDS "${_generated_dir}/entities.h")
set(LIBOWFAT_PUBLIC_HEADERS
buffer.h byte.h fmt.h ip4.h ip6.h mmap.h scan.h socket.h str.h stralloc.h
uint16.h uint32.h uint64.h open.h textcode.h tai.h taia.h dns.h iopause.h case.h
openreadclose.h readclose.h ndelay.h array.h io.h safemult.h iob.h havealloca.h
errmsg.h cdb.h cdb_make.h rangecheck.h iarray.h va_narg.h isset.h
compiletimeassert.h critbit.h parse.h compiler.h clamp.h
)
foreach(_hdr IN LISTS LIBOWFAT_PUBLIC_HEADERS)
if(EXISTS "${_generated_dir}/${_hdr}")
configure_file("${_generated_dir}/${_hdr}" "${_generated_libowfat_dir}/${_hdr}" COPYONLY)
else()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${_hdr}" "${_generated_libowfat_dir}/${_hdr}" COPYONLY)
endif()
endforeach()
file(GLOB LIBOWFAT_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/array/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/buffer/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/byte/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/case/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/cdb/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/critbit/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/dns/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/fmt/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/io/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/mmap/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/mult/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/open/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/scan/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/socket/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/str/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/stralloc/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/tai/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/taia/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/textcode/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/uint/*.c"
"${CMAKE_CURRENT_SOURCE_DIR}/unix/*.c"
)
add_library(libowfat_objects OBJECT ${LIBOWFAT_SOURCES})
add_dependencies(libowfat_objects libowfat_entities)
target_compile_definitions(libowfat_objects PRIVATE _REENTRANT)
target_include_directories(libowfat_objects
PRIVATE
"${_generated_dir}"
"${CMAKE_CURRENT_SOURCE_DIR}"
PUBLIC
"$<BUILD_INTERFACE:${_generated_dir}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
if(MARS_LIBOWFAT_BUILD_SHARED)
set_property(TARGET libowfat_objects PROPERTY POSITION_INDEPENDENT_CODE ON)
endif()
set(_libowfat_targets)
if(MARS_LIBOWFAT_BUILD_STATIC)
add_library(libowfat_static STATIC $<TARGET_OBJECTS:libowfat_objects>)
list(APPEND _libowfat_targets libowfat_static)
add_library(libowfat::static ALIAS libowfat_static)
set_target_properties(libowfat_static PROPERTIES
OUTPUT_NAME "${MARS_LIBOWFAT_OUTPUT_NAME}"
VERSION "${PROJECT_VERSION}")
endif()
if(MARS_LIBOWFAT_BUILD_SHARED)
add_library(libowfat_shared SHARED $<TARGET_OBJECTS:libowfat_objects>)
list(APPEND _libowfat_targets libowfat_shared)
add_library(libowfat::shared ALIAS libowfat_shared)
set_target_properties(libowfat_shared PROPERTIES
OUTPUT_NAME "${MARS_LIBOWFAT_OUTPUT_NAME}"
VERSION "${PROJECT_VERSION}"
SOVERSION "${PROJECT_VERSION_MAJOR}")
endif()
foreach(_target IN LISTS _libowfat_targets)
target_compile_definitions(${_target} PUBLIC _REENTRANT)
target_include_directories(${_target}
PUBLIC
"$<BUILD_INTERFACE:${_generated_dir}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
endforeach()
if(MARS_LIBOWFAT_BUILD_SHARED)
add_library(libowfat::libowfat ALIAS libowfat_shared)
elseif(MARS_LIBOWFAT_BUILD_STATIC)
add_library(libowfat::libowfat ALIAS libowfat_static)
endif()
if(MARS_LIBOWFAT_INSTALL)
install(TARGETS ${_libowfat_targets}
EXPORT mars-libowfat-targets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(DIRECTORY "${_generated_libowfat_dir}/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libowfat"
FILES_MATCHING PATTERN "*.h")
install(EXPORT mars-libowfat-targets
NAMESPACE libowfat::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/mars-libowfat")
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/mars-libowfat-config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/mars-libowfat-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/mars-libowfat")
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/mars-libowfat-config-version.cmake"
VERSION "${PROJECT_VERSION}"
COMPATIBILITY SameMajorVersion)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/mars-libowfat-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/mars-libowfat-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/mars-libowfat")
endif()
message(STATUS "mars-libowfat ${PROJECT_VERSION}: building ${MARS_LIBOWFAT_OUTPUT_NAME} static=${MARS_LIBOWFAT_BUILD_STATIC} shared=${MARS_LIBOWFAT_BUILD_SHARED}")

43
README.md Normal file
View File

@@ -0,0 +1,43 @@
# mars-libowfat
This repository is a mars-nwe special-purpose fork of libowfat.
The original Makefile/GNUmakefile build is kept intact. The additional
`CMakeLists.txt` is intended for mars-nwe consumers that need libowfat as a
standalone CMake dependency, either under the traditional `libowfat` name or
under the NetWare-oriented `libnwowfat` name.
## CMake build
Out-of-tree builds are supported and recommended:
```sh
cmake -S . -B build -DMARS_LIBOWFAT_OUTPUT_NAME=nwowfat
cmake --build build
```
The output name can be selected with:
```sh
-DMARS_LIBOWFAT_OUTPUT_NAME=owfat
-DMARS_LIBOWFAT_OUTPUT_NAME=nwowfat
```
By default both static and shared libraries are built:
```sh
-DMARS_LIBOWFAT_BUILD_STATIC=ON
-DMARS_LIBOWFAT_BUILD_SHARED=ON
```
The version is read from the first line of `CHANGES`; currently that yields
`0.35`, so the shared library is produced as `libowfat.so.0.35` or
`libnwowfat.so.0.35` with the usual soname symlinks.
## glibc compatibility
The CMake build uses the system C compiler and standard glibc-style feature
checks instead of the old dietlibc-oriented defaults. Generated compatibility
headers such as `haveip6.h`, `havesendfile.h`, `iopause.h`, `select.h`, and
`entities.h` are created in the build tree, so the source tree stays clean and
out-of-tree builds work.

View File

@@ -1,7 +1,7 @@
#include <unistd.h>
#include "buffer.h"
char buffer_1_space[128];
static buffer it = BUFFER_INIT(write,1,buffer_1_space,sizeof buffer_1_space);
char buffer_1small_space[128];
static buffer it = BUFFER_INIT(write,1,buffer_1small_space,sizeof buffer_1small_space);
buffer *buffer_1small = &it;

View File

@@ -0,0 +1,9 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/mars-libowfat-targets.cmake")
if(TARGET libowfat::libowfat_shared AND NOT TARGET libowfat::libowfat)
add_library(libowfat::libowfat ALIAS libowfat::libowfat_shared)
elseif(TARGET libowfat::libowfat_static AND NOT TARGET libowfat::libowfat)
add_library(libowfat::libowfat ALIAS libowfat::libowfat_static)
endif()

View File

@@ -6,6 +6,6 @@
#include "windoze.h"
#include <libowfat/socket.h>
int socket_accept4_makenonblocking(int s,char ip[4],uint16 *port) {
int socket_accept4_makenonblocking_setcloseonexec(int s,char ip[4],uint16 *port) {
return socket_accept4_flags(s,ip,port,SOCKET_NONBLOCK | SOCKET_CLOEXEC);
}

View File

@@ -6,6 +6,6 @@
#include "windoze.h"
#include <libowfat/socket.h>
int socket_accept4_makenonblocking(int s,char ip[4],uint16 *port) {
int socket_accept4_setcloseonexec(int s,char ip[4],uint16 *port) {
return socket_accept4_flags(s,ip,port,SOCKET_CLOEXEC);
}

View File

@@ -6,6 +6,6 @@
#include "windoze.h"
#include <libowfat/socket.h>
int socket_accept6_makenonblocking(int s,char ip[16],uint16 *port,uint32* scope_id) {
int socket_accept6_makenonblocking_setcloseonexec(int s,char ip[16],uint16 *port,uint32* scope_id) {
return socket_accept6_flags(s,ip,port,scope_id,SOCKET_NONBLOCK | SOCKET_CLOEXEC);
}

View File

@@ -6,6 +6,6 @@
#include "windoze.h"
#include <libowfat/socket.h>
int socket_accept6_makenonblocking(int s,char ip[16],uint16 *port,uint32* scope_id) {
int socket_accept6_setcloseonexec(int s,char ip[16],uint16 *port,uint32* scope_id) {
return socket_accept6_flags(s,ip,port,scope_id,SOCKET_CLOEXEC);
}