Skip to content

Commit 087a641

Browse files
authored
Merge pull request #5491 from xmake-io/archive
Add cli.archive and .xmz archive format
2 parents 3d7af5a + 3b013f0 commit 087a641

File tree

13 files changed

+507
-27
lines changed

13 files changed

+507
-27
lines changed

.github/workflows/cosmocc.yml

+6-13
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,17 @@ jobs:
3737
- name: Build
3838
run: |
3939
cd core
40-
xmake f -p linux --cosmocc=y -y -cvD
40+
xmake f --embed=y -y -cvD
4141
xmake -v
4242
cd ..
4343
4444
- name: Tests
4545
run: |
46-
source scripts/srcenv.profile
47-
xmake --version
48-
xmake lua -v -D tests/run.lua
49-
xrepo --version
46+
ls -l core/build/
47+
core/build/xmake --version
48+
core/build/xmake lua -v -D tests/run.lua
5049
51-
- name: Artifact
52-
run: |
53-
brew install gnu-tar
54-
cd core
55-
xmake pack -y --autobuild=n --basename=xmake -f zip -o ../artifacts xmake
56-
cd ..
5750
- uses: actions/upload-artifact@v2
5851
with:
59-
name: xmake-latest.zip
60-
path: artifacts/xmake.zip
52+
name: xmake
53+
path: core/build/xmake

core/src/xmake/engine.c

+206-5
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@
4949
#ifdef TB_CONFIG_OS_HAIKU
5050
# include <image.h>
5151
#endif
52+
#ifdef __COSMOPOLITAN__
53+
# include <sys/utsname.h>
54+
#endif
55+
56+
// for uid
57+
#ifndef TB_CONFIG_OS_WINDOWS
58+
# include <unistd.h>
59+
# include <errno.h>
60+
#endif
61+
62+
// for embed files
63+
#ifdef XM_EMBED_ENABLE
64+
# include "lz4/prefix.h"
65+
#endif
5266

5367
/* //////////////////////////////////////////////////////////////////////////////////////
5468
* macros
@@ -81,6 +95,11 @@ typedef struct __xm_engine_t
8195
// the engine name
8296
tb_char_t name[64];
8397

98+
#ifdef XM_EMBED_ENABLE
99+
// the temporary directory
100+
tb_char_t tmpdir[TB_PATH_MAXN];
101+
#endif
102+
84103
}xm_engine_t;
85104

86105
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -584,6 +603,13 @@ static luaL_Reg const g_package_functions[] =
584603
// the lua global instance for signal handler
585604
static lua_State* g_lua = tb_null;
586605

606+
// the xmake script files data
607+
#ifdef XM_EMBED_ENABLE
608+
static tb_byte_t g_xmake_xmz_data[] = {
609+
#include "xmake.xmz.h"
610+
};
611+
#endif
612+
587613
/* //////////////////////////////////////////////////////////////////////////////////////
588614
* private implementation
589615
*/
@@ -631,7 +657,7 @@ static tb_bool_t xm_engine_save_arguments(xm_engine_t* engine, tb_int_t argc, tb
631657
return tb_true;
632658
}
633659

634-
static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path, tb_size_t maxn)
660+
static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t** argv, tb_char_t* path, tb_size_t maxn)
635661
{
636662
// check
637663
tb_assert_and_check_return_val(engine && path && maxn, tb_false);
@@ -722,6 +748,16 @@ static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path
722748
}
723749
#endif
724750

751+
if (!ok && argv)
752+
{
753+
tb_char_t const* p = argv[0];
754+
if (p && tb_file_info(p, tb_null))
755+
{
756+
tb_strlcpy(path, p, maxn);
757+
ok = tb_true;
758+
}
759+
}
760+
725761
} while (0);
726762

727763
// ok?
@@ -737,16 +773,42 @@ static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path
737773
return ok;
738774
}
739775

