前言
常见的在Windows系统中开发Linux C/C++程序的方法,是在Windows系统中安装配置Cygwin或MinGW,构建GCC编译环境,然后在Eclipse/CLion等IDE中配置相应的GCC工具链,以此实现在Windows环境中编译运行Linux C/C++程序。
这种方法可用,但也有很多缺陷:
- 安装比较复杂,尤其是如何选择安装组件,对新手上手难度很高;
- 扩展性较差,Linux环境编程往往依赖于很多动态库或者头文件,原生Linux系统如CentOS、Ubuntu都有较好的安装包工具;
这些原因都使得Cygwin/MinGW仅适用于一些较轻量级的编程和调试。对于复杂的开源程序,解决编译问题就足以让人焦头烂额。
时代在进步,开发工具也在发展,Win10推出原生Linux子系统,CLion v2018.3开始支持远程开发。这使得在Windows系统中开发Linux C/C++程序有了新的路线。
下面逐一阐述配置CLion和Linux子系统工具链的相关操作,并尽可能提示可能出现的问题及解决方法。
1 启用Linux子系统
Windows Subsystem for Linux(简称WSL),即Windows环境下的Linux子系统。WSL并非默认启用,请参考《启用Windows10的Linux子系统并安装图形界面》1进行开启。
基本步骤:
- 控制面版中启用Linux子系统功能;
- 设置中启用开发人员模式;
- Windows应用商店安装一个Linux发行版本,下以Ubuntu系统为例。
2 配置Ubuntu子系统
连接CLion和Ubuntu子系统需要对Ubuntu子系统进行一些环境配置,比如开启ssh服务(CLion通过SFTP协议完成远程调试)、安装GCC和CMake环境(CLion依赖的编译工具链)。
2.1 配置apt国内源
使用官方源,软件下载和更新会比较慢,可以参考《Linux——Ubuntu 18.04 LTS更换国内apt更新源》2更换国内源。
基本步骤:
- 备份原官方源
sudo mv /etc/apt/sources.list /etc/apt/sources.list.bk
- 编写新的更新源(以清华源为例)
sudo vi /etc/apt/sources.list
复制以下内容到sources.list
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse
# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-proposed main restricted universe multiverse
保存后退出
- 对新源进行更新
sudo apt-get update
2.2 配置ssh服务
配置ssh服务参考《windows 下使用Linux子系统》3
基本步骤:
- 安装OpenSSH
sudo apt-get install openssh-server
- 修改ssh配置文件
备份原ssh配置文件
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bk
修改ssh配置文件
sudo vi /etc/ssh/sshd_config
编辑调整以下 ssh 相关的设置项
Port 8022 # 更换新的端口
ListenAddress 0.0.0.0 # 去掉前面的'#'
UsePrivilegeSeparation no
PermitRootLogin yes
#StrictModes yes # 在前面加上'#'
PasswordAuthentication yes
更换端口号是必要的,因为Linux子系统与Win10系统使用相同的IP地址,默认端口号可能会与Win10系统的ssh服务产生冲突。
- 生成ssh key
生成host key
sudo ssh-keygen -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key
生成user key
ssh-keygen -t rsa
- 启动ssh服务
sudo /etc/init.d/ssh start
验证ssh服务状态
/etc/init.d/ssh status
确认ssh服务已启动
* sshd is running
- 设置ssh服务自启动
如果不设置ssh服务自启动,每次电脑重启后都需要手动启动Linux子系统ssh服务。
常用的Ubuntu设置ssh服务自启动方法,如“sudo update-rc.d ssh enable”、“sudo systemctl enable ssh”、修改“/etc/rc.d/rc.local”等,均不适用于Linux子系统。
可用的方法参考《Win10 wsl linux子系统ssh服务自启动设置》4
2.3 安装GCC编译环境
sudo apt-get install build-essential
2.4 安装CMake
通过“sudo apt-get install cmake”安装的CMake版本较低,可能不满足开发需求,推荐通过源码编译安装。
基本步骤:
- 下载CMake安装包
到CMake官网选择需要的版本,注意版本不一定选择最新,CLion可能不支持。
wget https://cmake.org/files/v3.14/cmake-3.14.3.tar.gz
- 解压并编译安装
依次执行
tar zxvf cmake-3.14.3.tar.gz
cd cmake-3.14.3/
./bootstrap
make
sudo make install
2.5 配置远程桌面/Xming*
如果有使用Linux子系统图形化界面的需求,可以配置Windows远程桌面连接或Xming,具体请参考《Windows10 Linux子系统安装图形化界面的两种方法及其对比》5
3 配置CLion工具链远程调试Ubuntu子系统程序
CLion从v2018.3版本才开始全面支持远程开发,详情参见release note,因此需要安装v2018.3或更高版本。配置过程参考《使用Clion优雅的完全远程自动同步和远程调试c++》6
3.1 安装CLion
从CLion官网下载Windows版安装包,安装过程不赘述。
3.2 设置编译工具链(Toolchains)
因为是远程调试,CLion的工具链就要配置为远程主机的工具链,而Ubuntu子系统就是我们这个案例中的远程主机。
打开CLion的设置界面(File -> Setings),添加一个工具链,环境选择Rmote Host,也可以选择WSL。其实WSL也算是远程主机,并且远程主机的配置能够完全兼容WSL模式。考虑兼容远程主机调试模式,所以下面以远程主机配置方式配置工具链。
点击右侧图标配置登录信息,Host填localhost或127.0.0.1,端口设置为8022(本文2.2节配置的ssh端口号),设置Ubuntu子系统的用户名和密码。
如果登录证书配置成功会显示Connected,将CMake配置为2.4节中安装的cmake命令路径,软件会自动检测Make和C/C++编译器,如果没有检测到可以自行配置。可以给工具链起一个名字保存。
3.3 设置CMake编译时使用的环境变量(Build)
在CMake页面的Environment栏中填入编译时所依赖的环境变量。注意是Ubuntu系统的环境变量(远程编译时无法加载Ubuntu系统的profile和bashrc等文件)。
为什么要设置编译时环境变量?举个例子,在CMakeList.txt中如果使用find_program()查找一个叫“aocl”的程序。
如果该程序不在默认的PATH搜索路径中,则会在加载CMakeList.txt时报错:
此时,就要按照上面的方法,将此程序的路径添加到PATH环境变量中。
跑个题,如果对ssh环境变量问题感兴趣的朋友,可以参考《ssh连接远程主机执行脚本的环境变量问题》7。但可惜的是,CLion通过ssh调用cmake编译时并不会启动bash或sh,因此无法加载bashrc等文件获取环境变量,因此必须在IDE中进行配置。
3.4 设置远程同步(Deployment)
CLion远程调试的基本原理是将本地工程同步到远程主机,然后使用配置好的远程主机工具链对远程工程进行编译和调试。同时CLion会将远程主机上的依赖头文件同步到本地,以便在本地解析头文件8。默认情况下,CLion将工程同步到/tmp目录下,我们也可以手动配置同步目录( Setings->Deployment)。
- 设置远程主机连接(Connection)
在已经配置好远程主机工具链后,同步的连接默认也是配置好的。如果没有配置,可以手动添加一个连接,注意协议选择SFTP。
- 设置工程映射的路径(Mappings)
Mappings页面可以配置映射路径(Deployment path),注意这个路径是一个相对路径,其父目录由Connection页面的“Root path”指定。
至此CLion的远程编译环境就算是配好了。不出意外,就可以正常编译了。
3.5 设置程序运行时使用的环境变量(Run)
程序编译成功后,运行或调试时可能依赖于某些Ubuntu子系统的环境变量,比如依赖某些动态库(LD_LIBRARY_PATH),或需要调用某些可执行程序(PATH)。基于3.3节中提到的相同原因,我们必须将这些环境变量显式配给CLion。
3.6 设置CLion中使用的Terminal为Ubuntu子系统Terminal*
我们是将CLion安装在Windows系统中的,所以默认情况下,CLion中使用的Terminal就是Windows系统的cmd。如果有需要,我们可以将这个Terminal改为Ubuntu子系统的Terminal。( Setings->Tools->Terminal)
到这里配置就全部完成了~