Skip to content

Commit b03442d

Browse files
authored
Merge pull request #8 from lichifeng/refactor-2024-linux
Modifications compiling on alpine. Add a static library option. Updated spdlog.
2 parents 3411068 + ea6a663 commit b03442d

113 files changed

Lines changed: 7423 additions & 7270 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docker-publish.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,18 @@ jobs:
1818
username: ${{ secrets.DOCKERHUB_USERNAME }}
1919
password: ${{ secrets.DOCKERHUB_TOKEN }}
2020

21-
- name: Build and push Docker image
21+
- name: Build and push Docker image (default)
2222
uses: docker/build-push-action@v5
2323
with:
2424
context: .
2525
push: true
2626
tags: lichifeng/mgxparser:latest
27+
file: Dockerfile
28+
29+
- name: Build and push Docker image (alpine)
30+
uses: docker/build-push-action@v5
31+
with:
32+
context: .
33+
push: true
34+
tags: lichifeng/mgxparser:alpine
35+
file: Dockerfile.alpine

CMakeLists.txt

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Project info
66
project(
77
MgxParser
8-
VERSION 0.5.0
8+
VERSION 0.5.2
99
LANGUAGES CXX
1010
HOMEPAGE_URL "https://github.com/lichifeng/MgxParser"
1111
DESCRIPTION "MgxParser is a C++ lib used to parse Age of Empires II game records."
@@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD 17)
1717
set(CMAKE_CXX_STANDARD_REQUIRED True)
1818
set(CMAKE_POSITION_INDEPENDENT_CODE true)
1919
set(USE_BM_SEARCH 1)
20+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Release)
2021

