V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhiqiang
V2EX  ›  C

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

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

    之前系统是在 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
    @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
    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
    FifiLyu
        24
    FifiLyu  
       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
        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
    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   ·   实用小工具   ·   3594 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 10:50 · PVG 18:50 · LAX 02:50 · JFK 05:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.