C++的跨平台方案(如何解决不带 bom 的 utf8 源文件无法用 vs 编译) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhiqiang
V2EX    C

C++的跨平台方案(如何解决不带 bom 的 utf8 源文件无法用 vs 编译)

  •  
  •   zhiqiang 2017-11-02 21:46:59 +08:00 5574 次点击
    这是一个创建于 2912 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前系统是在 ubuntu 下开发的,整套 gcc/make 工具链已经比较熟悉。

    现在有部分功能想在 windows 下编译运行。首先考虑的是用 visual studio,但有个恶心的问题是,visual studio 要求 utf8 必须要有 bom。linux 下的 utf 源代码到 vs 下编译出现一大堆错误。

    刚刚尝试了 mingw/gcc才发现不支持多线程 mutex 之类的。在网上搜了下,说需要安装 w64 版本。但我看 w64 的 gcc 版本只有 4.8.3,而且还不确定有没有别的问题。

    不知道大家是怎么弄的,我估计大多数人还是用 vs,这时候该如何处理 bom 的问题?

    我想最简单的方法是 git 每次下载文件时自动加上 bom,上传文件时删掉 bom。不知道有没有现成的插件或者配置文件来做这件事情?

    第 1 条附言    2017-11-03 08:39:52 +08:00
    我想最简单的方法是:windows 下处理代码时,git 每次下载文件时自动加上 bom,上传文件时删掉 bom,类似于那个处理 windows 下换行的方法。

    有现成的配置文件来做这个吗?
    第 2 条附言    2017-11-05 21:16:59 +08:00
    多谢各位的出谋划策。

    @forcecharlie 提供的方案 /source-charset:utf-8 选项已测试在 vs2017 上通过。这个完全解决了我的问题。
    42 条回复    2017-11-09 02:13:35 +08:00
    wwqgtxx
        1
    wwqgtxx  
       2017-11-02 21:51:23 +08:00 via iPhone
    mingw64 的 gcc 都已经 7.1 了,你看的是什么古董版本
    wsy2220
        2
    wsy2220  
       2017-11-02 21:53:12 +08:00
    mingw-w64 已经到 gcc 7.2 了, 用 msys2 统一安装即可
    coderluan
        3
    coderluan  
       2017-11-02 21:59:36 +08:00
    C++的跨平台用 Cmake 啊,vs/gcc/icc 啥的都通用。
    missdeer
        4
    missdeer  
       2017-11-02 22:00:39 +08:00
    从来没关注过 BOM 的问题,一直默认就可以
    justou
        5
    justou  
       2017-11-02 22:12:49 +08:00   1
    哪个版本的 VS? 我试了下 VS2015 的, 没有要求 utf8 的源文件必须要有 BOM, 它自己也可以保存为没有 BOM 的 utf8, 但是每个文件都得手动保存(有个自动保存的插件 https://vlasovstudio.com/fix-file-encoding/), 也可以一个脚本全部批量加 BOM 嘛
    wwqgtxx
        6
    wwqgtxx  
       2017-11-03 00:23:37 +08:00
    @justou 如果没有 bom 的话一旦源代码有中文就 cl 会编译错误,但是有 bom 的话,gcc 直接不认
    wevsty
        7
    wevsty  
       2017-11-03 01:02:45 +08:00
    有 BOM 才是最通用的做法。
    带 BOM 的 UTF-8 编码的源码文件在 GCC 上应该是不会编译错误的。不知道你用的是什么古老的版本才会出错。
    lbtinglb
        8
    lbtinglb  
       2017-11-03 02:04:44 +08:00   1
    @wevsty 带 bom 的 UTF-8 官方是不推荐的
    [link]( http://www.unicode.org/versions/Unicode5.0.0/ch02.pdf)
    msg7086
        9
    msg7086  
       2017-11-03 06:27:20 +08:00
    $ pacman -Ss gcc
    mingw32/mingw-w64-i686-gcc 7.2.0-1 (mingw-w64-i686-toolchain)
    GNU Compiler Collection (C,C++,OpenMP) for MinGW-w64
    mingw64/mingw-w64-x86_64-gcc 7.2.0-1 (mingw-w64-x86_64-toolchain) [installed]
    GNU Compiler Collection (C,C++,OpenMP) for MinGW-w64

    嗯?
    snnn
        10
    snnn  
       2017-11-03 08:08:40 +08:00 via Android
    加 bom,或者换 windows 的 codepage
    zhiqiang
        11
    zhiqiang  
    OP
       2017-11-03 08:29:09 +08:00
    @wwqgtxx 我之前看的 http://mingw-w64.org/doku.php/download。我试试 @wsy2220 说的 msys2。这些东西比较乱。
    zhiqiang
        12
    zhiqiang  
    OP
       2017-11-03 08:34:02 +08:00
    @wevsty 不光是 gcc。还有一些别的东西。我不想更改这个。毕竟 Linux 下才是根本,windows 上只是顺带的,不希望变动太多。
    htfy96
        13
    htfy96  
       2017-11-03 08:37:26 +08:00
    记得 gcc 应该可以支持 BOM 吧,WPS 开发人员写过一篇文章 http://bbs.wps.cn/thread-22332423-1-1.html
    dtgio
        14
    dtgio  
       2017-11-03 08:38:05 +08:00 via iPhone
    用脚本加 bom 可以吗?
    yulitian888
        15
    yulitian888  
       2017-11-03 08:40:37 +08:00
    不妨试试升一下 VS2017 ?
    zhiqiang
        16
    zhiqiang  
    OP
       2017-11-03 08:41:15 +08:00
    @htfy96 这个也太复杂了,看着就头晕。。。
    zhidian
        17
    zhidian  
       2017-11-03 08:43:21 +08:00
    用 cmake 生成的 VS 工程, 从来没听说过你这个问题. 在 win, linux, macOS 上都没听过, 给你一个例子: https://git.io/vFZMx
    zhiqiang
        18
    zhiqiang  
    OP
       2017-11-03 08:43:26 +08:00
    @yulitian888 vs2017 支持不带 bom 的 utf8 吗,我搜了一下没说呢。你装了的话帮我试试,注意文件里面要有中文(可以是注释)。
    zhiqiang
        19
    zhiqiang  
    OP
       2017-11-03 08:44:36 +08:00
    @zhidian boost 当然没问题。仅含英文的 utf8 文件当作 ansi 了。要测试的话,要用含中文的 utf8 源代码文件来测试。
    yulitian888
        20
    yulitian888  
       2017-11-03 08:49:17 +08:00
    @zhiqiang 我不做 c++的,所以 VS2017 里没装 c++的部分,不是很确定能不能用。不过在 VS2015 的时候,c#也出现了 BOM 问题,而之前和 2017 版都没有问题。
    wangxn
        21
    wangxn  
       2017-11-03 08:51:18 +08:00 via Android   1
    GCC 当然支持编译带 BOM 的文件了,即使默认不行,加个参数就行。
    但问题是值不值得加这三个二进制字节到一个纯文本文件中去,譬如 Git 这些都支持不好。
    归根到底还是西方话语霸权搞出 UTF-8 这个奇葩来,老老实实用 UCS2 这种(伪)定长编码多好。
    ipwx
        22
    ipwx  
       2017-11-03 08:57:23 +08:00
    @wangxn 定长编码天生和 C 语言的 '\0' 终结符相冲,会造成 tons of trouble。
    justou
        23
    justou  
       2017-11-03 09:10:10 +08:00   1
    @wwqgtxx 对,我就是用无 BOM 的 utf8, cout 了一行字符串, 因为源文件是 utf-8 no BOM 的, 只有在这种情况下 cl 才会按照源文件编码读入字符串字节, 其它情况下似乎都会按照本地编码读入字符串, 除非字符串字面量用 u8 等修饰符(u8"utf8 编码的字面量", c++11), 我用的 notepad++创建的 3 个文件, 内容都是:

    #include <iostream>

    int main()
    {
    std::cout << "VS UTF-8 BOM 问题" << std::endl;
    return 0;
    }

    一个是本地的 cp936 编码, 一个是 utf8 no bom, 另一个 utf8 with bom. 控制台输出分别是:

    cp936: VS UTF-8 BOM 问题

    utf8 no bom: VS UTF-8 BOM (cp936 去解码 utf8 编码的字符串, "问题"乱码了)

    utf8 with bom: VS UTF-8 BOM 问题 (有 bom 的 utf8 字符串字面量还是按照 cp936 的字节读入的,所以正常)

    VS2015 编译没遇到任何错误或警告.

    测试工程: 链接: http://pan.baidu.com/s/1slVyEW9 密码:didy
    mN71eOOprFyMsnPx
        24
    mN71eOOprFyMsnPx  
       2017-11-03 09:16:44 +08:00
    我多年前遇到一样的问题。我的解决办法是,全部文件都是 BOM+UTF8。仅仅发现在 CentOS5 平台默认 gcc 编译有问题,需要删除 BOM。其它 Linux 发行版都没问题,当然 VS 编译也 OK。

    CentOS6/7
    Windows XP/2003/7

    这些平台用 BOM+UTF8 都没问题。
    zhiqiang
        25
    zhiqiang  
    OP
       2017-11-03 09:25:01 +08:00
    @justou 挺奇怪的。含中文 utf8 without bom 在 vs 下 cl 出错,在网上案例很多,我这里也早试过不行。你这个行的话,是不是巧合?

    而且我的源代码里,只有注释有中文,代码其实都没有中文的。
    zhiqiang
        26
    zhiqiang  
    OP
       2017-11-03 09:30:44 +08:00
    @justou 我刚在你的测试样例上试了下,加入中文注释,会出现 warning,但编译还能成功。

    我的工程可能结构比较复杂,编译会直接出错。
    enenaaa
    &nbs;   27
    enenaaa  
       2017-11-03 09:33:19 +08:00
    @zhiqiang vs 编译不带 BOM 的源码文件。遇到 cp936 不存在的字符才会出问题。 好的话是出警告, 也有因为字符识别错误报错的。
    我一般是在中文后面加点换行或英文字符。。
    justou
        28
    justou  
       2017-11-03 09:33:36 +08:00
    @zhiqiang 试了下, 加了注释中文,也没问题(VS2015 企业版 update3). 因为我想在 VS 里面默认保存 no bom utf8 之前在网上搜索过方案, 也找到了(见 5L), 如果连 VS 都不能支持 no bom 的话, 那个插件几乎没啥用了
    forcecharlie
        29
    forcecharlie  
       2017-11-03 09:33:48 +08:00   3
    策略一,使用 UTF-8 Without BOM 但不使用中文注释,字符串资源用 RC 文件保存或者其他。

    当然如果只是注释中有中文,只要不是 /W4 就不会出问题。

    策略二,使用 Visual C++ 2015 or Later 添加参数 /source-charset:utf-8
    https://msdn.microsoft.com/en-us/library/mt708819.aspx
    https://msdn.microsoft.com/en-us/library/mt708821.aspx
    justou
        30
    justou  
       2017-11-03 09:37:39 +08:00
    @enenaaa 对, 像这种警告: warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss, 之前使用一些第三方库时遇到过很多
    wangxn
        31
    wangxn  
       2017-11-03 09:49:18 +08:00 via Android
    @ipwx 这不会造成问题的,C/C++的 wchar_t 就是定长编码。\0 只有在全部字节都是 0 才是有效的,其他情况都是编码的一部分。
    ipwx
        32
    ipwx  
       2017-11-03 10:37:40 +08:00
    @wangxn 问题是一堆历史遗留的库呀~ 如果强行推广 UCS-2,可以预见一堆 PHP 的扩展库、一堆 C/C++ 的第三方库,一堆算法库…… 全都挂掉,都要重写。代价太大,所以还是用了 UTF-8 这种 compatible 模式。
    wwqgtxx
        33
    wwqgtxx  
       2017-11-03 11:15:04 +08:00 via iPhone
    @zhiqiang mingw-w64 的文档更新的很慢,最新版你要去 sf.net 上下
    allenx
        34
    allenx  
       2017-11-03 11:26:34 +08:00
    utf8 with bom 可能更好点,低版本 vs 不支持不带 bom 的 utf8 格式。
    gnaggnoyil
        35
    gnaggnoyil  
       2017-11-03 11:40:19 +08:00   1
    LZ 想要的是不是 git hook?去./.git/hooks 下看看有没有你想要的.
    julykitt
        36
    julykitt  
       2017-11-03 12:07:33 +08:00
    安装 git 的时候又让你选 pull 是 Windows,push 是 Unix 的选项啊。你可以试试
    zsx
        37
    zsx  
       2017-11-03 12:55:57 +08:00
    cl /utf-8
    owt5008137
        38
    owt5008137  
       2017-11-03 13:09:35 +08:00
    1. 写个脚本,全部换成带 BOM
    2. WSL
    3. 我这里的 Mingw64 里是有 mutex 和线程库的
    heliumhgy
        39
    heliumhgy  
       2017-11-03 15:23:28 +08:00 via Android
    msbuild /p:source-charset=utf8 xx.sln
    纯记忆手打。。。
    iobzo
        40
    iobzo  
       2017-11-03 17:42:32 +08:00
    VS 有插件叫 ForceUTF8 nobom
    somebody
        41
    somebody  
       2017-11-03 19:34:18 +08:00
    研究一下 Qt 的源码,Qt 支持你用的所有工具链
    FrankHB
        42
    FrankHB  
       2017-11-09 02:13:35 +08:00
    很明显受到了严重过时信息的干扰。

    直接上 msys2 省事,配 ArchLinux 基本开发环境部署脚本都不怎么需要改。习惯 Ubuntu 的看着办。

    保险起见事前准备阅读理解(也包括线程实现之类的破事):

    https://github.com/FrankHB/pl-docs/blob/master/zh-CN/mingw-vs-mingw-v64.md

    https://bitbucket.org/FrankHB/yslib/wiki/Prerequisitions.zh-CN.md

    要性能好不在乎部署成本 /不要 ABI 兼容不介意做小白鼠可以 https://gcc-mcf.lhmouse.com/

    要对 Win32 的工具友好,纯文本 [文件] 强制要求 UTF-8+BOM+CRLF。(反正像样点的工具都支持这种配置。
    )如果只是用于 cat 的片段,或者是不认识文件头的弱鸡 shell (说你呢 cmd ),一律不使用 BOM。AutoCRLF ……呵呵呵……谁用谁知道。

    WSL 嘛……在 Win32 下互操作挑编辑器(没官方支持,可能编辑完 WSL 没法访问),试了下 EditPlus 可以。另外最近多任务并发看来有些内核层次上导致的 bug。

    Qt 源码之类的就不用浪费时间了。不过其实大多数情况下 VS 当编辑器以外用本身就是浪费时间(暴论)。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2451 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 11:42 PVG 19:42 LAX 04:42 JFK 07:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86