Clang+llvm windows运行环境配置

下了官网Pre-built Binaries:Clang for Windows llvm.org/releases/3.5.0/LLVM-3.5.0-win32.exe 03 Sep 2014 3.5.0

The LLVM Compiler Infrastructure(llvm.org) download LLVMllvm.org/releases/

由于刚刚安装了 TDM GCC 4.9.2 tdm64-gcc-4.9.2-3.exe 2014 December 12th(tdm-gcc.tdragon.net)

mklinkC:\mingw指向tdm64-gcc-4.9.2-3安装目录。

/* hello.c */
#include <stdio.h>

int main() {
  printf("hello world\n");
  return 0;
}

>clang hello.c

hello.c:2:10:fatal error: 'stdio.h' file not found

#include <stdio.h>

         ^

1 error generated.


难道又要下载 LLVM + Clang 源代码,修改 llvm-3.5.0.src\tools\clang\lib\Frontend\下的 InitHeaderSearch.cpp,添加tdm64-gcc-4.9.2-3 C/C++ include search path头文件搜索路径,重新编译一次(具体参看旧文Clang+llvm在windows下面怎么配置运行)。看了3.5.0源码,官网Pre-builtBinaries支持到MiniGW 4.8.2难道每次使用新版 MinGW,都要重复这恼人的编译。


现在,告诉你,只要添加几个环境变量即可。

PATH添加 编译器和LLVM+Clang Command Line Path 命令行运行路径。

至于C/C++ include search path 头文件搜索路径:

使用 MinGW 的,要设置:

C_INCLUDE_PATH

CPLUS_INCLUDE_PATH

使用 Visual C++ 的,要设置:

INCLUDE


当然,如果有附加的链接库

MinGW 设置LIBRARY_PATH

VisualC++ 设置LIB


下面以使用 tdm64-gcc-4.9.2 为例:

Run-Clang.bat

@remset run llvm+clang with mingw path env
@echooff
setMINGW_HOME=c:\mingw
setMINGW_VERSION=4.9.2
set"PATH=%MINGW_HOME%\bin;%PATH%"
set"C_INCLUDE_PATH=%MINGW_HOME%\include;%MINGW_HOME%\x86_64-w64-mingw32\include"
set"CPLUS_INCLUDE_PATH=%C_INCLUDE_PATH%;%MINGW_HOME%\lib\gcc\x86_64-w64-mingw32\%MINGW_VERSION%\include;%MINGW_HOME%\lib\gcc\x86_64-w64-mingw32\%MINGW_VERSION%\include\c++;%MINGW_HOME%\lib\gcc\x86_64-w64-mingw32\%MINGW_VERSION%\include\c++\x86_64-w64-mingw32;%MINGW_HOME%\lib\gcc\x86_64-w64-mingw32\%MINGW_VERSION%\include\c++\backward"
setLLVM_HOME=c:\llvm
set"PATH=%LLVM_HOME%\bin;%PATH%"
%comspec%

转载请注明引用地址 :http://blog.csdn.net/gocad/article/details/42297829 谢谢

如果使用 tdm32-gcc-4.9.2 则

C_INCLUDE_PATH=%MINGW_HOME%\include
CPLUS_INCLUDE_PATH=%MINGW_HOME%\include;%MINGW_HOME%\lib\gcc\mingw32\%MINGW_VERSION%\include;%MINGW_HOME%\lib\gcc\mingw32\%MINGW_VERSION%\include\c++;%MINGW_HOME%\lib\gcc\mingw32\%MINGW_VERSION%\include\c++\mingw32;%MINGW_HOME%\lib\gcc\mingw32\%MINGW_VERSION%\include\c++\backward
使用其它版本 MinGW 的,请根据各版本实际路径设置。当然也可以自己编辑成像vcvars32.bat带参数调用。

VisualC++ 用户调用现成的Visual Studio Native Tools Command Prompt,或自己调用 vcvars32.bat 设置 Visual C++ 命令行编译环境。 或Installing MSVC integration


下面是有些需要注意的地方

关于 m32/-m64, clang, clang++,clang-cl

默认 ( Target: i686-pc-windows-gnu/i686-pc-windows-msvc,Thread model: posix )

m32( Target:i386-pc-windows-gnu/i386-pc-windows-msvc,Thread model: posix )

m64(Target: x86_64-pc-windows-gnu/x86_64-pc-windows-msvc,Thread model: posix )

这与tdm64-gcc-4.9.2默认-m64不同所以要编译 x64 执行代码请显式调用-m64


