The YSLib project - main repository
修订版 | 8ba6f0b263b39612545898a00bed3107e9b0f8d2 (tree) |
---|---|
时间 | 2020-11-09 19:24:52 |
作者 | FrankHB <frankhb1989@gmai...> |
Commiter | FrankHB |
更新主分支版本: build 902 rev 10 。
@@ -9,3 +9,4 @@ | ||
9 | 9 | cc06d61d194ea87c4319f6416fe4d08462432d5b V0.6 |
10 | 10 | c8fcb2e1bc843a92013da1954d3aec0594a92754 V0.7 |
11 | 11 | 141f2222e1d742fdc1055634c04b121f94d20ed8 V0.8 |
12 | +db41e0c9c6e87374c5252290a83621ebba5bc3bc V0.9 |
@@ -28,9 +28,9 @@ | ||
28 | 28 | T := -o$(space) |
29 | 29 | |
30 | 30 | ifeq ($(CONF), debug) |
31 | - C_LTO := | |
31 | + C_LTO ?= | |
32 | 32 | else |
33 | - C_LTO := -flto | |
33 | + C_LTO ?= -flto | |
34 | 34 | endif |
35 | 35 | CFLAGS ?= -c -O3 $(C_LTO) -pipe -Wno-attributes -fvisibility=hidden -DNO_LCMS |
36 | 36 | CFLAGS += $(INCLUDE) |
@@ -25,9 +25,9 @@ | ||
25 | 25 | |
26 | 26 | C_CXXFLAGS_GC ?= -fdata-sections -ffunction-sections |
27 | 27 | ifeq ($(CONF), debug) |
28 | - C_LTO := | |
28 | + C_LTO ?= | |
29 | 29 | else |
30 | - C_LTO := -flto | |
30 | + C_LTO ?= -flto -ffat-lto-objects | |
31 | 31 | endif |
32 | 32 | C_CXXFLAGS ?= -O3 $(C_LTO) -fPIC -pipe -Wno-attributes -fexceptions $(C_CXXFLAGS_GC) |
33 | 33 | CFLAGS ?= $(C_CXXFLAGS) |
@@ -73,9 +73,9 @@ | ||
73 | 73 | |
74 | 74 | RESOURCE := $(RCFILE:.rc=.coff) |
75 | 75 | ifeq ($(CONF), debug) |
76 | - C_LTO := | |
76 | + C_LTO ?= | |
77 | 77 | else |
78 | - C_LTO := -flto | |
78 | + C_LTO ?= -flto -ffat-lto-objects | |
79 | 79 | endif |
80 | 80 | C_CXXFLAGS ?= -O3 $(C_LTO) -fdata-sections -ffunction-sections -pipe -Wno-attributes -fexceptions -DNDEBUG |
81 | 81 | CFLAGS ?= $(C_CXXFLAGS) -DDISABLE_PERF_MEASUREMENT $(WIN32_CFLAGS) |
@@ -14,6 +14,20 @@ | ||
14 | 14 | |
15 | 15 | Unmodified library code should compile, but wrappers based on old code might not work as before. |
16 | 16 | |
17 | +## Since build 902 | |
18 | + | |
19 | +On platform with possibly both G++ and Clang++ available, the LTO option is refined to have `-ffat-lto-object` to be built by G++ by default. | |
20 | + | |
21 | +The makefile variable `C_LTO` (on all platforms) is overridable now, to allow different options for toolchains incompatible to the default value. | |
22 | + | |
23 | +This makes the generated archive compatible both to G++ and Clang++, with (hopefully) some degrees of LTO available in some configurations without rebuilt the library for different compilers. | |
24 | + | |
25 | +## Since build 900 | |
26 | + | |
27 | +Now different configurations to build the library are used. | |
28 | + | |
29 | +LTO is enabled in makefiles for release configurations through variable `C_LTO`. The option `-flto` should be compatible to both G++ and Clang++. | |
30 | + | |
17 | 31 | ## Since build 600 |
18 | 32 | |
19 | 33 | Based on previous revision b520: |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Main.cpp |
12 | 12 | \ingroup MaintenanceTools |
13 | 13 | \brief 宿主构建工具:递归查找源文件并编译和静态链接。 |
14 | -\version r3984 | |
14 | +\version r4009 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 473 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-02-06 14:33:55 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-21 04:45 +0800 | |
20 | + 2020-10-27 00:16 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -43,7 +43,8 @@ | ||
43 | 43 | #include YFM_NPL_Dependency // for NPL::DepsEventType, NPL, A1, Forms, |
44 | 44 | // NPL::DecomposeMakefileDepList, NPL::FilterMakefileDependencies, |
45 | 45 | // NPL::Install*; |
46 | -#include <iostream> // for std::cout; | |
46 | +#include <ystdex/string.hpp> // for ystdex::write_literal; | |
47 | +#include <iostream> // for std::cout, std::endl; | |
47 | 48 | #include YFM_YSLib_Core_YConsole // for YSLib::Consoles; |
48 | 49 | #include <ystdex/concurrency.h> // for ystdex::task_pool; |
49 | 50 | #if YCL_Win32 |
@@ -387,24 +388,23 @@ | ||
387 | 388 | // XXX: Overriding. |
388 | 389 | rctx.GetRecordRef().Define("SHBuild_BaseTerminalHook_", |
389 | 390 | ValueObject(function<void(const string&, const string&)>( |
390 | - [](const string& n, const string& val){ | |
391 | - // XXX: Errors from 'std::printf' and 'std::puts' are | |
392 | - // ignored. | |
391 | + [&](const string& n, const string& val){ | |
393 | 392 | using namespace Consoles; |
393 | + auto& os(context.GetOutputStreamRef()); | |
394 | + Terminal te; | |
394 | 395 | |
395 | - Terminal te; | |
396 | 396 | { |
397 | 397 | const auto t_gd(te.LockForeColor(DarkCyan)); |
398 | 398 | |
399 | - std::printf("%s", n.c_str()); | |
399 | + YSLib::IO::StreamPut(os, n.c_str()); | |
400 | 400 | } |
401 | - std::printf(" = \""); | |
401 | + ystdex::write_literal(os, " = \""); | |
402 | 402 | { |
403 | 403 | const auto t_gd(te.LockForeColor(DarkRed)); |
404 | 404 | |
405 | - std::printf("%s", val.c_str()); | |
405 | + YSLib::IO::StreamPut(os, val.c_str()); | |
406 | 406 | } |
407 | - std::puts("\""); | |
407 | + os.put('"') << std::endl; | |
408 | 408 | }))); |
409 | 409 | })); |
410 | 410 | TryLoadSource(context, name, is); |
@@ -1053,7 +1053,11 @@ | ||
1053 | 1053 | } |
1054 | 1054 | else if(xargc == 1) |
1055 | 1055 | { |
1056 | - std::printf("%s%s%s", "Usage: [ENV ...] ", | |
1056 | + using YSLib::IO::StreamPut; | |
1057 | + using YSLib::sfmt; | |
1058 | + auto& os(std::cout); | |
1059 | + | |
1060 | + StreamPut(os, sfmt("%s%s%s", "Usage: [ENV ...] ", | |
1057 | 1061 | quote(string(xargv[0])).c_str(), |
1058 | 1062 | " SRCPATH [OPTIONS ... [-- ARGS...]]\n" |
1059 | 1063 | "\tThis program is a tool to build the source tree, with some" |
@@ -1066,12 +1070,13 @@ | ||
1066 | 1070 | "\n[ENV ...]\n\tThe environment variables settings in shell." |
1067 | 1071 | " (Note not all shells support this syntax, but the" |
1068 | 1072 | " environment variables are still effective.)" |
1069 | - " Currently accepted settings are listed below:\n\n"); | |
1073 | + " Currently accepted settings are listed below:\n\n").c_str()); | |
1070 | 1074 | for(const auto& env : DeEnvs) |
1071 | - std::printf(" %s\n\t%s Default value is %s.\n\n", env[0], | |
1075 | + StreamPut(os, sfmt(" %s\n\t%s Default value is %s.\n\n", env[0], | |
1072 | 1076 | env[2], env[1][0] == '\0' ? "empty" |
1073 | - : Quote(string(env[1])).c_str()); | |
1074 | - std::puts("SRCPATH\n\tThe source directory to be recursively" | |
1077 | + : Quote(string(env[1])).c_str()).c_str()); | |
1078 | + ystdex::write_literal(os, | |
1079 | + "SRCPATH\n\tThe source directory to be recursively" | |
1075 | 1080 | " searched. A subdirectory thereof would be ignored implicitly " |
1076 | 1081 | " if its name is beginned with a dot ('.') character. A" |
1077 | 1082 | " subdirectory whose name is same to one of the names specified" |
@@ -1087,13 +1092,14 @@ | ||
1087 | 1092 | " building mode, respectively. In the building mode, all" |
1088 | 1093 | " options including these prefixed values of SHBuild_CFLAGS or" |
1089 | 1094 | " SHBuild_CXXFLAGS would be sent to the building backends," |
1090 | - " except for listed below (handled by this program):\n"); | |
1095 | + " except for listed below (handled by this program):\n\n"); | |
1091 | 1096 | for(const auto& opt : OptionsTable) |
1092 | 1097 | { |
1093 | - std::printf(" %s%s\n", opt.prefix, opt.option_arg); | |
1098 | + StreamPut(os, | |
1099 | + sfmt(" %s%s\n", opt.prefix, opt.option_arg).c_str()); | |
1094 | 1100 | for(const auto& des : opt.option_details) |
1095 | - std::printf("\t%s\n", des); | |
1096 | - std::putchar('\n'); | |
1101 | + StreamPut(os, sfmt("\t%s\n", des).c_str()); | |
1102 | + os << '\n'; | |
1097 | 1103 | } |
1098 | 1104 | } |
1099 | 1105 | }, {}, Err, [](const std::exception& e, RecordLevel lv){ |
@@ -72,8 +72,6 @@ | ||
72 | 72 | |
73 | 73 | # shellcheck source=./SHBuild-common-toolchain.sh |
74 | 74 | . "$SHBuild_Bin/SHBuild-common-toolchain.sh" |
75 | -AR=$(SHBuild_GetAR_ "$CXX" "$AR") | |
76 | -export AR | |
77 | 75 | if [[ "$SHBuild_Debug" != '' ]]; then |
78 | 76 | SHBuild_Puts 'Use debug configuration '"$SHBuild_Conf"'.' |
79 | 77 | CXXFLAGS_OPT_DBG='-O0 -g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC' |
@@ -112,7 +110,7 @@ | ||
112 | 110 | if [[ "$SHBuild_Env_OS" == 'Win32' ]]; then |
113 | 111 | SHBuild_YF_SystemLibs='-lgdi32 -limm32' |
114 | 112 | else |
115 | - SHBuild_YF_SystemLibs='-Wl,-dy -lxcb -lpthread' | |
113 | + SHBuild_YF_SystemLibs='-Wl,-dy -lxcb' | |
116 | 114 | SHBuild_YF_CFlags_freetype="$(pkg-config --cflags freetype2 2> /dev/null)" |
117 | 115 | # XXX: The default value of %SHBuild_YF_CFlags_freetype is known having |
118 | 116 | # quotes. |
@@ -133,17 +131,18 @@ | ||
133 | 131 | : "${SHBuild_YF_Libs_FreeImage:=-lFreeImage}" |
134 | 132 | fi |
135 | 133 | |
136 | -LIBS="$LIBS_RPATH -L\"$(SHBuild_2w "$SHBuild_Bin/../lib")\"" | |
134 | +LIBS="$LIBS_RPATH -L\"$(SHBuild_2m "$SHBuild_Bin/../lib")\"" | |
137 | 135 | |
138 | 136 | if [[ "$SHBuild_Static" == '' ]]; then |
139 | 137 | SHBuild_YSLib_Flags="-DYF_DLL -DYB_DLL \ |
140 | 138 | $SHBuild_YF_CFlags_freetype -I\"$SHBuild_Bin/../include\"" |
141 | 139 | export LIBS="$LIBS $SHBuild_YSLib_LibNames" |
142 | 140 | else |
143 | - # XXX: Use 'g++' even when %CXX is 'clang++' to work around LTO issue for | |
144 | - # static executables in Linux. | |
141 | + # XXX: Use 'g++' even when %CXX is 'clang++' to work around the LTO issue | |
142 | + # for static executables in Linux. | |
143 | + # TODO: Test for other platforms? | |
145 | 144 | if SHBuild_Put "$CXX" | grep clang++ > /dev/null; then |
146 | - # XXX: No prefix and postfix of %CXX are supported yet. | |
145 | + # XXX: No prefix and postfix of %LD are supported yet. | |
147 | 146 | LD=g++ |
148 | 147 | fi |
149 | 148 | SHBuild_YSLib_Flags="$SHBuild_YF_CFlags_freetype \ |
@@ -14,7 +14,7 @@ | ||
14 | 14 | $assert-nonempty |
15 | 15 | $env-de! |
16 | 16 | $redef! |
17 | - SHBuild_2w | |
17 | + SHBuild_CheckCXX | |
18 | 18 | SHBuild_GetPlatformStrings |
19 | 19 | SHBuild_Platform_Detect |
20 | 20 | build-with-conf-opt |
@@ -27,6 +27,7 @@ | ||
27 | 27 | system-ok |
28 | 28 | system-or-puts |
29 | 29 | system-check |
30 | + system-quote-m_ | |
30 | 31 | win32? |
31 | 32 | ) load (++ SR_Share_NPLA1_ "/SHBuild-YSLib-common.txt"); |
32 | 33 |
@@ -37,7 +38,7 @@ | ||
37 | 38 | $def! host-platform_ SHBuild_Platform_Detect env-os env-arch; |
38 | 39 | $env-de! SHBuild_YSLib_Platform host-platform_; |
39 | 40 | |
40 | -$def! SR_Prefix_ SHBuild_DirectoryOf_ (SHBuild_DirectoryOf_ SR_Var_NPLA1_); | |
41 | +$def! SR_Prefix_ SHBuild_DirectoryOf_ (SHBuild_DirectoryOf_ SR_Share_NPLA1_); | |
41 | 42 | $def! SR_Bin_ ++ SR_Prefix_ "/bin"; |
42 | 43 | $def! SR_Include_ ++ SR_Prefix_ "/include"; |
43 | 44 | $def! SR_Lib_ ++ SR_Prefix_ "/lib"; |
@@ -83,7 +84,6 @@ | ||
83 | 84 | $unless (dynamic) puts "Static mode turned on by configuration."; |
84 | 85 | $def! SHBuild_Dest ++ (safeenv-get "SHBuild_BuildPrefix") "." SHBuild_Conf; |
85 | 86 | "XXX", "No extra configuration arguments are supported yet."; |
86 | - "TODO", "Implement SHBuild_GetAR_."; | |
87 | 87 | safeenv-set "CXXFLAGS_COMMON" ""; |
88 | 88 | $redef! debug |
89 | 89 | $or? debug (not? (string-empty? (safeenv-get "SHBuild_Debug"))); |
@@ -102,10 +102,10 @@ | ||
102 | 102 | $def! SHBuild_YF_CFlags_freetype "" |
103 | 103 | ) |
104 | 104 | ( |
105 | - $def! SHBuild_YF_SystemLibs "-Wl,-dy -lxcb -lpthread"; | |
105 | + $def! SHBuild_YF_SystemLibs "-Wl,-dy -lxcb"; | |
106 | 106 | $def! SHBuild_YF_CFlags_freetype system-or-puts env-os |
107 | 107 | (cons-cmd "pkg-config" "--cflags" "freetype2") |
108 | - (++ "-I\"" SR_Include_ "\"") | |
108 | + (++ "-I" (system-quote-m_ env-os SR_Include_)) | |
109 | 109 | ); |
110 | 110 | $defl! stat-file? (filename) |
111 | 111 | ( |
@@ -123,27 +123,29 @@ | ||
123 | 123 | ); |
124 | 124 | $env-de! SHBuild_YF_Libs_FreeImage ++ "-lFreeImage" ($if (debug) "d" ""); |
125 | 125 | $def! LIBS |
126 | - ++ (safeenv-get "LIBS_RPATH") " -L\"" (SHBuild_2w env-os SR_Lib_) "\""; | |
126 | + ++ (safeenv-get "LIBS_RPATH") " -L" (system-quote-m_ env-os SR_Lib_); | |
127 | 127 | $if (dynamic) |
128 | 128 | ( |
129 | 129 | $def! SHBuild_YSLib_Flags ++ "-DYF_DLL -DYB_DLL " |
130 | - SHBuild_YF_CFlags_freetype " -I\"" SR_Include_ "\""; | |
130 | + SHBuild_YF_CFlags_freetype " -I" | |
131 | + (system-quote-m_ env-os SR_Include_); | |
131 | 132 | safeenv-set "LIBS" (SHBuild_TrimOptions_ |
132 | 133 | (cons-cmd LIBS SHBuild_YSLib_LibNames)) |
133 | 134 | ) |
134 | 135 | ( |
135 | - "XXX", "Use 'g++' even when %CXX is 'clang++' to work around LTO issue", | |
136 | - " for static executables in Linux."; | |
137 | - $if (rmatch? (safeenv-get "CXX") ".*clang++.*") | |
136 | + "XXX", "Use 'g++' even when %CXX is 'clang++' to work around the LTO", | |
137 | + " issue for static executables in Linux."; | |
138 | + "TODO", "Test for other platforms?"; | |
139 | + $if (eqv? (SHBuild_CheckCXX env-os (safeenv-get "CXX")) "Clang++") | |
138 | 140 | ( |
139 | - "XXX", "No prefix and postfix of %CXX are supported yet."; | |
141 | + "XXX", "No prefix and postfix of %LD are supported yet."; | |
140 | 142 | safeenv-set "LD" "g++" |
141 | 143 | ); |
142 | - $def! SHBuild_YSLib_Flags | |
143 | - ++ SHBuild_YF_CFlags_freetype " -I\"" SR_Include_ "\""; | |
144 | + $def! SHBuild_YSLib_Flags ++ SHBuild_YF_CFlags_freetype " -I" | |
145 | + (system-quote-m_ env-os SR_Include_); | |
144 | 146 | $def! SHBuild_YSLib_LibNames cons-cmd SHBuild_YSLib_LibNames |
145 | 147 | SHBuild_YF_Libs_FreeImage SHBuild_YF_Libs_freetype |
146 | - (++ "-L\"" SR_Lib_ "\"") SHBuild_YF_SystemLibs; | |
148 | + (++ "-L" (system-quote-m_ env-os SR_Lib_)) SHBuild_YF_SystemLibs; | |
147 | 149 | safeenv-set "LIBS" (SHBuild_TrimOptions_ |
148 | 150 | (cons-cmd LIBS "-Wl,dn" SHBuild_YSLib_LibNames)) |
149 | 151 | ); |
@@ -5,7 +5,7 @@ | ||
5 | 5 | : "${SHBuild_Bin:=$(cd "$(dirname "$0")" && pwd)}" |
6 | 6 | : "${SHBuild:="$SHBuild_Bin/SHBuild"}" |
7 | 7 | |
8 | -"$SHBuild" -xcmd,RunNPLFile "$SHBuild_Bin/../var/NPLA1/SHBuild-BuildApp.txt" \ | |
8 | +"$SHBuild" -xcmd,RunNPLFile "$SHBuild_Bin/../share/NPLA1/SHBuild-BuildApp.txt" \ | |
9 | 9 | "$@" |
10 | 10 | # TODO: Package. |
11 | 11 |
@@ -14,6 +14,7 @@ | ||
14 | 14 | $env-de! |
15 | 15 | $redef! |
16 | 16 | SHBuild_2m |
17 | + SHBuild_CheckCXX | |
17 | 18 | SHBuild_EchoVar_N |
18 | 19 | SHBuild_GetPlatformStrings |
19 | 20 | SHBuild_GetSystemPrefix |
@@ -28,6 +29,7 @@ | ||
28 | 29 | safeenv-set |
29 | 30 | system-check |
30 | 31 | system-or-puts |
32 | + system-quote-m_ | |
31 | 33 | putss |
32 | 34 | win32? |
33 | 35 | ) load ($let () ($import! std.system env-get; env-get "SHBuild_Common")); |
@@ -85,8 +87,8 @@ | ||
85 | 87 | " is used instead) normally, so it is safe here."; |
86 | 88 | $if (win32? env-os) |
87 | 89 | ( |
88 | - $env-de! INCLUDES_freetype ++ "-I" | |
89 | - (system-quote (SHBuild_2m env-os BD_3rdparty_freetype_inc_)); | |
90 | + $env-de! INCLUDES_freetype | |
91 | + ++ "-I" (system-quote-m_ env-os BD_3rdparty_freetype_inc_); | |
90 | 92 | $def! CFLAGS_freetype_other "" |
91 | 93 | ) |
92 | 94 | ( |
@@ -103,19 +105,18 @@ | ||
103 | 105 | ) |
104 | 106 | ( |
105 | 107 | $if debug ($redef! target-name ++ "debug " target-name); |
106 | - $defl! libdname (lib) ++ lib ($if debug "d" ""); | |
108 | + $defl! dnameof (lib) ++ lib ($if debug "d" ""); | |
107 | 109 | $if nskip ($let* |
108 | 110 | ( |
109 | 111 | (repo-base SHBuild_2m env-os YSLib_BaseDir) |
110 | - (YF_SystemLibs | |
111 | - $if (win32? env-os) "-lgdi32 -limm32" "-lxcb -lpthread") | |
112 | + (YF_SystemLibs $if (win32? env-os) "-lgdi32 -limm32" "-lxcb") | |
112 | 113 | (DIR_YFramework ++ repo-base "/YFramework") |
113 | - (LIBS_YFramework SHBuild_TrimOptions_ (++ " -L\"" (SHBuild_2m env-os | |
114 | - (++ DIR_YFramework "/" env-host-lib)) | |
115 | - "\" -l" (libdname "FreeImage") " -lfreetype " YF_SystemLibs)) | |
114 | + (LIBS_YFramework SHBuild_TrimOptions_ (++ " -L" | |
115 | + (system-quote-m_ env-os (++ DIR_YFramework "/" env-host-lib)) | |
116 | + " -l" (dnameof "FreeImage") " -lfreetype " YF_SystemLibs)) | |
116 | 117 | ) |
117 | 118 | ( |
118 | - $defl! incsub (dir) ++ "-I\"" (SHBuild_2m env-os dir) "\""; | |
119 | + $defl! incsub (dir) ++ "-I" (system-quote-m_ env-os dir); | |
119 | 120 | $def! INCLUDES_YBase SHBuild_TrimOptions_ |
120 | 121 | (incsub (++ repo-base "/YBase/include")); |
121 | 122 | $def! INCLUDES_YFramework SHBuild_TrimOptions_ (++ |
@@ -142,39 +143,59 @@ | ||
142 | 143 | (++ outdir "/stdinc.h") CXX |
143 | 144 | (cons-cmd "-xc++-header" CXXFLAGS); |
144 | 145 | $def! inc-pch list "-include" |
145 | - (++ "\"" outdir "/stdinc.h" "\"") | |
146 | + (system-quote-m_ env-os (++ outdir "/stdinc.h")) | |
146 | 147 | ) |
147 | 148 | ( |
148 | 149 | puts "Skipped building precompiled file."; |
149 | 150 | $def! inc-pch () |
150 | 151 | ); |
151 | 152 | $def! DFLAG_B_YB $if dynamic "-DYB_BUILD_DLL" ""; |
153 | + "XXX", "Here %env-get is used because %LDFLAGS should be", | |
154 | + " set recently rathen than in the safe environment."; | |
155 | + $import! std.system env-get; | |
156 | + $def! LDFLAGS env-get "LDFLAGS"; | |
157 | + "NOTE", "The prefix 'lib' is explicit, see %InstLibD."; | |
152 | 158 | $defl! build-lib (lib-name inc-pch .opts) |
153 | - system-check (apply cons-cmd (append (list e_S1_SHBuild_ | |
154 | - SHBOPT (++ "-xn," LIBPFX (libdname lib-name))) (restv | |
155 | - (() cmd-get-args)) (list (++ repo-base "/" lib-name) | |
156 | - CXXFLAGS) opts inc-pch)); | |
157 | - safeenv-restore "LIBS"; | |
159 | + $let ((dname ++ (dnameof lib-name))) | |
160 | + ( | |
161 | + "TODO", "Make import library output configurable."; | |
162 | + $if ($and? dynamic (win32? env-os)) | |
163 | + (safeenv-set "LDFLAGS" | |
164 | + (cons-cmd (++ "-Wl,--out-implib,\"" | |
165 | + (SHBuild_2m env-os | |
166 | + (++ outdir "/lib" dname ".dll.a")) "\"") | |
167 | + LDFLAGS)); | |
168 | + system-check (apply cons-cmd | |
169 | + (append (list e_S1_SHBuild_ SHBOPT | |
170 | + (++ "-xn," LIBPFX dname)) | |
171 | + (restv (() cmd-get-args)) | |
172 | + (list (++ repo-base "/" lib-name) CXXFLAGS) opts | |
173 | + inc-pch)) | |
174 | + ); | |
175 | + $if dynamic (safeenv-restore "LIBS"); | |
176 | + "XXX", "Workarounds."; | |
158 | 177 | $def! mingw32r $and? (eqv? host-platform_ "MinGW32") |
159 | 178 | (not? debug); |
160 | 179 | build-lib "YBase" inc-pch DFLAG_B_YB INCLUDES_YBase |
161 | 180 | ($if mingw32r "-fno-lto" ""); |
162 | - $if dynamic (safeenv-set "LIBS" (cons-cmd (++ "-L" outdir) | |
163 | - (++ "-l" (libdname "YBase")) LIBS_YFramework)); | |
181 | + $if dynamic (safeenv-set "LIBS" (cons-cmd (++ "-L" | |
182 | + (system-quote-m_ env-os outdir)) | |
183 | + (++ "-l" (dnameof "YBase")) LIBS_YFramework)); | |
164 | 184 | "XXX", "Precompiled header is not available as it", |
165 | 185 | " requires '-D__NO_INLINE__ -U__OPTIMIZE__'."; |
166 | 186 | "XXX", "See $2020-10 @ doc/Workflow.txt."; |
167 | - $def! mingw64 eqv? host-platform_ "MinGW64"; | |
187 | + $def! mingw64g $and? (eqv? host-platform_ "MinGW64") | |
188 | + (eqv? (SHBuild_CheckCXX env-os CXX) "G++"); | |
168 | 189 | $defl! fix-flags () |
169 | 190 | ( |
170 | 191 | $cond |
171 | - (mingw64 $if dynamic | |
192 | + (mingw64g $if dynamic | |
172 | 193 | "-Og -g -fno-var-tracking-assignments" |
173 | 194 | "-O1 -g -fno-var-tracking-assignments") |
174 | 195 | (mingw32r "-fno-lto") |
175 | 196 | (#t "") |
176 | 197 | ); |
177 | - build-lib "YFramework" ($if mingw64 () inc-pch) | |
198 | + build-lib "YFramework" ($if mingw64g () inc-pch) | |
178 | 199 | (() fix-flags) ($if dynamic "-DYB_DLL" "") |
179 | 200 | ($if dynamic "-DYF_BUILD_DLL" "") "-DFREEIMAGE_LIB" |
180 | 201 | (SHBuild_TrimOptions_ (++ INCLUDES_YFramework " " |
@@ -217,13 +238,13 @@ | ||
217 | 238 | ( |
218 | 239 | puts "Installing headers and libraries ..."; |
219 | 240 | |
220 | - $def! (SR_DSO_Dest SR_DSO_Imp) | |
241 | + $def! (SR_DSO_Dest imp-sfx) | |
221 | 242 | $if (win32? env-os) (list SR_Bin_ ".a") (list SR_Lib_ ""); |
222 | 243 | |
223 | 244 | $import! env_SHB_ InstInc InstLibS InstLibD InstSHBuild; |
224 | 245 | $defl! SHB_InstInc (srcdir) InstInc srcdir SR_Include_; |
225 | 246 | $defl! SHB_InstLibD (build-dir name) |
226 | - InstLibD build-dir name SR_Lib_ SR_DSO_Dest SR_DSO_Imp; | |
247 | + InstLibD build-dir name SR_Lib_ SR_DSO_Dest imp-sfx #t; | |
227 | 248 | |
228 | 249 | for-each-ltr SHBuild_EnsureDirectory_ (list SR_Bin_ SR_Include_ SR_Lib_ |
229 | 250 | SR_Share_ SR_Share_NPLA1_ SR_Var_NPLA1_); |
@@ -301,9 +322,9 @@ | ||
301 | 322 | safeenv-restore "LDFLAGS", |
302 | 323 | safeenv-restore "LIBS"; |
303 | 324 | safeenv-set "LIBS" (SHBuild_TrimOptions_ (cons-cmd (safeenv-get "LIBS") "-L" |
304 | - (system-quote (SHBuild_2m env-os SR_Lib_)) "-lYFramework -lYBase")); | |
325 | + (system-quote-m_ env-os SR_Lib_) "-lYFramework -lYBase")); | |
305 | 326 | $def! INCLUDES_ ++ (safeenv-get "INCLUDES") " -I" |
306 | - (system-quote (SHBuild_2m env-os SR_Include_)); | |
327 | + (system-quote-m_ env-os SR_Include_); | |
307 | 328 | |
308 | 329 | $let ((target-name "Stage 2 SHBuild")) |
309 | 330 | ( |
@@ -206,17 +206,36 @@ | ||
206 | 206 | ); |
207 | 207 | force (eval% sym e) |
208 | 208 | ); |
209 | +$defl! SHBuild_ar_ok_ (env-os ar) | |
210 | + system-ok (cons-cmd (system-quote ar) "--help" "1&> " (get-tmp-nul env-os) | |
211 | + "2>" (get-nul-dev env-os)); | |
212 | +$defl! SHBuild_GetAR_ (env-os cxx ar) | |
213 | + $let ((SHBuild_CXX_Style_ SHBuild_CheckCXX env-os cxx)) | |
214 | + $cond (($and? (eqv? SHBuild_CXX_Style_ "Clang++") | |
215 | + (SHBuild_ar_ok_ env-os "llvm-ar")) "llvm-ar") | |
216 | + (($and? (eqv? SHBuild_CXX_Style_ "G++") | |
217 | + (SHBuild_ar_ok_ env-os "gcc-ar")) "gcc-ar") | |
218 | + (#t ar); | |
219 | +$defl! system-quote-m_ (env-os s) system-quote (SHBuild_2m env-os s); | |
209 | 220 | |
210 | -$defl! get-thread-option (cxx err-out) | |
221 | +$defl! get-thread-options (env-os cxx err-out) | |
211 | 222 | ( |
212 | 223 | "TODO", "Impl without pthread?"; |
213 | - $defl! dmp-test (name) (system-ok (cons-cmd (system-quote cxx) | |
224 | + $defl! dmp-test (name) (system-ok (cons-cmd (system-quote-m_ env-os cxx) | |
214 | 225 | "-dumpspecs 2>& 1 | grep" name ">" err-out)); |
215 | - $if (dmp-test "no-pthread:") | |
216 | - ($if (dmp-test "mthreads:") "-mthreads" "") "-pthread" | |
226 | + $cond | |
227 | + ((dmp-test "mthreads:") list "-mthreads" "-mthreads") | |
228 | + ((compile-ok "int main(){}" cxx | |
229 | + (get-tmp-nul env-os) "-Werror -mthreads" err-out) | |
230 | + list ($if (compile-ok "int main(){}" cxx | |
231 | + (get-tmp-nul env-os) "-c -Werror -mthreads" err-out) | |
232 | + "-mthreads" "-D_MT") "-mthreads") | |
233 | + (($or? (dmp-test "no-pthread:") (not? (compile-ok "int main(){}" | |
234 | + cxx (get-tmp-nul env-os) "-pthread" err-out))) list "" "") | |
235 | + (#t list "-pthread" "-pthread") | |
217 | 236 | ); |
218 | -$defl! get-thread-option-silent (env-os cxx) | |
219 | - get-thread-option cxx (get-nul-dev env-os); | |
237 | +$defl! get-thread-options-silent (env-os cxx) | |
238 | + get-thread-options env-os cxx (get-nul-dev env-os); | |
220 | 239 | $defl! get-SHBOPT_ (outdir shbopt-ext use-ld) |
221 | 240 | ( |
222 | 241 | $def! opt cons-cmd (++ "-xd,\"" outdir "\"") shbopt-ext; |
@@ -251,21 +270,25 @@ | ||
251 | 270 | $defl! build-with-conf-opt (outdir env-os debug dynamic shbopt-ext app |
252 | 271 | do-ld-ext do-build) |
253 | 272 | ( |
273 | + $def! use-ld $or? dynamic app; | |
254 | 274 | $def! CXXFLAGS_OPT_DBG |
255 | 275 | $if debug ("-O0 -g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC") ""; |
256 | 276 | ($env-de! CXX "g++"; safeenv-set "CXX" CXX), |
257 | - "TODO", "Implement SHBuild_GetAR_."; | |
258 | - ($env-de! AR "ar"; safeenv-set "AR" AR), | |
277 | + ($env-de! AR (SHBuild_GetAR_ env-os CXX "ar"); safeenv-set "AR" AR), | |
259 | 278 | ($env-de! ARFLAGS "rcs"; safeenv-set "ARFLAGS" ARFLAGS), |
260 | 279 | ($env-de! LD CXX; safeenv-set "LD" LD); |
261 | 280 | "TODO", "Add sanity checks."; |
262 | 281 | $env-de! C_CXXFLAGS_GC "-fdata-sections -ffunction-sections"; |
282 | + "XXX", "%LDFLAGS_GC is used to the environment detection despite %use-ld."; | |
263 | 283 | $env-de! LDFLAGS_GC |
264 | 284 | ($if (eqv? env-os "OS_X") "-Wl,--dead-strip" "-Wl,--gc-sections"); |
265 | - "NOTE", "See https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options,", | |
266 | - "also https://clang.llvm.org/docs/ClangCommandLineReference.html#linker-flags."; | |
267 | - $env-de! LDFLAGS_STRIP "-s"; | |
268 | - "#", "-Wl,--print-gc-sections"; | |
285 | + $if use-ld | |
286 | + ( | |
287 | + "NOTE", "See https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options,", | |
288 | + "also https://clang.llvm.org/docs/ClangCommandLineReference.html#linker-flags."; | |
289 | + $env-de! LDFLAGS_STRIP "-s"; | |
290 | + "#", "-Wl,--print-gc-sections" | |
291 | + ); | |
269 | 292 | $def! SHBuild_CXX_Style_ SHBuild_CheckCXX env-os CXX; |
270 | 293 | $unless (compile-ok-silent env-os "int main(){}" CXX |
271 | 294 | (cons-cmd C_CXXFLAGS_GC LDFLAGS_GC)) |
@@ -282,12 +305,15 @@ | ||
282 | 305 | "-Winvalid-pch" "-Wmissing-declarations" "-Wmissing-include-dirs" |
283 | 306 | "-Wmultichar" "-Wno-format-nonliteral" "-Wredundant-decls" "-Wshadow" |
284 | 307 | "-Wsign-conversion"; |
285 | - $def! cxxflags_impl_common_thrd_ get-thread-option-silent env-os CXX; | |
308 | + $def! (cxxflags_impl_common_thrd_ ldflags_impl_common_thrd_) | |
309 | + get-thread-options-silent env-os CXX; | |
286 | 310 | $env-de! CXXFLAGS_IMPL_WARNING ""; |
287 | 311 | $env-de! C_CXXFLAGS_COMMON_IMPL_ ""; |
288 | 312 | $env-de! CXXFLAGS_IMPL_OPT ""; |
289 | 313 | $env-de! C_CXXFLAGS_IMPL_WARNING ""; |
290 | - $env-de! LDFLAGS_IMPL_OPT ""; | |
314 | + $if use-ld ($env-de! LDFLAGS_IMPL_OPT ""); | |
315 | + "TODO", "Expose this option?"; | |
316 | + $def! use_lld_ #f; | |
291 | 317 | $cond |
292 | 318 | ((eqv? SHBuild_CXX_Style_ "Clang++") |
293 | 319 | ( |
@@ -296,8 +322,16 @@ | ||
296 | 322 | $set-if-empty! CXXFLAGS_IMPL_WARNING cons-cmd |
297 | 323 | "-Wno-deprecated-register" "-Wno-mismatched-tags" |
298 | 324 | "-Wno-missing-braces" "-Wshorten-64-to-32" "-Wweak-vtables"; |
299 | - $set-if-empty! CXXFLAGS_IMPL_OPT "-flto"; | |
300 | - $set-if-empty! LDFLAGS_IMPL_OPT "-flto" | |
325 | + "XXX", "LTO is disabled by default for compatibility to the", | |
326 | + " prebuilt binaries."; | |
327 | + "#", "$set-if-empty! CXXFLAGS_IMPL_OPT", "-flto"; | |
328 | + $if use-ld | |
329 | + ( | |
330 | + "#", "$set-if-empty! LDFLAGS_IMPL_OPT", "-flto"; | |
331 | + "XXX", "This is the only choice to support LTO on MinGW32 now.", | |
332 | + "It is still not ready to link successfully."; | |
333 | + "#", "$if (win32? env-os) ($redef! use_lld_ #t)" | |
334 | + ) | |
301 | 335 | )) |
302 | 336 | ((eqv? SHBuild_CXX_Style_ "G++") |
303 | 337 | ( |
@@ -311,10 +345,15 @@ | ||
311 | 345 | $set-if-empty! CXXFLAGS_IMPL_OPT cons-cmd |
312 | 346 | "-fexpensive-optimizations" "-flto=jobserver" |
313 | 347 | "-fno-enforce-eh-specs"; |
314 | - "XXX", "Workarond for LTO bug on MinGW. See https://sourceware.org/bugzilla/show_bug.cgi?id=12762."; | |
315 | - $set-if-empty! LDFLAGS_IMPL_OPT $if (win32? env-os) | |
316 | - "-fexpensive-optimizations -flto -Wl,-allow-multiple-definition" | |
317 | - "-fexpensive-optimizations -flto" | |
348 | + $if use-ld | |
349 | + ( | |
350 | + "XXX", "Workarond for LTO bug on MinGW. See https://sourceware.org/bugzilla/show_bug.cgi?id=12762."; | |
351 | + $set-if-empty! LDFLAGS_IMPL_OPT | |
352 | + $if (win32? env-os) | |
353 | + (++ "-fexpensive-optimizations -flto" | |
354 | + " -Wl,-allow-multiple-definition") | |
355 | + "-fexpensive-optimizations -flto" | |
356 | + ) | |
318 | 357 | )); |
319 | 358 | $env-de! CFLAGS_STD "-std=c11"; |
320 | 359 | $env-de! CFLAGS_WARNING cons-cmd C_CXXFLAGS_WARNING C_CXXFLAGS_IMPL_WARNING; |
@@ -336,38 +375,58 @@ | ||
336 | 375 | C_CXXFLAGS_COMMON_IMPL_ CXXFLAGS_OPT_DBG); |
337 | 376 | $def! CFLAGS get-lang-flags "CFLAGS" CFLAGS_COMMON; |
338 | 377 | $def! CXXFLAGS get-lang-flags "CXXFLAGS" CXXFLAGS_COMMON; |
339 | - "#", "%LDFLAGS_OPT_DBG is always set despite %debug configuration in", | |
340 | - " %SHBuild-BuildApp.sh."; | |
341 | - $env-de! LDFLAGS_OPT_DBG $if debug "" | |
342 | - (cons-cmd LDFLAGS_STRIP LDFLAGS_IMPL_OPT LDFLAGS_GC); | |
343 | - $def! LDFLAGS_DYN_BASE safeenv-get "LDFLAGS_DYN_BASE"; | |
344 | - $def! LIBS_RPATH safeenv-get "LIBS_RPATH"; | |
345 | - $if (win32? env-os) ($set-if-empty! LDFLAGS_DYN_BASE "-shared -Wl,--dll") | |
346 | - ( | |
347 | - $set-if-empty! LDFLAGS_DYN_BASE "-shared"; | |
348 | - $set-if-empty! LIBS_RPATH ++ "-Wl,-rpath," | |
349 | - (SHBuild_QuoteS_ "$ORIGIN:$ORIGIN/../lib") | |
350 | - ); | |
351 | 378 | SHB_SetupPlatformVars_ (() get-current-environment) env-os; |
352 | - $env-de! LDFLAGS_DYN_EXTRA cons-cmd "-Wl,--no-undefined" | |
353 | - (++ "-Wl,--dynamic-list-data,--dynamic-list-cpp-new," | |
354 | - "--dynamic-list-cpp-typeinfo"); | |
355 | - $env-de! LDFLAGS_DYN cons-cmd LDFLAGS_DYN_BASE LDFLAGS_DYN_EXTRA; | |
356 | - "#", "Forced setting %LDFLAGS for debug configurations?"; | |
357 | - $def! LDFLAGS cons-cmd C_CXXFLAGS_PIC cxxflags_impl_common_thrd_ | |
358 | - LDFLAGS_OPT_DBG; | |
359 | - "#", "%LDFLAGS_OPT_DBG is set to ' ' in %SHBuild-BuildApp.sh."; | |
360 | - "#", "Following settings are not in %SHBuild-common-options.sh."; | |
361 | - $redef! LDFLAGS SHBuild_TrimOptions_ (cons-cmd (SHBuild_TrimOptions_ | |
362 | - LDFLAGS) ($if app (cons-cmd ($if dynamic LIBS_RPATH "") | |
363 | - (do-ld-ext env-os)) ($if dynamic (cons-cmd LDFLAGS_DYN) "-Wl,--dn"))); | |
364 | - safeenv-set "LDFLAGS" LDFLAGS; | |
365 | - $def! SHBOPT get-SHBOPT_ outdir shbopt-ext ($or? dynamic app); | |
379 | + $if use-ld | |
380 | + ( | |
381 | + "#", "%LDFLAGS_OPT_DBG is always set despite %debug configuration in", | |
382 | + " %SHBuild-BuildApp.sh."; | |
383 | + $env-de! LDFLAGS_OPT_DBG $if debug "" | |
384 | + (cons-cmd LDFLAGS_STRIP LDFLAGS_IMPL_OPT LDFLAGS_GC); | |
385 | + $def! LDFLAGS_DYN_BASE safeenv-get "LDFLAGS_DYN_BASE"; | |
386 | + $def! LIBS_RPATH safeenv-get "LIBS_RPATH"; | |
387 | + $if (win32? env-os) | |
388 | + ($set-if-empty! LDFLAGS_DYN_BASE | |
389 | + ($if use_lld_ "-shared" "-shared -Wl,--dll")) | |
390 | + ( | |
391 | + $set-if-empty! LDFLAGS_DYN_BASE "-shared"; | |
392 | + $set-if-empty! LIBS_RPATH ++ "-Wl,-rpath," | |
393 | + (SHBuild_QuoteS_ "$ORIGIN:$ORIGIN/../lib") | |
394 | + ); | |
395 | + "XXX", "Here '-Wl,' options are separated to improve compatibility for", | |
396 | + " LLVM."; | |
397 | + "XXX", "Dynamic symbol exports are only available for ELF targets"; | |
398 | + $if use_lld_ | |
399 | + ( | |
400 | + $env-de! LDFLAGS_DYN_EXTRA cons-cmd "-Wl,-undefined,error" | |
401 | + ($if (win32? env-os) "" | |
402 | + (++ "-Wl,--export-dynamic-symbol='_ZTS*'" | |
403 | + " -Wl,--export-dynamic-symbol='_ZTI*'")) | |
404 | + ) | |
405 | + ( | |
406 | + $env-de! LDFLAGS_DYN_EXTRA cons-cmd "-Wl,--no-undefined" | |
407 | + (++ "-Wl,--dynamic-list-data,--dynamic-list-cpp-new," | |
408 | + "--dynamic-list-cpp-typeinfo"); | |
409 | + ); | |
410 | + $env-de! LDFLAGS_DYN cons-cmd LDFLAGS_DYN_BASE LDFLAGS_DYN_EXTRA; | |
411 | + "#", "Forced setting %LDFLAGS for debug configurations?"; | |
412 | + $def! LDFLAGS | |
413 | + cons-cmd C_CXXFLAGS_PIC ldflags_impl_common_thrd_ LDFLAGS_OPT_DBG; | |
414 | + "TODO", "Test and exclude Anrdoid?"; | |
415 | + $if use_lld_ ($redef! LDFLAGS cons-cmd "-fuse-ld=lld" LDFLAGS); | |
416 | + "#", "%LDFLAGS_OPT_DBG is set to ' ' in %SHBuild-BuildApp.sh."; | |
417 | + "#", "Following settings are not in %SHBuild-common-options.sh."; | |
418 | + $redef! LDFLAGS SHBuild_TrimOptions_ | |
419 | + (cons-cmd (SHBuild_TrimOptions_ LDFLAGS) | |
420 | + ($if app (cons-cmd ($if dynamic LIBS_RPATH "") (do-ld-ext env-os)) | |
421 | + ($if dynamic (cons-cmd LDFLAGS_DYN) "-Wl,--dn"))); | |
422 | + safeenv-set "LDFLAGS" LDFLAGS | |
423 | + ); | |
424 | + $def! SHBOPT get-SHBOPT_ outdir shbopt-ext use-ld; | |
366 | 425 | $defl! echo-var (var) SHBuild_EchoVar var (value-of var); |
367 | 426 | "XXX", "The values of following variables may be overriden in 'do-build'."; |
368 | 427 | "TODO", "Print actual values being used in 'do-build' as possible."; |
369 | 428 | echo-var "CXXFLAGS"; |
370 | - echo-var "LDFLAGS"; | |
429 | + $if use-ld (echo-var "LDFLAGS"); | |
371 | 430 | echo-var "SHBOPT"; |
372 | 431 | do-build CXX CXXFLAGS SHBOPT LIBPFX |
373 | 432 | ); |
@@ -400,7 +459,7 @@ | ||
400 | 459 | $assert-nonempty dst, |
401 | 460 | $assert-nonempty src; |
402 | 461 | "TODO", |
403 | - "More specific error handling in system-check and SHBuld command?"; | |
462 | + "More specific error handling in system-check and SHBuild command?"; | |
404 | 463 | $cond |
405 | 464 | ((eqv? type "Link") ( |
406 | 465 | e_rm_ dst; |
@@ -449,7 +508,7 @@ | ||
449 | 508 | InstSHBuild "HardLink" (++ to-dir "/lib" name ".a") |
450 | 509 | (++ from-dir "/" LIBPFX name ".a") |
451 | 510 | ); |
452 | - $defl! InstLibD (from-dir name to-dir SR_DSO_Dest SR_DSO_Imp) | |
511 | + $defl! InstLibD (from-dir name to-dir SR_DSO_Dest imp-sfx simulate-imp) | |
453 | 512 | ( |
454 | 513 | $assert-nonempty from-dir, |
455 | 514 | $assert-nonempty SR_DSO_Dest, |
@@ -457,8 +516,14 @@ | ||
457 | 516 | $def! target ++ LIBPFX name DSOSFX; |
458 | 517 | $def! dest ++ SR_DSO_Dest "/" target; |
459 | 518 | InstSHBuild "HardLink" dest (++ from-dir "/" target); |
460 | - $unless (string-empty? SR_DSO_Imp) ($assert-nonempty to-dir) | |
461 | - (InstSHBuild "Link" (++ to-dir "/" target SR_DSO_Imp) dest) | |
519 | + "NOTE", "See $2020-11 @ doc/Workflow.txt."; | |
520 | + $unless (string-empty? imp-sfx) ($assert-nonempty to-dir) | |
521 | + ($let ((inst-method $if (simulate-imp) "Link" "HardLink") | |
522 | + (implib-src $if (simulate-imp) dest | |
523 | + (++ from-dir "/" target imp-sfx))) | |
524 | + InstSHBuild inst-method (++ to-dir "/lib" name DSOSFX imp-sfx) | |
525 | + implib-src | |
526 | + ) | |
462 | 527 | ); |
463 | 528 | $defl! InstInc (from-dir to-dir) |
464 | 529 | ( |
@@ -476,7 +541,6 @@ | ||
476 | 541 | ); |
477 | 542 | $defl! InstNPLA1Module_ (from-dir to-dir name) |
478 | 543 | ( |
479 | - "TODO", "Use other location for NPLA1 library?"; | |
480 | 544 | $assert-nonempty name, |
481 | 545 | $assert-nonempty to-dir, |
482 | 546 | $assert-nonempty from-dir; |
@@ -6,10 +6,9 @@ | ||
6 | 6 | # XXX: The error is ignored. |
7 | 7 | # shellcheck disable=2164 |
8 | 8 | : "${SHBuild_AppBaseDir=$(cd "$(dirname "$0")"; pwd)}" |
9 | -: "${AR:=gcc-ar}" | |
10 | 9 | # shellcheck source=./SHBuild-common-toolchain.sh |
11 | 10 | . "$SHBuild_ToolDir/SHBuild-common-toolchain.sh" # for |
12 | -# SHBuidd-common-toolchain.sh, CXX. | |
11 | +# SHBuid-common-toolchain.sh, CXX. | |
13 | 12 | |
14 | 13 | : "${C_CXXFLAGS_GC:=-fdata-sections -ffunction-sections}" |
15 | 14 |
@@ -62,12 +61,30 @@ | ||
62 | 61 | -Wsign-conversion \ |
63 | 62 | "}" |
64 | 63 | |
64 | +# The call of %SHBuild_CheckCXX should have initialized %SHBuild_Env_TempDir. | |
65 | 65 | # TODO: Impl without pthread? |
66 | 66 | if "$CXX" -dumpspecs 2>& 1 | grep mthreads: > /dev/null; then |
67 | 67 | CXXFLAGS_IMPL_COMMON_THRD_='-mthreads' |
68 | -fi | |
69 | -if ! "$CXX" -dumpspecs 2>& 1 | grep no-pthread: > /dev/null; then | |
68 | + LDFLAGS_IMPL_COMMON_THRD_='-mthreads' | |
69 | +elif echo 'int main(){}' | "$CXX" -xc++ \ | |
70 | + -o"$SHBuild_Env_TempDir/null" -Werror -mthreads - 2> /dev/null; then | |
71 | + if echo 'int main(){}' | "$CXX" -xc++ \ | |
72 | + -o"$SHBuild_Env_TempDir/null" -c -Werror -mthreads - 2> /dev/null; then | |
73 | + CXXFLAGS_IMPL_COMMON_THRD_='-mthreads' | |
74 | + else | |
75 | + CXXFLAGS_IMPL_COMMON_THRD_='-D_MT' | |
76 | + fi | |
77 | + LDFLAGS_IMPL_COMMON_THRD_='-mthreads' | |
78 | +elif "$CXX" -dumpspecs 2>& 1 | grep no-pthread: > /dev/null; then | |
79 | + CXXFLAGS_IMPL_COMMON_THRD_='' | |
80 | + LDFLAGS_IMPL_COMMON_THRD_='' | |
81 | +elif echo 'int main(){}' | "$CXX" -xc++ \ | |
82 | + -o"$SHBuild_Env_TempDir/null" -pthread - 2> /dev/null; then | |
70 | 83 | CXXFLAGS_IMPL_COMMON_THRD_='-pthread' |
84 | + LDFLAGS_IMPL_COMMON_THRD_='-pthread' | |
85 | +else | |
86 | + CXXFLAGS_IMPL_COMMON_THRD_='-pthread' | |
87 | + LDFLAGS_IMPL_COMMON_THRD_='-pthread' | |
71 | 88 | fi |
72 | 89 | |
73 | 90 | # NOTE: The compiler should be specified earlier than this line to |
@@ -81,8 +98,14 @@ | ||
81 | 98 | -Wshorten-64-to-32 \ |
82 | 99 | -Wweak-vtables \ |
83 | 100 | "}" |
84 | - : "${CXXFLAGS_IMPL_OPT:=-flto}" | |
85 | - : "${LDFLAGS_IMPL_OPT:=-flto}" | |
101 | + LDFLAGS_IMPL_USE_LLD_= | |
102 | + # XXX: This is the only choice to support LTO on MinGW32 now, but not | |
103 | + # ready to work. | |
104 | + # TODO: Expose this option? | |
105 | + # LDFLAGS_IMPL_USE_LLD_=true | |
106 | + #: "${CXXFLAGS_IMPL_OPT:=-flto}" | |
107 | + #: "${LDFLAGS_IMPL_OPT:=-flto}" | |
108 | + # XXX: LTO is disabled by default for compatibility to the prebuilt binaries. | |
86 | 109 | elif [[ $SHBuild_CXX_Style_ == "G++" ]]; then |
87 | 110 | : "${C_CXXFLAGS_IMPL_WARNING:=" \ |
88 | 111 | -Wdouble-promotion \ |
@@ -179,11 +202,26 @@ | ||
179 | 202 | : "${DSOSFX:=.so}" |
180 | 203 | fi |
181 | 204 | |
182 | -: "${LDFLAGS_DYN_EXTRA:="-Wl,--no-undefined -Wl,--dynamic-list-data,\ | |
183 | ---dynamic-list-cpp-new,--dynamic-list-cpp-typeinfo"}" | |
205 | +if [[ "$LDFLAGS_IMPL_USE_LLD_" == '' ]]; then | |
206 | + : "${LDFLAGS_DYN_EXTRA:="-Wl,--no-undefined -Wl,--dynamic-list-data,\ | |
207 | + --dynamic-list-cpp-new,--dynamic-list-cpp-typeinfo"}" | |
208 | +else | |
209 | + if [[ "$SHBuild_Env_OS" == 'Win32' ]]; then | |
210 | + : "${LDFLAGS_DYN_EXTRA:="-Wl,-undefined,error"}" | |
211 | + else | |
212 | + # XXX: Here '-Wl,' options are separated to improve compatibility for | |
213 | + # LLVM. | |
214 | + : "${LDFLAGS_DYN_EXTRA:="-Wl,-undefined,error \ | |
215 | + -Wl,--export-dynamic-symbol='_ZTS*' \ | |
216 | + -Wl,--export-dynamic-symbol='_ZTI*'"}" | |
217 | + fi | |
218 | +fi | |
184 | 219 | |
185 | 220 | : "${LDFLAGS_DYN:="$LDFLAGS_DYN_BASE $LDFLAGS_DYN_EXTRA"}" |
186 | 221 | |
187 | -: "${LDFLAGS:="$C_CXXFLAGS_PIC $CXXFLAGS_IMPL_COMMON_THRD_ $LDFLAGS_OPT_DBG"}" | |
222 | +: "${LDFLAGS:="$C_CXXFLAGS_PIC $LDFLAGS_IMPL_COMMON_THRD_ $LDFLAGS_OPT_DBG"}" | |
223 | +if [[ "$LDFLAGS_IMPL_USE_LLD_" != '' ]]; then | |
224 | + LDFLAGS="-fuse-ld=lld $LDFLAGS" | |
225 | +fi | |
188 | 226 | LDFLAGS="${LDFLAGS// / }" |
189 | 227 |
@@ -72,7 +72,7 @@ | ||
72 | 72 | export CC |
73 | 73 | : "${CXX:=g++}" |
74 | 74 | export CXX |
75 | -: "${AR:=ar}" | |
75 | +: "${AR:=$(SHBuild_GetAR_ "$CXX" ar)}" | |
76 | 76 | export AR |
77 | 77 | : "${ARFLAGS:=rcs}" |
78 | 78 | export ARFLAGS |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2015-2019 FrankHB. | |
2 | + © 2015-2020 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file streambuf.hpp |
12 | 12 | \ingroup YStandardEx |
13 | 13 | \brief ISO C++ 标准库标准流缓冲扩展。 |
14 | -\version r210 | |
14 | +\version r242 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 636 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-09-22 11:19:27 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2019-07-22 23:43 +0800 | |
20 | + 2020-10-26 17:35 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -52,6 +52,41 @@ | ||
52 | 52 | } |
53 | 53 | |
54 | 54 | |
55 | +/*! | |
56 | +\brief 刷新输入缓冲区到字符串。 | |
57 | +\since build 902 | |
58 | +*/ | |
59 | +template<typename _tChar, class _tTraits, class _tAlloc> | |
60 | +std::ios_base::iostate | |
61 | +flush_input(std::basic_streambuf<_tChar, _tTraits>& buf, | |
62 | + std::basic_string<_tChar, _tTraits, _tAlloc>& str) | |
63 | +{ | |
64 | + std::streamsize cnt(buf.in_avail()); | |
65 | + | |
66 | + if(cnt == 0) | |
67 | + return std::ios_base::goodbit; | |
68 | + if(cnt > 0) | |
69 | + { | |
70 | + const auto l(str.length()); | |
71 | + using _tSize = decltype(l); | |
72 | + const auto m(std::streamsize(str.max_size() - l)); | |
73 | + | |
74 | + if(cnt < m) | |
75 | + { | |
76 | + str.resize(l + _tSize(cnt)); | |
77 | + buf.sgetn(&str[l], cnt); | |
78 | + return std::ios_base::goodbit; | |
79 | + } | |
80 | + else | |
81 | + { | |
82 | + str.resize(str.max_size()); | |
83 | + buf.sgetn(&str[l], m); | |
84 | + } | |
85 | + } | |
86 | + return std::ios_base::failbit; | |
87 | +} | |
88 | + | |
89 | + | |
55 | 90 | //! \since build 711 |
56 | 91 | //@{ |
57 | 92 | /*! |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file string.hpp |
12 | 12 | \ingroup YStandardEx |
13 | 13 | \brief ISO C++ 标准字符串扩展。 |
14 | -\version r3120 | |
14 | +\version r3132 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 304 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-04-26 20:12:19 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-25 07:06 +0800 | |
20 | + 2020-10-26 16:37 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -1635,7 +1635,7 @@ | ||
1635 | 1635 | extract(std::basic_istream<_tChar, _tTraits>& is, |
1636 | 1636 | std::basic_string<_tChar, _tTraits, _tAlloc>& str, _func f) |
1637 | 1637 | { |
1638 | - typename std::basic_string<_tChar, _tTraits, _tAlloc>::size_type n(0); | |
1638 | + bool changed = {}; | |
1639 | 1639 | // NOTE: The type shall be explicit. |
1640 | 1640 | std::ios_base::iostate st(std::ios_base::goodbit); |
1641 | 1641 |
@@ -1643,14 +1643,16 @@ | ||
1643 | 1643 | k{typename std::basic_istream<_tChar, _tTraits>::sentry(is, true)}) |
1644 | 1644 | { |
1645 | 1645 | const auto msize(str.max_size()); |
1646 | + const auto eof(_tTraits::eof()); | |
1646 | 1647 | const auto p_buf(is.rdbuf()); |
1647 | 1648 | |
1648 | 1649 | yassume(p_buf); |
1649 | - str.erase(); | |
1650 | + // NOTE: ISO C++ requires call of 'str.erase()' for 'std::getline'. | |
1651 | + // Using 'clear' should be equivalent on behavior, and usually more | |
1652 | + // efficient. | |
1653 | + str.clear(); | |
1650 | 1654 | try |
1651 | 1655 | { |
1652 | - const auto eof(_tTraits::eof()); | |
1653 | - | |
1654 | 1656 | for(auto c(p_buf->sgetc()); ; c = p_buf->snextc()) |
1655 | 1657 | { |
1656 | 1658 | if(_tTraits::eq_int_type(c, eof)) |
@@ -1660,7 +1662,7 @@ | ||
1660 | 1662 | } |
1661 | 1663 | if(f(c, *p_buf)) |
1662 | 1664 | { |
1663 | - ++n; | |
1665 | + changed = true; | |
1664 | 1666 | break; |
1665 | 1667 | } |
1666 | 1668 | if(!(str.length() < msize)) |
@@ -1669,7 +1671,7 @@ | ||
1669 | 1671 | break; |
1670 | 1672 | } |
1671 | 1673 | str.append(1, _tTraits::to_char_type(c)); |
1672 | - ++n; | |
1674 | + changed = true; | |
1673 | 1675 | } |
1674 | 1676 | } |
1675 | 1677 | catch(...) |
@@ -1678,10 +1680,9 @@ | ||
1678 | 1680 | rethrow_badstate(is, std::ios_base::badbit); |
1679 | 1681 | } |
1680 | 1682 | } |
1681 | - if(n == 0) | |
1683 | + if(!changed) | |
1682 | 1684 | st |= std::ios_base::failbit; |
1683 | - if(st) | |
1684 | - is.setstate(st); | |
1685 | + is.setstate(st); | |
1685 | 1686 | return is; |
1686 | 1687 | } |
1687 | 1688 |
@@ -12,13 +12,13 @@ | ||
12 | 12 | \ingroup YCLib |
13 | 13 | \ingroup Win32 |
14 | 14 | \brief YCLib MinGW32 平台公共扩展。 |
15 | -\version r2286 | |
15 | +\version r2287 | |
16 | 16 | \author FrankHB <frankhb1989@gmail.com> |
17 | 17 | \since build 427 |
18 | 18 | \par 创建时间: |
19 | 19 | 2013-07-10 15:35:19 +0800 |
20 | 20 | \par 修改时间: |
21 | - 2020-10-21 04:34 +0800 | |
21 | + 2020-11-08 22:09 +0800 | |
22 | 22 | \par 文本编码: |
23 | 23 | UTF-8 |
24 | 24 | \par 模块名称: |
@@ -540,7 +540,7 @@ | ||
540 | 540 | DirectoryFindData::Read() |
541 | 541 | { |
542 | 542 | const auto chk_err( |
543 | - [this](const char* fn, ErrorCode ec) YB_NONNULL(1){ | |
543 | + [this](const char* fn, ErrorCode ec) YB_NONNULL(2){ | |
544 | 544 | const auto err(::GetLastError()); |
545 | 545 | |
546 | 546 | if(err != ec) |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r7931 | |
14 | +\version r7974 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 663 |
17 | 17 | \par 创建时间: |
18 | 18 | 2016-01-07 10:32:34 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-09-30 12:03 +0800 | |
20 | + 2020-11-03 14:08 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -503,27 +503,6 @@ | ||
503 | 503 | //! \since build 845 |
504 | 504 | DefDeCopyAssignment(ValueCategoryMismatch) |
505 | 505 | }; |
506 | - | |
507 | - | |
508 | -/*! | |
509 | -\brief 列表类型错误。 | |
510 | -\note 预期列表或列表引用。 | |
511 | - | |
512 | -列表类型或非列表类型不匹配的错误。 | |
513 | -*/ | |
514 | -class YF_API ListTypeError : public TypeError | |
515 | -{ | |
516 | -public: | |
517 | - //! \since build 834 | |
518 | - using TypeError::TypeError; | |
519 | - //! \since build 845 | |
520 | - DefDeCopyCtor(ListTypeError) | |
521 | - //! \brief 虚析构:类定义外默认实现。 | |
522 | - ~ListTypeError() override; | |
523 | - | |
524 | - //! \since build 845 | |
525 | - DefDeCopyAssignment(ListTypeError) | |
526 | -}; | |
527 | 506 | //@} |
528 | 507 | |
529 | 508 |
@@ -549,21 +528,25 @@ | ||
549 | 528 | |
550 | 529 | |
551 | 530 | /*! |
552 | -\brief 无效语法。 | |
553 | - | |
554 | -特定上下文中的语法错误。 | |
531 | +\brief 列表类型错误。 | |
532 | +\note 预期列表或列表引用。 | |
533 | +\since build 834 | |
534 | +\todo 捕获并保存类型信息。 | |
535 | + | |
536 | +列表类型或非列表类型不匹配的错误。 | |
555 | 537 | */ |
556 | -class YF_API InvalidSyntax : public NPLException | |
538 | +class YF_API ListTypeError : public TypeError | |
557 | 539 | { |
558 | 540 | public: |
559 | - using NPLException::NPLException; | |
541 | + //! \since build 834 | |
542 | + using TypeError::TypeError; | |
560 | 543 | //! \since build 845 |
561 | - DefDeCopyCtor(InvalidSyntax) | |
544 | + DefDeCopyCtor(ListTypeError) | |
562 | 545 | //! \brief 虚析构:类定义外默认实现。 |
563 | - ~InvalidSyntax() override; | |
546 | + ~ListTypeError() override; | |
564 | 547 | |
565 | 548 | //! \since build 845 |
566 | - DefDeCopyAssignment(InvalidSyntax) | |
549 | + DefDeCopyAssignment(ListTypeError) | |
567 | 550 | }; |
568 | 551 | |
569 | 552 |
@@ -571,10 +554,11 @@ | ||
571 | 554 | \brief 参数不匹配。 |
572 | 555 | \since build 771 |
573 | 556 | */ |
574 | -class YF_API ParameterMismatch : public InvalidSyntax | |
557 | +class YF_API ParameterMismatch : public ListTypeError | |
575 | 558 | { |
576 | 559 | public: |
577 | - using InvalidSyntax::InvalidSyntax; | |
560 | + //! \since build 902 | |
561 | + using ListTypeError::ListTypeError; | |
578 | 562 | //! \since build 845 |
579 | 563 | DefDeCopyCtor(ParameterMismatch) |
580 | 564 | //! \brief 虚析构:类定义外默认实现。 |
@@ -617,6 +601,25 @@ | ||
617 | 601 | |
618 | 602 | |
619 | 603 | /*! |
604 | +\brief 无效语法。 | |
605 | + | |
606 | +特定上下文中的语法错误。 | |
607 | +*/ | |
608 | +class YF_API InvalidSyntax : public NPLException | |
609 | +{ | |
610 | +public: | |
611 | + using NPLException::NPLException; | |
612 | + //! \since build 845 | |
613 | + DefDeCopyCtor(InvalidSyntax) | |
614 | + //! \brief 虚析构:类定义外默认实现。 | |
615 | + ~InvalidSyntax() override; | |
616 | + | |
617 | + //! \since build 845 | |
618 | + DefDeCopyAssignment(InvalidSyntax) | |
619 | +}; | |
620 | + | |
621 | + | |
622 | +/*! | |
620 | 623 | \brief 标识符错误。 |
621 | 624 | \since build 726 |
622 | 625 |
@@ -838,10 +841,13 @@ | ||
838 | 841 | TermToTags(TermNode&); |
839 | 842 | |
840 | 843 | /*! |
844 | +\note 后两个参数传递给 TermToStringWithReferenceMark ,预期用法通常相同。 | |
845 | +\sa TermToStringWithReferenceMark | |
846 | +*/ | |
847 | +//@{ | |
848 | +/*! | |
841 | 849 | \brief 对列表项抛出指定预期访问值的类型的异常。 |
842 | 850 | \throw ListTypeError 消息中包含由参数指定的预期访问值的类型的异常。 |
843 | -\note 后两个参数传递给 TermToStringWithReferenceMark ,预期用法通常相同。 | |
844 | -\sa TermToStringWithReferenceMark | |
845 | 851 | \since build 855 |
846 | 852 | */ |
847 | 853 | YB_NORETURN YF_API void |
@@ -849,6 +855,15 @@ | ||
849 | 855 | bool); |
850 | 856 | |
851 | 857 | /*! |
858 | +\brief 抛出对非列表值预期列表类型的异常。 | |
859 | +\throw ListTypeError 值不是列表。 | |
860 | +\since build 902 | |
861 | +*/ | |
862 | +YB_NORETURN YF_API void | |
863 | +ThrowListTypeErrorForNonlist(const TermNode&, bool); | |
864 | +//@} | |
865 | + | |
866 | +/*! | |
852 | 867 | \brief 标记记号节点:递归变换节点,转换其中的词素为记号值。 |
853 | 868 | \note 先变换子节点。 |
854 | 869 | \since build 753 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.h |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r8452 | |
14 | +\version r8458 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 472 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-02-02 17:58:24 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-19 06:22 +0800 | |
20 | + 2020-11-03 10:35 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -206,11 +206,12 @@ | ||
206 | 206 | //@} |
207 | 207 | |
208 | 208 | /*! |
209 | -\brief 抛出第一参数不符合预期值类别的异常。 | |
210 | -\throw ValueCategory 第一参数值类别错误。 | |
209 | +\brief 抛出不符合预期值类别的异常。 | |
210 | +\throw ValueCategory 值类别错误。 | |
211 | +\since build 902 | |
211 | 212 | */ |
212 | 213 | YB_NORETURN YF_API void |
213 | -ThrowValueCategoryErrorForFirstArgument(const TermNode&); | |
214 | +ThrowValueCategoryError(const TermNode&); | |
214 | 215 | //@} |
215 | 216 | |
216 | 217 |
@@ -964,7 +965,7 @@ | ||
964 | 965 | \sa Wrapping |
965 | 966 | \since build 751 |
966 | 967 | |
967 | - 对每一个子项求值,重复 Wrapping 次; | |
968 | + 求值每一个参数子项,整体重复 Wrapping 次; | |
968 | 969 | 然后断言检查项,对可调用的项调用 Hanlder 。 |
969 | 970 | 项检查不存在或在检查通过后,变换无参数规约,然后对节点调用 Hanlder , |
970 | 971 | 否则抛出异常。 |
@@ -1637,6 +1638,7 @@ | ||
1637 | 1638 | \since build 899 |
1638 | 1639 | |
1639 | 1640 | 指定字符串参数作为加载对象描述,结合自身状态加载输入为待求值的项。 |
1641 | + 加载翻译单元时,加载例程被同步地调用。 | |
1640 | 1642 | */ |
1641 | 1643 | Loader Load{DefaultLoad}; |
1642 | 1644 | /*! |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file FileIO.h |
12 | 12 | \ingroup YCLib |
13 | 13 | \brief 平台相关的文件访问和输入/输出接口。 |
14 | -\version r3176 | |
14 | +\version r3201 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 616 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-07-14 18:50:35 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-24 04:29 +0800 | |
20 | + 2020-10-26 11:02 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -35,15 +35,22 @@ | ||
35 | 35 | // std::system_error, YTraceDe, array, wstring, string_view; |
36 | 36 | #include YFM_YCLib_Reference // for unique_ptr_from; |
37 | 37 | #include <ios> // for std::ios_base::sync_with_stdio; |
38 | -#include <fstream> // for std::filebuf; | |
39 | -#if __GLIBCXX__ | |
40 | -# include <ext/stdio_filebuf.h> // for __gnu_cxx::stdio_filebuf; | |
38 | +#include <fstream> // for std::basic_filebuf, std::filebuf, std::wfilebuf, | |
39 | +// std::basic_ifstream, std::basic_ofstream, std::basic_fstream, | |
40 | +// std::ifstream, std::ofstream, std::fstream, std::wifstream, std::wofstream, | |
41 | +// std::wfstream; | |
42 | +#if __GLIBCXX__ || _LIBCPP_VERSION || YB_IMPL_MSCPP | |
43 | +#include <istream> // for std::basic_istream; | |
44 | +#include <ostream> // for std::basic_ostream; | |
45 | +# if __GLIBCXX__ | |
46 | +# include <ext/stdio_filebuf.h> // for __gnu_cxx::stdio_filebuf; | |
41 | 47 | // ystdex::exchange; |
42 | -#elif YB_IMPL_MSCPP | |
43 | -# include <ystdex/cstdio.h> // for ystdex::openmode_conv; | |
44 | -# include <locale> // for std::use_facet, std::codecvt; | |
48 | +# elif YB_IMPL_MSCPP | |
49 | +# include <ystdex/cstdio.h> // for ystdex::openmode_conv; | |
50 | +# include <locale> // for std::use_facet, std::codecvt; | |
51 | +# endif | |
45 | 52 | #endif |
46 | -#include <iosfwd> // for std::ostream; | |
53 | +#include <iosfwd> // for std::istream, std::ostream; | |
47 | 54 | |
48 | 55 | namespace platform |
49 | 56 | { |
@@ -1041,6 +1048,19 @@ | ||
1041 | 1048 | |
1042 | 1049 | |
1043 | 1050 | /*! |
1051 | +\brief 从流中输入字符串。 | |
1052 | +\pre 断言:第二参数非空。 | |
1053 | +\note Win32 平台:检查流是否使用控制台。若使用控制台,刷新同步的流并使用控制台输出。 | |
1054 | +\sa std::getline | |
1055 | +\since build 902 | |
1056 | + | |
1057 | +无格式输入字符串行。 | |
1058 | +默认使用 std::getline ,但可对特定的流实现检查并使用不同的方式。 | |
1059 | +*/ | |
1060 | +YF_API void | |
1061 | +StreamGet(std::istream&, string&); | |
1062 | + | |
1063 | +/*! | |
1044 | 1064 | \brief 向流中输出字符串。 |
1045 | 1065 | \pre 断言:第二参数非空。 |
1046 | 1066 | \note Win32 平台:检查流是否使用控制台。若使用控制台,刷新流并使用控制台输出。 |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2009-2019 FrankHB. | |
2 | + © 2009-2020 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Font.h |
12 | 12 | \ingroup Adaptor |
13 | 13 | \brief 平台无关的字体库。 |
14 | -\version r3540 | |
14 | +\version r3542 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 296 |
17 | 17 | \par 创建时间: |
18 | 18 | 2009-11-12 22:02:40 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2019-01-03 17:49 +0800 | |
20 | + 2020-11-03 13:46 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -301,7 +301,7 @@ | ||
301 | 301 | public: |
302 | 302 | //! \since build 421 |
303 | 303 | SmallBitmapData(::FT_GlyphSlot, FontStyle); |
304 | - SmallBitmapData(SmallBitmapData&&); | |
304 | + SmallBitmapData(SmallBitmapData&&) ynothrow; | |
305 | 305 | ~SmallBitmapData(); |
306 | 306 | }; |
307 | 307 | //@} |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file YAdaptor.h |
12 | 12 | \ingroup Adaptor |
13 | 13 | \brief 外部库关联。 |
14 | -\version r2444 | |
14 | +\version r2448 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since 早于 build 132 |
17 | 17 | \par 创建时间: |
18 | 18 | 2010-02-22 20:16:21 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-23 05:55 +0800 | |
20 | + 2020-11-09 17:56 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -39,7 +39,8 @@ | ||
39 | 39 | // <set>, <stack>, <unordered_map>, <unordered_set>, <vector>, |
40 | 40 | // <ystdex/memory_resource.h>, platform::basic_types, YFM_YCLib_Container, |
41 | 41 | // platform::basic_utilities, platform::containers, '*string_view', |
42 | -// MakePathString, uopen, 'uf*', 'up*', 'omode_conv*', StreamPut, etc; | |
42 | +// MakePathString, uopen, 'uf*', 'up*', 'omode_conv*', StreamGet, StreamPut, | |
43 | +// etc; | |
43 | 44 | #include YFM_YCLib_Reference // for YFM_YCLib_Reference, platform::references, |
44 | 45 | // <memory>, '*_ptr', 'make*_ptr', lref; |
45 | 46 | #include YFM_YCLib_Keys // for <bitset>, YCLib key space; |
@@ -322,6 +323,8 @@ | ||
322 | 323 | using platform::DefaultPMode; |
323 | 324 | using platform::omode_conv; |
324 | 325 | using platform::omode_convb; |
326 | +//! \since build 902 | |
327 | +using platform::StreamGet; | |
325 | 328 | //! \since build 901 |
326 | 329 | using platform::StreamPut; |
327 | 330 | //! \since build 901 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Dependency.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief 依赖管理。 |
14 | -\version r3792 | |
14 | +\version r3808 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 623 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-08-09 22:14:45 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-25 06:11 +0800 | |
20 | + 2020-11-03 09:42 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -27,12 +27,14 @@ | ||
27 | 27 | |
28 | 28 | #include "NPL/YModules.h" |
29 | 29 | #include YFM_NPL_Dependency // for set, string, ystdex::isspace, std::istream, |
30 | -// YSLib::unique_ptr, YSLib::share_move, TokenValue, ystdex::bind1, | |
31 | -// ValueObject, NPL::AllocateEnvironment, std::piecewise_construct, | |
32 | -// NPL::forward_as_tuple, LiftOther, Collapse, LiftOtherOrCopy, NPL::IsMovable, | |
33 | -// LiftTermOrCopy, ResolveTerm, LiftTermValueOrCopy, MoveResolved, | |
34 | -// ResolveIdentifier, ystdex::plus, std::placeholders, NPL::ResolveRegular, | |
35 | -// ystdex::tolower, ystdex::swap_dependent, LiftTermRef, LiftTerm, NPL::Deref, | |
30 | +// YSLib::unique_ptr, YSLib::share_move, A1::NameTypedReducerHandler, std::ref, | |
31 | +// RelaySwitched, ThrowNonmodifiableErrorForAssignee, ThrowValueCategoryError, | |
32 | +// TokenValue, ystdex::bind1, ValueObject, NPL::AllocateEnvironment, | |
33 | +// std::piecewise_construct, NPL::forward_as_tuple, LiftOther, Collapse, | |
34 | +// LiftOtherOrCopy, NPL::IsMovable, LiftTermOrCopy, ResolveTerm, | |
35 | +// LiftTermValueOrCopy, MoveResolved, ResolveIdentifier, ystdex::plus, | |
36 | +// std::placeholders, NPL::ResolveRegular, ystdex::tolower, | |
37 | +// ystdex::swap_dependent, LiftTermRef, LiftTerm, NPL::Deref, | |
36 | 38 | // YSLib::IO::StreamPut; |
37 | 39 | #include YFM_NPL_NPLA1Forms // for NPL::Forms functions; |
38 | 40 | #include YFM_YSLib_Service_FileSystem // for YSLib::IO::*; |
@@ -367,7 +369,7 @@ | ||
367 | 369 | return; |
368 | 370 | ThrowNonmodifiableErrorForAssignee(); |
369 | 371 | } |
370 | - ThrowValueCategoryErrorForFirstArgument(nd); | |
372 | + ThrowValueCategoryError(nd); | |
371 | 373 | } |
372 | 374 | |
373 | 375 | //! \since build 856 |
@@ -1239,9 +1241,13 @@ | ||
1239 | 1241 | // NOTE: SHBuild builtins. |
1240 | 1242 | renv.DefineChecked("SHBuild_BaseTerminalHook_", |
1241 | 1243 | ValueObject(function<void(const string&, const string&)>( |
1242 | - [](const string& n, const string& val) ynothrow{ | |
1243 | - // XXX: Error from 'std::printf' is ignored. | |
1244 | - std::printf("%s = \"%s\"\n", n.c_str(), val.c_str()); | |
1244 | + [&](const string& n, const string& val) ynothrow{ | |
1245 | + auto& os(context.GetOutputStreamRef()); | |
1246 | + | |
1247 | + YSLib::IO::StreamPut(os, | |
1248 | + YSLib::sfmt("%s = \"%s\"", n.c_str(), val.c_str()).c_str()); | |
1249 | + if(os) | |
1250 | + os << std::endl; | |
1245 | 1251 | }))); |
1246 | 1252 | RegisterUnary<Strict, const string>(renv, "SHBuild_BuildGCH_existed_", |
1247 | 1253 | [](const string& str) -> bool{ |
@@ -1283,6 +1289,7 @@ | ||
1283 | 1289 | if(const auto p_hook = AccessPtr< |
1284 | 1290 | function<void(const string&, const string&)>>(*p)) |
1285 | 1291 | (*p_hook)(n, val); |
1292 | + return ValueToken::Unspecified; | |
1286 | 1293 | }, term); |
1287 | 1294 | }); |
1288 | 1295 | RegisterStrict(renv, "SHBuild_Install_HardLink", [&](TermNode& term){ |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA 公共接口。 |
14 | -\version r3361 | |
14 | +\version r3367 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 663 |
17 | 17 | \par 创建时间: |
18 | 18 | 2016-01-07 10:32:45 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-09-30 12:05 +0800 | |
20 | + 2020-11-03 13:13 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -589,6 +589,13 @@ | ||
589 | 589 | } |
590 | 590 | |
591 | 591 | void |
592 | +ThrowListTypeErrorForNonlist(const TermNode& term, bool has_ref) | |
593 | +{ | |
594 | + throw ListTypeError(ystdex::sfmt("Expected a list, got '%s'.", | |
595 | + TermToStringWithReferenceMark(term, has_ref).c_str())); | |
596 | +} | |
597 | + | |
598 | +void | |
592 | 599 | TokenizeTerm(TermNode& term) |
593 | 600 | { |
594 | 601 | for(auto& child : term) |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 公共接口。 |
14 | -\version r20096 | |
14 | +\version r20148 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 473 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-02-02 18:02:47 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-19 05:23 +0800 | |
20 | + 2020-11-05 13:38 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -34,14 +34,14 @@ | ||
34 | 34 | // NPL::forward_as_tuple, uintmax_t, TokenValue, function, std::allocator_arg, |
35 | 35 | // stack, vector, std::find_if, TermTags, TermReference, GetLValueTagsOf, |
36 | 36 | // NPL::TryAccessLeaf, NPL::IsMovable, in_place_type, InvalidReference, |
37 | -// IsBranch, NPL::Deref, IsLeaf, ResolveTerm, ystdex::update_thunk, | |
38 | -// NPL::Access, ystdex::retry_on_cond, AccessFirstSubterm, ystdex::bind1, | |
39 | -// ystdex::make_transform, IsBranchedList, std::placeholders, NoContainer, | |
40 | -// ystdex::try_emplace, Environment, shared_ptr, ystdex::unique_guard, | |
41 | -// NPL::AsTermNode, CategorizeBasicLexeme, DeliteralizeUnchecked, | |
42 | -// CheckReducible, Deliteralize, ystdex::isdigit, ResolveIdentifier, | |
43 | -// IsNPLAExtendedLiteral, ystdex::ref_eq, NPL::TryAccessTerm, | |
44 | -// YSLib::share_move, ystdex::call_value_or, Session; | |
37 | +// IsBranch, NPL::Deref, IsLeaf, ResolveTerm, ThrowListTypeErrorForNonlist, | |
38 | +// ystdex::update_thunk, NPL::Access, ystdex::retry_on_cond, | |
39 | +// AccessFirstSubterm, ystdex::bind1, ystdex::make_transform, IsBranchedList, | |
40 | +// std::placeholders, NoContainer, ystdex::try_emplace, Environment, | |
41 | +// shared_ptr, ystdex::unique_guard, NPL::AsTermNode, CategorizeBasicLexeme, | |
42 | +// DeliteralizeUnchecked, CheckReducible, Deliteralize, ystdex::isdigit, | |
43 | +// ResolveIdentifier, IsNPLAExtendedLiteral, ystdex::ref_eq, | |
44 | +// NPL::TryAccessTerm, YSLib::share_move, ystdex::call_value_or, Session; | |
45 | 45 | #include "NPLA1Internals.h" // for A1::Internals API; |
46 | 46 | #include YFM_NPL_Dependency // for A1::OpenUnique; |
47 | 47 | #include <ystdex/exception.h> // for ystdex::unsupported; |
@@ -647,38 +647,44 @@ | ||
647 | 647 | // with the correct implementation of the reference collapse. |
648 | 648 | ResolveTerm([&, n_p, o_tags](TermNode& nd, |
649 | 649 | ResolvedTermReferencePtr p_ref){ |
650 | - const bool ellipsis(last != t.end()); | |
651 | - const auto n_o(nd.size()); | |
652 | - | |
653 | - if(n_p == n_o || (ellipsis && n_o >= n_p - 1)) | |
654 | - { | |
655 | - auto tags(o_tags); | |
656 | - | |
657 | - // NOTE: All tags as type qualifiers should be checked | |
658 | - // here. Currently only glvalues can be qualified. | |
659 | - // XXX: Term tags are currently not respected in | |
660 | - // prvalues. | |
661 | - if(p_ref) | |
662 | - { | |
663 | - const auto ref_tags(p_ref->GetTags()); | |
664 | 650 | |
665 | - tags = (tags | |
666 | - & ~(TermTags::Unique | TermTags::Temporary)) | |
667 | - | (ref_tags & TermTags::Unique); | |
668 | - tags |= ref_tags & TermTags::Nonmodifying; | |
651 | + if(IsList(nd)) | |
652 | + { | |
653 | + const bool ellipsis(last != t.end()); | |
654 | + const auto n_o(nd.size()); | |
655 | + | |
656 | + if(n_p == n_o || (ellipsis && n_o >= n_p - 1)) | |
657 | + { | |
658 | + auto tags(o_tags); | |
659 | + | |
660 | + // NOTE: All tags as type qualifiers should be checked | |
661 | + // here. Currently only glvalues can be qualified. | |
662 | + // XXX: Term tags are currently not respected in | |
663 | + // prvalues. | |
664 | + if(p_ref) | |
665 | + { | |
666 | + const auto ref_tags(p_ref->GetTags()); | |
667 | + | |
668 | + tags = (tags | |
669 | + & ~(TermTags::Unique | TermTags::Temporary)) | |
670 | + | (ref_tags & TermTags::Unique); | |
671 | + tags |= ref_tags & TermTags::Nonmodifying; | |
672 | + } | |
673 | + MatchSubterms(t.begin(), last, nd, nd.begin(), tags, | |
674 | + p_ref ? p_ref->GetEnvironmentReference() : r_env, | |
675 | + ellipsis | |
676 | +#if NPL_Impl_NPLA1_AssertParameterMatch | |
677 | + , t.end() | |
678 | +#endif | |
679 | + ); | |
669 | 680 | } |
670 | - MatchSubterms(t.begin(), last, nd, nd.begin(), tags, | |
671 | - p_ref ? p_ref->GetEnvironmentReference() : r_env, | |
672 | - ellipsis | |
673 | -#if NPL_Impl_NPLA1_AssertParameterMatch | |
674 | - , t.end() | |
675 | -#endif | |
676 | - ); | |
681 | + else if(!ellipsis) | |
682 | + throw ArityMismatch(n_p, n_o); | |
683 | + else | |
684 | + ThrowInsufficientTermsError(); | |
677 | 685 | } |
678 | - else if(!ellipsis) | |
679 | - throw ArityMismatch(n_p, n_o); | |
680 | 686 | else |
681 | - ThrowInsufficientTermsError(); | |
687 | + ThrowListTypeErrorForNonlist(nd, p_ref); | |
682 | 688 | }, o); |
683 | 689 | } |
684 | 690 | else |
@@ -718,7 +724,13 @@ | ||
718 | 724 | { |
719 | 725 | if(i != last) |
720 | 726 | { |
721 | - ystdex::update_thunk(act, [=, &o_tm, &r_env]{ | |
727 | + // XXX: Use explicit captures here to ensure ISO C++20 | |
728 | + // compatibility. | |
729 | + ystdex::update_thunk(act, [this, i, j, last, tags, ellipsis, | |
730 | +#if NPL_Impl_NPLA1_AssertParameterMatch | |
731 | + t_end, | |
732 | +#endif | |
733 | + &o_tm, &r_env]{ | |
722 | 734 | return MatchSubterms(std::next(i), last, o_tm, std::next(j), |
723 | 735 | #if NPL_Impl_NPLA1_AssertParameterMatch |
724 | 736 | tags, r_env, ellipsis, t_end); |
@@ -788,7 +800,7 @@ | ||
788 | 800 | } |
789 | 801 | |
790 | 802 | void |
791 | -ThrowValueCategoryErrorForFirstArgument(const TermNode& term) | |
803 | +ThrowValueCategoryError(const TermNode& term) | |
792 | 804 | { |
793 | 805 | throw ValueCategoryMismatch(ystdex::sfmt("Expected a reference for the 1st " |
794 | 806 | "argument, got '%s'.", TermToString(term).c_str())); |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPLA1Forms.cpp |
12 | 12 | \ingroup NPL |
13 | 13 | \brief NPLA1 语法形式。 |
14 | -\version r19495 | |
14 | +\version r19504 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 882 |
17 | 17 | \par 创建时间: |
18 | 18 | 2014-02-15 11:19:51 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-15 03:01 +0800 | |
20 | + 2020-11-09 00:53 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -39,8 +39,8 @@ | ||
39 | 39 | // LiftOtherOrCopy, ResolveTerm, ystdex::equality_comparable, |
40 | 40 | // std::allocator_arg, NPL::AsTermNode, ystdex::exchange, |
41 | 41 | // NPL::SwitchToFreshEnvironment, TermTags, ystdex::expand_proxy, |
42 | -// NPL::AccessRegular, GetLValueTagsOf, RegularizeTerm, | |
43 | -// ThrowValueCategoryErrorForFirstArgument, TermReference, | |
42 | +// NPL::AccessRegular, TermReference, GetLValueTagsOf, RegularizeTerm, | |
43 | +// ThrowValueCategoryError, ThrowListTypeErrorForNonlist, | |
44 | 44 | // NPL::TryAccessReferencedLeaf, ystdex::invoke_value_or, |
45 | 45 | // ystdex::call_value_or, RelaySwitched, LiftMovedOther, LiftCollapsed, |
46 | 46 | // ystdex::make_transform, NPL::AllocateEnvironment, NPL::TryAccessTerm, |
@@ -332,7 +332,7 @@ | ||
332 | 332 | } |
333 | 333 | |
334 | 334 | //! \since build 899 |
335 | -YF_API void | |
335 | +void | |
336 | 336 | BindParameterChecked(const shared_ptr<Environment>& p_env, const TermNode& t, |
337 | 337 | TermNode& o) |
338 | 338 | { |
@@ -1229,12 +1229,12 @@ | ||
1229 | 1229 | if(has_ref) |
1230 | 1230 | { |
1231 | 1231 | if(YB_UNLIKELY(!IsBranchedList(nd))) |
1232 | - throw ListTypeError(ystdex::sfmt( | |
1233 | - "Expected a non-empty list for the 1st argument, got '%s'.", | |
1232 | + throw ListTypeError( | |
1233 | + ystdex::sfmt("Expected a non-empty list, got '%s'.", | |
1234 | 1234 | TermToStringWithReferenceMark(nd, true).c_str())); |
1235 | 1235 | } |
1236 | 1236 | else |
1237 | - ThrowValueCategoryErrorForFirstArgument(nd); | |
1237 | + ThrowValueCategoryError(nd); | |
1238 | 1238 | } |
1239 | 1239 | |
1240 | 1240 | //! \since build 874 |
@@ -1305,9 +1305,7 @@ | ||
1305 | 1305 | swap(nd_x, nd_new); |
1306 | 1306 | } |
1307 | 1307 | else |
1308 | - throw ListTypeError(ystdex::sfmt("Expected a list for" | |
1309 | - " the 2nd argument, got '%s'.", | |
1310 | - TermToStringWithReferenceMark(nd_y, p_ref_y).c_str())); | |
1308 | + ThrowListTypeErrorForNonlist(nd_y, p_ref_y); | |
1311 | 1309 | }, y); |
1312 | 1310 | }, term); |
1313 | 1311 | } |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file FileIO.cpp |
12 | 12 | \ingroup YCLib |
13 | 13 | \brief 平台相关的文件访问和输入/输出接口。 |
14 | -\version r3696 | |
14 | +\version r3796 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 615 |
17 | 17 | \par 创建时间: |
18 | 18 | 2015-07-14 18:53:12 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-25 06:07 +0800 | |
20 | + 2020-10-26 16:39 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -28,18 +28,20 @@ | ||
28 | 28 | #undef __STRICT_ANSI__ // for ::fileno, ::pclose, ::popen, ::_wfopen; |
29 | 29 | #include "YCLib/YModules.h" |
30 | 30 | #include YFM_YCLib_FileIO // for std::is_same, ystdex::underlying_type_t, |
31 | -// ystdex::invoke_result_t, ystdex::invoke, RetryOnInterrupted, | |
32 | -// std::errc::function_not_supported, YCL_CallF_CAPI, std::is_integral, | |
33 | -// ystdex::invoke, Nonnull, ystdex::temporary_buffer; | |
34 | -#include YFM_YCLib_NativeAPI // for Mode, ::HANDLE, struct ::stat, | |
31 | +// ystdex::invoke_result_t, ystdex::invoke, RetryOnInterrupted, Deref, | |
32 | +// std::errc::function_not_supported, YCL_CallF_CAPI, ystdex::invoke, Nonnull, | |
33 | +// ystdex::temporary_buffer; | |
34 | +#include YFM_YCLib_NativeAPI // for Mode, ::HANDLE, ReadConsoleW, struct ::stat, | |
35 | 35 | // platform_ex::cstat, platform_ex::estat ::GetConsoleMode, OpenMode, |
36 | 36 | // YCL_CallGlobal, ::close, ::fcntl, F_GETFL, ::setmode, ::fchmod, ::_chsize, |
37 | 37 | // ::ftruncate, ::fsync, ::_wgetcwd, ::getcwd, ::chdir, ::rmdir, ::unlink, |
38 | 38 | // !defined(__STRICT_ANSI__) API, ::GetCurrentDirectoryW; |
39 | +#include <ystdex/string.hpp> // for std::char_traits, std::getline, | |
40 | +// ystdex::write_ntcts; | |
39 | 41 | #include YFM_YCLib_FileSystem // for NodeCategory::*, CategorizeNode; |
40 | 42 | #include <ystdex/functional.hpp> // for ystdex::compose, ystdex::addrof; |
41 | -#include <ystdex/string.hpp> // for ystdex::write_ntcts; | |
42 | -#include <ystdex/streambuf.hpp> // for ystdex::streambuf_equal; | |
43 | +#include <ystdex/streambuf.hpp> // for ystdex::flush_input, | |
44 | +// ystdex::streambuf_equal; | |
43 | 45 | #if YCL_DS |
44 | 46 | # include "CHRLib/YModules.h" |
45 | 47 | # include YFM_CHRLib_CharacterProcessing // for CHRLib::MakeMBCS, |
@@ -56,9 +58,11 @@ | ||
56 | 58 | # include <ystdex/ios.hpp> // for ystdex::rethrow_badstate; |
57 | 59 | # include YFM_Win32_YCLib_Consoles // for platform_ex::WConsole; |
58 | 60 | # include <ext/stdio_sync_filebuf.h> // for __gnu_cxx::stdio_sync_filebuf; |
61 | +// NOTE: Headers for complete std::istream and std::ostream shall be already | |
62 | +// included. | |
59 | 63 | # endif |
60 | -# include YFM_Win32_YCLib_MinGW32 // for | |
61 | -// platform_ex::UnlockFile, platform_ex::LockFile, platform_ex::TryLockFile; | |
64 | +# include YFM_Win32_YCLib_MinGW32 // for platform_ex::UnlockFile, | |
65 | +// YCL_CallF_Win32, platform_ex::LockFile, platform_ex::TryLockFile; | |
62 | 66 | # include YFM_Win32_YCLib_NLS // for platform_ex::UTF8ToWCS, |
63 | 67 | // platform_ex::WCSToUTF8; |
64 | 68 |
@@ -160,6 +164,80 @@ | ||
160 | 164 | #endif |
161 | 165 | |
162 | 166 | #if YCL_Win32 && __GLIBCXX__ |
167 | +//! since build 902 | |
168 | +bool | |
169 | +StreamGetFromFileDescriptor(std::istream& is, int fd, string& str) | |
170 | +{ | |
171 | + const auto h(ToHandle(fd)); | |
172 | + | |
173 | + if(h != INVALID_HANDLE_VALUE) | |
174 | + { | |
175 | + unsigned long mode; | |
176 | + | |
177 | + if(::GetConsoleMode(h, &mode)) | |
178 | + { | |
179 | + bool changed = {}; | |
180 | + std::ios_base::iostate st(std::ios_base::goodbit); | |
181 | + | |
182 | + if(const auto k{typename std::istream::sentry(is, true)}) | |
183 | + { | |
184 | + // NOTE: See the implementation of %ystdex::extract. | |
185 | + str.clear(); | |
186 | + try | |
187 | + { | |
188 | + const auto p_buf(is.rdbuf()); | |
189 | + | |
190 | + st |= ystdex::flush_input(Deref(p_buf), str); | |
191 | + if(st == std::ios_base::goodbit) | |
192 | + { | |
193 | + using wtraits = std::char_traits<wchar_t>; | |
194 | + const auto msize(str.max_size()); | |
195 | + const auto eof(wtraits::eof()); | |
196 | + | |
197 | + while(true) | |
198 | + { | |
199 | + if(!(str.length() < msize)) | |
200 | + { | |
201 | + st |= std::ios_base::failbit; | |
202 | + break; | |
203 | + } | |
204 | + | |
205 | + wchar_t buf[1]; | |
206 | + unsigned long n; | |
207 | + | |
208 | + YCL_CallF_Win32(ReadConsoleW, h, buf, 1, &n, | |
209 | + yimpl({})); | |
210 | + | |
211 | + const auto c(buf[0]); | |
212 | + | |
213 | + if(wtraits::eq_int_type(c, eof)) | |
214 | + { | |
215 | + st |= std::ios_base::eofbit; | |
216 | + break; | |
217 | + } | |
218 | + if(wtraits::eq_int_type(c, '\n')) | |
219 | + { | |
220 | + changed = true; | |
221 | + break; | |
222 | + } | |
223 | + str += platform_ex::WCSToUTF8(wstring{c}); | |
224 | + changed = true; | |
225 | + } | |
226 | + } | |
227 | + } | |
228 | + CatchExpr(..., | |
229 | + ystdex::rethrow_badstate(is, std::ios_base::badbit)) | |
230 | + } | |
231 | + if(!changed) | |
232 | + st |= std::ios_base::failbit; | |
233 | + is.setstate(st); | |
234 | + return true; | |
235 | + } | |
236 | + } | |
237 | + return {}; | |
238 | +} | |
239 | + | |
240 | +//! since build 901 | |
163 | 241 | YB_NONNULL(3) bool |
164 | 242 | StreamPutToFileDescriptor(std::ostream& os, int fd, const char* s) |
165 | 243 | { |
@@ -748,6 +826,31 @@ | ||
748 | 826 | |
749 | 827 | |
750 | 828 | void |
829 | +StreamGet(std::istream& is, string& str) | |
830 | +{ | |
831 | +#if YCL_Win32 | |
832 | + if(const auto p_sb = is.rdbuf()) | |
833 | + { | |
834 | + // TODO: Implement for other standard library implementations. | |
835 | +# if __GLIBCXX__ | |
836 | + if(const auto p = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(p_sb)) | |
837 | + { | |
838 | + if(StreamGetFromFileDescriptor(is, p->fd(), str)) | |
839 | + return; | |
840 | + } | |
841 | + if(const auto p | |
842 | + = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(p_sb)) | |
843 | + { | |
844 | + if(StreamGetFromFileDescriptor(is, ::_fileno(p->file()), str)) | |
845 | + return; | |
846 | + } | |
847 | +#endif | |
848 | + } | |
849 | +#endif | |
850 | + std::getline(is, str); | |
851 | +} | |
852 | + | |
853 | +void | |
751 | 854 | StreamPut(std::ostream& os, const char* s) |
752 | 855 | { |
753 | 856 | YAssertNonnull(s); |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file FileSystem.cpp |
12 | 12 | \ingroup YCLib |
13 | 13 | \brief 平台相关的文件系统接口。 |
14 | -\version r4947 | |
14 | +\version r4978 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 312 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-05-30 22:41:35 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-25 06:11 +0800 | |
20 | + 2020-11-08 22:04 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -26,27 +26,27 @@ | ||
26 | 26 | |
27 | 27 | |
28 | 28 | #include "YCLib/YModules.h" |
29 | -#include YFM_YCLib_FileSystem // for basic_string, default_delete, | |
30 | -// make_observer, std::min, std::accumulate, std::tm, ystdex::read_uint_le, | |
31 | -// YAssertNonnull, ystdex::write_uint_le, std::bind, std::ref, | |
32 | -// ystdex::retry_on_cond; | |
29 | +#include YFM_YCLib_FileSystem // for basic_string, std::is_integral, | |
30 | +// std::chrono::system_clock, YAssertNonnull, default_delete, make_observer, | |
31 | +// ystdex::retry_on_cond, std::tm, std::is_same, std::min, std::accumulate, | |
32 | +// ystdex::read_uint_le, std::bind, std::ref, ystdex::write_uint_le; | |
33 | 33 | #include YFM_YCLib_FileIO // for platform_ex::MakePathStringW, |
34 | 34 | // platform_Ex::MakePathStringU, MakePathString, Deref, ystdex::throw_error, |
35 | 35 | // std::invalid_argument, std::errc::function_not_supported, YCL_CallF_CAPI, |
36 | 36 | // CategorizeNode, complete FileDescriptor, ystdex::ntctslen, std::wctob, |
37 | -// std::towupper, ystdex::restrict_length, std::min, ystdex::ntctsicmp, | |
37 | +// std::towupper, ystdex::restrict_length, ystdex::ntctsicmp, | |
38 | 38 | // std::errc::invalid_argument, std::strchr; |
39 | -#include YFM_YCLib_NativeAPI // for Mode, struct ::stat, ::stat, | |
40 | -// ::GetFileAttributesW, platform_ex::cstat, platform_ex::estat, ::futimens, | |
41 | -// ::linkat, ::symlink, ::lstat, ::readlink; | |
39 | +#include YFM_YCLib_NativeAPI // for ::dev_t, ::ino_t, Mode, struct ::stat, | |
40 | +// ::stat, ::GetFileAttributesW, platform_ex::cstat, platform_ex::estat, | |
41 | +// ::futimens, ::linkat, ::symlink, ::lstat, ::readlink; | |
42 | 42 | #include "CHRLib/YModules.h" |
43 | 43 | #include YFM_CHRLib_CharacterProcessing // for CHRLib::MakeUCS2LE; |
44 | -#include <ystdex/ctime.h> // for ystdex::is_date_range_valid, | |
44 | +#include <ystdex/ctime.h> // for std::time_t, ystdex::is_date_range_valid, | |
45 | 45 | // ystdex::is_time_no_leap_valid; |
46 | 46 | #if YCL_Win32 |
47 | -# include YFM_Win32_YCLib_MinGW32 // for platform_ex::FileAttributes, | |
48 | -// platform_ex::GetErrnoFromWin32, platform_ex::Invalid, | |
49 | -// platform_ex::ConvertTime, platform_ex::ToHandle, | |
47 | +# include YFM_Win32_YCLib_MinGW32 // for YCL_CallF_Win32, | |
48 | +// platform_ex::FileAttributes, platform_ex::GetErrnoFromWin32, | |
49 | +// platform_ex::Invalid, platform_ex::ConvertTime, platform_ex::ToHandle, | |
50 | 50 | // platform_ex::QueryFileNodeID, platform_ex::QueryFileLinks, |
51 | 51 | // platform_ex::QueryFileTime, platform_ex::SetFileTime, |
52 | 52 | // platform_ex::ResolveReparsePoint, platform_ex::DirectoryFindData; |
@@ -274,20 +274,35 @@ | ||
274 | 274 | yunused(fd), yunused(times); |
275 | 275 | ystdex::throw_error(std::errc::function_not_supported, yfsig); |
276 | 276 | #else |
277 | + // XXX: This should at least work in WSL since Windows 10 1809. See | |
278 | + // https://github.com/Microsoft/WSL/issues/1399. | |
277 | 279 | YCL_CallF_CAPI(, ::futimens, fd, times); |
278 | 280 | #endif |
279 | 281 | } |
280 | 282 | |
283 | +//! \since build 902 | |
284 | +FileTime | |
285 | +ToFileTime(std::time_t t) ynothrow | |
286 | +{ | |
287 | + // NOTE: Sicne ISO C++20, std::chrono::system_clock is specified to measure | |
288 | + // UNIX time. This is still true before ISO C++20 for supported platforms | |
289 | + // other than %YCL_Win32 here, which makes the system time directly usable | |
290 | + // as the filesystem time. Nevertheless, this is not relied on, except the | |
291 | + // conversion here. | |
292 | + // TODO: Use ISO C++20 %std::chrono::file_time equivalence. | |
293 | + return std::chrono::system_clock::from_time_t(t).time_since_epoch(); | |
294 | +} | |
295 | + | |
281 | 296 | //! \since build 631 |
282 | 297 | //@{ |
283 | 298 | const auto get_st_atime([](struct ::stat& st){ |
284 | - return FileTime(st.st_atime); | |
299 | + return ToFileTime(st.st_atime); | |
285 | 300 | }); |
286 | 301 | const auto get_st_mtime([](struct ::stat& st){ |
287 | - return FileTime(st.st_mtime); | |
302 | + return ToFileTime(st.st_mtime); | |
288 | 303 | }); |
289 | 304 | const auto get_st_matime([](struct ::stat& st){ |
290 | - return array<FileTime, 2>{FileTime(st.st_mtime), FileTime(st.st_atime)}; | |
305 | + return array<FileTime, 2>{ToFileTime(st.st_mtime), ToFileTime(st.st_atime)}; | |
291 | 306 | }); |
292 | 307 | //@} |
293 | 308 | #endif |
@@ -488,6 +503,7 @@ | ||
488 | 503 | { |
489 | 504 | #if YCL_DS |
490 | 505 | YAssertNonnull(path); |
506 | + yunused(path); | |
491 | 507 | ystdex::throw_error(std::errc::function_not_supported, yfsig); |
492 | 508 | #elif YCL_Win32 |
493 | 509 | // TODO: Simplify? |
@@ -916,7 +932,7 @@ | ||
916 | 932 | // empty directories. |
917 | 933 | return CallNothrow({}, [=]{ |
918 | 934 | return CallFuncWithAttr([](const wchar_t* wstr, FileAttributes attr) |
919 | - YB_ATTR_LAMBDA_QUAL(ynothrow, YB_NONNULL(1)){ | |
935 | + YB_ATTR_LAMBDA_QUAL(ynothrow, YB_NONNULL(2)){ | |
920 | 936 | return attr & FileAttributes::Directory ? ::_wrmdir(wstr) == 0 |
921 | 937 | : UnlinkWithAttr(wstr, attr); |
922 | 938 | }, path); |
@@ -1,5 +1,5 @@ | ||
1 | 1 | /* |
2 | - © 2009-2016, 2019 FrankHB. | |
2 | + © 2009-2016, 2019-2020 FrankHB. | |
3 | 3 | |
4 | 4 | This file is part of the YSLib project, and may only be used, |
5 | 5 | modified, and distributed under the terms of the YSLib project |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Font.cpp |
12 | 12 | \ingroup Adaptor |
13 | 13 | \brief 平台无关的字体库。 |
14 | -\version r3675 | |
14 | +\version r3680 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 296 |
17 | 17 | \par 创建时间: |
18 | 18 | 2009-11-12 22:06:13 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2019-01-04 11:15 +0800 | |
20 | + 2020-11-03 13:46 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -45,6 +45,7 @@ | ||
45 | 45 | # define YF_Impl_Use_FT_Internal true |
46 | 46 | # include <freetype/internal/internal.h> // for FreeType internal macros; |
47 | 47 | # include FT_INTERNAL_TRUETYPE_TYPES_H // for TT_Face, TT_FaceRec_; |
48 | +# include <ystdex/type_pun.hpp> // for ystdex::aligned_cast; | |
48 | 49 | #endif |
49 | 50 | |
50 | 51 | using namespace ystdex; |
@@ -266,6 +267,7 @@ | ||
266 | 267 | } |
267 | 268 | } |
268 | 269 | Typeface::SmallBitmapData::SmallBitmapData(SmallBitmapData&& sbit_dat) |
270 | + ynothrow | |
269 | 271 | : width(sbit_dat.width), height(sbit_dat.height), left(sbit_dat.left), |
270 | 272 | top(sbit_dat.top), format(sbit_dat.format), max_grays(sbit_dat.width), |
271 | 273 | pitch(sbit_dat.pitch), xadvance(sbit_dat.xadvance), |
@@ -324,7 +326,8 @@ | ||
324 | 326 | // XXX: Hack for using %ttmtx.c and %sfobjs.c of FreeType 2.4.11. |
325 | 327 | if(FT_IS_SFNT(face)) |
326 | 328 | { |
327 | - const auto ttface(reinterpret_cast<::TT_Face>(face)); | |
329 | + // XXX: Downcast. | |
330 | + const auto ttface(ystdex::aligned_cast<::TT_Face>(face)); | |
328 | 331 | |
329 | 332 | // NOTE: See %Typeface::SmallBitmapData::SmallBitmapData. |
330 | 333 | // NOTE: %sfnt_done_face in "sfobjs.c" still releases vertical metrics. |
@@ -7,9 +7,21 @@ | ||
7 | 7 | . SHBuild-common.sh |
8 | 8 | SHBuild_CheckHostPlatform |
9 | 9 | SHBuild_AssertNonempty SHBuild_Host_Platform |
10 | -: "${SHBuild_AppBaseDir:="$(dirname "$0")/../build/$SHBuild_Host_Platform"}" | |
10 | +# XXX: %SHBuild_BuildDir is external. | |
11 | +# shellcheck disable=2154 | |
12 | +if [[ "$SHBuild_BuildDir" != '' ]]; then | |
13 | + : "${SHBuild_AppBaseDir:="$SHBuild_BuildDir"}" | |
14 | +else | |
15 | + : "${SHBuild_AppBaseDir:="$(dirname "$0")/../build/$SHBuild_Host_Platform"}" | |
16 | +fi | |
11 | 17 | mkdir -p "$SHBuild_AppBaseDir" |
12 | 18 | SHBuild_AppBaseDir="$(cd "$SHBuild_AppBaseDir"; pwd)" |
19 | +: "${SHBuild_SystemPrefix:=$(SHBuild_GetSystemPrefix "$SHBuild_Host_Platform")}" | |
20 | +# XXX: %SHBuild_Sysroot is external. | |
21 | +# shellcheck disable=2154 | |
22 | +if [[ "$SHBuild_SysRoot" != '' ]]; then | |
23 | + export SHBuild_Bin="$SHBuild_SysRoot$SHBuild_SystemPrefix/bin" | |
24 | +fi | |
13 | 25 | # shellcheck source=../Tools/Scripts/SHBuild-BuildApp.sh |
14 | 26 | . SHBuild-BuildApp.sh "$@" |
15 | 27 | SrcDir=$(cd "$(dirname "$0")"; pwd) |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file ChangeLog.V0.9.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 版本更新历史记录 - V0.9 。 |
14 | -\version r592 | |
14 | +\version r821 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 800 |
17 | 17 | \par 创建时间: |
18 | 18 | 2020-10-12 17:19:23 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-25 09:04 +0800 | |
20 | + 2020-11-09 18:09 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -34,6 +34,236 @@ | ||
34 | 34 | ( |
35 | 35 | / %YBase.YStandardEx $= |
36 | 36 | ( |
37 | + / DLI "simplified and optimized function template %extract#1" @ %String, | |
38 | + + "function template %flush_input" @ %StreamBuffer | |
39 | + ), | |
40 | + / %YFramework $= | |
41 | + ( | |
42 | + / %YCLib $= | |
43 | + ( | |
44 | + / %FileSystem $= | |
45 | + ( | |
46 | + / DLDI @ "platform %DS" @ "function %ReadLink#1" ^ 'yunused', | |
47 | + // To eliminate G++ warning: [-Wunuwed-variable]. | |
48 | + * "wrong %FileTime conversion from %::time_t" | |
49 | + @ !"platform %Win32" @ "functions %(GetFileAccessTimeOf, \ | |
50 | + GetFileModificationTimeOf, \ | |
51 | + GetFileModificationAndAccessTimeOf)" $orig (@ | |
52 | + "member %FileDescriptor::GetModificationTime" $since b624) | |
53 | + ), | |
54 | + + "function %StreamGet" @ %FileIO ^ $dep_from | |
55 | + ("%ystdex::flush_input" @ %YBase.YStandardEx.StreamBuffer) | |
56 | + ), | |
57 | + / %YSLib.Adaptor $= | |
58 | + ( | |
59 | + + 'using platform::StreamGet;' @ %YAdaptor | |
60 | + $dep_from ("%StreamGet" @ %YCLib.FileIO), | |
61 | + // See $2020-10 @ %Documentation::Workflow. | |
62 | + / DLDI @ "class %Typeface" @ %Font $= | |
63 | + ( | |
64 | + + 'ynothrow' @ "internal bitmap data", | |
65 | + / "destructor" ^ "%ystdex::aligned_cast" ~ 'reinterpret_cast' | |
66 | + ) | |
67 | + ), | |
68 | + / %NPL $= | |
69 | + ( | |
70 | + / @ "function %LoadModule_SHBuild" @ %Dependency $= | |
71 | + ( | |
72 | + * "missing basic hook adjustment" $since b901 | |
73 | + $= (/ $impl ^ "%REPLContext::GetOutputStreamRef" | |
74 | + ~ "%std::prinf"), | |
75 | + / "applicative %SHBuild_EchoVar returned '#inert'" | |
76 | + ), | |
77 | + / "base class %InvalidSyntax" @ "class %ParameterMismatch" @ %NPLA | |
78 | + -> "%ListTypeError", | |
79 | + // Now exceptions from %ThrowInsufficientTermsError \ | |
80 | + and %ListTypeError can be caught together. | |
81 | + / %NPLA1 $= | |
82 | + ( | |
83 | + / "function %ThrowValueCategoryError" | |
84 | + -> "%ThrowValueCategoryError", | |
85 | + // This is more general, although at current all the uses \ | |
86 | + are still for the cases of 1st argument. | |
87 | + + "function %ThrowListTypeErrorForNonlist", | |
88 | + / ThrowListTypeErrorForInvalidType | |
89 | + * "missing check for list of arguments" | |
90 | + @ "functions %(MatchParameter, BindParameter)" | |
91 | + $orig (@ "function %BindParameter" $since b777) | |
92 | + $= (/ "checked to throw %ListTypeError on failure" | |
93 | + ^ $dep_from "%ThrowListTypeErrorForNonlist"), | |
94 | + // This is for the case like a parameter subterm '(.x)' \ | |
95 | + matching a non-list argument. | |
96 | + / DLI "avoided deprecated lambda capture '=' with implicit \ | |
97 | + 'this'" @ "functions %(BindParamater, MatchParameter)" | |
98 | + // To eliminate Clang++ 10 warning: \ | |
99 | + [-Wdeprecated-this-capture]. | |
100 | + ), | |
101 | + / %NPLA1Forms $= | |
102 | + ( | |
103 | + ( | |
104 | + / $forced "removed 'for the 1st argument'" @ "error messages" | |
105 | + @ "functions %(FirstAt, FirstRef, SetFirst, SetFirstAt, \ | |
106 | + SetFirstRef, SetRest, SetRestRef, CheckListReference)" | |
107 | + $dep_from "%ThrowValueCategoryError"; | |
108 | + / $comp "possible wrong 'for the 1st argument'" | |
109 | + @ "message" @ "function %CheckListReference" $since b855 | |
110 | + // The corresponding applicative is for the general case, \ | |
111 | + rather than only for the 1st argument. | |
112 | + ), | |
113 | + / "removed 'for the 2nd argument" @ "exception message" | |
114 | + @ "functions %(SetRest, SetRestRef)" | |
115 | + ^ $dep_from ("%ThrowListTypeErrorForNonlist" @ %NPLA1), | |
116 | + // This is consistent to the change above. It also enables \ | |
117 | + the possibility to be reused with other cases. | |
118 | + * $impl "redundant 'YF_API' on entity without external linkage" | |
119 | + $since b899 $dep_to "Clang++ compiling error" | |
120 | + // Also to prevent Clang++ error. | |
121 | + ) | |
122 | + ), | |
123 | + * $re_add(b896) "wrong 'YB_NONNULL(1)'" @ ("lambda-expression" | |
124 | + @ "platform %Win32" @ "function %uremove" @ %FileSystem $orig | |
125 | + (@ %FileIO $since b639), "member function %DirectoryFindData::Read" | |
126 | + @ %'YCLib_(Win32)'.MinGW32 $since b701) | |
127 | + $dep_to "Clang++ compiling error" | |
128 | + $= (/ $impl 'YB_NONNULL(1)' -> 'YB_NONNULL(2)') | |
129 | + // Also to prevent Clang++ error. | |
130 | + ), | |
131 | + / %Tools $= | |
132 | + ( | |
133 | + / "improved basic terminal hook and string printing" @ %SHBuild.Main | |
134 | + ^ "%(std::cout, YSLib::IO::StreamPut, ystdex::write_literal)" | |
135 | + ~ "%std::(printf, puts)", | |
136 | + // See $2020-10 @ %Documentation::Workflow. | |
137 | + / %Scripts $= | |
138 | + ( | |
139 | + ( | |
140 | + - "%AR setting" @ "%SHBuild-common-options.sh", | |
141 | + + "default value" @ "%AR" @ "%SHBuild-common-toolchain.sh" | |
142 | + ^ "detection"; | |
143 | + / @ "%SHBuild-BuildApp.sh" $= | |
144 | + ( | |
145 | + - "%AR setting"; | |
146 | + * "%AR overriden from the environment not used" | |
147 | + $orig (@ "%SHBuild-appconf.sh" $since b546) | |
148 | + ) | |
149 | + ), | |
150 | + / "Clang++ detection" @ "%SHBuild-BuildApp.txt" | |
151 | + ^ "%SHBuild_CheckCXX" ~ 'rmatch?', | |
152 | + // This is more accurate, but a bit inefficiet. | |
153 | + / "improved thread detection and distinguished thread flags \ | |
154 | + for %CXXFLAGS and %LDFLAGS" $= | |
155 | + ( | |
156 | + // MinGW Clang++ supports '-mthreads' at the linker command, \ | |
157 | + but not the compiler command. | |
158 | + / "improved detection" @ "%SHBuild-common-toolchain.sh", | |
159 | + / @ "%SHBuild-YSLib-common.txt" $= | |
160 | + ( | |
161 | + / "functions ('get-thread-option', \ | |
162 | + 'get-thread-option-silent') | |
163 | + -> ('get-thread-options', 'get-thread-options-silent'); | |
164 | + * $comp "thread flags detection" | |
165 | + $orig (@ "%SHBuild-common-toolchain.sh" $since b791) | |
166 | + // This was not consistent to the original \ | |
167 | + %SHBuild-common-options.sh since then. | |
168 | + ); | |
169 | + / "default value" @ "%LDFLAGS" ^ "thread-specific flags" | |
170 | + @ "(%SHBuild-common-toolchain.sh, \ | |
171 | + SHBuild-YSLib-common.txt)"; | |
172 | + - "redundant system library option '-lpthread'" | |
173 | + $effective @ ("%(SHBuild-BuildApp.sh, \ | |
174 | + SHBuild-BuildApp.txt, SHBuild-YSLib-build.txt)") | |
175 | + ), | |
176 | + / "improved support for LLVM-based toolchains" | |
177 | + @ "%(SHBuild-common-toolchain.sh, SHBuild-YSLib-common.txt)" | |
178 | + $= | |
179 | + ( | |
180 | + / "refined options to supported LLD as the linker"; | |
181 | + + "stub to enable LLD for Clang++" @ "platform %Win32" | |
182 | + ), | |
183 | + / @ "%SHBuild-YSLib-common.txt" $= | |
184 | + ( | |
185 | + + "%AR detection", | |
186 | + // This is consistent with %SHBuild-common-toolchain.sh. | |
187 | + + "'lib' prefix" @ "installed import library names", | |
188 | + // This already works without the prefix. Now the names \ | |
189 | + are more consistent to Cygwin and MSYS2. | |
190 | + / "simplified" @ "%LD not used in the command" $= | |
191 | + ( | |
192 | + / "disabled showing %LDFLAG"; | |
193 | + / DLI "disabled unused 'LDFLAGS*' and 'LIBS*' settings" | |
194 | + ), | |
195 | + + "real import library installation support" | |
196 | + // See $2020-11 @ %Documentation::Workflow. | |
197 | + ), | |
198 | + / @ "%SHBuild-YSLib-build.txt" $= | |
199 | + ( | |
200 | + / DLDI "simplified 'system-quote' with 'SHBuild_2m' calls", | |
201 | + / "YSLib libraries building" $= | |
202 | + ( | |
203 | + / DLDI "removed unused %LIBS restoring", | |
204 | + * $re_add(b838) "possibly missing quotes on '-L' argument \ | |
205 | + of output directory on the %LIBS environment" | |
206 | + $since b796 ^ 'system-quote', | |
207 | + + "import library generation", | |
208 | + * "missing compiler check" @ "workaround specific for G++" | |
209 | + $since b900 | |
210 | + // The option '-fno-var-tracking-assignments' is not \ | |
211 | + compatible to Clang++. | |
212 | + ), | |
213 | + / $forced DLDI "library installation" | |
214 | + $dep_from ("real import library installation support" | |
215 | + @ "%SHBuild-YSLib-common.txt") | |
216 | + // See $2020-11 @ %Documentation::Workflow. | |
217 | + ), | |
218 | + / "disabled LTO for Clang++" @ "%(SHBuild-YSLib-common.txt, \ | |
219 | + SHBuild-common-options.sh)" $dep_to "cross-compiler ABI fix", | |
220 | + // LLD seems the only option to recognize the LLVM bitcode, \ | |
221 | + but the final linking still does not work. Note this is \ | |
222 | + directly fixed in the common scripts. | |
223 | + ( | |
224 | + / DLI "simplified quotes in path not following ','" | |
225 | + ^ "simplified 'system-quote' with 'SHBuild_2m' calls" | |
226 | + $effective @ "%(SHBuild-YSLib-build.txt, SHBuild-Buildapp.txt)"; | |
227 | + * $comp "wrong normalization of path" @ "%LIBS" | |
228 | + @ "%SHBuild-BuildApp.txt" | |
229 | + $orig (@ "%SHBuild-BuildApp.sh" $since b563) | |
230 | + ), | |
231 | + * $comp "wrong normalization of path" @ "%LIBS" | |
232 | + @ "%SHBuild-BuildApp.sh" $since b563 | |
233 | + (/ $impl ^ 'SHBuild_2m' ~ 'SHBuild_2w') | |
234 | + ) | |
235 | + ), | |
236 | + ( | |
237 | + * "missing fat LTO object support" @ "%(Makefile.mingw, Makefile.gnu)" | |
238 | + @ "%3rdparty/FreeImage" $since b900; | |
239 | + / $forced "rebuilt library %FreeImage for %release configurations" | |
240 | + @ "platform %(MinGW32, MinGW64, Linux)" $dep_to "cross-compiler ABI fix" | |
241 | + ), | |
242 | + * $comp "Clang++ build issues" $since b639 $= | |
243 | + ( | |
244 | + * "Clang++ compiling error" @ "platform %Win32" $since b639, | |
245 | + * $comp "Clang++ linking broken" $since b900 | |
246 | + $dep_all_from "cross-compiler ABI fix", | |
247 | + // Currently fat LTO objects are the only way to support both G++ \ | |
248 | + and Clang++ with probably partial LTO support in some \ | |
249 | + confiugrations. | |
250 | + ), | |
251 | + / "make %C_LTO overridable" $effective @ "all makefiles" | |
252 | + @ "%3rdparty/FreeImage", | |
253 | + / @ "%SHBuild-YSTest.sh" @ "project %YSTest" $= | |
254 | + ( | |
255 | + / "checked %SHBuild_BuildDir to override application base directory" | |
256 | + / "checked %SHBuild_SystemPrefix and %SHBuild_SysRoot to set and \ | |
257 | + export %SHBuild_Bin" | |
258 | + // This allows overriding of %$SHBuild_SysRoot to determine \ | |
259 | + different Sysroot directory and build directory being used. | |
260 | + ) | |
261 | +), | |
262 | + | |
263 | +b901 | |
264 | +( | |
265 | + / %YBase.YStandardEx $= | |
266 | + ( | |
37 | 267 | + $re_ex(b178) $dev $lib "#pragma directive" |
38 | 268 | @ 'YB_IMPL_GNUCPP >= 100000' @ "metafunction \ |
39 | 269 | %have_common_nonempty_virtual_base" @ %TypeOperation, |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file NPL.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief NPL 规范和实现规格说明。 |
14 | -\version r17309 | |
14 | +\version r17316 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 304 |
17 | 17 | \par 创建时间: |
18 | 18 | 2012-04-25 10:34:20 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-21 10:50 +0800 | |
20 | + 2020-11-03 13:15 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -2659,11 +2659,11 @@ | ||
2659 | 2659 | 其它 NPL 异常都从此类直接或间接派生,包括: |
2660 | 2660 | NPL::TypeError |
2661 | 2661 | NPL::ValueCategoryMismatch |
2662 | +NPL::ListReductionFailure | |
2662 | 2663 | NPL::ListTypeError 列表类型(@5.4.2.1) 错误。 |
2663 | -NPL::ListReductionFailure | |
2664 | -NPL::InvalidSyntax | |
2665 | 2664 | NPL::ParameterMismatch |
2666 | 2665 | NPL::ArityMismatch |
2666 | +NPL::InvalidSyntax | |
2667 | 2667 | NPL::BadIdentifier |
2668 | 2668 | NPL::InvalidReference |
2669 | 2669 | 除 @6.2.2 外,NPLA 实现可能抛出这些异常或派生实现定义的派生这些类的其它异常。 |
@@ -2697,6 +2697,7 @@ | ||
2697 | 2697 | NPL::TermToStringWithReferenceMark |
2698 | 2698 | NPL::TermToTags |
2699 | 2699 | NPL::ThrowListTypeErrorForInvalidType |
2700 | +NPL::ThrowListTypeErrorForNonlist | |
2700 | 2701 | NPL::TokenizeTerm |
2701 | 2702 | NPL::TryAccessLeaf |
2702 | 2703 | NPL::TryAccessTerm |
@@ -3092,7 +3093,7 @@ | ||
3092 | 3093 | A1::ThrowInvalidSyntaxError |
3093 | 3094 | A1::ThrowNonmodifiableErrorForAssignee |
3094 | 3095 | A1::ThrowUnsupportedLiteralError |
3095 | -A1::ThrowValueCategoryErrorForFirstArgument | |
3096 | +A1::ThrowValueCategoryError | |
3096 | 3097 | |
3097 | 3098 | @7.4 规约实现: |
3098 | 3099 | NPLA1 在 NPL::A1 中提供不同粒度的规约和求值实现 API 。 |
@@ -4252,7 +4253,7 @@ | ||
4252 | 4253 | <bindings> :元素为 <binding> 的列表,形式为 (<binding>...) 。 |
4253 | 4254 | <body> :出现在元素的末尾 <expressions>? 形式,用于函数体(@8.4.5) 等替换求值的目标。 |
4254 | 4255 | <expression-sequence> :同 <body> 但蕴含顺序求值。 |
4255 | -求值 <expression-sequence> 的结果被定义为求值其最后一个子表达式(若存在)的结果,或当不存在子表达式时为 #inert 。 | |
4256 | +求值 <expression-sequence> 的结果被定义为求值其最后一个子表达式(若存在)的结果,或当不存在子表达式时为未指定值(@7.2.2)。 | |
4256 | 4257 | <consequent> :同 <expression> ,仅用于 <test> 求值为 #t 时。 |
4257 | 4258 | <alternate> :同 <expression> ,仅用于 <test> 求值不为 #t 时。 |
4258 | 4259 | <definiend> :被绑定项的目标,是包含符号的 DAG(@4.2.4) 表达式。详见 @7.7.3 。 |
@@ -4736,8 +4737,9 @@ | ||
4736 | 4737 | 类似 Kernel ,谓词的名称使用 ? 结尾,除 <- 结尾外的用于(不直接通过求值操作数或其子表达式产生的副作用的)修改(@9.4.5.1) 的(同时是改变操作(@4.1.4.2) )函数的名称使用 ! 结尾。 |
4737 | 4738 | 和 Kernel 类似,管理状态(@9.4.5.1) 的变化不需要指示可修改;此外,类似地,不改变可观察行为(@4.1.3) 的隐藏状态的修改不属于上述可修改。 |
4738 | 4739 | 和 Kernel 不同,不使用以上可修改的操作仍可引起对象修改,如隐式的转移操作(@9.4.5.1.2) 。 |
4739 | -和谓词使用惰性(inert) 值的 Kernel 不同,后者的结果是未指定值(@7.2.2)。 | |
4740 | +和使用可用谓词 inert? 判断的惰性(inert) 值的 Kernel 不同,后者的结果是未指定值(@7.2.2) 。 | |
4740 | 4741 | 未指定值的类型未指定,因此用于修改的函数可能返回 A1::ValueToken::Unspecified(@7.2.2) 外的其它值;但应满足 @10.2 。 |
4742 | +作为一等实体的未指定值和 Kernel 类似,仍为 #inert(@9.3.1) ,但不提供谓词判断其类型。 | |
4741 | 4743 | 除去以上后缀,以引用标记字符(@7.7.3.4) 结尾的表示涉及引用的操作。 |
4742 | 4744 | 一些操作以结尾引用标记字符和不以引用标记字符结尾的名称提供多个版本。其中不含结尾的引用标记字符的表示操作的结果不是引用值,要求按值传递(@8.4.5.4) 。 |
4743 | 4745 | 其它一些操作可能只提供以 % 结尾的版本。 |
@@ -11,13 +11,13 @@ | ||
11 | 11 | /*! \file Workflow.txt |
12 | 12 | \ingroup Documentation |
13 | 13 | \brief 工作流汇总报告。 |
14 | -\version r3935 | |
14 | +\version r3964 | |
15 | 15 | \author FrankHB <frankhb1989@gmail.com> |
16 | 16 | \since build 433 |
17 | 17 | \par 创建时间: |
18 | 18 | 2013-07-31 01:27:41 +0800 |
19 | 19 | \par 修改时间: |
20 | - 2020-10-24 07:33 +0800 | |
20 | + 2020-11-09 13:21 +0800 | |
21 | 21 | \par 文本编码: |
22 | 22 | UTF-8 |
23 | 23 | \par 模块名称: |
@@ -2060,7 +2060,7 @@ | ||
2060 | 2060 | This is caused by the upstream change of value of 'NAME_MAX' macro in the header <sys/syslimit.h>. |
2061 | 2061 | The value previously in devkitARM r44 (as used by b611) is 768, and was changed to 255. |
2062 | 2062 | See https://github.com/devkitPro/newlib/commit/770821c9e4745d69c2df69624f0e4b1f759ecfb6. |
2063 | - The value of 'platform::FAT::LFN::MaxMBCSLength' is adapted in 'YCLib.FileSystem' for 2 reasons: | |
2063 | + The value of 'platform::FAT::LFN::MaxMBCSLength' is adapted in YFramework module YCLib::FileSystem for 2 reasons: | |
2064 | 2064 | To make the static assertion in 'YCLib_(DS).DSIO' happy, otherwise it does not compile. |
2065 | 2065 | To make the actual limitation sane, otherwise the length error condition is wrong. |
2066 | 2066 | The value of 'platform::FAT::LFN::MaxLength' (for UCS-2 sequence) is also changed to keep it not greater than length of converted MBCS. |
@@ -3475,7 +3475,7 @@ | ||
3475 | 3475 | The 'list::erase' implementation for range is optimized to the 'clear()' case check (like Microsoft VC++) and have less update to pointers otherwise. |
3476 | 3476 | The necessity for the previous builds is from the fact that 'std::list' implementation in libstdc++ on the Android configurations (with CrystaX) are still not conforming to C++11, and it breaks 'NPL::TermNode' allocator-extended construction in YFramework.NPL.SContext. |
3477 | 3477 | However, since it also needs to fix 'std::stack' (thus, including 'std::deque') if nothing is changed in the client code in YFramework.NPL.SContext, update to the official NDK r20 is planned instead. |
3478 | - The update requires to implemented YCLib.FileIO support for libc++ and a few other fixes, but no need to replace the 'std' types. | |
3478 | + The update requires to implemented YCLib::FileIO support for libc++ and a few other fixes, but no need to replace the 'std' types. | |
3479 | 3479 | YFramework still plans to change to 'ystdex::list' now as it is believed to have better performance (at least in x86_64-linux). |
3480 | 3480 | Another bonus is it supports incomplete value types specified in [WG21 N4510], which is adopted as an ISO C++17 feature. |
3481 | 3481 | This is considered to be used in 'ystdex::pmr::memory_resource' implementations when the pool type was not exposed. Is not the case now. |
@@ -3937,7 +3937,15 @@ | ||
3937 | 3937 | Currently, the bug has effects on the 'SHBuild' tool in the YSLib project. |
3938 | 3938 | This is effected by calls of 'EncodeArg' and 'DecodeArg' since build 561 which had replaced calls of 'MBCSToMBCS' since build 476. |
3939 | 3939 | Client code should also be careful. |
3940 | - In general, client programs should better leave the code pages untouched (without calls to '::SetConsoleCP' and '::SetConsoleOutputCP') unless some encodings are explicitly depended on by design. | |
3940 | + In general, client programs should better leave the code pages untouched (without calls to '::SetConsoleCP' and '::SetConsoleOutputCP') unless some encodings are explicitly depended on by design. | |
3941 | + See also https://dev.to/mattn/please-stop-hack-chcp-65001-27db | |
3942 | + To work around the problem, console API for wide strings should be used if the stream is console-based. | |
3943 | + Results from '::_isatty' and '::GetConsoleMode' disagree. | |
3944 | + See https://alfps.wordpress.com/2011/12/08/unicode-part-2-utf-8-stream-mode/. | |
3945 | + See also klisp source 'ksystem.win32.c'. | |
3946 | + Also note the default logger in YFramework module YCLib::Debug uses console output in Win32. | |
3947 | + The improvement is implemented by 'platform::StreamGet' and 'platform::StreamPut' in YFramework module YCLib::FileIO. | |
3948 | + They are introduced as 'YSLib::IO::StreamGet' and 'YSLib::IO::StreamPut' respectively in YFramework module YSLib::Adaptor::YAdaptor. | |
3941 | 3949 | Command line vector should be use UTF-16 encoding instead of the deprecated ANSI code page. |
3942 | 3950 | For the reasons above, handling of the command line for Win32 platforms is reimplemented in YFramework. |
3943 | 3951 | This is now implemented by getting the platform-specific command line and parsing it according to the initialization of UCRT implementation, exposed by 'platform_ex::ParseCommandArguments' in YFramework module 'YCLib_(Win32).MinGW32'. |
@@ -3948,6 +3956,26 @@ | ||
3948 | 3956 | Since the C++ implementation can be referenced, this is not strictly necessary, in contrast to freestanding environments without aid of CRT (like Rust). |
3949 | 3957 | However, the reimplementation provides better compatibility by avoiding referencing the internal interface of the CRT implementations. |
3950 | 3958 | Note it can also serve to 'YSLib::ArgumentsVector' in module YSLib::Core::YCoreUtility by direct accesses to its member. |
3959 | + SHBuild is adatped to the change using 'platform_ex::ParseCommandArguments' and and 'YSLib::IO::StreamPut'. | |
3960 | + This is now more friendly to the Windows console. | |
3961 | + For input from the standard stream, using of 'YSLib::IO::StreamGet' solves the similar problem in Windows console for input functions | |
3962 | + This at least includes 'system' and 'system-get' in 'std.system' module. | |
3963 | +Import library names being installed are changed. | |
3964 | + Import libraries are simulated by links or copies of the dynamic libraries. | |
3965 | + Whether the libraries are links should be same to the MinGW-style toolchain. | |
3966 | + Although the library names can work without any prefix (by having a name of the dynamic library name with a postfix '.a'), now always have the 'lib' prefix. | |
3967 | + This is more consistent to the current practice like Cygwin and MSYS2. | |
3968 | + Note in such platforms dynamic libraries can have prefix other than 'lib' like 'cyg' or 'msys-' in the name of dynamic library files. | |
3969 | + Also note libraries may or may have the prefix. For example, Qt libraries in MSYS2's MinGW platforms has no 'lib' prefix in the DLL names, but many others have. | |
3970 | + | |
3971 | +$2020-11: | |
3972 | + | |
3973 | +report.impl: | |
3974 | +Import library installation routines are enhanced. | |
3975 | + Now real import libraries instead of links to DLL can be installed on demand. | |
3976 | + This is necessary for linkers not supporting import from DLL on linking. | |
3977 | + For example, LLVM's lld on MinGW32 only supports linking to the import libraries rather than linking to DLLs directly (as ld.bfd). | |
3978 | + This is not enabled now, although lld seems the only option to support LTO objects from Clang++. | |
3951 | 3979 | |
3952 | 3980 | //// |
3953 | 3981 |