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

feat: Native windows port #168

Merged
merged 4 commits into from
Dec 30, 2023
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
110 changes: 85 additions & 25 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ option(PIPY_STATIC "statically link to libc" OFF)
option(PIPY_LTO "enable LTO" ON)
option(PIPY_USE_NTLS, "Use externally compiled TongSuo Crypto library instead of OpenSSL. Used with PIPY_OPENSSL" OFF)

set(BUILD_SHARED_LIBS OFF)
set(BUILD_TESTING OFF)

add_subdirectory(deps/yajl-2.1.0)

option(BUILD_tools "build the xmlwf tool for expat library" OFF)
Expand Down Expand Up @@ -74,9 +77,23 @@ else()
message("LTO is disabled")
endif()

if(WIN32)
set(LIB_Z zlib.lib)
set(LIB_CRYPTO libcrypto.lib)
set(LIB_SSL libssl.lib)
set(LIB_BROTLI libbrotlidec-static.lib)
set(EXT_SHELL cmd)
else(WIN32)
set(LIB_Z libz.a)
set(LIB_CRYPTO libcrypto.a)
set(LIB_SSL libssl.a)
set(LIB_BROTLI libbrotlidec-static.a)
set(EXT_SHELL sh)
endif(WIN32)

if(PIPY_ZLIB)
set(ZLIB_INC_DIR ${PIPY_ZLIB}/include)
set(ZLIB_LIB ${PIPY_ZLIB}/lib/libz.a)
set(ZLIB_LIB ${PIPY_ZLIB}/lib/${LIB_Z})
else()
add_subdirectory(deps/zlib-1.3)
set(ZLIB_INC_DIR "${CMAKE_SOURCE_DIR}/deps/zlib-1.3" "${CMAKE_BINARY_DIR}/deps/zlib-1.3")
Expand All @@ -90,26 +107,41 @@ if(PIPY_OPENSSL)

set(OPENSSL_INC_DIR ${PIPY_OPENSSL}/include)
set(OPENSSL_LIB_DIR ${PIPY_OPENSSL}/lib)

else()
set(OPENSSL_SRC_DIR ${CMAKE_SOURCE_DIR}/deps/openssl-3.2.0)
set(OPENSSL_LIB_DIR ${OPENSSL_SRC_DIR}/build)
set(OPENSSL_INC_DIR ${OPENSSL_SRC_DIR}/include ${OPENSSL_LIB_DIR}/include)

add_custom_command(
OUTPUT ${OPENSSL_LIB_DIR}/libcrypto.a ${OPENSSL_LIB_DIR}/libssl.a
WORKING_DIRECTORY ${OPENSSL_SRC_DIR}
COMMAND mkdir -p ${OPENSSL_SRC_DIR}/build
COMMAND cd ${OPENSSL_SRC_DIR}/build && ../config no-shared no-tests && make -j
VERBATIM
COMMENT "Building OpenSSL"
)
file(MAKE_DIRECTORY "${OPENSSL_SRC_DIR}/build")

if(WIN32)
add_custom_command(
OUTPUT ${OPENSSL_LIB_DIR}/${LIB_CRYPTO} ${OPENSSL_LIB_DIR}/${LIB_SSL}
WORKING_DIRECTORY ${OPENSSL_SRC_DIR}/build
COMMAND cmd ARGS /C set
COMMAND perl ARGS ../Configure no-shared no-tests VC-WIN64A
COMMAND nmake
VERBATIM
COMMENT "Building OpenSSL"
)
else()
add_custom_command(
OUTPUT ${OPENSSL_LIB_DIR}/${LIB_CRYPTO} ${OPENSSL_LIB_DIR}/${LIB_SSL}
WORKING_DIRECTORY ${OPENSSL_SRC_DIR}
COMMAND mkdir -p ${OPENSSL_SRC_DIR}/build
COMMAND cd ${OPENSSL_SRC_DIR}/build && ../config no-shared no-tests && make -j
VERBATIM
COMMENT "Building OpenSSL"
)
endif()
endif()

