初始可用。
This commit is contained in:
20
.clang-format
Normal file
20
.clang-format
Normal file
@@ -0,0 +1,20 @@
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
PointerAlignment: Left
|
||||
AccessModifierOffset: -4
|
||||
ReflowComments: true
|
||||
SpacesBeforeTrailingComments: 3
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterFunction: true
|
||||
AfterClass: true
|
||||
TabWidth: 4
|
||||
ColumnLimit: 130
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<.*>'
|
||||
Priority: 1
|
||||
- Regex: '^".*"'
|
||||
Priority: 2
|
||||
12
.clangd
Normal file
12
.clangd
Normal file
@@ -0,0 +1,12 @@
|
||||
Hover:
|
||||
ShowAKA: Yes
|
||||
Diagnostics:
|
||||
UnusedIncludes: None # 禁用未使用头文件提示
|
||||
Suppress: [
|
||||
anon_type_definition, # 禁用匿名的typedef提示
|
||||
unused-variable, # 禁用未使用变量提示
|
||||
unused-function, # 禁用未使用函数提示
|
||||
unused-includes,
|
||||
]
|
||||
ClangTidy:
|
||||
Remove: misc-unused-alias-decls
|
||||
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# Xmake cache
|
||||
.xmake/
|
||||
build/
|
||||
|
||||
# MacOS Cache
|
||||
.DS_Store
|
||||
compile_commands.json
|
||||
|
||||
vv
|
||||
124
.vscode/settings.json
vendored
Normal file
124
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"files.autoSave": "onFocusChange",
|
||||
"editor.fontSize": 14,
|
||||
"editor.fontFamily": "'Source Code Pro', 'Source Code Pro', 'Source Code Pro'",
|
||||
"editor.wordWrap": "on",
|
||||
"terminal.integrated.fontFamily": "'Source Code Pro'",
|
||||
"cmake.configureOnOpen": false,
|
||||
"C_Cpp.intelliSenseEngine": "default",
|
||||
"C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||
"editor.inlayHints.enabled": "off",
|
||||
"editor.unicodeHighlight.allowedLocales": {
|
||||
"ja": true,
|
||||
"zh-hant": true,
|
||||
"zh-hans": true
|
||||
},
|
||||
"xmake.additionalConfigArguments": [
|
||||
|
||||
],
|
||||
"files.associations": {
|
||||
"*.cfg": "json",
|
||||
"xstring": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"cctype": "cpp",
|
||||
"charconv": "cpp",
|
||||
"chrono": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"exception": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"fstream": "cpp",
|
||||
"functional": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"ios": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"iterator": "cpp",
|
||||
"limits": "cpp",
|
||||
"list": "cpp",
|
||||
"locale": "cpp",
|
||||
"map": "cpp",
|
||||
"memory": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ratio": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"thread": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"utility": "cpp",
|
||||
"vector": "cpp",
|
||||
"xfacet": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xiosbase": "cpp",
|
||||
"xlocale": "cpp",
|
||||
"xlocbuf": "cpp",
|
||||
"xlocinfo": "cpp",
|
||||
"xlocmes": "cpp",
|
||||
"xlocmon": "cpp",
|
||||
"xlocnum": "cpp",
|
||||
"xloctime": "cpp",
|
||||
"xmemory": "cpp",
|
||||
"xmemory0": "cpp",
|
||||
"xstddef": "cpp",
|
||||
"xtr1common": "cpp",
|
||||
"xtree": "cpp",
|
||||
"xutility": "cpp",
|
||||
"bit": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"coroutine": "cpp",
|
||||
"format": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"bitset": "cpp",
|
||||
"complex": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"set": "cpp",
|
||||
"variant": "cpp",
|
||||
"expected": "cpp",
|
||||
"source_location": "cpp",
|
||||
"regex": "cpp",
|
||||
"*.in": "cpp",
|
||||
"deque": "cpp",
|
||||
"future": "cpp",
|
||||
"queue": "cpp",
|
||||
"resumable": "cpp",
|
||||
"any": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"random": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"cfenv": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"ranges": "cpp",
|
||||
"typeindex": "cpp"
|
||||
}
|
||||
}
|
||||
116
script/quick-xmake-install.bat
Normal file
116
script/quick-xmake-install.bat
Normal file
@@ -0,0 +1,116 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
title Quick XMake 右键菜单安装
|
||||
echo =========================================
|
||||
echo Quick XMake - 右键菜单安装工具
|
||||
echo =========================================
|
||||
echo.
|
||||
|
||||
REM 获取当前目录
|
||||
for %%I in ("%~dp0.") do set "TOOLDIR=%%~fI"
|
||||
set "DLLPATH=%TOOLDIR%\quick-xmake.dll"
|
||||
|
||||
REM 检查 DLL 文件是否存在
|
||||
if not exist "%DLLPATH%" (
|
||||
echo 错误: quick-xmake.dll 未找到
|
||||
echo 请将此批处理文件与 quick-xmake.dll 放在同一目录
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo 正在安装右键菜单...
|
||||
echo.
|
||||
|
||||
REM 清理旧的注册表项
|
||||
echo 清理旧的注册表项...
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake" /f 2>nul
|
||||
|
||||
REM 创建一级菜单
|
||||
echo 创建一级菜单...
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake" /ve /d "" /f
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 创建一级菜单失败
|
||||
goto :error
|
||||
)
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake" /v "MUIVerb" /d "quick-xmake" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake" /v "Icon" /d "%%SystemRoot%%\System32\shell32.dll,50" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake" /v "SubCommands" /d "" /f
|
||||
|
||||
REM 创建二级菜单项
|
||||
echo 创建二级菜单项...
|
||||
|
||||
REM 二级菜单:Create
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\create" /ve /d "" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\create" /v "MUIVerb" /d "Create" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\create\command" /ve /d "rundll32.exe \"%DLLPATH%\",ContextMenuHandler \"%%V\" 0" /f
|
||||
|
||||
REM 二级菜单:Build
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\build" /ve /d "" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\build" /v "MUIVerb" /d "Build" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\build\command" /ve /d "rundll32.exe \"%DLLPATH%\",ContextMenuHandler \"%%V\" 1" /f
|
||||
|
||||
REM 二级菜单:Set debug mode
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-debug" /ve /d "" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-debug" /v "MUIVerb" /d "Set debug mode" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-debug\command" /ve /d "rundll32.exe \"%DLLPATH%\",ContextMenuHandler \"%%V\" 2" /f
|
||||
|
||||
REM 二级菜单:Set release mode
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-release" /ve /d "" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-release" /v "MUIVerb" /d "Set release mode" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-release\command" /ve /d "rundll32.exe \"%DLLPATH%\",ContextMenuHandler \"%%V\" 3" /f
|
||||
|
||||
REM 二级菜单:Run
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\run" /ve /d "" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\run" /v "MUIVerb" /d "Run" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\run\command" /ve /d "rundll32.exe \"%DLLPATH%\",ContextMenuHandler \"%%V\" 4" /f
|
||||
|
||||
REM 二级菜单:Template
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\template" /ve /d "" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\template" /v "MUIVerb" /d "Template" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\template\command" /ve /d "rundll32.exe \"%DLLPATH%\",ContextMenuHandler \"%%V\" 5" /f
|
||||
|
||||
echo.
|
||||
echo =========================================
|
||||
echo 安装成功!
|
||||
echo =========================================
|
||||
echo.
|
||||
echo 菜单结构:
|
||||
echo 在文件夹空白处右键 =》 quick-xmake =》
|
||||
echo ├── Create
|
||||
echo ├── Build
|
||||
echo ├── Set debug mode
|
||||
echo ├── Set release mode
|
||||
echo └── Run
|
||||
echo.
|
||||
echo 注意事项:
|
||||
echo 1. 本脚本已自动以管理员权限运行
|
||||
echo 2. 新菜单需要重新打开资源管理器才能显示
|
||||
echo 3. 需要重启资源管理器吗?
|
||||
echo.
|
||||
choice /c YN /n /m "重启资源管理器 (Y/N): "
|
||||
if %errorlevel% equ 1 (
|
||||
echo 正在重启资源管理器...
|
||||
taskkill /f /im explorer.exe >nul 2>&1
|
||||
start explorer.exe
|
||||
echo 资源管理器已重启
|
||||
) else (
|
||||
echo 您可以选择稍后手动重启资源管理器
|
||||
echo 或重新打开文件夹查看新菜单
|
||||
)
|
||||
echo.
|
||||
pause
|
||||
exit /b 0
|
||||
|
||||
:error
|
||||
echo.
|
||||
echo 安装过程中出现错误,请检查:
|
||||
echo 1. 是否以管理员身份运行
|
||||
echo 2. 注册表权限是否正常
|
||||
echo 3. 文件路径是否包含特殊字符
|
||||
echo 4. DLL文件是否被其他程序占用
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
61
script/quick-xmake-uninstall.bat
Normal file
61
script/quick-xmake-uninstall.bat
Normal file
@@ -0,0 +1,61 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
title Quick XMake 右键菜单卸载
|
||||
echo =========================================
|
||||
echo Quick XMake - 右键菜单卸载工具
|
||||
echo =========================================
|
||||
echo.
|
||||
|
||||
echo 正在卸载右键菜单...
|
||||
echo.
|
||||
|
||||
REM 删除所有注册表项(从最深层开始)
|
||||
echo 删除二级菜单命令...
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\run\command" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\template\command" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-release\command" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-debug\command" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\build\command" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\create\command" /f 2>nul
|
||||
|
||||
echo 删除二级菜单...
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\run" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\template" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-release" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\set-debug" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\build" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell\create" /f 2>nul
|
||||
|
||||
echo 删除一级菜单...
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake\shell" /f 2>nul
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\quick-xmake" /f 2>nul
|
||||
|
||||
echo.
|
||||
echo =========================================
|
||||
echo 卸载成功!
|
||||
echo =========================================
|
||||
echo.
|
||||
echo 已删除以下菜单项:
|
||||
echo ├── Create
|
||||
echo ├── Build
|
||||
echo ├── Set debug mode
|
||||
echo ├── Set release mode
|
||||
echo └── Run
|
||||
echo.
|
||||
echo 注意事项:
|
||||
echo 1. 您需要重启资源管理器才能看到菜单被移除
|
||||
echo 2. 是否现在重启资源管理器?
|
||||
echo.
|
||||
choice /c YN /n /m "重启资源管理器 (Y/N): "
|
||||
if %errorlevel% equ 1 (
|
||||
echo 正在重启资源管理器...
|
||||
taskkill /f /im explorer.exe >nul 2>&1
|
||||
start explorer.exe
|
||||
echo 资源管理器已重启
|
||||
) else (
|
||||
echo 您可以选择稍后手动重启资源管理器
|
||||
)
|
||||
echo.
|
||||
pause
|
||||
exit /b 0
|
||||
334
src/main.cpp
Normal file
334
src/main.cpp
Normal file
@@ -0,0 +1,334 @@
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <filesystem>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <shlobj.h>
|
||||
#include <spdlog/sinks/rotating_file_sink.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static std::shared_ptr<spdlog::logger> logger;
|
||||
|
||||
// 全局常量
|
||||
const char* MENU_NAME = "quick-xmake";
|
||||
const char* SUBMENU_NAMES[] = {"create", "build", "set-debug", "set-release"};
|
||||
const int SUBMENU_COUNT = 4;
|
||||
|
||||
std::string WcharToChar(const wchar_t* wp, size_t m_encode = CP_ACP)
|
||||
{
|
||||
std::string str;
|
||||
int len = WideCharToMultiByte(m_encode, 0, wp, wcslen(wp), NULL, 0, NULL, NULL);
|
||||
char* m_char = new char[len + 1];
|
||||
WideCharToMultiByte(m_encode, 0, wp, wcslen(wp), m_char, len, NULL, NULL);
|
||||
m_char[len] = '\0';
|
||||
str = m_char;
|
||||
delete m_char;
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string u8_to_ansi(const std::string& str)
|
||||
{
|
||||
int wideCharLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
|
||||
if (wideCharLen <= 0) {
|
||||
return "";
|
||||
}
|
||||
std::wstring wideStr(wideCharLen, L'\0');
|
||||
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &wideStr[0], wideCharLen);
|
||||
int gbkLen = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
if (gbkLen <= 0) {
|
||||
return "";
|
||||
}
|
||||
std::string gbkStr(gbkLen, '\0');
|
||||
WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), -1, &gbkStr[0], gbkLen, nullptr, nullptr);
|
||||
|
||||
gbkStr.resize(gbkLen - 1);
|
||||
return gbkStr;
|
||||
}
|
||||
std::string ansi_to_u8(const std::string& str)
|
||||
{
|
||||
int wideCharLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);
|
||||
if (wideCharLen <= 0) {
|
||||
return "";
|
||||
}
|
||||
std::wstring wideStr(wideCharLen, L'\0');
|
||||
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &wideStr[0], wideCharLen);
|
||||
|
||||
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
if (utf8Len <= 0) {
|
||||
return "";
|
||||
}
|
||||
std::string utf8Str(utf8Len, '\0');
|
||||
WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), -1, &utf8Str[0], utf8Len, nullptr, nullptr);
|
||||
|
||||
utf8Str.resize(utf8Len - 1);
|
||||
return utf8Str;
|
||||
}
|
||||
|
||||
std::string GetQuickXmakeLogPath()
|
||||
{
|
||||
try {
|
||||
fs::path userDir;
|
||||
char* userProfileEnv = std::getenv("USERPROFILE");
|
||||
if (userProfileEnv != nullptr) {
|
||||
userDir = fs::path(userProfileEnv);
|
||||
} else {
|
||||
char* homeEnv = std::getenv("HOME");
|
||||
if (homeEnv != nullptr) {
|
||||
userDir = fs::path(homeEnv);
|
||||
}
|
||||
}
|
||||
if (userDir.empty() || !fs::exists(userDir)) {
|
||||
userDir = fs::current_path();
|
||||
}
|
||||
|
||||
fs::path logPath = userDir / ".config" / "quick-xmake" / "quick-xmake.log";
|
||||
|
||||
try {
|
||||
fs::create_directories(logPath.parent_path());
|
||||
} catch (const std::exception& e) {
|
||||
logger->error("Failed to create log directory: {}", ansi_to_u8(e.what()));
|
||||
return "quick-xmake.log";
|
||||
}
|
||||
|
||||
return logPath.string();
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
logger->error("Failed to get user directory: {}", ansi_to_u8(e.what()));
|
||||
return "quick-xmake.log";
|
||||
}
|
||||
}
|
||||
|
||||
int ReplaceTemplate(const std::string& projectDir)
|
||||
{
|
||||
fs::path p(projectDir);
|
||||
p.append("xmake.lua");
|
||||
|
||||
if (!fs::exists(p)) {
|
||||
logger->error("xmake.lua not found in {}", projectDir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ifstream in(p.string());
|
||||
std::string content(std::istreambuf_iterator<char>(in), {});
|
||||
in.close();
|
||||
|
||||
std::string newLuaContent = R"(
|
||||
add_rules("mode.debug", "mode.release")
|
||||
add_rules("plugin.compile_commands.autoupdate", {outputdir = "build"})
|
||||
|
||||
if is_plat("windows") then
|
||||
add_cxxflags("/utf-8")
|
||||
-- add_defines("WIN32_LEAN_AND_MEAN")
|
||||
end
|
||||
|
||||
set_languages("c++17")
|
||||
)";
|
||||
|
||||
std::string lpre = R"(add_rules("mode.debug", "mode.release"))";
|
||||
boost::replace_all(content, lpre, newLuaContent);
|
||||
std::ofstream out(p.string());
|
||||
out << content;
|
||||
out.close();
|
||||
|
||||
fs::path pm(projectDir);
|
||||
pm.append("src");
|
||||
pm.append("main.cpp");
|
||||
if (!fs::exists(pm)) {
|
||||
logger->error("main.cpp not found in {}", projectDir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ifstream inCpp(pm.string());
|
||||
std::string contentCpp(std::istreambuf_iterator<char>(inCpp), {});
|
||||
inCpp.close();
|
||||
|
||||
std::string newCppContent =
|
||||
R"(#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#endif
|
||||
)";
|
||||
|
||||
std::string mpre = R"(int main(int argc, char **argv) {)";
|
||||
boost::replace_all(contentCpp, mpre, newCppContent);
|
||||
std::ofstream outCpp(pm.string());
|
||||
outCpp << contentCpp;
|
||||
outCpp.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExecuteCmd(const std::string& exe, std::vector<std::string>& args, const std::string& workDir)
|
||||
{
|
||||
try {
|
||||
// 构建 xmake 命令
|
||||
std::string xmakeCmd = "\"" + exe + "\"";
|
||||
for (const auto& arg : args) {
|
||||
xmakeCmd += " \"" + arg + "\"";
|
||||
}
|
||||
|
||||
// 完整的 cmd 命令:先 cd 到目录,然后执行 xmake,使用 /k 保持窗口打开
|
||||
std::string fullCmd = "cd /d \"" + workDir + "\" && " + xmakeCmd;
|
||||
|
||||
logger->info("Command line: cmd /k {}", fullCmd);
|
||||
|
||||
STARTUPINFOA si = {sizeof(STARTUPINFOA)};
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
|
||||
// 设置控制台窗口
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_SHOW;
|
||||
|
||||
// 构建包含 /k 的命令行
|
||||
std::string cmdLine = "cmd.exe /k \"" + fullCmd + "\"";
|
||||
|
||||
BOOL success = CreateProcess(NULL, // 应用程序名称
|
||||
const_cast<char*>(cmdLine.c_str()), // 完整的命令行
|
||||
NULL, // 进程安全属性
|
||||
NULL, // 线程安全属性
|
||||
FALSE, // 不继承句柄
|
||||
CREATE_NEW_CONSOLE, // 创建新控制台
|
||||
NULL, // 环境块
|
||||
NULL, // 工作目录(已经在命令中指定)
|
||||
&si, // STARTUPINFO
|
||||
&pi // PROCESS_INFORMATION
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
logger->error("CreateProcess failed: {}", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 立即返回,不等待进程结束
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
logger->info("Process started successfully, console will remain open");
|
||||
return 0; // 立即返回成功
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
logger->error("Exception: {}", ansi_to_u8(e.what()));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) HRESULT CALLBACK ContextMenuHandler(HWND hwnd, HINSTANCE hinst, LPCSTR lpszCmdLine, int nCmdShow)
|
||||
{
|
||||
std::shared_ptr<void> quit(nullptr, [](void*) {
|
||||
if (logger) {
|
||||
logger->flush();
|
||||
}
|
||||
spdlog::shutdown();
|
||||
});
|
||||
|
||||
auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(GetQuickXmakeLogPath(), 1024 * 1024 * 50, 3);
|
||||
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l]: %v");
|
||||
std::vector<spdlog::sink_ptr> sinks{file_sink};
|
||||
logger = std::make_shared<spdlog::logger>("quick-xmake", sinks.begin(), sinks.end());
|
||||
logger->set_level(spdlog::level::debug);
|
||||
spdlog::register_logger(logger);
|
||||
|
||||
// 记录开始
|
||||
logger->info("=== ContextMenuHandler called ===");
|
||||
|
||||
std::string path = ansi_to_u8(lpszCmdLine);
|
||||
logger->info("path:[{}], nCmdShow:[{}]", path, nCmdShow);
|
||||
|
||||
std::vector<std::string> vecArg;
|
||||
boost::split(vecArg, path, boost::is_any_of(" "));
|
||||
if (vecArg.size() < 2) {
|
||||
logger->error("invalid args: {}", path);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
boost::trim_if(vecArg[0], boost::is_any_of("\""));
|
||||
// 0 是创建
|
||||
if (vecArg[1] == "0") {
|
||||
std::vector<std::string> args = {"create", "-l", "c++", "-P", "."};
|
||||
int ec = ExecuteCmd("xmake", args, vecArg[0]);
|
||||
if (ec != 0) {
|
||||
logger->error("xmake create failed, exit_code: {}", ec);
|
||||
} else {
|
||||
logger->info("xmake create success");
|
||||
}
|
||||
}
|
||||
// 1 是 build
|
||||
else if (vecArg[1] == "1") {
|
||||
std::vector<std::string> args = {"build", "-P", "."};
|
||||
int ec = ExecuteCmd("xmake", args, vecArg[0]);
|
||||
if (ec != 0) {
|
||||
logger->error("xmake build failed, exit_code: {}", ec);
|
||||
} else {
|
||||
logger->info("xmake build success");
|
||||
}
|
||||
}
|
||||
// 2 是设置 debug
|
||||
else if (vecArg[1] == "2") {
|
||||
std::vector<std::string> args = {"f", "-m", "debug", "-P", "."};
|
||||
int ec = ExecuteCmd("xmake", args, vecArg[0]);
|
||||
if (ec != 0) {
|
||||
logger->error("xmake config debug failed, exit_code: {}", ec);
|
||||
} else {
|
||||
logger->info("xmake config debug success");
|
||||
}
|
||||
}
|
||||
// 3 是设置 release
|
||||
else if (vecArg[1] == "3") {
|
||||
std::vector<std::string> args = {"f", "-m", "release", "-P", "."};
|
||||
int ec = ExecuteCmd("xmake", args, vecArg[0]);
|
||||
if (ec != 0) {
|
||||
logger->error("xmake config release failed, exit_code: {}", ec);
|
||||
} else {
|
||||
logger->info("xmake config release success");
|
||||
}
|
||||
}
|
||||
// 4 是运行
|
||||
else if (vecArg[1] == "4") {
|
||||
std::vector<std::string> args = {"run", "-P", "."};
|
||||
int ec = ExecuteCmd("xmake", args, vecArg[0]);
|
||||
if (ec != 0) {
|
||||
logger->error("xmake run failed, exit_code: {}", ec);
|
||||
} else {
|
||||
logger->info("xmake run success");
|
||||
}
|
||||
}
|
||||
// 5 是替换
|
||||
else if (vecArg[1] == "5") {
|
||||
auto r = ReplaceTemplate(vecArg[0]);
|
||||
if (r) {
|
||||
logger->info("replace template success");
|
||||
} else {
|
||||
logger->error("replace template failed");
|
||||
}
|
||||
} else {
|
||||
logger->error("invalid vecArg[1]: {}", vecArg[1]);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
logger->info("=== ContextMenuHandler end ===");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// DLL入口点
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// int main()
|
||||
// {
|
||||
// std::cout << "Hello World!\n";
|
||||
// ContextMenuHandler(NULL, NULL, "D:\\XmakeDemo\\simple_demo\\000 0", 0);
|
||||
// return 0;
|
||||
// }
|
||||
100
xmake.lua
Normal file
100
xmake.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
add_rules("mode.debug", "mode.release")
|
||||
add_rules("plugin.compile_commands.autoupdate", {outputdir = "build"})
|
||||
|
||||
if is_plat("windows") then
|
||||
add_cxxflags("/utf-8")
|
||||
add_defines("WIN32_LEAN_AND_MEAN")
|
||||
end
|
||||
|
||||
set_languages("c++17")
|
||||
|
||||
add_requires("spdlog 1.17.0")
|
||||
add_requires("fmt 12.1.0", {
|
||||
configs = {
|
||||
header_only = true
|
||||
}
|
||||
})
|
||||
add_requires("boost 1.90.0", {
|
||||
configs = {
|
||||
header_only = true
|
||||
}
|
||||
})
|
||||
|
||||
target("quick-xmake")
|
||||
-- set_kind("binary")
|
||||
set_kind("shared")
|
||||
add_files("src/*.cpp")
|
||||
add_syslinks("shell32", "user32", "ole32", "advapi32")
|
||||
add_packages("spdlog")
|
||||
add_packages("boost")
|
||||
add_packages("fmt")
|
||||
|
||||
--
|
||||
-- If you want to known more usage about xmake, please see https://xmake.io
|
||||
--
|
||||
-- ## FAQ
|
||||
--
|
||||
-- You can enter the project directory firstly before building project.
|
||||
--
|
||||
-- $ cd projectdir
|
||||
--
|
||||
-- 1. How to build project?
|
||||
--
|
||||
-- $ xmake
|
||||
--
|
||||
-- 2. How to configure project?
|
||||
--
|
||||
-- $ xmake f -p [macosx|linux|iphoneos ..] -a [x86_64|i386|arm64 ..] -m [debug|release]
|
||||
--
|
||||
-- 3. Where is the build output directory?
|
||||
--
|
||||
-- The default output directory is `./build` and you can configure the output directory.
|
||||
--
|
||||
-- $ xmake f -o outputdir
|
||||
-- $ xmake
|
||||
--
|
||||
-- 4. How to run and debug target after building project?
|
||||
--
|
||||
-- $ xmake run [targetname]
|
||||
-- $ xmake run -d [targetname]
|
||||
--
|
||||
-- 5. How to install target to the system directory or other output directory?
|
||||
--
|
||||
-- $ xmake install
|
||||
-- $ xmake install -o installdir
|
||||
--
|
||||
-- 6. Add some frequently-used compilation flags in xmake.lua
|
||||
--
|
||||
-- @code
|
||||
-- -- add debug and release modes
|
||||
-- add_rules("mode.debug", "mode.release")
|
||||
--
|
||||
-- -- add macro definition
|
||||
-- add_defines("NDEBUG", "_GNU_SOURCE=1")
|
||||
--
|
||||
-- -- set warning all as error
|
||||
-- set_warnings("all", "error")
|
||||
--
|
||||
-- -- set language: c99, c++11
|
||||
-- set_languages("c99", "c++11")
|
||||
--
|
||||
-- -- set optimization: none, faster, fastest, smallest
|
||||
-- set_optimize("fastest")
|
||||
--
|
||||
-- -- add include search directories
|
||||
-- add_includedirs("/usr/include", "/usr/local/include")
|
||||
--
|
||||
-- -- add link libraries and search directories
|
||||
-- add_links("tbox")
|
||||
-- add_linkdirs("/usr/local/lib", "/usr/lib")
|
||||
--
|
||||
-- -- add system link libraries
|
||||
-- add_syslinks("z", "pthread")
|
||||
--
|
||||
-- -- add compilation and link flags
|
||||
-- add_cxflags("-stdnolib", "-fno-strict-aliasing")
|
||||
-- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true})
|
||||
--
|
||||
-- @endcode
|
||||
--
|
||||
|
||||
Reference in New Issue
Block a user