diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..acd3b91 --- /dev/null +++ b/CMakeLists.txt @@ -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 \n#include \n#include \nint main(void) { struct sockaddr_in6 x; (void)x; return 0; }" LIBC_HAS_IP6) +check_c_source_compiles("#include \n#include \n#include \nint main(void) { struct sockaddr_in6 x; x.sin6_scope_id = 0; return 0; }" LIBC_HAS_SCOPE_ID) +check_c_source_compiles("#include \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 \n#include \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 \nint main(void) { return epoll_create(1) < 0; }" HAVE_EPOLL) +check_c_source_compiles("#include \nint main(void) { return 0; }" HAVE_DEVPOLL) +check_c_source_compiles("#include \n#include \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 \nint main(void) { char c; return pread(0, &c, 1, 0) < 0; }" HAVE_PREAD) +check_c_source_compiles("#include \n#include \nint main(void) { return accept4(-1, 0, 0, SOCK_CLOEXEC); }" HAVE_ACCEPT4) +check_c_source_compiles("#include \nint main(void) { struct pollfd p; return poll(&p, 0, 0); }" HAVE_POLL) +check_c_source_compiles("#include \nint main(void) { fd_set fds; FD_ZERO(&fds); return 0; }" HAVE_SYS_SELECT_H) +check_c_source_compiles("#include \n#include \nint main(void) { void *p = alloca(1); return p == 0; }" HAVE_ALLOCA_H) +check_c_source_compiles("#include \n#include \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 \n") +if(HAVE_ALLOCA_H) + file(APPEND "${_generated_dir}/havealloca.h" "#include \n") +endif() +if(HAVE_MALLOC_H) + file(APPEND "${_generated_dir}/havealloca.h" "#include \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 + "$" + "$") +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 $) + 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 $) + 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 + "$" + "$") +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}") diff --git a/README.md b/README.md new file mode 100644 index 0000000..2c0b314 --- /dev/null +++ b/README.md @@ -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. diff --git a/buffer/buffer_1small.c b/buffer/buffer_1small.c index 5e88ea5..1efa8ce 100644 --- a/buffer/buffer_1small.c +++ b/buffer/buffer_1small.c @@ -1,7 +1,7 @@ #include #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 = ⁢ diff --git a/cmake/mars-libowfat-config.cmake.in b/cmake/mars-libowfat-config.cmake.in new file mode 100644 index 0000000..2f5574f --- /dev/null +++ b/cmake/mars-libowfat-config.cmake.in @@ -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() diff --git a/socket/socket_accept4_makenonblocking_setcloseonexec.c b/socket/socket_accept4_makenonblocking_setcloseonexec.c index 2398fda..72b8a21 100644 --- a/socket/socket_accept4_makenonblocking_setcloseonexec.c +++ b/socket/socket_accept4_makenonblocking_setcloseonexec.c @@ -6,6 +6,6 @@ #include "windoze.h" #include -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); } diff --git a/socket/socket_accept4_setcloseonexec.c b/socket/socket_accept4_setcloseonexec.c index a6b64bf..2c81950 100644 --- a/socket/socket_accept4_setcloseonexec.c +++ b/socket/socket_accept4_setcloseonexec.c @@ -6,6 +6,6 @@ #include "windoze.h" #include -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); } diff --git a/socket/socket_accept6_makenonblocking_setcloseonexec.c b/socket/socket_accept6_makenonblocking_setcloseonexec.c index 862bd80..f2414aa 100644 --- a/socket/socket_accept6_makenonblocking_setcloseonexec.c +++ b/socket/socket_accept6_makenonblocking_setcloseonexec.c @@ -6,6 +6,6 @@ #include "windoze.h" #include -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); } diff --git a/socket/socket_accept6_setcloseonexec.c b/socket/socket_accept6_setcloseonexec.c index bd2491d..73f965c 100644 --- a/socket/socket_accept6_setcloseonexec.c +++ b/socket/socket_accept6_setcloseonexec.c @@ -6,6 +6,6 @@ #include "windoze.h" #include -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); }