776+
#ifdef XM_EMBED_ENABLE
777+
static tb_bool_t xm_engine_get_temporary_directory(tb_char_t* path, tb_size_t maxn, tb_char_t const* name, tb_char_t const* version_cstr)
778+
{
779+
tb_char_t data[TB_PATH_MAXN] = {0};
780+
if (tb_directory_temporary(data, sizeof(data)))
781+
{
782+
// get euid
783+
tb_int_t euid = 0;
784+
#ifndef TB_CONFIG_OS_WINDOWS
785+
euid = geteuid();
786+
#endif
787+
788+
tb_snprintf(path, maxn, "%s/.%s%d/%s", data, name, euid, version_cstr);
789+
return tb_true;
790+
}
791+
return tb_false;
792+
}
793+
#endif
794+
740795
static tb_bool_t xm_engine_get_program_directory(xm_engine_t* engine, tb_char_t* path, tb_size_t maxn, tb_char_t const* programfile)
741796
{
742797
// check
743798
tb_assert_and_check_return_val(engine && path && maxn, tb_false);
744799

745800
tb_bool_t ok = tb_false;
801+
tb_char_t data[TB_PATH_MAXN] = {0};
746802
do
747803
{
804+
#ifdef XM_EMBED_ENABLE
805+
// get it from the temporary directory
806+
tb_strlcpy(path, engine->tmpdir, maxn);
807+
ok = tb_true;
808+
break;
809+
#endif
810+
748811
// get it from the environment variable first
749-
tb_char_t data[TB_PATH_MAXN] = {0};
750812
if (tb_environment_first("XMAKE_PROGRAM_DIR", data, sizeof(data)) && tb_path_absolute(data, path, maxn))
751813
{
752814
ok = tb_true;
@@ -899,7 +961,18 @@ static tb_void_t xm_engine_init_host(xm_engine_t* engine)
899961

900962
// init system host
901963
tb_char_t const* syshost = tb_null;
902-
#if defined(TB_CONFIG_OS_WINDOWS)
964+
#if defined(__COSMOPOLITAN__)
965+
struct utsname buffer;
966+
if (uname(&buffer) == 0)
967+
{
968+
if (tb_strstr(buffer.sysname, "Darwin"))
969+
syshost = "macosx";
970+
else if (tb_strstr(buffer.sysname, "Linux"))
971+
syshost = "linux";
972+
else if (tb_strstr(buffer.sysname, "Windows"))
973+
syshost = "windows";
974+
}
975+
#elif defined(TB_CONFIG_OS_WINDOWS)
903976
syshost = "windows";
904977
#elif defined(TB_CONFIG_OS_MACOSX)
905978
syshost = "macosx";
@@ -980,7 +1053,22 @@ static tb_void_t xm_engine_init_arch(xm_engine_t* engine)
9801053

9811054
// init system architecture
9821055
tb_char_t const* sysarch = tb_null;
983-
#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
1056+
#if defined(__COSMOPOLITAN__)
1057+
struct utsname buffer;
1058+
if (uname(&buffer) == 0)
1059+
{
1060+
sysarch = buffer.machine;
1061+
if (tb_strstr(buffer.sysname, "Windows"))
1062+
{
1063+
if (!tb_strcmp(buffer.machine, "x86_64"))
1064+
sysarch = "x64";
1065+
else if (!tb_strcmp(buffer.machine, "i686") || !tb_strcmp(buffer.machine, "i386"))
1066+
sysarch = "x86";
1067+
}
1068+
else if (!tb_strcmp(buffer.machine, "aarch64"))
1069+
sysarch = "arm64";
1070+
}
1071+
#elif defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
9841072
// the GetNativeSystemInfo function type
9851073
typedef void (WINAPI *GetNativeSystemInfo_t)(LPSYSTEM_INFO);
9861074

@@ -1090,6 +1178,109 @@ static tb_pointer_t xm_engine_lua_realloc(tb_pointer_t udata, tb_pointer_t data,
10901178
}
10911179
#endif
10921180

1181+
#ifdef XM_EMBED_ENABLE
1182+
static tb_bool_t xm_engine_extract_programfiles(xm_engine_t* engine, tb_char_t const* programdir)
1183+
{
1184+
tb_file_info_t info = {0};
1185+
if (tb_file_info(programdir, &info)) return tb_true;
1186+
1187+
tb_byte_t const* data = g_xmake_xmz_data;
1188+
tb_size_t size = sizeof(g_xmake_xmz_data);
1189+
1190+
// do decompress
1191+
tb_bool_t ok = tb_false;
1192+
LZ4F_errorCode_t code;
1193+
LZ4F_decompressionContext_t ctx = tb_null;
1194+
tb_buffer_t result;
1195+
do
1196+
{
1197+
tb_buffer_init(&result);
1198+
1199+
code = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
1200+
if (LZ4F_isError(code)) break;
1201+
1202+
tb_byte_t buffer[8192];
1203+
tb_bool_t failed = tb_false;
1204+
while (1)
1205+
{
1206+
size_t advance = (size_t)size;
1207+
size_t buffer_size = sizeof(buffer);
1208+
code = LZ4F_decompress(ctx, buffer, &buffer_size, data, &advance, tb_null);
1209+
if (LZ4F_isError(code))
1210+
{
1211+
failed = tb_true;
1212+
break;
1213+
}
1214+
1215+
if (buffer_size == 0) break;
1216+
data += advance;
1217+
size -= advance;
1218+
1219+
tb_buffer_memncat(&result, buffer, buffer_size);
1220+
}
1221+
tb_assert_and_check_break(!failed && tb_buffer_size(&result));
1222+
1223+
ok = tb_true;
1224+
} while (0);
1225+
1226+
// extract files to programdir
1227+
if (ok)
1228+
{
1229+
data = tb_buffer_data(&result);
1230+
size = tb_buffer_size(&result);
1231+
tb_byte_t const* p = data;
1232+
tb_byte_t const* e = data + size;
1233+
tb_size_t n = 0;
1234+
tb_char_t filepath[TB_PATH_MAXN];
1235+
tb_int_t pos = tb_snprintf(filepath, sizeof(filepath), "%s/", programdir);
1236+
while (p < e)
1237+
{
1238+
// get filepath
1239+
n = (tb_size_t)tb_bits_get_u16_be(p);
1240+
p += 2;
1241+
tb_assert_and_check_break(pos + n + 1 < sizeof(filepath));
1242+
tb_strncpy(filepath + pos, (tb_char_t const*)p, n);
1243+
filepath[pos + n] = '\0';
1244+
p += n;
1245+
1246+
// get filedata
1247+
n = (tb_size_t)tb_bits_get_u32_be(p);
1248+
p += 4;
1249+
1250+
// write file
1251+
tb_trace_d("extracting %s, %lu bytes ..", filepath, n);
1252+
tb_stream_ref_t stream = tb_stream_init_from_file(filepath, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC);
1253+
tb_assert_and_check_break(stream);
1254+
1255+
if (tb_stream_open(stream))
1256+
{
1257+
tb_stream_bwrit(stream, p, n);
1258+
tb_stream_exit(stream);
1259+
}
1260+
1261+
p += n;
1262+
}
1263+
ok = (p == e);
1264+
if (!ok)
1265+
{
1266+
tb_trace_e("extract program files failed");
1267+
}
1268+
}
1269+
else
1270+
{
1271+
tb_trace_e("decompress program files failed, %s", LZ4F_getErrorName(code));
1272+
}
1273+
1274+
if (ctx)
1275+
{
1276+
LZ4F_freeDecompressionContext(ctx);
1277+
ctx = tb_null;
1278+
}
1279+
tb_buffer_exit(&result);
1280+
return ok;
1281+
}
1282+
#endif
1283+
10931284
/* //////////////////////////////////////////////////////////////////////////////////////
10941285
* implementation
10951286
*/
@@ -1208,6 +1399,12 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c
12081399
lua_pushstring(engine->lua, version_cstr);
12091400
lua_setglobal(engine->lua, "_VERSION");
12101401

1402+
#ifdef XM_EMBED_ENABLE
1403+
// init the temporary directory
1404+
if (!xm_engine_get_temporary_directory(engine->tmpdir, sizeof(engine->tmpdir), name, version_cstr))
1405+
break;
1406+
#endif
1407+
12111408
// init short version string
12121409
tb_snprintf(version_cstr, sizeof(version_cstr), "%u.%u.%u", version->major, version->minor, version->alter);
12131410
lua_pushstring(engine->lua, version_cstr);
@@ -1294,11 +1491,15 @@ tb_int_t xm_engine_main(xm_engine_ref_t self, tb_int_t argc, tb_char_t** argv, t
12941491
if (!xm_engine_get_project_directory(engine, path, sizeof(path))) return -1;
12951492

12961493
// get the program file
1297-
if (!xm_engine_get_program_file(engine, path, sizeof(path))) return -1;
1494+
if (!xm_engine_get_program_file(engine, argv, path, sizeof(path))) return -1;
12981495

12991496
// get the program directory
13001497
if (!xm_engine_get_program_directory(engine, path, sizeof(path), path)) return -1;
13011498

1499+
#ifdef XM_EMBED_ENABLE
1500+
if (!xm_engine_extract_programfiles(engine, path)) return -1;
1501+
#endif
1502+
13021503
// append the main script path
13031504
tb_strcat(path, "/core/_xmake_main.lua");
13041505

core/src/xmake/xmake.lua

+14
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,17 @@ target("xmake")
5555
add_defines("UNICODE", "_UNICODE")
5656
end
5757

58+
-- embed all script files
59+
add_rules("utils.bin2c", {linewidth = 16, extensions = ".xmz"})
60+
on_config(function (target)
61+
import("utils.archive.archive")
62+
if has_config("embed") then
63+
local archivefile = path.join(target:autogendir(), "bin2c", "xmake.xmz")
64+
print("archiving %s ..", archivefile)
65+
os.tryrm(archivefile)
66+
local rootdir = path.normalize(path.join(os.projectdir(), "..", "xmake"))
67+
archive(archivefile, rootdir, {recurse = true, curdir = rootdir})
68+
target:add("files", archivefile)
69+
target:add("defines", "XM_EMBED_ENABLE=1")
70+
end
71+
end)

core/xmake.lua

+5-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,11 @@ if has_config("cosmocc") then
5555
set_policy("build.ccache", false)
5656
end
5757

58-
-- the cosmocc option
59-
option("cosmocc", {default = false, category = "option", description = "Use cosmocc toolchain to build once and run anywhere."})
58+
-- use cosmocc toolchain
59+
option("cosmocc", {default = false, description = "Use cosmocc toolchain to build once and run anywhere."})
60+
61+
-- embed all script files
62+
option("embed", {default = false, description = "Embed all script files."})
6063

6164
-- the runtime option
6265
option("runtime")

tests/run.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ if option.get("diagnosis") then table.insert(params, "-D") end
1111

1212
function _run_test(script)
1313
assert(script:endswith("test.lua"))
14-
os.execv("xmake", table.join("lua", params, path.join(os.scriptdir(), "runner.lua"), script))
14+
os.execv(os.programfile(), table.join("lua", params, path.join(os.scriptdir(), "runner.lua"), script))
1515
end
1616

1717
-- run test with the given name

0 commit comments

Comments
 (0)