add_custom_target(OpenSSL DEPENDS ${OPENSSL_LIB_DIR}/libcrypto.a ${OPENSSL_LIB_DIR}/libssl.a)
add_custom_target(OpenSSL DEPENDS ${OPENSSL_LIB_DIR}/${LIB_CRYPTO} ${OPENSSL_LIB_DIR}/${LIB_SSL})

if(PIPY_BROTLI)
set(BROTLI_INC_DIR ${PIPY_BROTLI}/include)
set(BROTLI_LIB ${PIPY_BROTLI}/lib/libbrotlidec-static.a)
set(BROTLI_LIB ${PIPY_BROTLI}/lib/${LIB_BROTLI})
else()
set(BROTLI_BUNDLED_MODE OFF CACHE BOOL "" FORCE)
set(BROTLI_DISABLE_TESTS ON CACHE BOOL "" FORCE)
Expand All @@ -119,10 +151,19 @@ else()
endif(PIPY_BROTLI)

add_definitions(
-D_GNU_SOURCE
-DPIPY_HOST="${CMAKE_HOST_SYSTEM} ${CMAKE_HOST_SYSTEM_PROCESSOR}"
-DXML_STATIC=1
)

if(WIN32)
add_definitions(
-D_WIN32_WINNT=0x0601
-D_USE_MATH_DEFINES
)
else()
add_definitions(-D_GNU_SOURCE)
endif()

include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-Wdelete-non-abstract-non-virtual-dtor"
COMPILER_SUPPORTS_DELETE_NON_ABSTRACT_NON_VIRTUAL_DTOR)
Expand All @@ -132,13 +173,24 @@ if(COMPILER_SUPPORTS_DELETE_NON_ABSTRACT_NON_VIRTUAL_DTOR)
$<$<COMPILE_LANGUAGE:CXX>:-Wno-delete-non-abstract-non-virtual-dtor>)
endif()

add_compile_options(
-Wall
-Wno-overloaded-virtual
-Wno-delete-non-virtual-dtor
-Wno-sign-compare
-Wno-deprecated-declarations
)
if(MSVC)
add_compile_options(
-Wno-unused-private-field
-Wno-overloaded-virtual
-Wno-delete-abstract-non-virtual-dtor
-Wno-delete-non-abstract-non-virtual-dtor
-Wno-deprecated-declarations
-Wno-inconsistent-dllimport
)
else(MSVC)
add_compile_options(
-Wall
-Wno-overloaded-virtual
-Wno-delete-non-virtual-dtor
-Wno-sign-compare
-Wno-deprecated-declarations
)
endif(MSVC)

