标签:cpp

以下是与标签 “cpp” 相关联的文章

vscode 编译调试 C++ 单文件代码

安装

  • 安装 vscode
  • 安装插件 c/c++ c/c++ snippets

设置

  • 需要先打开一个目录,以下配置文件生成于该目录的 .vscode 目录下
  • IntelliSense 设置

C-S-p c/cpp: Edit Configurations..

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "D:/mingw540-x64/x86_64-w64-mingw32/include/c++",
                "${workspaceRoot}"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE"
            ],
            "intelliSenseMode": "msvc-x64",
            "browse": {
                "path": [
                    "D:/mingw540-x64/x86_64-w64-mingw32/include/c++",
                    "${workspaceRoot}"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            }
        }
    ],
    "version": 3
}
  • 编译设置

C-S-p Tasks: Configure Task Runner

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "g++ build",
            "type": "shell",
            "command": "g++.exe",
            "args": ["-g","${file}","-o","${file}.exe", "-std=c++1y"], 
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "cpp",
                "fileLocation": ["absolute"],
                "pattern": {
                    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        },
        {
            "taskName": "clang++ build",
            "type": "shell",
            "command": "clang++.exe",
            "args": ["-target", "x86_64-pc-windows-gnu", "-g","${file}","-o","${file}.exe", "-std=c++1y"], 
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "cpp",
                "fileLocation": ["absolute"],
                "pattern": {
                    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error|fatal error):\\s+(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        }
    ]
}
  • 调试设置

Debug -> Start Debugging

{
        "version": "0.2.0",
        "configurations": [
            {
                "name": "(gdb) Launch",
                "type": "cppdbg",
                "request": "launch",
                "program": "${file}.exe",
                "args": [],
                "stopAtEntry": false,
                "cwd": "${workspaceRoot}",
                "environment": [],
                "externalConsole": true,
                "MIMode": "gdb",
                "miDebuggerPath": "gdb.exe",
                "setupCommands": [
                    {
                        "description": "Enable pretty-printing for gdb",
                        "text": "-enable-pretty-printing",
                        "ignoreFailures": true
                    }
                ]
            }
        ]
    }

快捷键

  • 编译 C-S-b
  • 调试 F5

MINGW 和 jni 相关几个问题

生成 jni 头文件方法

# file: src/com/litchi/HelloWord.java
cd src
javah com/litchi/HelloWorld

MINGW 编译 jni 无法被 java 加载问题

因为 dll 中导出的函数签名与 VC 生成的不一致。需要加上编译参数

-Wl,--add-stdcall-alias

用 strip 减小可执行文件大小

动态库 *.so *.dll

可以删除所有符号

strip -s *.so 

静态库 *.a

只能删除调试符号

strp -g --strip-unneeded *.a

windows 下安装 clang5.0

  • 下载 llvm5.0-win64 ,安装到 D:/llvm64-500
  • 下载 MinGW-W64 GCC-5.4.0 x86_64-posix-seh , 安装到 D:/mingw64-540
    • 5.4.0 当前的稳定版本(Qt 当前使用 5.3.0)
    • x86_64 是 64 位版本, i686 是 32 位版本
    • posix 支持 c++11 线程,win32 无 c++11 线程特性
    • clang 默认连接 seh 版本,不能用 sjlj 版本
  • D:/llvm64-500/bin D:/mingw64-540/bin 添加到 PATH 变量
  • 添加下列环境变量

    CC=clang
    CXX=clang++
    CFLAGS=-target x86_64-pc-windows-gnu
    CXXFLAGS=-target x86_64-pc-windows-gnu
    
  • clang3.7 版本之前,不需要设置 CFLAGS CXXFLAGS 编译目标,因为 windows 下仅支持 MinGW 编译工具;clang3.8 版本之后,需要设置编译目标,因为可以支持 MSVC 编译工具,默认编译目标是 i686-pc-windows-msvc 。修改编译目标为 x86_64-pc-windows-gnu .
  • clang 的 -target 编译目标需要在命令行中指定,gcc 可以直接从环境变量中读取。
  • 如果需要 64 位编译环境,则 llvm 和 mingw 都要安装 64 位版本的。
  • 如果是 64 位系统,可以直接安装 llvm 64 位,兼容编译 32 位和 64 位程序
  • 切换 64/32 位编译系统,需要做以下设置(LLVM 使用 64 位,不用切换)
    • 切换环境变量 CFLAGS, CXXFLAGS, LDFLAGS
    • 切换 PATH mingw32-540/mingw64-540
    • clion toolchain 切换 mingw32/mingw64

GCC 多个 lib 同名函数链接冲突问题

问题描述

  • 用 gcc 编译两个动态库 lib1.so lib2.so, 程序 app 链接到这两个动态库
  • lib1.so 中定义了全局变量 var=1 , lib2.so 中定义全局变量 var=2 。即相同变量 var 在不同 lib 中定义值不同。
  • lib1.so 中定义了函数 fun1() { print(var); }
  • lib2.so 中定义了函数 fun2() { func1(); print(var); } , 即 lib2.so 依赖 lib1.so
  • 运行 app,调用 fun1fun2 ,输出 var 的值是相同的。

问题分析

  • gcc 链接时,有个默认规则:当一个符号需要被加入全局符号表时,如果相同的符号名已经存在,则后加入的符号被忽略
  • 用 VC 编译链接这个程序, fun1fun2 会输出不同值: VC 在发现多个依赖库中有同名符号时, 会符号重定义, 而不是默认的选择一个

问题解决

  • 使用编译参数 -fvisibility=hidden ,使所有符号默认不导出
  • 将 fun1 和 fun2 声明为导出符号

    #define MY_API __attribute__((visibility("default")))
    void MY_API fun1();
    void MY_API fun2();
    
  • fun1fun2 可以输出各自 lib 中定义的值。

在 ubuntu server 上搭建 C++ 远程开发环境

  • 安装开发软件

    apt install build-essential
    apt install clang
    apt install cmake
    apt install git
    apt install subversion
    apt install ninja ninja-build
    apt install gcc-multilib g++-multilib lib32z1-dev
    
  • 安装并配置 samba

    apt install samba
    apt install smbclient
    cp /etc/samba/smb.conf /etc/samba/smb.conf.bak
    
    emacs /etc/samba/smb.conf
    
    [share]
      comment = Share Folder require password
      browseable = yes
      path = /home/share
      create mask = 0777
      directory mask = 0777
      valid users = share
      force user = nobody
      force group = nogroup
      public = yes
      writable = yes
      available = yes
    
    groupadd share -g 6000
    useradd share -u 6000 -g 6000 -s /sbin/nologin -d /dev/null
    smbpasswd -a share
    
    mkdir /home/share
    chmod 777 /home/share
    /etc/init.d/smbd restart