2122
# Prepare source files to be compiled
2223
aux_source_directory(./src SRC_ROOT)
@@ -29,22 +30,31 @@ set(MGXPARSER_SRCS ${DEFAULT_ANALYZER} ${DEFAULT_ANALYZER_BODY} ${SRC_ROOT} ${TO
2930
# WARNING: png depends on libz, so put it before z
3031
set(MGXPARSER_DEPENDENCIES ssl crypto png z)
3132

33+
# Create an option for building static libraries
34+
OPTION(BUILD_STATIC "Build static libraries" ON)
35+
3236
# Create static and shared libraries
3337
add_library("${PROJECT_NAME}_OBJECT" OBJECT ${MGXPARSER_SRCS})
3438
add_library("${PROJECT_NAME}_SHARED" SHARED $<TARGET_OBJECTS:${PROJECT_NAME}_OBJECT>)
35-
add_library("${PROJECT_NAME}_STATIC" STATIC $<TARGET_OBJECTS:${PROJECT_NAME}_OBJECT>)
3639
target_link_libraries("${PROJECT_NAME}_SHARED" ${MGXPARSER_DEPENDENCIES})
37-
target_link_libraries("${PROJECT_NAME}_STATIC" ${MGXPARSER_DEPENDENCIES})
40+
41+
if(BUILD_STATIC)
42+
add_library("${PROJECT_NAME}_STATIC" STATIC $<TARGET_OBJECTS:${PROJECT_NAME}_OBJECT>)
43+
target_link_libraries("${PROJECT_NAME}_STATIC" ${MGXPARSER_DEPENDENCIES})
44+
endif()
3845

3946
# Create static and shared executables
40-
add_executable("${PROJECT_NAME}_S_EXE" demo.cc)
41-
target_link_libraries("${PROJECT_NAME}_S_EXE" ${PROJECT_NAME}_STATIC)
42-
target_link_options("${PROJECT_NAME}_S_EXE" PRIVATE "-static")
47+
if(BUILD_STATIC)
48+
add_executable("${PROJECT_NAME}_S_EXE" demo.cc)
49+
target_link_libraries("${PROJECT_NAME}_S_EXE" ${PROJECT_NAME}_STATIC)
50+
target_link_options("${PROJECT_NAME}_S_EXE" PRIVATE "-static")
51+
endif()
52+
4353
add_executable("${PROJECT_NAME}_D_EXE" demo.cc)
4454
target_link_libraries("${PROJECT_NAME}_D_EXE" ${PROJECT_NAME}_SHARED)
4555
set_target_properties(${PROJECT_NAME}_D_EXE PROPERTIES
46-
BUILD_WITH_INSTALL_RPATH TRUE
47-
INSTALL_RPATH "$ORIGIN"
56+
BUILD_WITH_INSTALL_RPATH TRUE
57+
INSTALL_RPATH "$ORIGIN"
4858
)
4959

5060
set(
@@ -59,14 +69,16 @@ set(
5969
)
6070
target_include_directories("${PROJECT_NAME}_OBJECT" PRIVATE ${MGXPARSER_INCLUDE})
6171
target_include_directories("${PROJECT_NAME}_D_EXE" PRIVATE ${MGXPARSER_INCLUDE})
62-
target_include_directories("${PROJECT_NAME}_S_EXE" PRIVATE ${MGXPARSER_INCLUDE})
72+
if(BUILD_STATIC)
73+
target_include_directories("${PROJECT_NAME}_S_EXE" PRIVATE ${MGXPARSER_INCLUDE})
74+
endif()
6375

6476
# Compile Node.js Addon
6577
add_definitions(-DNAPI_VERSION=3)
6678
# 检查napi.h是否存在于CMAKE_JS_INC目录中
6779
find_path(NAPI_H_FOUND "node_api.h" PATHS ${CMAKE_JS_INC})
6880

69-
# 如果napi.h和CMAKE_JS_LIB都存在,创建mgxnodeS库
81+
# 如果napi.h和CMAKE_JS_LIB都存在,创建mgxnode库,node-addon必然是动态库
7082
if(NAPI_H_FOUND)
7183
# Include Node-API wrappers
7284
execute_process(COMMAND node -p "require('node-addon-api').include"
@@ -135,14 +147,14 @@ if (BUILD_TESTING)
135147
${CMAKE_CURRENT_SOURCE_DIR}/test/test.cc
136148
)
137149
target_include_directories("${PROJECT_NAME}_TEST" PRIVATE ${MGXPARSER_INCLUDE})
138-
target_link_libraries("${PROJECT_NAME}_TEST" ${PROJECT_NAME}_STATIC)
150+
target_link_libraries("${PROJECT_NAME}_TEST" ${PROJECT_NAME}_SHARED)
139151
target_link_libraries("${PROJECT_NAME}_TEST" GTest::gtest_main)
140152
add_executable(
141153
"CURSOR_TEST"
142154
${CMAKE_CURRENT_SOURCE_DIR}/test/cursor_test.cc
143155
src/tools/cursor.cc
144156
)
145-
target_link_libraries("CURSOR_TEST" ${PROJECT_NAME}_STATIC)
157+
target_link_libraries("CURSOR_TEST" ${PROJECT_NAME}_SHARED)
146158
target_link_libraries("CURSOR_TEST" GTest::gtest_main)
147159
include(GoogleTest)
148160
gtest_discover_tests("${PROJECT_NAME}_TEST")

Dockerfile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
# 使用多阶段构建,第一阶段用于编译
1+
# Usage: docker build -t mgxparser-alpine -f Dockerfile.alpine .
2+
# url -X POST -F "file=@/root/projects/MgxParser/MgxParser/test/test_records/aitest.mgx2" -F "command={\"map\":\"HD\"}" http://localhost:4400
3+
4+
# Phase 1: Compile the native module
5+
26
FROM node:20-slim as builder
37

48
WORKDIR /app
@@ -12,12 +16,11 @@ RUN apt-get update && apt-get install -y \
1216
RUN npm install
1317
RUN npx cmake-js rebuild -p $(nproc)
1418

15-
# 第二阶段用于运行
19+
# Phase 2: Deploy the native module and the app
1620
FROM node:20-slim
1721

1822
WORKDIR /parser
1923

20-
# 从构建阶段复制文件
2124
COPY --from=builder /app/build/Release/mgxnode.node .
2225
COPY --from=builder /app/docker_exe/app.js .
2326
COPY --from=builder /app/docker_exe/package.json .

Dockerfile.alpine

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Usage: docker build -t mgxparser-alpine -f Dockerfile.alpine .
2+
# curl -X POST -F "file=@/root/projects/MgxParser/MgxParser/test/test_records/aitest.mgx2" -F "command={\"map\":\"HD\"}" http://localhost:4400
3+
4+
# Phase 1: Compile the native module
5+
FROM node:20.11.1-alpine3.19 as builder
6+
7+
WORKDIR /app
8+
9+
COPY . .
10+
11+
RUN apk add --no-cache \
12+
alpine-sdk \
13+
cmake \
14+
libpng-dev openssl-dev
15+
RUN npm install
16+
RUN npx cmake-js rebuild --CDBUILD_STATIC=OFF -p $(nproc)
17+
18+
19+
# Phase 2: Deploy the native module and the app
20+
FROM node:20.11.1-alpine3.19
21+
22+
WORKDIR /parser
23+
24+
COPY --from=builder /app/build/Release/mgxnode.node .
25+
COPY --from=builder /app/docker_exe/app.js .
26+
COPY --from=builder /app/docker_exe/package.json .
27+
28+
RUN apk update && apk add libpng openssl
29+
RUN npm install
30+
31+
CMD ["node", "app.js"]

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# **MgxParser**
2-
*This version(0.5.0) was compiled on 20240220*
2+
*This version(0.5.2) was compiled on 20240305*
33

44
## Introduction
55
MgxParser is a C++ lib used to parse Age of Empires II game records.
@@ -74,6 +74,9 @@ Those keys are ensured to be in the output:
7474
- **realext**: File extension of the extracted file in .zip archive. e.g. .mgx, .aoe2record, etc.
7575
- **gameTime**: Time when this game played. Later DE versions have this recorded. Older versions use last modified time of the record file. If the input stream is not a file, will be current time.
7676
- **message**: A string contains some hints about the parsing process.
77+
- **matchup**: Matchup of this game. e.g. "1v1", "4v4", "1v2v3", etc. "N/A" if not available.
78+
- **version.code**: A string indicates the version of the record. e.g. "AOC10C", "DE", etc. "UNSUPPORTED" if not available.
79+
- **rawEncoding**: The encoding of the record file. e.g. "UTF-8", "ISO-8859-1", etc. "UNKNOWN" if not detected.
7780
7881
### About 'status'
7982
The 'status' value can be checked to determine whether the parsing was successful:
@@ -121,7 +124,6 @@ get notified.
121124
These libraries are required to build MgxParser:
122125
- **CImg(bundled)**: Used to generate mini maps. This library is bundled into `libs/CImg`
123126
and compiled with MgxParser.
124-
- **movfuscator**: md5 function in this project was used to generate retroGuid
125127
of record. [Project page](https://github.com/xoreaxeaxeax/movfuscator/blob/ea37dae93fbcd93f642c71a53878da588bd7ddb4/validation/crypto-algorithms/md5_test.c)
126128
- **libpng**: Required by CImg.
127129
```sh
@@ -143,15 +145,14 @@ These libraries are required to build MgxParser:
143145
All dependencies of MgxParser are bundled into the executive file after compilation.
144146
145147
## How to compile
148+
A complie option `BUILD_STATIC` is provided to control whether to build a static library.
149+
Because some denpendencies don't provide a static version on alpine.
150+
146151
To compile this project, latest version of CMake is recommended. See
147152
https://apt.kitware.com/ for details on this. I use CMake `3.24.1` and never
148153
tested other versions. On Ubuntu18 and newer versions, fresh version of cmake
149154
can be installed by:
150155
```sh
151-
sudo snap install cmake --classic
152-
```
153-
or
154-
```sh
155156
sudo apt-get install cmake
156157
```
157158
@@ -181,6 +182,7 @@ The compiled node addon will be in `build/Release` directory.
181182
A demo of node addon is in `test/node_addon_test.js` directory.
182183
183184
## Version log
185+
- **0.5.2**: Modifications compiling on alpine. Add a static library option. Updated spdlog.
184186
- **0.5.0**: Refactored json output, make some keys mandatory. **Some key names changed!**
185187
- **0.4.6**: Replace md5 with openssl MD5 algorithm. Add ability to generate base64 encoded map data.
186188
- **0.4.5**: Reorganized source code. Refactored `parse()` function. Add node addon support. Add docker workflow.

libs/spdlog/async.h

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
#include <spdlog/details/registry.h>
1919
#include <spdlog/details/thread_pool.h>
2020

21+
#include <functional>
2122
#include <memory>
2223
#include <mutex>
23-
#include <functional>
2424

2525
namespace spdlog {
2626

@@ -31,27 +31,25 @@ static const size_t default_async_q_size = 8192;
3131
// async logger factory - creates async loggers backed with thread pool.
3232
// if a global thread pool doesn't already exist, create it with default queue
3333
// size of 8192 items and single thread.
34-
template<async_overflow_policy OverflowPolicy = async_overflow_policy::block>
35-
struct async_factory_impl
36-
{
37-
template<typename Sink, typename... SinkArgs>
38-
static std::shared_ptr<async_logger> create(std::string logger_name, SinkArgs &&... args)
39-
{
34+
template <async_overflow_policy OverflowPolicy = async_overflow_policy::block>
35+
struct async_factory_impl {
36+
template <typename Sink, typename... SinkArgs>
37+
static std::shared_ptr<async_logger> create(std::string logger_name, SinkArgs &&...args) {
4038
auto &registry_inst = details::registry::instance();
4139

4240
// create global thread pool if not already exists..
4341

4442
auto &mutex = registry_inst.tp_mutex();
4543
std::lock_guard<std::recursive_mutex> tp_lock(mutex);
4644
auto tp = registry_inst.get_tp();
47-
if (tp == nullptr)
48-
{
45+
if (tp == nullptr) {
4946
tp = std::make_shared<details::thread_pool>(details::default_async_q_size, 1U);
5047
registry_inst.set_tp(tp);
5148
}
5249

5350
auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...);
54-
auto new_logger = std::make_shared<async_logger>(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy);
51+
auto new_logger = std::make_shared<async_logger>(std::move(logger_name), std::move(sink),
52+
std::move(tp), OverflowPolicy);
5553
registry_inst.initialize_logger(new_logger);
5654
return new_logger;
5755
}
@@ -60,40 +58,43 @@ struct async_factory_impl
6058
using async_factory = async_factory_impl<async_overflow_policy::block>;
6159
using async_factory_nonblock = async_factory_impl<async_overflow_policy::overrun_oldest>;
6260

63-
template<typename Sink, typename... SinkArgs>
64-
inline std::shared_ptr<spdlog::logger> create_async(std::string logger_name, SinkArgs &&... sink_args)
65-
{
66-
return async_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
61+
template <typename Sink, typename... SinkArgs>
62+
inline std::shared_ptr<spdlog::logger> create_async(std::string logger_name,
63+
SinkArgs &&...sink_args) {
64+
return async_factory::create<Sink>(std::move(logger_name),
65+
std::forward<SinkArgs>(sink_args)...);
6766
}
6867

69-
template<typename Sink, typename... SinkArgs>
70-
inline std::shared_ptr<spdlog::logger> create_async_nb(std::string logger_name, SinkArgs &&... sink_args)
71-
{
72-
return async_factory_nonblock::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...);
68+
template <typename Sink, typename... SinkArgs>
69+
inline std::shared_ptr<spdlog::logger> create_async_nb(std::string logger_name,
70+
SinkArgs &&...sink_args) {
71+
return async_factory_nonblock::create<Sink>(std::move(logger_name),
72+
std::forward<SinkArgs>(sink_args)...);
7373
}
7474

7575
// set global thread pool.
76-
inline void init_thread_pool(
77-
size_t q_size, size_t thread_count, std::function<void()> on_thread_start, std::function<void()> on_thread_stop)
78-
{
79-
auto tp = std::make_shared<details::thread_pool>(q_size, thread_count, on_thread_start, on_thread_stop);
76+
inline void init_thread_pool(size_t q_size,
77+
size_t thread_count,
78+
std::function<void()> on_thread_start,
79+
std::function<void()> on_thread_stop) {
80+
auto tp = std::make_shared<details::thread_pool>(q_size, thread_count, on_thread_start,
81+
on_thread_stop);
8082
details::registry::instance().set_tp(std::move(tp));
8183
}
8284

83-
inline void init_thread_pool(size_t q_size, size_t thread_count, std::function<void()> on_thread_start)
84-
{
85+
inline void init_thread_pool(size_t q_size,
86+
size_t thread_count,
87+
std::function<void()> on_thread_start) {
8588
init_thread_pool(q_size, thread_count, on_thread_start, [] {});
8689
}
8790

88-
inline void init_thread_pool(size_t q_size, size_t thread_count)
89-
{
91+
inline void init_thread_pool(size_t q_size, size_t thread_count) {
9092
init_thread_pool(
9193
q_size, thread_count, [] {}, [] {});
9294
}
9395

9496
// get the global thread pool.
95-
inline std::shared_ptr<spdlog::details::thread_pool> thread_pool()
96-
{
97+
inline std::shared_ptr<spdlog::details::thread_pool> thread_pool() {
9798
return details::registry::instance().get_tp();
9899
}
99-
} // namespace spdlog
100+
} // namespace spdlog

0 commit comments

Comments
 (0)