49
49
#ifdef TB_CONFIG_OS_HAIKU
50
50
# include <image.h>
51
51
#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
52
66
53
67
/* //////////////////////////////////////////////////////////////////////////////////////
54
68
* macros
@@ -81,6 +95,11 @@ typedef struct __xm_engine_t
81
95
// the engine name
82
96
tb_char_t name [64 ];
83
97
98
+ #ifdef XM_EMBED_ENABLE
99
+ // the temporary directory
100
+ tb_char_t tmpdir [TB_PATH_MAXN ];
101
+ #endif
102
+
84
103
}xm_engine_t ;
85
104
86
105
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -584,6 +603,13 @@ static luaL_Reg const g_package_functions[] =
584
603
// the lua global instance for signal handler
585
604
static lua_State * g_lua = tb_null ;
586
605
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
+
587
613
/* //////////////////////////////////////////////////////////////////////////////////////
588
614
* private implementation
589
615
*/
@@ -631,7 +657,7 @@ static tb_bool_t xm_engine_save_arguments(xm_engine_t* engine, tb_int_t argc, tb
631
657
return tb_true ;
632
658
}
633
659
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 )
635
661
{
636
662
// check
637
663
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
722
748
}
723
749
#endif
724
750
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
+
725
761
} while (0 );
726
762
727
763
// ok?
@@ -737,16 +773,42 @@ static tb_size_t xm_engine_get_program_file(xm_engine_t* engine, tb_char_t* path
737
773
return ok ;
738
774
}
739
775
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
+
740
795
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 )
741
796
{
742
797
// check
743
798
tb_assert_and_check_return_val (engine && path && maxn , tb_false );
744
799
745
800
tb_bool_t ok = tb_false ;
801
+ tb_char_t data [TB_PATH_MAXN ] = {0 };
746
802
do
747
803
{
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
+
748
811
// get it from the environment variable first
749
- tb_char_t data [TB_PATH_MAXN ] = {0 };
750
812
if (tb_environment_first ("XMAKE_PROGRAM_DIR" , data , sizeof (data )) && tb_path_absolute (data , path , maxn ))
751
813
{
752
814
ok = tb_true ;
@@ -899,7 +961,18 @@ static tb_void_t xm_engine_init_host(xm_engine_t* engine)
899
961
900
962
// init system host
901
963
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 )
903
976
syshost = "windows" ;
904
977
#elif defined(TB_CONFIG_OS_MACOSX )
905
978
syshost = "macosx" ;
@@ -980,7 +1053,22 @@ static tb_void_t xm_engine_init_arch(xm_engine_t* engine)
980
1053
981
1054
// init system architecture
982
1055
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 )
984
1072
// the GetNativeSystemInfo function type
985
1073
typedef void (WINAPI * GetNativeSystemInfo_t )(LPSYSTEM_INFO );
986
1074
@@ -1090,6 +1178,109 @@ static tb_pointer_t xm_engine_lua_realloc(tb_pointer_t udata, tb_pointer_t data,
1090
1178
}
1091
1179
#endif
1092
1180
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
+
1093
1284
/* //////////////////////////////////////////////////////////////////////////////////////
1094
1285
* implementation
1095
1286
*/
@@ -1208,6 +1399,12 @@ xm_engine_ref_t xm_engine_init(tb_char_t const* name, xm_engine_lni_initalizer_c
1208
1399
lua_pushstring (engine -> lua , version_cstr );
1209
1400
lua_setglobal (engine -> lua , "_VERSION" );
1210
1401
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
+
1211
1408
// init short version string
1212
1409
tb_snprintf (version_cstr , sizeof (version_cstr ), "%u.%u.%u" , version -> major , version -> minor , version -> alter );
1213
1410
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
1294
1491
if (!xm_engine_get_project_directory (engine , path , sizeof (path ))) return -1 ;
1295
1492
1296
1493
// 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 ;
1298
1495
1299
1496
// get the program directory
1300
1497
if (!xm_engine_get_program_directory (engine , path , sizeof (path ), path )) return -1 ;
1301
1498
1499
+ #ifdef XM_EMBED_ENABLE
1500
+ if (!xm_engine_extract_programfiles (engine , path )) return -1 ;
1501
+ #endif
1502
+
1302
1503
// append the main script path
1303
1504
tb_strcat (path , "/core/_xmake_main.lua" );
1304
1505
0 commit comments