include_directories(
"${CMAKE_SOURCE_DIR}/src"
Expand Down Expand Up @@ -264,6 +316,7 @@ add_executable(pipy
src/net.cpp
src/nmi.cpp
src/options.cpp
src/os-platform.cpp
src/outbound.cpp
src/pipeline.cpp
src/pipeline-lb.cpp
Expand All @@ -289,9 +342,10 @@ add_executable(pipy

add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/deps/version.h
COMMAND ${CMAKE_SOURCE_DIR}/generate_version_h.sh
COMMAND ${CMAKE_SOURCE_DIR}/generate_version_h.${EXT_SHELL}
ARGS ${CMAKE_BINARY_DIR}/deps/version.h
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)

add_custom_target(GenVer DEPENDS ${CMAKE_BINARY_DIR}/deps/version.h)

Expand Down Expand Up @@ -349,6 +403,8 @@ endif(PIPY_RFC8998)

if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-exported_symbols_list ${CMAKE_SOURCE_DIR}/include/pipy/nmi-exports.lst")
elseif(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "/DEF:${CMAKE_SOURCE_DIR}/include/pipy/nmi-exports.def")
else()
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--dynamic-list ${CMAKE_SOURCE_DIR}/include/pipy/nmi-exports.txt")
endif()
Expand All @@ -362,10 +418,14 @@ target_link_libraries(
yajl_s
expat
${ZLIB_LIB}
${OPENSSL_LIB_DIR}/libssl.a
${OPENSSL_LIB_DIR}/libcrypto.a
${OPENSSL_LIB_DIR}/${LIB_CRYPTO}
${OPENSSL_LIB_DIR}/${LIB_SSL}
${BROTLI_LIB}
leveldb
-pthread
-ldl
)

if(WIN32)
target_link_libraries(pipy crypt32)
else()
target_link_libraries(pipy -pthread -ldl)
endif()
16 changes: 16 additions & 0 deletions generate_version_h.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@echo off

for /f %%i in ('git describe --abbrev^=0 --tags') do set VERSION=%%i

for /f %%i in ('git log -1 --format^=%%H') do set COMMIT=%%i

for /f "eol= tokens=* delims=" %%i in ('"git log -1 --format=%%cD"') do set COMMIT_DATE=%%i

echo #ifndef __VERSION_H__ >> %1
echo #define __VERSION_H__ >> %1
echo. >> %1
echo #define PIPY_VERSION "%VERSION%" >> %1
echo #define PIPY_COMMIT "%COMMIT%" >> %1
echo #define PIPY_COMMIT_DATE "%COMMIT_DATE%" >> %1
echo. >> %1
echo #endif // __VERSION_H__ >> %1
74 changes: 74 additions & 0 deletions include/pipy/nmi-exports.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
EXPORTS
pjs_undefined
pjs_null
pjs_boolean
pjs_number
pjs_string
pjs_object
pjs_array
pjs_native
pjs_copy
pjs_hold
pjs_free
pjs_type_of
pjs_class_of
pjs_class_id
pjs_is_undefined
pjs_is_null
pjs_is_nullish
pjs_is_string
pjs_is_empty_string
pjs_is_object
pjs_is_instance_of
pjs_is_array
pjs_is_function
pjs_is_native
pjs_is_equal
pjs_is_identical
pjs_to_boolean
pjs_to_number
pjs_to_string
pjs_string_get_length
pjs_string_get_char_code
pjs_string_get_utf8_size
pjs_string_get_utf8_data
pjs_object_get_property
pjs_object_set_property
pjs_object_delete
pjs_object_iterate
pjs_array_get_length
pjs_array_set_length
pjs_array_get_element
pjs_array_set_element
pjs_array_delete
pjs_array_push
pjs_array_pop
pjs_array_shift
pjs_array_unshift
pjs_array_splice
pjs_native_ptr
pipy_is_Data
pipy_is_MessageStart
pipy_is_MessageEnd
pipy_is_StreamEnd
pipy_Data_new
pipy_Data_push
pipy_Data_pop
pipy_Data_shift
pipy_Data_get_size
pipy_Data_get_data
pipy_MessageStart_new
pipy_MessageStart_get_head
pipy_MessageEnd_new
pipy_MessageEnd_get_tail
pipy_MessageEnd_get_payload
pipy_StreamEnd_new
pipy_StreamEnd_get_error
pipy_define_variable
pipy_define_pipeline
pipy_hold
pipy_free
pipy_output_event
pipy_get_variable
pipy_set_variable
pipy_schedule
4 changes: 4 additions & 0 deletions include/pipy/nmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
extern "C" {
#endif

#if defined(_MSC_VER)
#define NMI_EXPORT extern
#else
#define NMI_EXPORT extern __attribute__((used))
#endif

/*
* PipyJS
Expand Down
4 changes: 4 additions & 0 deletions src/api/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2249,7 +2249,11 @@ template<> void ClassDef<FilterConfigurator>::init() {

// FilterConfigurator.use
method("use", [](Context &ctx, Object *thiz, Value &result) {
#ifndef _WIN32
static const std::string s_dot_so(".so");
#else
static const std::string s_dot_so(".dll");
#endif
auto config = thiz->as<FilterConfigurator>()->trace_location(ctx);
std::string module;
Array *modules;
Expand Down
4 changes: 2 additions & 2 deletions src/api/http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,8 +681,8 @@ auto File::to_message(pjs::Str *accept_encoding) -> pipy::Message* {
while (i < s.length() && std::isblank(s[i])) i++;
if (i < s.length()) {
auto n = 0; while (std::isalpha(s[i+n])) n++;
if (n == 4 && !strncasecmp(&s[i], "gzip", n)) has_gzip = true;
else if (n == 2 && !strncasecmp(&s[i], "br", n)) has_br = true;
if (n == 4 && utils::iequals(&s[i], "gzip", n)) has_gzip = true;
else if (n == 2 && utils::iequals(&s[i], "br", n)) has_br = true;
i += n;
while (i < s.length() && s[i] != ',') i++;
}
Expand Down
6 changes: 6 additions & 0 deletions src/api/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
#include "filters/http.hpp"
#include "filters/connect.hpp"

#ifndef _WIN32
#include <syslog.h>
#endif

namespace pipy {
namespace logging {
Expand Down Expand Up @@ -331,6 +333,7 @@ void Logger::FileTarget::Writer::shutdown() {
//

Logger::SyslogTarget::SyslogTarget(Priority priority) {
#ifndef _WIN32
switch (priority) {
case Priority::EMERG : m_priority = LOG_EMERG; break;
case Priority::ALERT : m_priority = LOG_ALERT; break;
Expand All @@ -342,14 +345,17 @@ Logger::SyslogTarget::SyslogTarget(Priority priority) {
case Priority::DEBUG : m_priority = LOG_DEBUG; break;
default : m_priority = LOG_INFO; break;
}
#endif
}

void Logger::SyslogTarget::write(const Data &msg) {
#ifndef _WIN32
auto len = msg.size();
uint8_t buf[len+1];
msg.to_bytes(buf);
buf[len] = 0;
syslog(m_priority, "%s", buf);
#endif
}

//
Expand Down
21 changes: 21 additions & 0 deletions src/api/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@
#include <sys/stat.h>
#include <fstream>

#ifdef _WIN32
#define S_IFLNK (_S_IFDIR | _S_IFREG)
#define S_ISDIR(mode) (((mode)&_S_IFMT) == _S_IFDIR)
#define S_ISREG(mode) (((mode)&_S_IFMT) == _S_IFREG)
#define S_ISCHR(mode) (((mode)&_S_IFMT) == _S_IFCHR)
#define S_ISBLK(mode) (((mode)&_S_IFMT) == 0)
#define S_ISFIFO(mode) (((mode)&_S_IFMT) == _S_IFIFO)
#define S_ISLNK(mode) (((mode)&_S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode)&_S_IFMT) == 0)
#endif

extern "C" char **environ;

namespace pipy {
Expand Down Expand Up @@ -127,8 +138,13 @@ template<> void ClassDef<OS>::init() {
method("stat", [](Context &ctx, Object*, Value &ret) {
Str *filename;
if (!ctx.arguments(1, &filename)) return;
#ifdef _WIN32
struct _stat st;
if (_stat(filename->c_str(), &st)) {
#else
struct stat st;
if (stat(filename->c_str(), &st)) {
#endif
ret = Value::null;
} else {
auto s = OS::Stats::make();
Expand All @@ -140,8 +156,13 @@ template<> void ClassDef<OS>::init() {
s->gid = st.st_gid;
s->rdev = st.st_rdev;
s->size = st.st_size;
#ifdef _WIN32
s->blksize = 4096;
s->blocks = 512;
#else
s->blksize = st.st_blksize;
s->blocks = st.st_blocks;
#endif
s->atime = st.st_atime;
s->mtime = st.st_mtime;
s->ctime = st.st_ctime;
Expand Down
Loading