还有 tdm64-gcc-4.9.2 默认 m64支持 __int128 is supported on thishost. ( 见c++config.h )

如果同时使用 STL algorithm 与 m32,请将 CPLUS_INCLUDE_PATH 中的%MINGW_HOME%\lib\gcc\x86_64-w64-mingw32\%MINGW_VERSION%\include\c++\x86_64-w64-mingw32更改为%MINGW_HOME%\lib\gcc\x86_64-w64-mingw32\%MINGW_VERSION%\include\c++\x86_64-w64-mingw32\32以免编译错误

如果要用Clang+llvm+MinGW编译 32位执行代码,最好还是使用 MinGW(32),避免因使用 MinGW-w64 设置不恰当,而生成的编译错误。

 

Clang具体调用模式与使用的命令参数,请用v命令选项进行追踪

-v    Show commands to run and use verbose output

例如:

D:\>clang++ -v hello.c
clang version 3.5.0 (217039)
Target: i686-pc-windows-gnu
Thread model: posix
clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
 "c:\llvm\bin\clang++.exe" -cc1 -triple i686-pc-windows-gnu -emit-obj -mrelax-al
l -disable-free -main-file-name hello.c -mrelocation-model static -mdisable-fp-e
lim -fmath-errno -masm-verbose -mconstructor-aliases -target-cpu pentium4 -v -dw
arf-column-info -resource-dir "c:\\llvm\\bin\\..\\lib\\clang\\3.5.0" -c-isystem
"c:\\mingw\\include" -c-isystem "c:\\mingw\\x86_64-w64-mingw32\\include" -cxx-is
ystem "c:\\mingw\\include" -cxx-isystem "c:\\mingw\\x86_64-w64-mingw32\\include"
 -cxx-isystem "c:\\mingw\\lib\\gcc\\x86_64-w64-mingw32\\4.9.2\\include" -cxx-isy
stem "c:\\mingw\\lib\\gcc\\x86_64-w64-mingw32\\4.9.2\\include\\c++" -cxx-isystem
 "c:\\mingw\\lib\\gcc\\x86_64-w64-mingw32\\4.9.2\\include\\c++\\x86_64-w64-mingw
32" -cxx-isystem "c:\\mingw\\lib\\gcc\\x86_64-w64-mingw32\\4.9.2\\include\\c++\\
backward" -fdeprecated-macro -fdebug-compilation-dir "D:\\" -ferror-limit 19 -fm
essage-length 80 -mstackrealign -fno-use-cxa-atexit -fobjc-runtime=gcc -fcxx-exc
eptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o "C:\\Temp\
\hello-0a5974.o" -x c++ hello.c
clang -cc1 version 3.5.0 based upon LLVM 3.5.0 default target i686-pc-windows-gnu
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.0"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.0/x86_64-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.0/i686-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.0/backward"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.1"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.1/x86_64-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.1/i686-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.1/backward"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.2"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.2/x86_64-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.2/i686-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.2/backward"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.3"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.3/x86_64-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.3/i686-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.7.3/backward"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.0"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.0/x86_64-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.0/i686-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.0/backward"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.1"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.1/x86_64-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.1/i686-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.1/backward"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.2"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.2/x86_64-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.2/i686-w64-mingw32"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0/../../../include/
c++/4.8.2/backward"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.0/include/c++"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.0/include/c++/mingw32"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.0/include/c++/backward"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.1/include/c++"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.1/include/c++/mingw32"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.1/include/c++/backward"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.2/include/c++"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.2/include/c++/mingw32"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.2/include/c++/backward"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.3/include/c++"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.3/include/c++/mingw32"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.7.3/include/c++/backward"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.0/include/c++"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.0/include/c++/mingw32"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.0/include/c++/backward"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.1/include/c++"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.1/include/c++/mingw32"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.1/include/c++/backward"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.2/include/c++"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.2/include/c++/mingw32"
ignoring nonexistent directory "c:/MinGW/lib/gcc/mingw32/4.8.2/include/c++/backward"
ignoring nonexistent directory "/usr/include/c++/4.4"
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0\../../../i686-w64
-mingw32/include"
ignoring nonexistent directory "c:\llvm\bin\..\lib\clang\3.5.0\../../../x86_64-w
64-mingw32/include"
ignoring nonexistent directory "/mingw/include"
ignoring nonexistent directory "/usr/include"
ignoring duplicate directory "c:\mingw\include"
#include "..." search starts here:
#include <...> search starts here:
 c:\mingw\include
 c:\mingw\x86_64-w64-mingw32\include
 c:\mingw\lib\gcc\x86_64-w64-mingw32\4.9.2\include
 c:\mingw\lib\gcc\x86_64-w64-mingw32\4.9.2\include\c++
 c:\mingw\lib\gcc\x86_64-w64-mingw32\4.9.2\include\c++\x86_64-w64-mingw32
 c:\mingw\lib\gcc\x86_64-w64-mingw32\4.9.2\include\c++\backward
 c:\llvm\bin\..\lib\clang\3.5.0\include
 c:\llvm\bin\..\lib\clang\3.5.0\../../../include
