mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-03-21 02:10:11 +08:00
Merge branch 'master' of https://github.com/LCTT/TranslateProject
This commit is contained in:
commit
0225c7ef96
288
published/20210514 Drop Autotools for CMake.md
Normal file
288
published/20210514 Drop Autotools for CMake.md
Normal file
@ -0,0 +1,288 @@
|
||||
[#]: subject: "Drop Autotools for CMake"
|
||||
[#]: via: "https://opensource.com/article/21/5/cmake"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "amwps290"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13419-1.html"
|
||||
|
||||
抛弃 Autotools 向 CMake 迈进吧
|
||||
======
|
||||
|
||||
> CMake 是一个跨平台的编译、测试和打包软件,即使你以前从来没有使用过构建系统,也可以轻松上手。
|
||||
|
||||

|
||||
|
||||
在我以前的文章 [Autotools 入门][2] 一文中,我说明了如何使用 Autotools 来管理和打包代码。这是一个强大且通用的平台,可轻松集成到许多打包系统中,包括 RPM、APT、[pkgsrc][3] 等等。它的语法和结构可能会令人困惑,但幸运的是,我们还有其他选择,开源的 [CMake][4] 就是其中一个。
|
||||
|
||||
CMake 是一个用于构建、测试和打包软件的跨平台套件。它使用简单而清晰的语法,因此即使你以前从未使用过构建系统,也很容易开始使用。
|
||||
|
||||
### 安装 CMake
|
||||
|
||||
CMake 可能已经安装在你的 Linux 系统上。如果没有,你可以使用发行版的程序包管理器进行安装:
|
||||
|
||||
```
|
||||
$ sudo dnf install cmake
|
||||
```
|
||||
|
||||
在 Debian 或者其他相似的系统上:
|
||||
|
||||
```
|
||||
$ sudo apt install cmake
|
||||
```
|
||||
|
||||
在 Mac 上,你可以使用 [MacPorts][5] 或者 [Homebrew][6] 来安装:
|
||||
|
||||
```
|
||||
$ sudo port install cmake
|
||||
```
|
||||
|
||||
在 Windows 上,你可以使用 [Chocolatey][7] 或者直接从 [CMake 网站][8] 下载二进制来安装。
|
||||
|
||||
### 使用 CMake
|
||||
|
||||
对于想要从源代码构建软件的开发人员或用户来说,CMake 是一种快速简便的编译和安装方法。 CMake 分阶段工作:
|
||||
|
||||
1. 首先,在 `cmake` 步骤中,CMake 扫描计算机查看一些默认设置。默认设置包括库的位置以及在系统上安装软件的位置。
|
||||
2. 接下来,使用系统上的 `make` 命令(在 Linux 上是 GUN Make,在 [NetBSD][9] 上是 NetBSD Make)来编译程序。这个过程通常是将人类可读的源代码转换成机器语言。
|
||||
3. 最后,在 `make install` 一步中,那些编译过的文件将被拷贝到(在 `cmake` 步骤中扫描出来的)计算机上合适的位置。
|
||||
|
||||
这看起来很简单,当你使用 CMake 时就是这样。
|
||||
|
||||
### CMake 的可移植性
|
||||
|
||||
CMake 在设计时就考虑了可移植性。虽然它不能使你的项目在所有 POSIX 平台上都能正常工作(这取决于作为开发者的你),但它可以确保将标记为要安装的文件安装到已知平台上最合适的位置。而且由于有了 CMake 之类的工具,对于高级用户而言,根据其系统需求自定义和覆盖任何不合适的选项都很容易。
|
||||
|
||||
使用 CMake,你只需要知道将哪些文件安装到哪个常规位置即可。它会照顾其他一切。不再需要自定义安装脚本,它们有可能在任何未经测试的操作系统上失败。
|
||||
|
||||
### 打包
|
||||
|
||||
像 Autotools 一样,CMake 也得到了很好的打包支持。无论它们是打包成 RPM 还是 DEB 或 TGZ(或其他任何东西),将带有 CMake 的项目交给打包者,他们的工作既简单又直接。打包工具支持 CMake,因此可能不需要进行任何修补或者调整。在许多情况下,可以自动将 CMake 项目整合到工作流中。
|
||||
|
||||
### 如何使用 CMake
|
||||
|
||||
要在项目中使用 CMake,只需在项目目录中创建 `CMakeLists.txt` 文件。首先,声明最低要求的 CMake 版本以及项目名称和版本。CMake 会努力在尽可能长时间内保持兼容性,但是随着你使用的时间越长,并且关注它最新的开发动态,你就会知道哪些特性是你所依赖的。
|
||||
|
||||
```
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(Hello VERSION 1.0)
|
||||
```
|
||||
|
||||
如你可能已经看到的那样,CMake 的语法是一个带有括号和参数的命令。大写的 `VERSION` 字符串不是任意的,也不只是格式。它们是 `project` 命令中的有效参数。
|
||||
|
||||
在继续之前,先写一个简单的 C 或者 C++ 的 `hello world` 程序。为了简单,我就写了六行 C 代码,并把它保存在 `hello.c` 中(为了匹配我在 `CMakeLists.txt` 中可执行文件的名字)。
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello open source\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
不过,不要搞错了,CMake 不仅适用于 C 和 C++。它可以处理任意文件,并且有许多可用的命令,因此它可以帮助你维护许多不同形式的项目。
|
||||
|
||||
CMake 网站中记录了所有有效的内置命令及其可用参数,因此无论你要做什么,都可以轻松发现所需的功能。不过,这是一个简单的示例,因此,你需要的下一个命令是必不可少的 —— 你必须为 CMake 定义要构建的代码:
|
||||
|
||||
```
|
||||
add_executable(Hello hello.c)
|
||||
```
|
||||
|
||||
这个命令指定了你编译后的二进制文件的名字为 `Hello`。因此,它与你在终端中执行带有 `-o Hello` 的 `gcc` 命令是一样的。
|
||||
|
||||
在一些比较复杂的项目中,你可能还需要使用库文件,你可以使用 `add library` 命令来链接库文件。
|
||||
|
||||
在你设置了你想要构建和标记为安装的文件之后,你必须要告诉 CMake 一旦用户安装了程序,最终的应用程序应该在哪个位置。
|
||||
|
||||
在这个简单的例子里,你仅需要做的一件事就是在你的 `CMakeLists.txt` 文件里添加 `install` 命令。`install` 命令接受几个参数。但是在这个例子中,你仅需要使用 `TARGET` 命令来指定你要安装文件的名字。
|
||||
|
||||
```
|
||||
install(TARGETS Hello)
|
||||
```
|
||||
|
||||
### 向 CMake 工程添加一些文件
|
||||
|
||||
一个软件项目向用户交付的往往不仅仅只有代码,还有一些其他的文件数据,例如手册或者是信息页、示例项目,或者是配置文件。你可以使用与包含编译文件时类似的工作流程,将任意数据包含在 CMake 项目中:在 `CMakelists.txt` 文件中使用 `file` 命令,然后说明一下这些文件要安装在哪里。
|
||||
|
||||
例如,你可以在这个项目中包含一个 `assets` 目录,你可以使用 `file` 命令,后面跟上 `COPY` 和 `DESTINATION` 参数来告诉 CMake 将这些额外的文件复制到你的分发包中。
|
||||
|
||||
```
|
||||
file(COPY assets DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
```
|
||||
|
||||
这个 `${CMAKE_CURRENT_BINARY_DIR}` 变量是一个特殊的 CMake 内置变量,表示 CMake 正在处理的目录。换句话说,你的任何文件都会被复制到编译目录(在你运行 `cmake` 命令后,这个过程会更加清晰,到时候回过头来看一下)。
|
||||
|
||||
因为这些额外的数据文件有些杂乱不堪(如果你不信的话,可以看一下 `/usr/share` 这个目录)。对于你自己的项目创建一个子文件夹对谁都有好处。最好也带上版本名字。你可以通过在 `CMAKE_CURRENT_BINARY_DIR` 中指定一个新的目录,使用你选择的项目名称,后面跟一个为你的项目命名的特殊变量和你在项目声明中为它设置的 `VERSION`。
|
||||
|
||||
```
|
||||
file(COPY assets DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/Hello-${Hello_VERSION}")
|
||||
```
|
||||
|
||||
### 定义安装位置
|
||||
|
||||
你已经定义你要编译的文件,因此现在你要告诉 CMake 你的程序要安装在哪个位置。比如你的主程序,这个要程使用 `install` 命令:
|
||||
|
||||
```
|
||||
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Hello-${Hello_VERSION}" TYPE DATA)
|
||||
```
|
||||
|
||||
这里有一些新的参数。`DIRECTORY` 参数指定了数据文件是一个目录,而不是一个文件(`FILE`)或者脚本(`SCRIPT`)。你使用的参数和复制一些额外文件到编译目录时是一样。另外,在 `install` 命令中 `TYPE` 或者 `DESTINATION` 必须要指定其一。`TYPE` 参数指定了通用的文件类型,这些文件通常将会被放到合适的位置。在 Linux 系统上,`TYPE DATA` 一般是 `/usr/local/share` 或者 `/usr/share`,除非用户定义了其他的位置。
|
||||
|
||||
这是诸如 CMake 之类的良好构建系统的强大功能之一。你不必担心文件的确切位置,因为你知道用户可以更改 CMake 的首选默认设置,并且 CMake 将构建代码以使其正常工作。
|
||||
|
||||
### 运行 CMake
|
||||
|
||||
CMake 有多种方式来让你执行命令,你可以在终端或者在一个可交互的程序上执行命令,或者你也可以使用它的图形界面(GUI)。我比较偏向于使用终端命令,但是我也喜欢使用一些其他的方式(相比与在 `Makefile` 中查找那些晦涩的变量然后去修改它们更胜一筹)。
|
||||
|
||||
对于编译过开源 C++ 项目的任何人,都熟悉的第一步是创建一个 `build` 目录,进入到该目录,然后运行 `cmake ..` 命令。 我是一个懒惰的打字员,所以我将构建目录命名为 `b`,但是你可以使用最合适的方式:
|
||||
|
||||
```
|
||||
$ mkdir b
|
||||
$ cd b
|
||||
$ cmake ..
|
||||
-- The C compiler identification is GNU 11.1.1
|
||||
-- The CXX compiler identification is GNU 11.1.1
|
||||
-- Detecting C compiler ABI info
|
||||
-- Detecting C compiler ABI info - done
|
||||
-- Check for working C compiler: /usr/bin/cc - skipped
|
||||
-- Detecting C compile features
|
||||
-- Detecting C compile features - done
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Check for working CXX compiler: /usr/bin/c++ - skipped
|
||||
-- Detecting CXX compile features
|
||||
-- Detecting CXX compile features - done
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /var/home/seth/demo-hello/b
|
||||
$
|
||||
```
|
||||
|
||||
这或多或少相当于经典的 `./configure; make; make install` 中的 `./configure`。看一下你的构建目录,CMake 已经帮你生成了几个新的文件,来让你的项目更完整。这里生成了 CMake 的数据文件、一个常规的 `Makefile` 文件(这是一个免费提供的 247 行的文件,但对于越复杂的项目,行数要多得多),还有一个包含这个示例程序的任意非编译数据的 `Hello-1.0` 目录。
|
||||
|
||||
```
|
||||
$ ls
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
Makefile
|
||||
Hello-1.0
|
||||
cmake_install.cmake
|
||||
```
|
||||
|
||||
接下来,你可以进行构建。你可以使用 CMake 的 `--build` 选项来做这件事,使用当前的构建目录作为源目录。
|
||||
|
||||
```
|
||||
$ cmake --build .
|
||||
Scanning dependencies of target Hello
|
||||
[ 50%] Building C object CMakeFiles/Hello.dir/hello.c.o
|
||||
[100%] Linking C executable Hello
|
||||
[100%] Built target Hello
|
||||
```
|
||||
|
||||
或者你可以运行 `make` 命令。这将读取由 CMake 生成的 `Makefile` 文件。在这个例子中,`make` 默认的行为就是由源程序 `hello.c` 生成目标文件。
|
||||
|
||||
```
|
||||
$ make
|
||||
Scanning dependencies of target Hello
|
||||
[ 50%] Building C object CMakeFiles/Hello.dir/hello.c.o
|
||||
[100%] Linking C executable Hello
|
||||
[100%] Built target Hello
|
||||
$
|
||||
```
|
||||
|
||||
如你所料,`Hello` 二进制可执行文件现在存在于当前的构建目录中。因为它是一个简单的自包含应用程序,所以你可以运行它进行测试:
|
||||
|
||||
```
|
||||
$ ./Hello
|
||||
Hello open source
|
||||
$
|
||||
```
|
||||
|
||||
最后,你可以用 `--install` 选项进行安装。因为我不希望我的简单的 “hello world” 应用程序真的被安装到我的系统上,我设置了 `--prefix` 选项,将 CMake 的目标从根目录(`/`)重定向到 `/tmp` 的一个子目录。
|
||||
|
||||
```
|
||||
$ cmake --install . --prefix /tmp/hello/
|
||||
-- Install configuration: ""
|
||||
-- Installing: /tmp/dist-hello/usr/local/bin/Hello
|
||||
-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0
|
||||
-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0/assets/file0
|
||||
-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0/assets/file1
|
||||
```
|
||||
|
||||
另外,你也可以运行 `make install` 来调用 `Makefile` 的安装动作。同样,为了避免在我的系统上安装一个演示程序,我在这个例子中设置了 `DESTDIR` 变量,将安装目标重定向到 `/tmp` 的一个子目录:
|
||||
|
||||
```
|
||||
$ mkdir /tmp/dist-hello
|
||||
$ make install DESTDIR=/tmp/dist-hello
|
||||
[100%] Built target Hello
|
||||
Install the project...
|
||||
-- Install configuration: ""
|
||||
-- Installing: /tmp/dist-hello/usr/local/bin/Hello
|
||||
-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0
|
||||
-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0/assets/file0
|
||||
-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0/assets/file1
|
||||
```
|
||||
|
||||
看一下输出的内容,来确定它具体的安装位置,这个程序已经安装好了。
|
||||
|
||||
### 快速自定义
|
||||
|
||||
CMake 的安装前缀(由 `CMAKE_INSTALL_PREFIX` 变量指定)默认是在 `/usr/local` 这个位置,但是所有的 CMake 变量都可以在你运行 `cmake` 命令的时候,加一个 `-D` 选项来改变它。
|
||||
|
||||
```
|
||||
$ cmake -DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
$ make install DESTDIR=/tmp/dist-hello
|
||||
$ make install DESTDIR=/tmp/dist-hello
|
||||
[100%] Built target Hello
|
||||
Install the project...
|
||||
-- Install configuration: ""
|
||||
-- Installing: /tmp/dist-hello/usr/bin/Hello
|
||||
-- Installing: /tmp/dist-hello/usr/share/Hello-1.0
|
||||
-- Installing: /tmp/dist-hello/usr/share/Hello-1.0/assets/file0
|
||||
-- Installing: /tmp/dist-hello/usr/share/Hello-1.0/assets/file1
|
||||
```
|
||||
|
||||
所有由 CMake 使用的变量都可以通过这种方式来修改。
|
||||
|
||||
### 交互式的 CMake
|
||||
|
||||
CMake 的交互模式是一种用于配置安装环境的友好而有用的方法。要让用户知道该项目使用的所有可能的 CMake 变量是一件工作量很大的事,因此 CMake 交互式界面是他们无需查看 `Makefile` 和 `CMakeLists` 即可发现自定义选项的简便方法。
|
||||
|
||||
为了调用这个交互式的 CMake,使用 `ccmake` 命令,在这个简单的项目里没有太多的东西。但是对于像 [Rosegarden][11] 这样的大型项目,这将非常有用。
|
||||
|
||||
![Rosegarden][12]
|
||||
|
||||
### CMake 的更多知识
|
||||
|
||||
还有很多很多的 CMake 知识需要去了解。作为一个开发者,我非常喜欢它简洁的语法、详尽的文档、可扩展性以及便捷性。作为一个用户我非常喜欢 CMake 友好且实用的错误提示信息还有它的用户界面,如果你的项目还未开始使用构建系统,请了解一下 CMake 吧。你以及以后尝试打包你应用程序的任何人都不会后悔。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/cmake
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[amwps290](https://github.com/amwps290)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/build_structure_tech_program_code_construction.png?itok=nVsiLuag "Someone wearing a hardhat and carrying code "
|
||||
[2]: https://opensource.com/article/19/7/introduction-gnu-autotools
|
||||
[3]: https://opensource.com/article/19/11/pkgsrc-netbsd-linux
|
||||
[4]: http://cmake.org
|
||||
[5]: https://opensource.com/article/20/11/macports
|
||||
[6]: https://opensource.com/article/20/6/homebrew-linux
|
||||
[7]: https://opensource.com/article/20/3/chocolatey
|
||||
[8]: https://cmake.org/download
|
||||
[9]: https://opensource.com/article/19/3/netbsd-raspberry-pi
|
||||
[10]: http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
|
||||
[11]: https://opensource.com/article/18/3/make-sweet-music-digital-audio-workstation-rosegarden
|
||||
[12]: https://opensource.com/sites/default/files/uploads/rosegarden-ccmake.jpg "Rosegarden"
|
||||
[13]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[14]: https://cmake.org/cmake/help/latest/
|
203
sources/tech/20201026 7 Git tricks that changed my life.md
Normal file
203
sources/tech/20201026 7 Git tricks that changed my life.md
Normal file
@ -0,0 +1,203 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (7 Git tricks that changed my life)
|
||||
[#]: via: (https://opensource.com/article/20/10/advanced-git-tips)
|
||||
[#]: author: (Rajeev Bera https://opensource.com/users/acompiler)
|
||||
|
||||
7 Git tricks that changed my life
|
||||
======
|
||||
These helpful tips will change the way you work with the popular version
|
||||
control system.
|
||||
![Computer screen with files or windows open][1]
|
||||
|
||||
Git is one of the most common version control systems available, and it's used on private systems and publicly hosted websites for all kinds of development work. Regardless of how proficient with Git I become, it seems there are always features left to discover. Here are seven tricks that have changed the way I work with Git.
|
||||
|
||||
### 1\. Autocorrection in Git
|
||||
|
||||
We all make typos sometimes, but if you have Git's auto-correct feature enabled, you can let Git automatically fix a mistyped subcommand.
|
||||
|
||||
Suppose you want to check the status with `git status` but you type `git stats` by accident. Under normal circumstances, Git tells you that 'stats' is not a valid command:
|
||||
|
||||
|
||||
```
|
||||
$ git stats
|
||||
git: ‘stats’ is not a git command. See ‘git --help’.
|
||||
|
||||
The most similar command is
|
||||
status
|
||||
```
|
||||
|
||||
To avoid similar scenarios, enable Git autocorrection in your Git configuration:
|
||||
|
||||
|
||||
```
|
||||
`$ git config --global help.autocorrect 1`
|
||||
```
|
||||
|
||||
If you want this to apply only to your current repository, omit the `--global` option.
|
||||
|
||||
This command enables the autocorrection feature. An in-depth tutorial is available at [Git Docs][2], but trying the same errant command as above gives you a good idea of what this configuration does:
|
||||
|
||||
|
||||
```
|
||||
$ git stats
|
||||
git: ‘stats’ is not a git command. See ‘git --help’.
|
||||
On branch master
|
||||
Your branch is up to date with ‘origin/master’.
|
||||
|
||||
nothing to commit, working tree clean
|
||||
```
|
||||
|
||||
Instead of suggesting an alternative subcommand, Git now just runs the top suggestion, which in this case was **git status**.
|
||||
|
||||
### 2\. Count your commits
|
||||
|
||||
There are many reasons you might need to count your commits. Many developers count the number of commits to judge when to increment the build number, for instance, or just to get a feel for how the project is progressing.
|
||||
|
||||
To count your commits is really easy and straightforward; here is the Git command:
|
||||
|
||||
|
||||
```
|
||||
`$ git rev-list --count`
|
||||
```
|
||||
|
||||
In the above command, the **branch-name** should be a valid branch name in your current repository.
|
||||
|
||||
|
||||
```
|
||||
$ git rev-list –count master
|
||||
32
|
||||
$ git rev-list –count dev
|
||||
34
|
||||
```
|
||||
|
||||
### 3\. Optimize your repo
|
||||
|
||||
Your code repository is valuable not only for you but also for your organization. You can keep your repository clean and up to date with a few simple practices. One of the best practices is to [use the .gitignore file][3]. By using this file, you are telling Git not to store many unwanted files like binaries, temporary files, and so on.
|
||||
|
||||
To optimize your repository further, you can use Git garbage collection.
|
||||
|
||||
|
||||
```
|
||||
`$ git gc --prune=now --aggressive`
|
||||
```
|
||||
|
||||
This command helps when you or your team heavily uses **pull** or **push** commands.
|
||||
|
||||
This command is an internal utility that cleans up unreachable or "orphaned" Git objects in your repository.
|
||||
|
||||
### 4\. Take a backup of untracked files
|
||||
|
||||
Most of the time, it's safe to delete all the untracked files. But many times, there is a situation wherein you want to delete, but also to create a backup of your untracked files just in case you need them later.
|
||||
|
||||
Git, along with some Bash command piping, makes it easy to create a zip archive for your untracked files.
|
||||
|
||||
|
||||
```
|
||||
$ git ls-files --others --exclude-standard -z |\
|
||||
xargs -0 tar rvf ~/backup-untracked.zip
|
||||
```
|
||||
|
||||
The above command makes an archive (and excludes files listed in .gitignore) with the name backup-untracked.zip
|
||||
|
||||
### 5\. Know your .git folder
|
||||
|
||||
Every repository has a .git folder. It is a special hidden folder.
|
||||
|
||||
|
||||
```
|
||||
$ ls -a
|
||||
. … .git
|
||||
```
|
||||
|
||||
Git mainly works with two things:
|
||||
|
||||
1. The working tree (the state of files in your current checkout)
|
||||
2. The path of your Git repository (specifically, the location of the .git folder, which contains the versioning information)
|
||||
|
||||
|
||||
|
||||
This folder stores all references and other important details like configurations, repository data, the state of HEAD, logs, and much more.
|
||||
|
||||
If you delete this folder, the current state of your source code is not deleted, but your remote information, such as your project history, is. Deleting this folder means your project (at least, the local copy) isn't under version control anymore. It means you cannot track your changes; you cannot pull or push from a remote.
|
||||
|
||||
Generally, there's not much you need to do, or should do, in your .git folder. It's managed by Git and is considered mostly off-limits. However, there are some interesting artifacts in this directory, including the current state of HEAD:
|
||||
|
||||
|
||||
```
|
||||
$ cat .git/HEAD
|
||||
ref: refs/heads/master
|
||||
```
|
||||
|
||||
It also contains, potentially, a description of your repository:
|
||||
|
||||
|
||||
```
|
||||
`$ cat .git/description`
|
||||
```
|
||||
|
||||
This is an unnamed repository; edit this file 'description' to name the repository.
|
||||
|
||||
The Git hooks folder is also here, complete with example hook files. You can read these samples to get an idea of what's possible through Git hooks, and you can also [read this Git hook introduction by Seth Kenlon][4].
|
||||
|
||||
### 6\. View a file of another branch
|
||||
|
||||
Sometimes you want to view the content of the file from another branch. It's possible with a simple Git command, and without actually switching your branch.
|
||||
|
||||
Suppose you have a file called [README.md][5], and it's in the **main** branch. You're working on a branch called **dev**.
|
||||
|
||||
With the following Git command, you can do it from the terminal.
|
||||
|
||||
|
||||
```
|
||||
`$ git show main:README.md`
|
||||
```
|
||||
|
||||
Once you execute this command, you can view the content of the file in your terminal.
|
||||
|
||||
### 7\. Search in Git
|
||||
|
||||
You can search in Git like a pro with one simple command. Better still, you can search in Git even if you aren't sure which commit—or even branch—you made your changes.
|
||||
|
||||
|
||||
```
|
||||
`$ git rev-list --all | xargs git grep -F ‘’`
|
||||
```
|
||||
|
||||
For example, suppose you want to search for the string "font-size: 52 px;" in your repository:
|
||||
|
||||
|
||||
```
|
||||
$ git rev-list –all | xargs git grep -F ‘font-size: 52 px;’
|
||||
F3022…9e12:HtmlTemplate/style.css: font-size: 52 px;
|
||||
E9211…8244:RR.Web/Content/style/style.css: font-size: 52 px;
|
||||
```
|
||||
|
||||
### Try these tips
|
||||
|
||||
I hope these advanced tips are useful and boost your productivity, saving you lots of time.
|
||||
|
||||
Do you have [Git tips][6] you love? Share them in the comments.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/10/advanced-git-tips
|
||||
|
||||
作者:[Rajeev Bera][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/acompiler
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_screen_windows_files.png?itok=kLTeQUbY (Computer screen with files or windows open)
|
||||
[2]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_code_help_autocorrect_code
|
||||
[3]: https://opensource.com/article/20/8/dont-ignore-gitignore
|
||||
[4]: https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6
|
||||
[5]: http://README.md
|
||||
[6]: https://acompiler.com/git-tips/
|
@ -1,151 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (ywxgod)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (6 predictions for JavaScript build tools)
|
||||
[#]: via: (https://opensource.com/article/20/11/javascript-build-tools)
|
||||
[#]: author: (Shedrack Akintayo https://opensource.com/users/shedrack-akintayo)
|
||||
|
||||
Javascript构建工具的6个预测
|
||||
======
|
||||
Javascript前端工具的生态系统充满着变数和竞争,且只有最好的工具才会存活下来。
|
||||
![Magnifying glass on code][1]
|
||||
|
||||
生产中的代码与开发中的有所不同. 在生产中,我们需要构建一些能运行得够快,能管理各种依赖关系,能自动执行任务,能加载外部模块等功能的包。而那些将开发中的代码转为生产代码的[javascript][2]工具我们就称之为 _构建工具。_
|
||||
|
||||
我们可以通过各个构建步骤以及其重要性来解释前端代码需要被“构建”的原因。
|
||||
|
||||
### 前端代码构建步骤
|
||||
|
||||
前端代码的构建涉及下面的四个步骤:
|
||||
|
||||
#### 1\. 转译
|
||||
|
||||
通过转译,开发者可以使用到语言最新,最热门的更新和扩展,以及浏览器兼容性的维护等。 这是使用[Babel][3]的一个例子:
|
||||
|
||||
|
||||
```
|
||||
// arrow function syntax in array map
|
||||
const double = [1, 2, 3].map((num) => num * 2);
|
||||
// after being transpiled
|
||||
const double = [1, 2, 3].map(function(num) {
|
||||
return num * 2;
|
||||
});
|
||||
```
|
||||
|
||||
#### 2\. 分包
|
||||
|
||||
分包是处理所有"import"与"require"语句的过程; 找到相匹配的JS代码片段,包和库; 将它们添加到适当的域中; 然后将它们打包到一个JS文件中. 常用的分包器包括 Browserify, Webpack, and Parcel.
|
||||
|
||||
#### 3\. 压缩
|
||||
|
||||
压缩是通过删除空白和代码注释来减少最终的文件大小。在压缩过程中,我们还可以更进一步添加代码混淆,混淆会更改变量名和方法名,使代码变得晦涩难懂,因此一旦代码交付到客户端,它就不是那么容易能让人读懂。下面是一个使用Grunt的例子:
|
||||
|
||||
|
||||
```
|
||||
// before minifying
|
||||
const double = [1, 2, 3].map(function(num) {
|
||||
return num * 2;
|
||||
});
|
||||
// after minifying
|
||||
const double = [1, 2, 3].map(function(num) {
|
||||
return num * 2;
|
||||
});
|
||||
```
|
||||
|
||||
#### 4\. 打包
|
||||
|
||||
完成上面的所有步骤之后, 我们需要将这些具有兼容性,且经过分包,压缩/混淆过的文件放置到某个地方。打包正是这样一个过程,它将上述步骤所产生的结果放置到开发者指定的某个位置上。这通常是通过分包器完成的.
|
||||
|
||||
### 前端构建工具
|
||||
|
||||
前端工具及构建工具可以分为以下几类:
|
||||
|
||||
* 包管理: NPM, Yarn
|
||||
* 转移器: Babel, etc.
|
||||
* 打包器: Webpack, Parcel, Browserify
|
||||
* 压缩混淆: UglifyJS, Packer, Minify, etc.
|
||||
|
||||
|
||||
|
||||
Javascript生态系统中有各种各样的构建工具可以使用,包括下面的这些:
|
||||
|
||||
#### Grunt and Bower
|
||||
|
||||
[Grunt][4] 作为一个命令行工具被引入,它仅提供一个脚本来指定和配置相关构建任务。[Bower][5] 作为包管理器,提供一种客户端包的管理方法而紧追其后。这两者,再加上NPM,它们经常被使用在一起,它们似乎可以满足大多数的自动化需求。Grunt的问题在于它无法提供给开发者配置更复杂任务的自由,而Bower使开发者管理的程序包是平常的两倍,因为它将前端包后后台包分开了 (例如,Bower components vs. Node modules)。
|
||||
|
||||
**Grunt与Bower的未来:** Grunt与Bower即将退出javascript工具生态,但是还有一些替代品。
|
||||
|
||||
#### Gulp and Browserify
|
||||
|
||||
[Gulp][6]是在Grunt发布后的一年半才发布的。然而Gulp让大家感觉很自然、舒服。用javascript来写构建脚本与用JSON来写相比更自由。你可以Gulp的构建脚本中编写函数,即时创建变量,在任何地方使用条件语句--但就这些,并不能说让我们的脚本变得特别自然和强大,只能说有这个可能。[Browserify][7]和Gulp可以配合使用。Browserify允许NPM包(用于后端Node服务器)被直接带入到前端,这直接让Bower废了。而这种用一个包管理器来处理前端后后台包的方式让人感到更好和更自然。
|
||||
|
||||
**Gulp的未来:** Gulp可能会被改进,以匹配当前流行的构建工具,但这完全取决于创作者的意愿。Gulp还在使用中,只是没有以前那么流行了。
|
||||
|
||||
#### Webpack and NPM/Yarn scripts
|
||||
|
||||
[Webpack][8]是现代前端开发工具中最热门的宠儿。Webpack是一个开源的javascript模块打包器. 它主要是为处理javascript而创作的,但如果包含相应的loaders,它也可以转换HTML、CSS和图片等前端资源。通过Webpack,你也可以像Gulp一样编写构建脚本,并通过[NPM/Yarn][9]来执行这些脚本.
|
||||
|
||||
**Webpack的未来:** Webpack是目前Javascript工具生态系统中最热门的工具,最近几乎所有的JS库都在使用React和Webpack. Webpack目前处于第四个版本,不会很快消失。(译者注:webpack目前已经发布了第五个版本了,且还在火热更新中)
|
||||
|
||||
#### Parcel
|
||||
|
||||
[Parcel][10]是一个web应用打包器,于2018年推出,因其开发者不同的体验而与众不同。Parcel能利用多核功能提供极快的性能,且还零配置。Parcel还是一个新星,其采用率并不高,特别是对于一些大型应用。与Webpack相比,开发人员更喜欢使用Webpack,因为Webpack有更广泛的支持和可定制性。
|
||||
|
||||
**The future of Parcel:** Parcel is very easy to use, it is faster than Webpack if you measure bundle and build time, and it also offers a better developer experience. The reason Parcel hasn't been adopted much might be because it's still relatively new. Parcel has a very bright future in the frontend build tools ecosystem, and it will be around for a while.
|
||||
|
||||
#### Rollup
|
||||
|
||||
[Rollup][11] is a module bundler for JavaScript that compiles small pieces of code into something larger and more complex, such as a library or an application. It is advisable to use Rollup when building a library with minimal third-party imports.
|
||||
|
||||
**The future of Rollup:** Rollup is super-cool and is being adopted rapidly. It has great features and will be part of the frontend tooling ecosystem for a long time.
|
||||
|
||||
### Learn more
|
||||
|
||||
The JavaScript tooling ecosystem is dynamic and competitive, and only the best tools survive. In the future, we will see tools that require less (or no) configuration, better customizability, more extensibility, and higher speed.
|
||||
|
||||
The tools you use for an application's frontend are a personal call that you need to make based on your project's requirements. Choose what works best for you, and most of the time, there are tradeoffs.
|
||||
|
||||
For more information, see:
|
||||
|
||||
* [JavaScript tooling: The evolution and future of JS/frontend build tools][12]
|
||||
* [Tools and modern workflow for frontend developers][13]
|
||||
* [Modern frontend: The tools and build process explained][14]
|
||||
* [Best build tools in frontend development][15]
|
||||
|
||||
|
||||
|
||||
* * *
|
||||
|
||||
_This article originally appeared on [Shedrack Akintayo's blog][16] and is republished with his permission._
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/11/javascript-build-tools
|
||||
|
||||
作者:[Shedrack Akintayo][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/shedrack-akintayo
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/find-file-linux-code_magnifying_glass_zero.png?itok=E2HoPDg0 (Magnifying glass on code)
|
||||
[2]: https://www.javascript.com/
|
||||
[3]: https://babeljs.io/
|
||||
[4]: https://gruntjs.com/
|
||||
[5]: https://bower.io/
|
||||
[6]: https://gulpjs.com/
|
||||
[7]: http://browserify.org/
|
||||
[8]: https://webpack.js.org/
|
||||
[9]: https://github.com/yarnpkg/yarn
|
||||
[10]: https://parceljs.org/
|
||||
[11]: https://rollupjs.org/guide/en/
|
||||
[12]: https://qmo.io/blog/javascript-tooling-the-evolution-and-future-of-js-front-end-build-tools/
|
||||
[13]: https://blog.logrocket.com/tools-and-modern-workflow-for-front-end-developers-505c7227e917/
|
||||
[14]: https://medium.com/@trevorpoppen/modern-front-end-the-tools-and-build-process-explained-36641b5c1a53
|
||||
[15]: https://www.developerdrive.com/best-build-tools-frontend-development/
|
||||
[16]: https://www.sheddy.xyz/posts/javascript-build-tools-past-and-beyond
|
@ -1,188 +0,0 @@
|
||||
[#]: subject: (4 tips for context switching in Git)
|
||||
[#]: via: (https://opensource.com/article/21/4/context-switching-git)
|
||||
[#]: author: (Olaf Alders https://opensource.com/users/oalders)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
4 tips for context switching in Git
|
||||
======
|
||||
Compare the pros and cons of four options to switch branches while
|
||||
working in Git.
|
||||
![Computer screen with files or windows open][1]
|
||||
|
||||
Anyone who spends a lot of time working with Git will eventually need to do some form of context switching. Sometimes this adds very little overhead to your workflow, but other times, it can be a real pain.
|
||||
|
||||
Let's discuss the pros and cons of some common strategies for dealing with context switching using this example problem:
|
||||
|
||||
> Imagine you are working in a branch called `feature-X`. You have just discovered you need to solve an unrelated problem. This cannot be done in `feature-X`. You will need to do this work in a new branch, `feature-Y`.
|
||||
|
||||
### Solution #1: stash + branch
|
||||
|
||||
Probably the most common workflow to tackle this issue looks something like this:
|
||||
|
||||
1. Halt work on the branch `feature-X`
|
||||
2. `git stash`
|
||||
3. `git checkout -b feature-Y origin/main`
|
||||
4. Hack, hack, hack…
|
||||
5. `git checkout feature-X` or `git switch -`
|
||||
6. `git stash pop`
|
||||
7. Resume work on `feature-X`
|
||||
|
||||
|
||||
|
||||
**Pros:** The nice thing about this approach is that this is a fairly easy workflow for simple changes. It can work quite well, especially for small repositories.
|
||||
|
||||
**Cons:** When using this workflow, you can have only one workspace at a time. Also, depending on the state of your repository, working with the stash can be non-trivial.
|
||||
|
||||
### Solution #2: WIP commit + branch
|
||||
|
||||
A variation on this solution looks quite similar, but it uses a WIP (Work in Progress) commit rather than the stash. When you're ready to switch back, rather than popping the stash, `git reset HEAD~1` unrolls your WIP commit, and you're free to continue, much as you did in the earlier scenario but without touching the stash.
|
||||
|
||||
1. Halt work on the branch `feature-X`
|
||||
2. `git add -u` (adds only modified and deleted files)
|
||||
3. `git commit -m "WIP"`
|
||||
4. `git checkout -b feature-Y origin/master`
|
||||
5. Hack, hack, hack…
|
||||
6. `git checkout feature-X` or `git switch -`
|
||||
7. `git reset HEAD~1`
|
||||
|
||||
|
||||
|
||||
**Pros:** This is an easy workflow for simple changes and also good for small repositories. You don't have to work with the stash.
|
||||
|
||||
**Cons:** You can have only one workspace at any time. Also, WIP commits can sneak into your final product if you or your code reviewer are not vigilant.
|
||||
|
||||
When using this workflow, you _never_ want to add a `--hard` to `git reset`. If you do this accidentally, you should be able to restore your commit using `git reflog`, but it's less heartstopping to avoid this scenario entirely.
|
||||
|
||||
### Solution #3: new repository clone
|
||||
|
||||
In this solution, rather than creating a new branch, you make a new clone of the repository for each new feature branch.
|
||||
|
||||
**Pros:** You can work in multiple workspaces simultaneously. You don't need `git stash` or even WIP commits.
|
||||
|
||||
**Cons:** Depending on the size of your repository, this can use a lot of disk space. (Shallow clones can help with this scenario, but they may not always be a good fit.) Additionally, your repository clones will be agnostic about each other. Since they can't track each other, you must track where your clones live. If you need git hooks, you will need to set them up for each new clone.
|
||||
|
||||
### Solution #4: git worktree
|
||||
|
||||
To use this solution, you may need to learn about `git add worktree`. Don't feel bad if you're not familiar with worktrees in Git. Many people get by for years in blissful ignorance of this concept.
|
||||
|
||||
#### What is a worktree?
|
||||
|
||||
Think of a worktree as the files in the repository that belong to a project. Essentially, it's a kind of workspace. You may not realize that you're already using worktrees. When using Git, you get your first worktree for free.
|
||||
|
||||
|
||||
```
|
||||
$ mkdir /tmp/foo && cd /tmp/foo
|
||||
$ git init
|
||||
$ git worktree list
|
||||
/tmp 0000000 [master]
|
||||
```
|
||||
|
||||
As you can see, the worktree exists even before the first commit. Now, add a new worktree to an existing project.
|
||||
|
||||
#### Add a worktree
|
||||
|
||||
To add a new worktree, you need to provide:
|
||||
|
||||
1. A location on disk
|
||||
2. A branch name
|
||||
3. Something to branch from
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
$ git clone <https://github.com/oalders/http-browserdetect.git>
|
||||
$ cd http-browserdetect/
|
||||
$ git worktree list
|
||||
/Users/olaf/http-browserdetect 90772ae [master]
|
||||
|
||||
$ git worktree add ~/trees/oalders/feature-X -b oalders/feature-X origin/master
|
||||
$ git worktree add ~/trees/oalders/feature-Y -b oalders/feature-Y e9df3c555e96b3f1
|
||||
|
||||
$ git worktree list
|
||||
/Users/olaf/http-browserdetect 90772ae [master]
|
||||
/Users/olaf/trees/oalders/feature-X 90772ae [oalders/feature-X]
|
||||
/Users/olaf/trees/oalders/feature-Y e9df3c5 [oalders/feature-Y]
|
||||
```
|
||||
|
||||
Like with most other Git commands, you need to be inside a repository when issuing this command. Once the worktrees are created, you have isolated work environments. The Git repository tracks where the worktrees live on disk. If Git hooks are already set up in the parent repository, they will also be available in the worktrees.
|
||||
|
||||
Don't overlook that each worktree uses only a fraction of the parent repository's disk space. In this case, the worktree requires about one-third of the original's disk space. This can scale very well. Once your repositories are measured in the gigabytes, you'll really come to appreciate these savings.
|
||||
|
||||
|
||||
```
|
||||
$ du -sh /Users/olaf/http-browserdetect
|
||||
2.9M
|
||||
|
||||
$ du -sh /Users/olaf/trees/oalders/feature-X
|
||||
1.0M
|
||||
```
|
||||
|
||||
**Pros:** You can work in multiple workspaces simultaneously. You don't need the stash. Git tracks all of your worktrees. You don't need to set up Git hooks. This is also faster than `git clone` and can save on network traffic since you can do this in airplane mode. You also get more efficient disk space use without needing to resort to a shallow clone.
|
||||
|
||||
**Cons:** This is yet another thing to remember. However, if you can get into the habit of using this feature, it can reward you handsomely.
|
||||
|
||||
### A few more tips
|
||||
|
||||
When you need to clean up your worktrees, you have a couple of options. The preferable way is to let Git remove the worktree:
|
||||
|
||||
|
||||
```
|
||||
`git worktree remove /Users/olaf/trees/oalders/feature-X`
|
||||
```
|
||||
|
||||
If you prefer a scorched-earth approach, `rm -rf` is also your friend:
|
||||
|
||||
|
||||
```
|
||||
`rm -rf /Users/olaf/trees/oalders/feature-X`
|
||||
```
|
||||
|
||||
However, if you do this, you may want to clean up any remaining files with `git worktree prune`. Or you can skip the `prune` now, and this will happen on its own at some point in the future via `git gc`.
|
||||
|
||||
### Notable notes
|
||||
|
||||
If you're ready to get started with `git worktree`, here are a few things to keep in mind.
|
||||
|
||||
* Removing a worktree does not delete the branch.
|
||||
* You can switch branches within a worktree.
|
||||
* You cannot simultaneously check out the same branch in multiple worktrees.
|
||||
* Like many other Git commands, `git worktree` needs to be run from inside a repository.
|
||||
* You can have many worktrees at once.
|
||||
* Create your worktrees from the same local checkout, or they will be agnostic about each other.
|
||||
|
||||
|
||||
|
||||
### git rev-parse
|
||||
|
||||
One final note: When using `git worktree`, your concept of where the root of the repository lives may depend on context. Fortunately, `git rev-parse` allows you to distinguish between the two.
|
||||
|
||||
* To find the parent repository's root: [code]`git rev-parse --git-common-dir`
|
||||
```
|
||||
* To find the root of the repository you're in: [code]`git rev-parse --show-toplevel`
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Choose the best method for your needs
|
||||
|
||||
As in many things, TIMTOWDI (there's more than one way to do it). What's important is that you find a workflow that suits your needs. What your needs are may vary depending on the problem at hand. Maybe you'll occasionally find yourself reaching for `git worktree` as a handy tool in your revision-control toolbelt.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/4/context-switching-git
|
||||
|
||||
作者:[Olaf Alders][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/oalders
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_screen_windows_files.png?itok=kLTeQUbY (Computer screen with files or windows open)
|
@ -0,0 +1,86 @@
|
||||
[#]: subject: (3 features released in Python 3.1 you should use in 2021)
|
||||
[#]: via: (https://opensource.com/article/21/5/python-31-features)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
3 features released in Python 3.1 you should use in 2021
|
||||
======
|
||||
Explore some of the underutilized but still useful Python features.
|
||||
![Python programming language logo with question marks][1]
|
||||
|
||||
This is the second in a series of articles about features that first appeared in a version of Python 3.x. Python 3.1 was first released in 2009, and even though it has been out for a long time, many of the features it introduced are underused and pretty cool. Here are three of them.
|
||||
|
||||
### Thousands formatting
|
||||
|
||||
When formatting large numbers, it is common to place commas every three digits to make the number more readable (e.g., 1,048,576 is easier to read than 1048576). Since Python 3.1, this can be done directly when using string formatting functions:
|
||||
|
||||
|
||||
```
|
||||
`"2 to the 20th power is {:,d}".format(2**20)`[/code] [code]`'2 to the 20th power is 1,048,576'`
|
||||
```
|
||||
|
||||
The `,d` format specifier indicates that the number must be formatted with commas.
|
||||
|
||||
### Counter class
|
||||
|
||||
The `collections.Counter` class, part of the standard library module `collections`, is a secret super-weapon in Python. It is often first encountered in simple solutions to interview questions in Python, but its value is not limited to that.
|
||||
|
||||
For example, find the five most common letters in the first eight lines of [Humpty Dumpty's song][2]:
|
||||
|
||||
|
||||
```
|
||||
hd_song = """
|
||||
In winter, when the fields are white,
|
||||
I sing this song for your delight.
|
||||
|
||||
In Spring, when woods are getting green,
|
||||
I'll try and tell you what I mean.
|
||||
|
||||
In Summer, when the days are long,
|
||||
Perhaps you'll understand the song.
|
||||
|
||||
In Autumn, when the leaves are brown,
|
||||
Take pen and ink, and write it down.
|
||||
"""
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
import collections
|
||||
|
||||
collections.Counter(hd_song.lower().replace(' ', '')).most_common(5)
|
||||
|
||||
```
|
||||
```
|
||||
`[('e', 29), ('n', 27), ('i', 18), ('t', 18), ('r', 15)]`
|
||||
```
|
||||
|
||||
### Executing packages
|
||||
|
||||
Python allows the `-m` flag to execute modules from the command line. Even some standard-library modules do something useful when they're executed; for example, `python -m cgi` is a CGI script that debugs the web server's CGI configuration.
|
||||
|
||||
However, until Python 3.1, it was impossible to execute _packages_ like this. Starting with Python 3.1, `python -m package` will execute the `__main__` module in the package. This is a good place to put debug scripts or commands that are executed mostly with tools and do not need to be short.
|
||||
|
||||
Python 3.0 was released over 11 years ago, but some of the features that first showed up in this release are cool—and underused. Add them to your toolkit if you haven't already.
|
||||
|
||||
Newcomers to python-ideas occasionally make reference to the idea of "Python 4000" when proposing...
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/python-31-features
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/python_programming_question.png?itok=cOeJW-8r (Python programming language logo with question marks)
|
||||
[2]: http://www2.open.ac.uk/openlearn/poetryprescription/humpty-dumptys-recitation.html
|
@ -0,0 +1,140 @@
|
||||
[#]: subject: (Slice infinite generators with this Python 3.7 feature)
|
||||
[#]: via: (https://opensource.com/article/21/5/python-37-features)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
Slice infinite generators with this Python 3.7 feature
|
||||
======
|
||||
Learn more about this and two other underutilized but still useful
|
||||
Python features.
|
||||
![Hands on a keyboard with a Python book ][1]
|
||||
|
||||
This is the eighth in a series of articles about features that first appeared in a version of Python 3.x. [Python 3.7][2] was first released in 2018, and even though it has been out for a few years, many of the features it introduced are underused and pretty cool. Here are three of them.
|
||||
|
||||
### Postponed evaluation of annotations
|
||||
|
||||
In Python 3.7, as long as the right `__future__` flags are activated, annotations are not evaluated during runtime:
|
||||
|
||||
|
||||
```
|
||||
from __future__ import annotations
|
||||
|
||||
def another_brick(wall: List[Brick], brick: Brick) -> Education:
|
||||
pass
|
||||
|
||||
```
|
||||
```
|
||||
`another_brick.__annotations__`
|
||||
```
|
||||
```
|
||||
` {'wall': 'List[Brick]', 'brick': 'Brick', 'return': 'Education'}`
|
||||
```
|
||||
|
||||
This allows recursive types (classes that refer to themselves) and other fun things. However, it means that if you want to do your own type analysis, you need to use `ast` explictly:
|
||||
|
||||
|
||||
```
|
||||
import ast
|
||||
raw_type = another_brick.__annotations__['wall']
|
||||
[parsed_type] = ast.parse(raw_type).body
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
subscript = parsed_type.value
|
||||
f"{subscript.value.id}[{subscript.slice.id}]"
|
||||
|
||||
```
|
||||
```
|
||||
` 'List[Brick]'`
|
||||
```
|
||||
|
||||
### itertools.islice supports __index__
|
||||
|
||||
Sequence slices in Python have long accepted all kinds of _int-like objects_ (objects that have `__index__()`) as valid slice parts. However, it wasn't until Python 3.7 that `itertools.islice`, the only way in core Python to slice infinite generators, gained this support.
|
||||
|
||||
For example, now it is possible to slice infinite generators by `numpy.short`-sized integers:
|
||||
|
||||
|
||||
```
|
||||
import numpy
|
||||
short_1 = numpy.short(1)
|
||||
short_3 = numpy.short(3)
|
||||
short_1, type(short_1)
|
||||
|
||||
```
|
||||
```
|
||||
` (1, numpy.int16)`
|
||||
```
|
||||
```
|
||||
|
||||
import itertools
|
||||
list(itertools.islice(itertools.count(), short_1, short_3))
|
||||
|
||||
```
|
||||
```
|
||||
` [1, 2]`
|
||||
```
|
||||
|
||||
### functools.singledispatch() annotation registration
|
||||
|
||||
If you thought [singledispatch][3] couldn't get any cooler, you were wrong. Now it is possible to register based on annotations:
|
||||
|
||||
|
||||
```
|
||||
import attr
|
||||
import math
|
||||
from functools import singledispatch
|
||||
|
||||
@attr.s(auto_attribs=True, frozen=True)
|
||||
class Circle:
|
||||
radius: float
|
||||
|
||||
@attr.s(auto_attribs=True, frozen=True)
|
||||
class Square:
|
||||
side: float
|
||||
|
||||
@singledispatch
|
||||
def get_area(shape):
|
||||
raise NotImplementedError("cannot calculate area for unknown shape",
|
||||
shape)
|
||||
|
||||
@get_area.register
|
||||
def _get_area_square(shape: Square):
|
||||
return shape.side ** 2
|
||||
|
||||
@get_area.register
|
||||
def _get_area_circle(shape: Circle):
|
||||
return math.pi * (shape.radius ** 2)
|
||||
|
||||
get_area(Circle(1)), get_area(Square(1))
|
||||
|
||||
```
|
||||
```
|
||||
` (3.141592653589793, 1)`
|
||||
```
|
||||
|
||||
### Welcome to 2017
|
||||
|
||||
Python 3.7 was released about four years ago, but some of the features that first showed up in this release are cool—and underused. Add them to your toolkit if you haven't already.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/python-37-features
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/python-programming-code-keyboard.png?itok=fxiSpmnd (Hands on a keyboard with a Python book )
|
||||
[2]: https://opensource.com/downloads/cheat-sheet-python-37-beginners
|
||||
[3]: https://opensource.com/article/19/5/python-singledispatch
|
@ -2,7 +2,7 @@
|
||||
[#]: via: (https://opensource.com/article/21/5/python-38-features)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -0,0 +1,130 @@
|
||||
[#]: subject: (How Python 3.9 fixed decorators and improved dictionaries)
|
||||
[#]: via: (https://opensource.com/article/21/5/python-39-features)
|
||||
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
How Python 3.9 fixed decorators and improved dictionaries
|
||||
======
|
||||
Explore some of the useful features of the recent version of Python.
|
||||
![Python in a coffee cup.][1]
|
||||
|
||||
This is the tenth in a series of articles about features that first appeared in a version of Python 3.x. Some of these versions have been out for a while. Python 3.9 was first released in 2020 with cool new features that are still underused. Here are three of them.
|
||||
|
||||
### Adding dictionaries
|
||||
|
||||
Say you have a dictionary with "defaults," and you want to update it with parameters. Before Python 3.9, the best option was to copy the defaults dictionary and then use the `.update()` method.
|
||||
|
||||
Python 3.9 introduced the union operator to dictionaries:
|
||||
|
||||
|
||||
```
|
||||
defaults = dict(who="someone", where="somewhere")
|
||||
params = dict(where="our town", when="today")
|
||||
defaults | params
|
||||
|
||||
```
|
||||
```
|
||||
` {'who': 'someone', 'where': 'our town', 'when': 'today'}`
|
||||
```
|
||||
|
||||
Note that the order matters. In this case, the `where` value from `params` overrides the default, as it should.
|
||||
|
||||
### Removing prefixes
|
||||
|
||||
If you have done ad hoc text parsing or cleanup with Python, you will have written code like:
|
||||
|
||||
|
||||
```
|
||||
def process_pricing_line(line):
|
||||
if line.startswith("pricing:"):
|
||||
return line[len("pricing:"):]
|
||||
return line
|
||||
process_pricing_line("pricing:20")
|
||||
|
||||
```
|
||||
```
|
||||
` '20'`
|
||||
```
|
||||
|
||||
This kind of code is prone to errors. For example, if the string is copied incorrectly to the next line, the price will become `0` instead of `20`, and it will happen silently.
|
||||
|
||||
Since Python 3.9, strings have a `.lstrip()` method:
|
||||
|
||||
|
||||
```
|
||||
`"pricing:20".lstrip("pricing:")`[/code] [code]` '20'`
|
||||
```
|
||||
|
||||
### Arbitrary decorator expressions
|
||||
|
||||
Previously, the rules about which expressions are allowed in a decorator were underdocumented and hard to understand. For example, while:
|
||||
|
||||
|
||||
```
|
||||
@item.thing
|
||||
def foo():
|
||||
pass
|
||||
```
|
||||
|
||||
is valid, and:
|
||||
|
||||
|
||||
```
|
||||
@item.thing()
|
||||
def foo():
|
||||
pass
|
||||
```
|
||||
|
||||
is valid, the similar:
|
||||
|
||||
|
||||
```
|
||||
@item().thing
|
||||
def foo():
|
||||
pass
|
||||
```
|
||||
|
||||
produces a syntax error.
|
||||
|
||||
Starting in Python 3.9, any expression is valid as a decorator:
|
||||
|
||||
|
||||
```
|
||||
from unittest import mock
|
||||
|
||||
item = mock.MagicMock()
|
||||
|
||||
@item().thing
|
||||
def foo():
|
||||
pass
|
||||
print(item.return_value.thing.call_args[0][0])
|
||||
|
||||
```
|
||||
```
|
||||
` <function foo at 0x7f3733897040>`
|
||||
```
|
||||
|
||||
While keeping to simple expressions in the decorator line is still a good idea, it is now a human decision, rather than the Python parser's option.
|
||||
|
||||
### Welcome to 2020
|
||||
|
||||
Python 3.9 was released about one year ago, but some of the features that first showed up in this release are cool—and underused. Add them to your toolkit if you haven't already.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/python-39-features
|
||||
|
||||
作者:[Moshe Zadka][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/moshez
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_python.jpg?itok=G04cSvp_ (Python in a coffee cup.)
|
@ -2,7 +2,7 @@
|
||||
[#]: via: (https://fedoramagazine.org/join-fedora-linux-enterprise-domain/)
|
||||
[#]: author: (ogutierrez https://fedoramagazine.org/author/ogutierrez/)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
@ -88,7 +88,7 @@ via: https://fedoramagazine.org/join-fedora-linux-enterprise-domain/
|
||||
|
||||
作者:[ogutierrez][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
88
sources/tech/20210523 3 reasons to learn Java in 2021.md
Normal file
88
sources/tech/20210523 3 reasons to learn Java in 2021.md
Normal file
@ -0,0 +1,88 @@
|
||||
[#]: subject: (3 reasons to learn Java in 2021)
|
||||
[#]: via: (https://opensource.com/article/21/5/java)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
3 reasons to learn Java in 2021
|
||||
======
|
||||
Java is powerful, diverse, scalable, and fun. Here's why—and how—you
|
||||
should be using it.
|
||||
![Learning and studying technology is the key to success][1]
|
||||
|
||||
Java was released in 1995, making it 26 years old as I'm writing this. It was proprietary at first, but in 2007, Java was released as open source under the GPL. To understand what makes Java important, you have to understand the problem it claims to solve. Then you can understand why and how it benefits developers and users.
|
||||
|
||||
The best way to understand what Java solves is to develop software, but just using software is a good start, too. As a developer, your troubles are likely to begin when you send software that works perfectly on your own computer to some other computer; it probably won't work. It _should_ work, but as any programmer knows, something always gets overlooked. This is compounded when you try the software on another operating system (OS). It's why there are so many download buttons on any given software site: a button for Windows, for macOS, for Linux, for mobiles, and sometimes even more.
|
||||
|
||||
As a user, a typical scenario is you want to download some great software but find it's not available for your platform. It seems a pity that such a thing still happens on computers so advanced that they can run virtualized computers within computers, keep old video games alive through emulation, and even fit in your pocket, but software delivery is actually pretty difficult.
|
||||
|
||||
Is there a better way? Probably.
|
||||
|
||||
### 1\. Write once, run everywhere
|
||||
|
||||
Code is surprisingly, maybe even disappointingly, specific to OS and architecture. Code has to be _compiled_ from a human-friendly programming language into machine language, a series of binary instructions derived from what a CPU is designed to respond to. It feels arcane in the world of advanced computers that we can't just write code and send it to anyone who wants to run it without worrying about what platform they're on.
|
||||
|
||||
Java is the solution to this incongruity. It's the realization of cross-platform code that works the same across any system you run it on. Java's approach to achieving this feat is counterintuitive at first. In a way, Java isn't compatible with anything but one computer. Stranger still, this computer doesn't actually exist. The computer that Java code targets is the Java Virtual Machine (JVM). This is a program written by Java's creators and distributed for practically any computing device you can think of. As long as you have it installed, any Java code you run is handled by this "imaginary" computer living inside your computer. Java code is executed by the JVM, which sends appropriate platform-specific instructions to your computer, so everything works the same on every OS and architecture.
|
||||
|
||||
Of course, the method used by Java isn't really the selling point here. Most users and many developers don't care how software compatibility is achieved, only that it happens. Many languages promise cross-platform functionality, and usually, that promise is ultimately true, but the journey isn't always easy. Programming languages must be compiled for their target platforms, scripting languages require platform-specific interpreters, and it's rare that either can ensure consistent access to low-level system resources. Cross-platform support is getting better and better, with libraries to help with translating paths and environment variables and settings, and some frameworks (notably [Qt][2]) do much to bridge the gap for peripheral access. But Java has it and delivers it consistently and reliably.
|
||||
|
||||
### 2\. Sensible code
|
||||
|
||||
Java's syntax is boring in the best of ways. If you took all the popular programming languages and put them in a rock tumbler, Java is what you'd get. Looking at source code written in Java, you more or less see the average of all the unique expressions of programming. Brackets indicate the scope of functions and flow control, variables are clearly declared and instantiated before being used, and there's a clear and consistent structure to expressions.
|
||||
|
||||
I've found that learning Java often encourages self-taught programmers using less structured languages to write smarter code. There are lots of "basic" programming lessons you can't learn by gleaning techniques from source code you study online, such as keeping global variable declarations together in the style of Java's public fields, properly anticipating and handling exceptions, using classes and functions, and more. Little touches borrowed from Java can make a big difference.
|
||||
|
||||
### 3\. Scaffolding and support
|
||||
|
||||
All the popular programming languages have great support systems in place. It's what makes popular languages popular. They all have lots of libraries; there are integrated development environments (IDEs) or IDE extensions for them, example code, free and paid training, and communities of developers. On the other hand, no programming language seems to have quite enough support when you get stuck trying to make something work.
|
||||
|
||||
I can't claim that Java can differentiate itself from these two universal but contradictory truths. Still, I have found that when I need a library for Java, I inevitably find not just one but several options for a given task. Often I don't want to use a library because I don't like how its developer chose to implement the functions I need, its license is a little different from what I prefer, or any other trivial point of contention. When there's bountiful support for a language, I have the luxury of being very selective. I get to choose one—among many perfectly suitable solutions—that will best achieve any requirement, however trivial.
|
||||
|
||||
Better yet, there's a healthy infrastructure around Java. Tools like [Apache Ant][3], [Gradle][4], and [Maven][5] help you manage your build and delivery process. Services like [Sonatype Nexus][6] help you monitor security. [Spring][7] and [Grails][8] make it easy to develop for the web, while [Quarkus][9] and [Eclipse Che][10] help with cloud development.
|
||||
|
||||
You can even choose what to use when approaching the Java language itself. [OpenJDK][11] provides classic, official Java, while [Groovy][12] is a simplified approach that resembles a scripting language (you might compare it to Python), and [Quarkus][13] provides a framework for container-first development.
|
||||
|
||||
There's a lot more, but suffice it to say that Java is a complete package regardless of what you're looking for.
|
||||
|
||||
### Bonus: Easy to learn
|
||||
|
||||
Java has proven to be a sensible solution for me and many developers in various industries. Here are some of the reasons I love to use Java.
|
||||
|
||||
You may have heard or inferred that Java is a "professional" language for clunky government sites and reserved for "real" developers. Don't be fooled by the many different reputations Java has garnered over its 25+ years! It's only half as terrifying as its reputation, meaning no more than any other language.
|
||||
|
||||
Programming is hard; there's no getting away from that. It requires you to think logically, it forces you to learn a new language with fewer expressive options than your native tongue, and it demands that you figure out how to solve problems that are difficult enough that they've driven you to programmatic automation. No language alleviates these issues.
|
||||
|
||||
However, learning curves for programming languages can differ in surprising ways. Some are easy to start but get complex when you start exploring the fine details. In other words, it might take just one line of code to print "hello world," but once you learn about classes or functions, you get to learn the language (or at least its data model) all over again. Java is Java from the beginning, but once you learn it, you have access to all of its many tricks and conveniences.
|
||||
|
||||
In short: Go learn Java! It's powerful, diverse, scalable, and fun. To help you on your way, [download our Java cheat sheet][14], which contains all the basic syntax you'll need as you work on your first dozen projects. After that, you won't need it anymore because Java is wonderfully consistent and predictable. Enjoy!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/java
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/studying-books-java-couch-education.png?itok=C9gasCXr (Learning and studying technology is the key to success)
|
||||
[2]: http://qt.io
|
||||
[3]: https://ant.apache.org/
|
||||
[4]: https://gradle.org
|
||||
[5]: https://spring.io/guides/gs/maven
|
||||
[6]: https://www.sonatype.com/products/repository-pro
|
||||
[7]: http://spring.io
|
||||
[8]: https://grails.org
|
||||
[9]: https://opensource.com/article/21/4/quarkus-tutorial
|
||||
[10]: https://opensource.com/article/19/10/cloud-ide-che
|
||||
[11]: http://adoptopenjdk.net
|
||||
[12]: https://opensource.com/article/20/12/groovy
|
||||
[13]: https://developers.redhat.com/products/quarkus/getting-started
|
||||
[14]: https://opensource.com/downloads/java-cheat-sheet
|
@ -0,0 +1,182 @@
|
||||
[#]: subject: (How to Install and Use XRDP on Ubuntu for Remote Desktop Connection)
|
||||
[#]: via: (https://itsfoss.com/xrdp-ubuntu/)
|
||||
[#]: author: (Hunter Wittenborn https://itsfoss.com/author/hunter/)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
How to Install and Use XRDP on Ubuntu for Remote Desktop Connection
|
||||
======
|
||||
|
||||
_**Brief: This is a beginner’s guide that shows the steps you need to follow for setting up XRDP on Ubuntu-based Linux distributions. With that, you can access your Ubuntu system from a different computer and use it graphically.**_
|
||||
|
||||
[Microsoft Remote Desktop Protocol][1](RDP) is a protocol that allows for graphical remote desktop connections from one computer to another. RDP works by having a main machine run software that allows several other computers to connect to it.
|
||||
|
||||
[XRDP][2] is an open-source implementation of RDP, removing the need to run any proprietary programs. XRDP not only tries to follow in the direction of RDP, but is also compatible with regular RDP clients such as [Remmina][3] and [GNOME Boxes][4].
|
||||
|
||||
Here’s what the XRDP connection screen looks like.
|
||||
|
||||
![][5]
|
||||
|
||||
### Things to keep in mind about using XRDP
|
||||
|
||||
While XRDP works great for getting remote access to machine, it’s important to know what XRDP _**isn’t**_ good at.
|
||||
|
||||
#### Do _n**ot**_ use XRDP if you need a secure connection
|
||||
|
||||
Connections made over XRDP can be viewed and modified by attackers, and should thus be avoided for any sensitive information. This can be alleviated through the use of an SSH connection or certificates, but both require a more complex setup and won’t be covered here.
|
||||
|
||||
#### XRDP doesn’t work well with theming by default
|
||||
|
||||
In my testing, XRDP didn’t ever seem to apply the theming [Ubuntu][6] comes with by default. Instructions for fixing this are available at the end of the article.
|
||||
|
||||
#### You need a desktop environment installed on the remote computer
|
||||
|
||||
You’ll need a graphical environment installed on the machine everything will connect to for any of this to work. If you are using a desktop Linux to be accessed remotely, it’s all good.
|
||||
|
||||
But if you are using a server operating system, it won’t work. Of course, [you can install GUI on your Ubuntu server][7] but you’ll be a lot better using SSH to use the remote system via command line.
|
||||
|
||||
### Using XRDP to connect to a Ubuntu Linux system remotely
|
||||
|
||||
Here’s the setup you need for this remote connection setup to work properly.
|
||||
|
||||
* A Linux system with XRDP server installed on it. This is the system which will be accessed remotely.
|
||||
* The remote system should either be on the same network as yours or it should have a public IP address.
|
||||
* You need to know the username and password of the remote Linux system, obviously.
|
||||
* Another system (be it Linux, macOS or Windows) with an RDP client installed on it.
|
||||
|
||||
|
||||
|
||||
![][8]
|
||||
|
||||
The process is really simple. Let’s see it in steps.
|
||||
|
||||
#### Step 1: Install XRDP on the ‘remote computer’
|
||||
|
||||
I am calling it remote computer for reference only. Of course, you need to have access to it in the first place for installing the XRDP package.
|
||||
|
||||
XRDP is included in the repositories of most distributions. On Ubuntu, you can find it in the universe repository and install it using this command:
|
||||
|
||||
```
|
||||
sudo apt install xrdp
|
||||
```
|
||||
|
||||
#### Step 2: Get the IP address of the ‘remote computer’
|
||||
|
||||
You’ll need the IP address of the remote system in order to connect to it. You can [get the IP address in Linux][9] using the ip command:
|
||||
|
||||
```
|
||||
ip address
|
||||
```
|
||||
|
||||
As you can see, the system in the example has IP address 192.168.0.107. This is on the subnet, of course.
|
||||
|
||||
```
|
||||
[email protected]:~$ ip address
|
||||
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
|
||||
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
||||
inet 127.0.0.1/8 scope host lo
|
||||
valid_lft forever preferred_lft forever
|
||||
2: wlp0s20f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
|
||||
link/ether dc:46:b9:fb:7a:c5 brd ff:ff:ff:ff:ff:ff
|
||||
inet 192.168.0.107/24 brd 192.168.0.255 scope global dynamic noprefixroute wlp0s20f3
|
||||
valid_lft 6183sec preferred_lft 6183sec
|
||||
```
|
||||
|
||||
#### Step 3: Connecting to a XRDP machine from ‘local computer’
|
||||
|
||||
The good news is that XRDP works right out of the box!
|
||||
|
||||
To connect to the machine you installed XRDP on, you’ll first need to install an RDP client on your local system (from where you are trying to connect to the remote system).
|
||||
|
||||
I’ll be using GNOME Boxes in this tutorial, which can be installed with the following:
|
||||
|
||||
```
|
||||
sudo apt install gnome-boxes
|
||||
```
|
||||
|
||||
GNOME Boxes is primarily used for virtual machines but it is also a good XRDP client. You may use other tools like Remmina.
|
||||
|
||||
Start the GNOME Boxes application. Click on the + sign and select “**Connect to a Remote Computer…**“.
|
||||
|
||||
![][10]
|
||||
|
||||
Next, enter the IP address of the machine you’re connecting to, prefixed with `rdp://`, and then connect as shown below:
|
||||
|
||||
![][11]
|
||||
|
||||
In the above example, I deployed an Ubuntu server on Linode cloud server. I also installed GNOME desktop on it. This server has a public IP address that can be accessed from anywhere. I have used the public IP address.
|
||||
|
||||
You should then be presented with a login screen. Keep “Session” set to “Xorg”, and just enter your username and password, then click “OK”:
|
||||
|
||||
![][5]
|
||||
|
||||
After, you should be presented with your desktop:
|
||||
|
||||
![][12]
|
||||
|
||||
And now you’re good to go! Everything will (mostly – more on that below) behave just the same as if the machine was right in front of you.
|
||||
|
||||
### Troubleshooting: Fixing theming issues with XRDP connection
|
||||
|
||||
In my testing on Ubuntu 20.04, the default Yaru theme didn’t seem to apply by default when connecting over. This can be fixed with some effort.
|
||||
|
||||
First, run this command on the **remote computer**:
|
||||
|
||||
```
|
||||
sudo apt install gnome-tweaks gnome-shell-extensions dconf-editor -y
|
||||
```
|
||||
|
||||
Next, open the Extensions app, and turn on the toggles shown below:
|
||||
|
||||
![][13]
|
||||
|
||||
Next, close your remote desktop session and log back in. Now, open up Tweaks and configure everything per the screenshot below:
|
||||
|
||||
![][14]
|
||||
|
||||
Lastly, open up dconf Editor, and navigate to `/org/gnome/shell/extensions/dash-to-dock/`. Set the values that are shown below:
|
||||
|
||||
* `custom-theme-shrink`: On
|
||||
* `dock-fixed`: On
|
||||
* `transparency-mode`: FIXED
|
||||
|
||||
|
||||
|
||||
And there you go, everything is good to go!
|
||||
|
||||
### Wrapping up
|
||||
|
||||
This should help you get started with XRDP on Ubuntu and other Linux systems. This is a convenient tool for connecting to remote systems, specially on the same network.
|
||||
|
||||
If something didn’t work quite right, or you just have any questions or comments, feel free to leave them below. I’ll try to help you out.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/xrdp-ubuntu/
|
||||
|
||||
作者:[Hunter Wittenborn][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/hunter/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://en.wikipedia.org/wiki/Remote_Desktop_Protocol
|
||||
[2]: https://en.wikipedia.org/wiki/Xrdp
|
||||
[3]: https://remmina.org/
|
||||
[4]: https://wiki.gnome.org/Apps/Boxes
|
||||
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/05/xrdp_connected_login.png?resize=716%2C582&ssl=1
|
||||
[6]: https://ubuntu.com/
|
||||
[7]: https://itsfoss.com/install-gui-ubuntu-server/
|
||||
[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/05/xrdp-ubuntu.png?resize=800%2C450&ssl=1
|
||||
[9]: https://itsfoss.com/check-ip-address-ubuntu/
|
||||
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/05/xrdp_gnome-boxes_connect-begin.png?resize=744%2C580&ssl=1
|
||||
[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/05/xrdp_gnome-boxes_rdp-connect.png?resize=757%2C514&ssl=1
|
||||
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/05/xrdp_connected_homescreen.png?resize=711%2C595&ssl=1
|
||||
[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/05/xrdp_extensions.png?resize=800%2C557&ssl=1
|
||||
[14]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2021/05/xrdp_tweaks.png?resize=800%2C550&ssl=1
|
190
translated/tech/20210414 4 tips for context switching in Git.md
Normal file
190
translated/tech/20210414 4 tips for context switching in Git.md
Normal file
@ -0,0 +1,190 @@
|
||||
[#]: subject: (4 tips for context switching in Git)
|
||||
[#]: via: (https://opensource.com/article/21/4/context-switching-git)
|
||||
[#]: author: (Olaf Alders https://opensource.com/users/oalders)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (Chao-zhi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
Git 中内容分支切换的 4 个方案
|
||||
======
|
||||
比较 Git 中四种切换分支的方法的优缺点。
|
||||
![打开文件或窗口的计算机屏幕][1]
|
||||
|
||||
所有需要大量使用 Git 的人都会用到分支切换。有时这仅仅占用少量时间和精力,但有时,这个操作会带来一段痛苦的经历。
|
||||
|
||||
让我们用以下这个例子来讨论一些处理上下文转换的常用策略的优缺点:
|
||||
|
||||
> 假设您在一个名为 `feature-X` 的分支中工作。你刚刚发现你需要解决一个无关的问题。这不能在 `feature-X` 中完成。你需要在一个新的分支 ` feature-Y` 中完成这项工作。
|
||||
|
||||
### 方案 1:stash + branch
|
||||
|
||||
解决此问题最常见的工作流可能如下所示:
|
||||
|
||||
1. 终止分支 `feature-X` 上的工作
|
||||
2. `git stash`
|
||||
3. `git checkout -b feature-Y origin/main`
|
||||
4. 一顿鼓捣,解决 `feature-Y` 的问题
|
||||
5. `git checkout feature-X` 或 `git switch -`
|
||||
6. `git stash pop`
|
||||
7. 继续在 `feature-X` 中工作
|
||||
|
||||
|
||||
|
||||
**优点:** 这种方法的优点在于,对于简单的更改,这是一个相当简单的工作流。它可以很好地工作,特别是对于小型仓库。
|
||||
|
||||
**缺点:** 使用此工作流时,一次只能有一个工作区。另外,根据仓库的状态,使用 stash 是一个麻烦的环节。
|
||||
|
||||
### 方案 2:WIP commit + branch
|
||||
|
||||
这个解决方案和前一个非常相似,但是它使用 WIP(Workin Progress)提交而不是 stash。当您准备好切换回来,而不是弹出 stash 时,`git reset HEAD~1` 会展开 WIP 提交,您可以自由地继续,就像之前的方案一样,但不会触及 stash。
|
||||
|
||||
1. 终止分支 `feature-X` 上的工作
|
||||
2. `git add -u` (仅仅添加修改和删除的操作)
|
||||
3. `git commit -m "WIP"`
|
||||
4. `git checkout -b feature-Y origin/master`
|
||||
5. 一顿鼓捣,解决 `feature-Y` 的问题
|
||||
6. `git checkout feature-X` 或 `git switch -`
|
||||
7. `git reset HEAD~1`
|
||||
|
||||
|
||||
|
||||
**优点:** 对于简单的更改,这是一个简单的工作流,对于小型仓库来说很好用。你不需要使用 stash。
|
||||
|
||||
**缺点:** 任何时候都只能有一个工作区。此外,如果您或您的代码审阅者不够谨慎,WIP 提交可能会合并到最终产品。
|
||||
|
||||
使用此工作流时,您**永远**不要想着将 `--hard` 添加到 `git reset`。如果您不小心这样做了,您应该能够使用 `git reflog` 恢复提交,但是您最好完全避免这种情况发生,否则你会听到心碎的声音。
|
||||
|
||||
### 方案 3: 克隆一个新仓库
|
||||
|
||||
在这个解决方案中,不是创建新的分支,而是为每个新的功能分支创建存储库的新克隆。
|
||||
|
||||
**优点:** 您可以同时在多个工作区中工作。你不需要 `git stash` 或者是 WIP 提交。
|
||||
|
||||
**缺点:** 需要考虑仓库的大小,因为这可能会占用大量磁盘空间(浅层克隆可以帮助解决这种情况,但它们可能并不总是很合适。)此外,您的仓库克隆将互不可知。因为他们不能互相追踪,所以你必须手动追踪你的克隆的源仓库。如果需要 git 钩子,则需要为每个新克隆设置它们。
|
||||
|
||||
### 方案 4: git worktree
|
||||
|
||||
要使用此解决方案,您可能需要了解 `git add worktree`。如果您不熟悉 Git 中的 worktrees,请不要难过。许多人多年来都对这个概念一无所知。
|
||||
|
||||
#### 什么是 worktree?
|
||||
|
||||
将 worktree 视为仓库中属于项目的文件。本质上,这是一种工作空间。你可能没有意识到你已经在使用 worktrees 了。开始使用 Git 时,您将自动获得第一个 worktree。
|
||||
|
||||
```
|
||||
$ mkdir /tmp/foo && cd /tmp/foo
|
||||
$ git init
|
||||
$ git worktree list
|
||||
/tmp 0000000 [master]
|
||||
```
|
||||
|
||||
你可以在以上代码看到,甚至在第一次 commit 前你就有了一个 worktree。接下来去尝试再添加一个 worktree 到你的项目中吧。
|
||||
|
||||
#### 添加一个 worktree
|
||||
|
||||
想要添加一个新的 worktree 你需要提供:
|
||||
|
||||
1. 硬盘上的一个位置
|
||||
2. 一个分支名
|
||||
3. 添加哪些分支
|
||||
|
||||
|
||||
|
||||
```
|
||||
$ git clone <https://github.com/oalders/http-browserdetect.git>
|
||||
$ cd http-browserdetect/
|
||||
$ git worktree list
|
||||
/Users/olaf/http-browserdetect 90772ae [master]
|
||||
|
||||
$ git worktree add ~/trees/oalders/feature-X -b oalders/feature-X origin/master
|
||||
$ git worktree add ~/trees/oalders/feature-Y -b oalders/feature-Y e9df3c555e96b3f1
|
||||
|
||||
$ git worktree list
|
||||
/Users/olaf/http-browserdetect 90772ae [master]
|
||||
/Users/olaf/trees/oalders/feature-X 90772ae [oalders/feature-X]
|
||||
/Users/olaf/trees/oalders/feature-Y e9df3c5 [oalders/feature-Y]
|
||||
```
|
||||
|
||||
与大多数其他 Git 命令一样,需要在仓库路径下使用此命令。一旦创建了 worktree ,就有了隔离的工作环境。Git 仓库跟踪 worktree 在磁盘上的位置。如果 Git 钩子已经在父仓库中设置好了,那么它们也可以在 worktree 中使用。
|
||||
|
||||
请注意到,每个 worktree 只使用父仓库磁盘空间的一小部分。在这种情况下,worktree 需要只大约三分之一的原始磁盘空间。这这非常适合进行扩展。如果您的仓库达到了千兆字节的级别,您就会真正体会到 worktree 对硬盘空间的节省。
|
||||
|
||||
```
|
||||
$ du -sh /Users/olaf/http-browserdetect
|
||||
2.9M
|
||||
|
||||
$ du -sh /Users/olaf/trees/oalders/feature-X
|
||||
1.0M
|
||||
```
|
||||
|
||||
**优点:** 您可以同时在多个工作区中工作。你不需要使用 stash。Git 跟踪所有的 worktree。你不需要设置 Git 钩子。这也比 `git clone` 更快,并且可以节省网络流量,因为您可以在飞行模式下执行此操作。您还可以更高效地使用磁盘空间,而无需使用浅层克隆。
|
||||
|
||||
**缺点:** 这是个需要你额外学习和记忆的新东西,但是如果你能养成使用这个功能的习惯,它会给你丰厚的回报。
|
||||
|
||||
### 额外的小技巧
|
||||
|
||||
有很多方式可以清除 worktrees,最受欢迎的方式是使用 Git 来移除 worktree:
|
||||
|
||||
|
||||
```
|
||||
`git worktree remove /Users/olaf/trees/oalders/feature-X`
|
||||
```
|
||||
|
||||
如果你喜欢 rm 大法,你也可以用 `rm -rf` 来删除 worktree。
|
||||
|
||||
|
||||
```
|
||||
`rm -rf /Users/olaf/trees/oalders/feature-X`
|
||||
```
|
||||
|
||||
但是,如果执行此操作,则可能需要使用 `git worktree prune` 清理所有剩余的文件。或者您现在可以跳过 `prune`,这将在将来的某个时候通过 `git gc` 自行完成。
|
||||
|
||||
### 注意事项
|
||||
|
||||
如果你准备尝试 `git worktree`, 请记住以下几点:
|
||||
|
||||
* 删除 worktree 不会删除分支。
|
||||
* 可以在 worktree 中切换分支。
|
||||
* 不能同时签出多个 worktree 中的同一分支。
|
||||
* 像其他命令一样,`git worktree` 需要从仓库内运行。
|
||||
* 你可以同时拥有许多 worktree。
|
||||
* 要从同一个本地签出创建 worktree,否则它们将互不可知。
|
||||
|
||||
|
||||
|
||||
### git rev-parse
|
||||
|
||||
最后一点注意:在使用 `git worktree` 时,仓库根所在的位置可能取决于文本。幸运的是,`git rev parse`允许您区分这两者。
|
||||
|
||||
* 要查找父仓库的根目录,请执行以下操作:
|
||||
|
||||
```
|
||||
git rev-parse --git-common-dir
|
||||
```
|
||||
|
||||
* 要查找你当前所在仓库的更目录,请执行:
|
||||
|
||||
```
|
||||
git rev-parse --show-toplevel
|
||||
```
|
||||
|
||||
|
||||
### 根据你的需要选择最好的方法
|
||||
|
||||
就像很多事情一样,TIMTOWDI (there's more than one way to do it,有不止一种方法解决问题)。重要的是你要找到一个适合你需要的工作流程。您的需求可能因手头的问题而异。也许你偶尔会发现自己将 `git worktree` 作为版本控制工具箱中的一个方便工具。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/4/context-switching-git
|
||||
|
||||
作者:[Olaf Alders][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[Chao-zhi](https://github.com/Chao-zhi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/oalders
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_screen_windows_files.png?itok=kLTeQUbY (Computer screen with files or windows open)
|
@ -1,231 +0,0 @@
|
||||
[#]: subject: "Drop Autotools for CMake"
|
||||
[#]: via: "https://opensource.com/article/21/5/cmake"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "amwps290"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
抛弃 Autotools 向 CMake 迈进吧
|
||||
======
|
||||
|
||||
CMake 是一个跨平台的编译,测试和打包软件,即使你以前从来没有使用过构建系统,也可以轻松上手。
|
||||
|
||||
![Someone wearing a hardhat and carrying code ][1]
|
||||
|
||||
在我以前的文章 [Autotools 入门][2] 一文中,我说明了如何使用 Autotools 来管理和打包代码。这是一个强大且通用的平台,可轻松集成到许多包系统中,包括 RPM,APT,[pkgsrc][3] 以及一些其他平台。它的语法和结构可能会令人困惑,但幸运的是,我们还有其他选择,开源的 [CMake][4] 就是其中一个。
|
||||
|
||||
CMake 是一个用于构建,测试和打包软件的跨平台套件。 它使用简单且语法比较清晰明了,因此即使您以前从未使用过构建系统,也很容易开始使用。
|
||||
|
||||
### 安装 CMake
|
||||
|
||||
CMake 可能已经安装在您的 Linux 系统上。 如果没有,您可以使用发行版的程序包管理器进行安装:
|
||||
|
||||
```
|
||||
`$ sudo dnf install cmake`
|
||||
```
|
||||
|
||||
在 Debian 或者其他相似的系统上:
|
||||
|
||||
```
|
||||
`$ sudo apt install cmake`
|
||||
```
|
||||
|
||||
在 Mac 上,你可以使用 [MacPorts][5] 或者 [Homebrew][6] 来安装:
|
||||
|
||||
|
||||
```
|
||||
`$ sudo port install cmake`
|
||||
```
|
||||
|
||||
在 Windows 上,你可以使用 [Chocolatey][7] 或者直接从 [CMake 网站][8]下载二进制来安装。
|
||||
|
||||
### 使用 CMake
|
||||
|
||||
对于想要从源代码构建软件的开发人员或用户来说,CMake 是一种快速简便的编译和安装方法。 CMake 分阶段工作:
|
||||
|
||||
1. 首先,在 `cmake` 步骤中,CMake 扫描计算机查看一些默认设置。 默认设置包括库的位置以及在系统上安装软件的位置。
|
||||
2. 接下来,使用系统上的 `make` 命令(在 Linux 上是 GUN Make,在 [NetBSD][9] 上是 NetBSD Make)来编译程序。这个过程通常是将人类可读的源代码转换成机器语言。
|
||||
3. 最后,在 `make install` 一步中,那些编译过的文件将被拷贝到计算机上合适的位置(在 `cmake` 步骤中扫描出来的)。
|
||||
|
||||
这看起来很简单,该你来使用 CMake 了。
|
||||
|
||||
### CMake 的可移植性
|
||||
|
||||
|
||||
CMake 在设计时就考虑了可移植性。 虽然它不能使您的项目在所有 POSIX 平台上都能正常工作(作为程序员这可能由你决定),但它可以确保将标记为要安装的文件安装到已知平台上最合适的位置。 而且由于有了 CMake 之类的工具,对于高级用户而言,根据其系统需求自定义和覆盖任何不合适的选项都很容易。
|
||||
|
||||
使用 CMake,您只需要知道将哪些文件安装到哪个常规位置即可。 它会照顾其他一切。 不再有在任何未经测试的操作系统上失败的自定义安装脚本。
|
||||
|
||||
### 打包
|
||||
|
||||
像 Autotools 一样,CMake 也得到了很好的打包支持。 无论他们是打包成 RPM 还是 DEB 或 TGZ(或其他任何东西),将带有 CMake 的项目交给打包者,他们的工作既简单又直接。 打包工具了解 CMake,因此可能不需要进行任何修补或者调整。 在许多情况下,可以自动将 CMake 项目整合到工作流中。
|
||||
|
||||
### 如何使用 CMake
|
||||
|
||||
要在项目中使用 CMake,只需在项目目录中创建 `CMakeLists.txt` 文件。 首先,声明最低要求的 CMake 版本以及项目名称和版本。 CMake 会努力保持尽可能长时间的兼容性,但是随着您使用时间的越来越长并且关注它最新的开发动态,您就会知道哪些特性是你所依赖的。
|
||||
|
||||
|
||||
```
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(Hello VERSION 1.0)
|
||||
```
|
||||
|
||||
如您可能已经看到的那样,CMake 的语法是一个带有括号和参数的命令。 大写的 `VERSION` 字符串不是任意的,也不只是格式。 它们是 `project` 命令中的有效参数。
|
||||
|
||||
在继续之前,先写一个简单的 C 或者 C++ 的 `hello world` 程序。为了简单,我就写了六行 C 代码,并把它保存在 `hello.c` 中(为了匹配我在 `CMakeLists.txt` 中可执行文件在名字)。
|
||||
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
[printf][10]("Hello open source\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
毫无疑问,CMake 不仅适用于 C 和 C++。 它可以处理任意文件,并且具有许多可用的命令,因此它可以帮助您维护许多不同形式的项目。
|
||||
|
||||
CMake 网站中的文档有所有有效的内置命令及其可用参数,因此无论您要做什么,都可以轻松发现所需的功能。 不过,这是一个简单的示例,因此,您需要的下一个命令是必不可少的——您必须为 CMake 定义要构建的代码:
|
||||
|
||||
```
|
||||
`add_executable(Hello hello.c)`
|
||||
```
|
||||
|
||||
这个命令指定了你编译后的二进制文件的名字。因此,它与您在终端中执行带有 `-o Hello` 的 `gcc` 命令是一样的。
|
||||
|
||||
在一些比较复杂的项目中,您可能还需要使用库文件,你可以使用 `add library` 命令来链接库文件。
|
||||
|
||||
在你已经定义你要编译的文件并且标记了你要安装。你必须要告诉 CMake 一旦用户安装了程序,最终的应用程序应该在哪个位置。
|
||||
|
||||
在这个简单的例子里,你仅需要做的一件事就是在你的 `CMakeLists.txt` 文件里添加 `install ` 命令。`install ` 命令接受几个参数。但是在这个例子中,你仅需要使用 `TARGET` 命令来指定你要安装文件的名字。
|
||||
|
||||
|
||||
```
|
||||
`install(TARGETS Hello)`
|
||||
```
|
||||
|
||||
### 向 CMake 工程添加一些文件
|
||||
|
||||
一个软件项目向用户交付的不仅仅只有代码,还有一些其他的文件数据,例如手册或者是信息页。示例项目,或者是配置文件。 您可以使用与包含编译文件时类似的工作流程,将任意数据包含在 CMake 项目中:在 `CMakelists.txt` 文件中使用 file 命令,然后说明一下这些文件要安装在哪里。
|
||||
|
||||
例如,你可以在这个项目中包含一个 `assets` 目录,你可以使用 `file` 命令,后面跟上 `COPY` 和 `DESTINATION` 参数来告诉 CMake 将这些额外的文件拷贝到你的发行包中。
|
||||
|
||||
```
|
||||
`file(COPY assets DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")`
|
||||
```
|
||||
|
||||
这个 `${CMAKE_CURRENT_BINARY_DIR}` 变量是一个特殊的 CMake 内置变量,表示 CMake 正在处理的这个目录。换句话说,你的任何文件都会被拷贝到编译目录(等你执行完来 `cmake` 命令,这个过程会更加清晰,到时候回过头来看一下)。
|
||||
|
||||
因为这些额外的数据文件有些杂乱不堪(如果你不信我的话,可以看一下 `/usr/share` 这个目录)。对于你自己的项目创建一个子文件夹是对谁都有好处的。最好也带上版本名字。你可以通过 `CMAKE_CURRENT_BINARY_DIR` 后边加上你的项目名字和版本名字来指定一个新目录。
|
||||
|
||||
|
||||
```
|
||||
`file(COPY assets DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/Hello-${Hello_VERSION}")`
|
||||
```
|
||||
|
||||
### 定义安装位置
|
||||
|
||||
你已经定义你要编译的文件,因此现在你要告诉 CMake 你的程序要安装在哪个位置。比如你的主程序。这个要程使用 `install` 命令:
|
||||
|
||||
|
||||
```
|
||||
`install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Hello-${Hello_VERSION}" TYPE DATA)`
|
||||
```
|
||||
|
||||
这里有一些新的参数。`DIRECTORY` 参数指定了数据文件是一个目录(而不是一个文件或者脚本)。你使用了和复制一些额外文件到编译目录时一样的参数。另外, 在 `install` 命令中 `TYPE` 或者 `DESTINATION` 中的一个必须要指定。`TYPE` 参数指定了通用的文件类型,这些文件通常将会被放到合适的位置。在 Linux 系统上,`TYPE DATA` 一般是 `/usr/local/share` 或者 `/usr/share`,除非用户定义了其他的位置。
|
||||
|
||||
这是诸如 CMake 之类的良好构建系统的强大功能之一。 您不必担心文件的确切位置,因为您知道用户可以更改 CMake 其首选默认设置,并且 CMake 将构建代码以使其正常工作。
|
||||
|
||||
### 运行 CMake
|
||||
|
||||
CMake 有多种方式来让你执行命令,你可以在终端或者在一个可交互的程序上执行命令,或者你也可以使用它的图形界面(GUI)。我比较偏向于使用终端命令,但是我也喜欢使用一些其他的方式(相比与在 Makefile 中查找那些晦涩的变量然后去修改他们,其他方式的确远胜一筹)。
|
||||
|
||||
对于编译那些的开源 C++ 项目的任何人都熟悉的第一步是创建一个 `build` 目录,进入到该目录,然后运行 `cmake ..` 命令。 我是一个懒惰的打字员,所以我将构建目录命名为`b`,但是您可以使用最合适的方法:
|
||||
|
||||
|
||||
```
|
||||
$ mkdir b$ cd b$ cmake ..\-- The C compiler identification is GNU 11.1.1\-- The CXX compiler identification is GNU 11.1.1\-- Detecting C compiler ABI info\-- Detecting C compiler ABI info - done\-- Check for working C compiler: /usr/bin/cc - skipped\-- Detecting C compile features\-- Detecting C compile features - done\-- Detecting CXX compiler ABI info\-- Detecting CXX compiler ABI info - done\-- Check for working CXX compiler: /usr/bin/c++ - skipped\-- Detecting CXX compile features\-- Detecting CXX compile features - done\-- Configuring done\-- Generating done\-- Build files have been written to: /var/home/seth/demo-hello/b$
|
||||
```
|
||||
|
||||
和传统的 `./configure; make; make install` 过程相比,与 `./configure` 这个步骤的相对应输出,谁多谁少。看一下你的构建目录,CMake 已经帮你生成了几个新的文件来让你的项目更完整。这里生成了 CMake 的数据文件,一个常规的 Makefile 文件(这是一个免费提供的 247 行的文件,但对于越复杂的项目,文件行数越多),还有一个包含这个示例程序的任意的非编译数据的 `Hello-1.0` 目录。
|
||||
|
||||
```
|
||||
$ lsCMakeCache.txtCMakeFilesMakefileHello-1.0cmake_install.cmake
|
||||
```
|
||||
|
||||
接下来,运行一下 `make` 命令,这将会读取由 CMake 生成的 `Makefile`。在这个例子中,Make 默认的行为就是由源程序 `hello.c` 生成目标文件。
|
||||
|
||||
```
|
||||
$ makeScanning dependencies of target Hello[ 50%] Building C object CMakeFiles/Hello.dir/hello.c.o[100%] Linking C executable Hello[100%] Built target Hello$
|
||||
```
|
||||
|
||||
如您所料,`Hello` 二进制可执行文件现在存在于当前的构建目录中。 因为它是一个简单的自包含应用程序,所以您可以运行一下它看一下效果是否和您想的一致:
|
||||
|
||||
```
|
||||
$ ./HelloHello open source$
|
||||
```
|
||||
|
||||
最后,运行一下 `make install` 来调用 `Makefile` 中的安装步骤。因为我不想让这个简单的 "hello world" 程序安装到我的系统中。因此,我通过设置 `DESTDIR` 变量来将 CMake 的目标位置从根目录(`/`) 变成了它的子目录 `/tmp`:
|
||||
|
||||
|
||||
```
|
||||
$ mkdir /tmp/dist-hello$ make install DESTDIR=/tmp/dist-hello[100%] Built target HelloInstall the project...\-- Install configuration: ""\-- Installing: /tmp/dist-hello/usr/local/bin/Hello\-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0\-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0/assets/file0\-- Installing: /tmp/dist-hello/usr/local/share/Hello-1.0/assets/file1
|
||||
```
|
||||
|
||||
看一下输出的内容,来确定它具体的安装位置,这个程序已经安装好了。
|
||||
|
||||
### 快速自定义
|
||||
|
||||
CMake 的安装路径(由 `CMAKE_INSTALL_PREFIX` 变量指定的)默认是在 `/usr/local` 这个位置,但是所有的 CMake 变量都可以在你运行 `cmake` 命令的时候,加一个 `-D` 选项来改变它。
|
||||
|
||||
```
|
||||
$ cmake -DCMAKE_INSTALL_PREFIX=/usr ..$ make install DESTDIR=/tmp/dist-hello$ make install DESTDIR=/tmp/dist-hello[100%] Built target HelloInstall the project...\-- Install configuration: ""\-- Installing: /tmp/dist-hello/usr/bin/Hello\-- Installing: /tmp/dist-hello/usr/share/Hello-1.0\-- Installing: /tmp/dist-hello/usr/share/Hello-1.0/assets/file0\-- Installing: /tmp/dist-hello/usr/share/Hello-1.0/assets/file1
|
||||
```
|
||||
|
||||
所有由 CMake 使用的变量都可以通过这种方式来修改
|
||||
|
||||
### 交互式的 CMake
|
||||
|
||||
CMake 的交互模式是一种用于配置安装环境的友好而有用的方法。 要让用户知道该项目使用的所有可能的 CMake 变量却是一件工程量很大的事,因此 CMake 交互式界面是他们无需查看 Makefile 和 CMakeLists 即可发现自定义选项的简便方法。
|
||||
|
||||
为了调用这个交互式的 CMake, 使用 `ccmake` 命令,在这个简单的项目里没有太多的东西。但是对于像 [Rosegarden][11] 这样的大型项目,这将非常有用。
|
||||
|
||||
![Rosegarden][12]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][13])
|
||||
|
||||
### CMake 的更多知识
|
||||
|
||||
还有很多很多的 CMake 知识需要去了解。作为一个开发者,我非常喜欢他简洁的语法,详尽的文档,可扩展性以及便捷性。作为一个用户我非常喜欢 CMake 友好且实用的错误提示信息还有它的界面,如果您的项目还未开始使用构建系统,看一眼 CMake 吧。您以及以后尝试打包您应用程序的任何人都不会后悔。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/cmake
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[amwps290](https://github.com/amwps290)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/build_structure_tech_program_code_construction.png?itok=nVsiLuag "Someone wearing a hardhat and carrying code "
|
||||
[2]: https://opensource.com/article/19/7/introduction-gnu-autotools
|
||||
[3]: https://opensource.com/article/19/11/pkgsrc-netbsd-linux
|
||||
[4]: http://cmake.org
|
||||
[5]: https://opensource.com/article/20/11/macports
|
||||
[6]: https://opensource.com/article/20/6/homebrew-linux
|
||||
[7]: https://opensource.com/article/20/3/chocolatey
|
||||
[8]: https://cmake.org/download
|
||||
[9]: https://opensource.com/article/19/3/netbsd-raspberry-pi
|
||||
[10]: http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
|
||||
[11]: https://opensource.com/article/18/3/make-sweet-music-digital-audio-workstation-rosegarden
|
||||
[12]: https://opensource.com/sites/default/files/uploads/rosegarden-ccmake.jpg "Rosegarden"
|
||||
[13]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[14]: https://cmake.org/cmake/help/latest/
|
@ -7,19 +7,18 @@
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
Are you using this magic method for filesystems from Python 3.6?
|
||||
你有在使用 Python 3.6 中针对文件系统的这个神奇方法吗?
|
||||
======
|
||||
Explore os.fspath and two other underutilized but still useful Python
|
||||
features.
|
||||
探索 os.fspath 和其他两个未被充分利用但仍然有用的 Python 特性。
|
||||
![Computer screen with files or windows open][1]
|
||||
|
||||
This is the seventh in a series of articles about features that first appeared in a version of Python 3.x. Python 3.6 was first released in 2016, and even though it has been out for a while, many of the features it introduced are underused and pretty cool. Here are three of them.
|
||||
这是关于首次出现在 Python 3.x 版本中的特性的系列文章中的第七篇。Python 3.6 首次发布于 2016 年,尽管它已经发布了一段时间,但它引入的许多特性都没有得到充分利用,而且相当酷。下面是其中的三个。
|
||||
|
||||
### Separated numeral constants
|
||||
### 分隔数字常数
|
||||
|
||||
Quick, which is bigger, `10000000` or `200000`? Would you be able to answer correctly while scanning through code? Depending on local conventions, in prose writing, you would use 10,000,000 or 10.000.000 for the first number. The trouble is, Python uses commas and periods for other reasons.
|
||||
快,哪个更大,`10000000` 还是 `200000`?你在看代码时能正确回答吗?根据当地的习惯,在写作中,你会用 10,000,000 或 10.000.000 来表示第一个数字。问题是,Python 使用逗号和句号是用于其他地方。
|
||||
|
||||
Fortunately, since Python 3.6, you can use underscores to separate digits. This works both directly in code and when using the `int()` convertor from strings:
|
||||
幸运的是,从 Python 3.6 开始,你可以使用下划线来分隔数字。这在代码中和使用字符串的 `int()` 转换器时都可以使用:
|
||||
|
||||
|
||||
```
|
||||
@ -29,11 +28,11 @@ math.log(10_000_000) / math.log(10)
|
||||
[/code] [code]` 7.0`[/code] [code]`math.log(int("10_000_000")) / math.log(10)`[/code] [code]` 7.0`
|
||||
```
|
||||
|
||||
### Tau is right
|
||||
### Tau 是对的
|
||||
|
||||
What's a 45-degree angle expressed in radians? One correct answer is `π/4`, but that's a little hard to remember. It's much easier to remember that a 45-degree angle is an eighth of a turn. As the [Tau Manifesto][2] explains, `2π`, called `Τ`, is a more natural constant.
|
||||
45 度角用弧度表示是多少?一个正确的答案是 `π/4`,但这有点难记。记住 45 度角是一个八分之一的转角要容易得多。正如 [Tau Manifesto][2] 所解释的,`2π`,称为 `Τ`,是一个更自然的常数。
|
||||
|
||||
In Python 3.6 and later, your math code can use the more intuitive constant:
|
||||
在 Python 3.6 及以后的版本中,你的数学代码可以使用更直观的常数:
|
||||
|
||||
|
||||
```
|
||||
@ -50,13 +49,13 @@ print("Sin of a quarter turn should be 1, go", round(math.sin(math.tau/4), 2))
|
||||
|
||||
### os.fspath
|
||||
|
||||
Starting in Python 3.6, there is a magic method that represents "convert to a filesystem path." When given an `str` or `bytes`, it returns the input.
|
||||
从 Python 3.6 开始,有一个神奇的方法表示”转换为文件系统路径“。当给定一个 `str` 或 `bytes` 时,它返回输入。
|
||||
|
||||
For all types of objects, it looks for an `__fspath__`method and calls it. This allows passing around objects that are "filenames with metadata."
|
||||
对于所有类型的对象,它寻找 `__fspath__` 方法并调用它。这允许传递的对象是”带有元数据的文件名“。
|
||||
|
||||
Normal functions like `open()` or `stat` will still be able to use them, as long as `__fspath__` returns the right thing.
|
||||
像 `open()` 或 `stat` 这样的普通函数仍然能够使用它们,只要 `__fspath__` 返回正确的东西。
|
||||
|
||||
For example, here is a function that writes some data into a file and then checks its size. It also logs the file name to standard output for tracing purposes:
|
||||
例如,这里有一个函数将一些数据写入一个文件,然后检查其大小。它还将文件名记录到标准输出,以便追踪:
|
||||
|
||||
|
||||
```
|
||||
@ -67,7 +66,7 @@ def write_and_test(filename):
|
||||
print("size of", filename, "is", os.path.getsize(filename))
|
||||
```
|
||||
|
||||
You can call it the way you would expect, with a string for a filename:
|
||||
你可以用你期望的方式来调用它,用一个字符串作为文件名:
|
||||
|
||||
|
||||
```
|
||||
@ -77,7 +76,7 @@ You can call it the way you would expect, with a string for a filename:
|
||||
size of plain.txt is 5
|
||||
```
|
||||
|
||||
However, it is possible to define a new class that adds information to the string representation of filenames. This allows the logging to be more detailed, without changing the original function:
|
||||
然而,可以定义一个新的类,为文件名的字符串表示法添加信息。这样可以使日志记录更加详细,而不改变原来的功能:
|
||||
|
||||
|
||||
```
|
||||
@ -91,7 +90,7 @@ class DocumentedFileName:
|
||||
return f"DocumentedFileName(fname={self.fname!r}, why={self.why!r})"
|
||||
```
|
||||
|
||||
Running the function with a `DocumentedFileName` instance as input allows the `open` and `os.getsize` functions to keep working while enhancing the logs:
|
||||
用 `DocumentedFileName` 实例作为输入运行该函数,允许 `open` 和 `os.getsize` 函数继续工作,同时增强日志:
|
||||
|
||||
|
||||
```
|
||||
@ -101,9 +100,9 @@ Running the function with a `DocumentedFileName` instance as input allows the `o
|
||||
size of DocumentedFileName(fname='documented.txt', why="because it's fun") is 5
|
||||
```
|
||||
|
||||
### Welcome to 2016
|
||||
### 欢迎来到 2016 年
|
||||
|
||||
Python 3.6 was released about five years ago, but some of the features that first showed up in this release are cool—and underused. Add them to your toolkit if you haven't already.
|
||||
Python 3.6 是在五年前发布的,但是在这个版本中首次出现的一些特性非常酷,而且没有得到充分利用。如果你还没使用,那么将他们添加到你的工具箱中。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user