End of search list.
 "c:\mingw\bin\g++.exe" -v -m32 -o a.out "C:\\Temp\\hello-0a5974.o"
Using built-in specs.
COLLECT_GCC=c:\mingw\bin\g++.exe
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/x86_64-w64-mingw32/4.9.2/lto-wra
pper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-4.9.2/configure --build=x86_64-w64-mingw32 --e
nable-targets=all --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable
-libgomp --enable-lto --enable-graphite --enable-cxx-flags=-DWINPTHREAD_STATIC -
-disable-build-with-cxx --disable-build-poststage1-with-cxx --enable-libstdcxx-d
ebug --enable-threads=posix --enable-version-specific-runtime-libs --enable-full
y-dynamic-string --enable-libstdcxx-threads --enable-libstdcxx-time --with-gnu-l
d --disable-werror --disable-nls --disable-win32-registry --prefix=/mingw64tdm -
-with-local-prefix=/mingw64tdm --with-pkgversion=tdm64-1 --with-bugurl=http://td
m-gcc.tdragon.net/bugs
Thread model: posix
gcc version 4.9.2 (tdm64-1)
COMPILER_PATH=c:/mingw/bin/../libexec/gcc/x86_64-w64-mingw32/4.9.2/;c:/mingw/bin
/../libexec/gcc/;c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x8
6_64-w64-mingw32/bin/
LIBRARY_PATH=c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/32/;c:/mingw/bin/.
./lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/lib/../lib32/;
c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/;c:/mingw/bin/../lib/gcc/;C:/Mi
nGW/lib/;D:/dev/msys64/usr/lib/;c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2
/../../../../x86_64-w64-mingw32/lib/;c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/
4.9.2/../../../
COLLECT_GCC_OPTIONS='-v' '-m32' '-o' 'a.out' '-mtune=generic' '-march=x86-64'
 c:/mingw/bin/../libexec/gcc/x86_64-w64-mingw32/4.9.2/collect2.exe -plugin c:/mi
ngw/bin/../libexec/gcc/x86_64-w64-mingw32/4.9.2/liblto_plugin-0.dll -plugin-opt=
c:/mingw/bin/../libexec/gcc/x86_64-w64-mingw32/4.9.2/lto-wrapper.exe -plugin-opt
=-fresolution=C:\Temp\cc83PMcQ.res -plugin-opt=-pass-through=-lmingw32 -plugin-o
pt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-th
rough=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lp
thread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32
-plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-
opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-th
rough=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-
lmsvcrt -m i386pe --exclude-libs=libpthread.a -Bdynamic -o a.out c:/mingw/bin/..
/lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/lib/../lib32/cr
t2.o c:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-min
gw32/lib/../lib32/crtbegin.o -Lc:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/
32 -Lc:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-min
gw32/lib/../lib32 -Lc:/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2 -Lc:/mingw/
bin/../lib/gcc -LC:/MinGW/lib -LD:/dev/msys64/usr/lib -Lc:/mingw/bin/../lib/gcc/
x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/lib -Lc:/mingw/bin/../li
b/gcc/x86_64-w64-mingw32/4.9.2/../../.. C:\Temp\hello-0a5974.o -Bstatic -lstdc++
 -Bdynamic -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -l
shell32 -luser32 -lkernel32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt c:/min
gw/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/lib/..
/lib32/crtend.o

D:\>


另外就是,关于 --driver-mode 参数:

clang++等效于 clang--driver-mode=g++

clang-cl等效于 clang--driver-mode=cl

--driver-mode可以覆盖内置或默认值:clang-cl --driver-mode=g++ 等效于 clang++

目前,clang-cl 编译 VC x64/amd64 STL algorithm 时,有时会编译不通过,如:

error LNK2019: unresolved external
 symbol __cxa_call_unexpected referenced in function "public: __int64 __cdecl std::_Temp_iterator<long>::_Maxlen(void)" (?_Maxlen@?$_Temp_iterator@J@std@@QEAA_JXZ)
error LNK2001: unresolved external
 symbol __gxx_personality_v0

参考LLVM/Clang On Windows 2013_09my.oschina.net/GIIoOS/blog/165542

下面引自(c.tieba.baidu.com/p/3290080396

关于 LLVM Clang。目前 Clang 在 Windows 下都是基于 MingW 的库,所以编译/链接的时候需要把相应的路径设置好。在我的绿色便携版中都已经设置好了。
llvm-3.5.0.src\tools\clang\tools\driver\driver.cpp
Clang在Windows上呈现有三种实现,一种是使用VisualStudio,一种是Mingw,还有一种是Cygwin,clang用一个参数是驱动模式--driver-mode
driver.cpp
staticconst struct {
const char*Suffix;
const char*ModeFlag;
} suffixes[] = {
{"clang", nullptr },
{"clang++", "--driver-mode=g++" },
{"clang-c++", "--driver-mode=g++" },
{"clang-cc", nullptr },
{"clang-cpp", "--driver-mode=cpp" },
{"clang-g++", "--driver-mode=g++" },
{"clang-gcc", nullptr },
{"clang-cl", "--driver-mode=cl" },
{"cc", nullptr },
{"cpp", "--driver-mode=cpp" },
{"cl" , "--driver-mode=cl" },
{"++", "--driver-mode=g++" },
};
 

下面引自Clang Compiler User’s Manual(clang.llvm.org/docs/UsersManual.html)

X86

The support for X86 (both 32-bit and 64-bit) is considered stable onDarwin (Mac OS X), Linux, FreeBSD, and Dragonfly BSD: it has been tested tocorrectly compile many large C, C++, Objective-C, and Objective-C++ codebases.

On x86_64-mingw32, passing i128(by value)is incompatible with the Microsoft x64 calling convention. You might need totweak WinX86_64ABIInfo::classify() in lib/CodeGen/TargetInfo.cpp.

For the X86 target, clang supports the -m16 command line argument which enables16-bit code output. This is broadly similar to using asm(".code16gcc") with the GNU toolchain.The generated code and the ABI remains 32-bit but the assembler emitsinstructions appropriate for a CPU running in 16-bit mode, with address-sizeand operand-size prefixes to enable 32-bit addressing and operations.

 

MinGW32

Clang works on some mingw32 distributions. Clang assumes directories asbelow;

  • C:/mingw/include
  • C:/mingw/lib
  • C:/mingw/lib/gcc/mingw32/4.[3-5].0/include/c++

On MSYS, a few tests might fail.

MinGW-w64

For 32-bit (i686-w64-mingw32), and 64-bit (x86_64-w64-mingw32), Clangassumes as below;

  • GCC versions 4.5.0 to 4.5.3, 4.6.0 to 4.6.2, or 4.7.0 (for the C++ header search path)
  • some_directory/bin/gcc.exe
  • some_directory/bin/clang.exe
  • some_directory/bin/clang++.exe
  • some_directory/bin/../include/c++/GCC_version
  • some_directory/bin/../include/c++/GCC_version/x86_64-w64-mingw32
  • some_directory/bin/../include/c++/GCC_version/i686-w64-mingw32
  • some_directory/bin/../include/c++/GCC_version/backward
  • some_directory/bin/../x86_64-w64-mingw32/include
  • some_directory/bin/../i686-w64-mingw32/include
  • some_directory/bin/../include

This directory layout is standard for any toolchain you will find on theofficial MinGW-w64 website.

Clang expects the GCC executable “gcc.exe” compiled for i686-w64-mingw32 (or x86_64-w64-mingw32) to be present on PATH.

Some tests might fail on x86_64-w64-mingw32.

clang-cl is an alternative command-line interface to Clang driver,designed for compatibility with the Visual C++ compiler, cl.exe.

To enable clang-cl to find system headers, libraries, and the linker whenrun from the command-line, it should be executed inside a Visual Studio NativeTools Command Prompt or a regular Command Prompt where the environment has beenset up using e.g. vcvars32.bat.

clang-cl can also be used from inside Visual Studio by using an LLVMPlatform Toolset.

转载请注明引用地址 :http://blog.csdn.net/gocad/article/details/42297829 谢谢


猜你喜欢

转载自blog.csdn.net/gocad/article/details/42297829