热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux编程|使用make

目录简单的makefile文件常规的makefile文件常用参数make内置规则后缀和模式规则make管理函数库在Linux环境中,make是一个非常重要的编译命令

目录

简单的 makefile 文件
常规的 makefile 文件
常用参数
make 内置规则
后缀和模式规则
make 管理函数库






在Linux 环境中,make 是一个非常重要的编译命令。不管是自己进行项目还是安装应用软件,用户经常会用到 make 或 make install 命令。

make 与 makefile 文件

make 工具,可以将大型的开发项目分解成多个更易于管理的模块。对于含有多个源文件的应用程序,使用 makemakefile 工具就可以简洁明快地理顺各个源文件之间纷繁复杂的相互关系。另外,make工具简化了编译程序的步骤,以及拥有根据源文件的更新情况进行部分编译的功能,使make 工具可以大大提高项目开发的效率,也可以减少程序中出现的错误。

用法:make [选项] [目标] ...

虽然make命令内置了很多智能机制,但光凭其自身是无法了解应该如何建立应用程序的。你必须为其提供一个文件,告诉它应用程序应该如何构造,这个文件称为 makefile 文件。 make 工具最主要最基本的功能就是通过 makefile 文件来描述源程序之间的互相关系并自动维护编译工作。而 makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并链接生成可执行文件,并要求定义源文件之间的依赖关系。

makefile文件一般都会和项目的其他源文件放在同一目录下。你的机器上可以同时存在许多不同的 makefile文件。事实上,如果管理的是一个大项目,你可以用多个不同的 makefile文件来分别管理项目的不同部分。

make命令和 makefile 文件的结合提供了一个在项目管理领域十分强大的工具。它不仅常被用于控制源代码的编译,而且还用于手册页的编写以及将应用程序安装到目标目录。

工作原理

在这里插入图片描述———图片来自网络,侵权删除

make 运用——多文件管理

对 make 的简单应用,对多文件的管理。在拥有多个源文件时,就不能使用 gcc -o a.out main.c 命令一步编译完成,通常需要先将所有源文件编译,然后再将所有的编译后的文件链接在一起形成可执行文件。通常这个过程都需要两行及其以上的命令才可以完成,这会使得编译步骤变得很繁琐,通过 make 工具可以简化编译步骤。

比如,在程序中创建多个文件,在 a.h 中包含 Sum() 函数的申明,在 b.h 中包好 Max() 函数的申明。

/* a.h *
int Sum(int a, int b);/* b.h */
int Max(int a, int b);

a.cb.c 中编写如下代码

/* a.c */
int Sum(int a, int b)
{return a + b;
}/* b.h */
int Max(int a, int b)
{return a > b ? a : b;
}

main.c 中编写如下程序

/* main.c */
#include
#include
#include "a.h"
#include "b.h"int main()
{int a = 2;int b = 3;printf("max: %d",Max(a, b) );printf("Sum: %d",Sum(a, b) );return 0;
}

以上是一个多文件的程序,对该程序进行编译主要有以下两个步骤

  • 对多个源文件进行编译(*.c => *.o)
    • 命令 gcc -c 1.c 2.c 3.c ……
  • 对编译后的文件进行链接(*.o => 可执行程序)
    • 命令 gcc [-I 头文件路径] main.o 1.o 2.o 3.o …… [-L 库文件路径] [-l+库名]

在此程序中,只需要用到以下两个命令:

gcc -c a.c b.c
gcc -o main mian.o a.o b.o

如图:
创建文件(tips:使用 cat 命令编辑文件时,使用Ctrl+D结束输入)
在这里插入图片描述
编译文件
在这里插入图片描述
程序运行正常,但是我们可以看到仅仅只有三个文件就需要这么多命令,而且,如果程序需要修改,我们又需要重复一遍上述命令,稍稍显得繁琐了一些,下面让我们编写一个简单 makefile 文件,简化编译步骤吧。



make 运用——编写简单的 makefile 文件

makefile 文件的逻辑很简单,一般包含三个部分

  1. 宏定义
  2. 源文件之间的相互依赖关系
  3. 可执行的命令

make 工具依赖 makefile 中的关系进行编译,这种依赖关系在多源文件的程序编译中尤为重要,通过这种依赖关系的定义, make 工具可以避免许多不必要的编译工作。

对此文件编写 makefile 文件

# 用‘#’注释掉内容
# main 为该程序需要生成的目标文件,‘:’后面的文件为组成目标文件的依赖文件
# 第二行的首行使用Tab键缩进(首行对齐)
main: main.o a.o b.ogcc -o main main.o a.o b.o# 接下来分别说明 a.o 与 b.o 的开源,即可
# 在使用make 命令时,会在指定的目录下搜索文件,如果搜索不到文件就会报错
# 这里可以不写 a.h 和 b.h 头文件,make 会自动检索(默认为当前工作目录)
main.o: main.cgcc -c main.ca.o: a.cgcc -c a.cb.o: b.cgcc -c b.c# 这里可以使用 make clean 清理不需要的文件,比如生成的中间文件 *.o文件
# 另外,这里在 rf 命令前加了 ‘-’ ,忽略 rm 的执行结果,如在指定被删除文件不存在的情况下忽略报错信息
clean:-rm -rf *.o

在Linux 系统中,习惯使用 makefile 作为文件名,如果要使用其他文件作为 makefile,可通过 -f参数指定。

  • make -f makefile_name 该命令会执行 makefile 中指定的命令,并且在屏幕上输出命令内容

由于会对该程序编写多个 makefile 文件,这里把文件命令为 makefile1,执行 makefile1 显示“make: ‘main’ is up to date.”好像出了点小状况,没关系,只需要删除之前已经生成的 “main” 文件即可。 在这里插入图片描述
有些学过 shell 编程的小伙伴可能会问了,与其写这么麻烦还不如直接写成 shell 脚本,shell 脚本写起来可方便多了,而且也能达到相同的目的。

没有错,shell 脚本的确也可以做到。首先需要说明的是,make 工具一般主要被用来管理一个软件程序项目(用来完成大型软件的自动编译),而 shell 脚本可以说是一系列命令的集合,shell 脚本按照预先编译好的命令将会把全部的文件编译。对于一些小的程序来说,shell 脚本编写确实比 make 方便很多,但make 有一个绝对性的优势,make 在编译时,会根据目标上一次编译的时间和目标所依赖的源文件的更新时间而自动判断应当编译哪个源文件。对于一个大型项目,源文件动则成千上万文件,而开发过程中常常需要对其中的一部分文件进行改动,如果每次编译都把所有文件都编译一遍显然是不明智的。

这也解释了,为什么之前没有删除 “main” 文件,而提示 “make: ‘main’ is up to date.” 的原因了。因为组成 “main” 的所有文件都没有更新。

使用 make clean 命令

通过执行 make clean 命令执行预先设定在 makefile 文件中的命令
在这里插入图片描述

# clean 定义方式
clean:-rm -rf *.o

可以看到,clean的定义方式与我们之前学过的函数很相似,“clean” 就是函数名,冒号后面紧跟着的就是函数的具体实现。make 中还有一个命令 make install ,试想,模仿 “clean” 的写法编写 “install”

编写 make install 命令

目标 install 依赖于 main(最终生成的目标文件),所以 make 命令知道它必须首先创建 main,然后才能执行制作该目标所需的其他命令。用于制作 install 目标的规则由几个shell 脚本命令组成。由于make命令在执行规则时会调用一个shell,并且会针对每个规则使用一个新shell ,所以必须在上面每行代码的结尾加上一个反斜杠\,让所有she脚本命令在逻辑上处于同一行,并作为一个整体传递给一个shell 执行。这个命令以符号@开头,表示make在执行这些规则之前不会在标准输出上显示命令本身。

在Linux 系统下,可执行程序一般都安装在 /**/bin 目录下,常见的有

  • /bin 是所有用户都可以访问并执行的可执行程序。包括超级用户及一般用户。
  • /usr/bin 是系统安装时自带的一些可执行程序。即系统程序。
  • /usr/local/bin 是用户自行编译安装时默认的可执行程序的安装位置。

这里我们只做测试,所以把该程序安装在当前目录下的 bin 目录中

install: main@if [ -d ./bin ]; \then \cp main ./bin; \chmod a+x ./bin/main; \chmod og-w ./bin/main; \echo "Installed in ./bin"; \else \echo "Sorry, './bin' does not found"; \fi

删除所有无关文件,执行makemake insstall命令
在这里插入图片描述

目标 install 按顺序执行多个命令将应用程序安装到其最终位置。它并没有在执行下一个命令前检查前一个命令的执行是否成功。如果这点很重要,你可以将这些命令用符号&连接起来,如下所示:

install: main@if [ -d ./bin ] ; \then \cp main ./bin && \chmod a+x ./bin/main && \chmod og-w ./bin/main && \echo "Installed in ./bin" ; \else \echo "Sorry, './bin' does not found"; \fi

make 运用——带宏定义的 makefile 文件

在编写 makefile 文件之前,先了解一下 makefile 文件中的参数,这些参数可以帮助我们更好的掌握 makefile 文件的编写。



makefile 文件常见的参数

makefile 中有一些预定义的宏变量

命 令 格 式含义
AR库文件维护程序的名称,默认值为ar 创建静态库.a
AS汇编程序的名称,默认值为as
CCC编译器的名称,默认值为cc
CPPC预编译器的名称,默认值为$(CC) –E
CXXC++编译器的名称,默认值为g++
FCFORTRAN编译器的名称,默认值为f77
RM文件删除程序的名称,默认值为rm –f
ARFLAGS库文件维护程序的选项,无默认值
ASFLAGS汇编程序的选项,无默认值
CFLAGSC编译器的选项,无默认值
CPPFLAGSC预编译的选项,无默认值
CXXFLAGSC++编译器的选项,无默认值
FFLAGSFORTRAN编译器的选项,无默认值

另外&#xff0c;在 UNIX 系统中&#xff0c; $*$&#64;$?$$<4 个特殊的宏值在执行命令的过程中会发生相应的变化。

定义
$?当前目标所依赖的文件列表中比当前目标文件还要新的文件
$&#64;当前目标的名字
$<当前依赖文件的名字
$*不包括后缀名的当前依赖文件的名字

在 makefile文件中&#xff0c;你可能还会看到下面两个有用的特殊字符&#xff0c;它们出现在命令之前

  • -&#xff1a;告诉make命令忽略所有错误。例如&#xff0c;如果想创建一个目录&#xff0c;但又想忽略任何错误&#xff08;比如目
    录已存在&#xff09;&#xff0c;你就可以在 mkdir命令的前面加上一个减号。你将在本章后面的例子中看到符号
    的应用。
  • &#64;&#xff1a;告诉make在执行某条命令前不要将该命令显示在标准输出上。如果想用echo命令给出一些
    说明信息&#xff0c;这个字符将非常有用。

除此之外&#xff0c;make 工具中提供了部分关键字&#xff0c;在使用 make 工具时可以指定所有makefile中的目标&#xff0c;通常情况下 make 默认“all” 参数。

  • “all”—— 这个伪目标是所有目标的目标&#xff0c;其功能一般是编译所有的目标。
  • “clean” —— 这个伪目标功能是删除所有被make创建的文件。
  • “install” —— 这个伪目标功能是安装已编译好的程序&#xff0c;其实就是把目标执行文件拷贝到指定的目标中去。
  • “print” —— 这个伪目标的功能是例出改变过的源文件。
  • “tar” —— 这个伪目标功能是把源程序打包备份。也就是一个tar文件。
  • “dist” —— 这个伪目标功能是创建一个压缩文件&#xff0c;一般是把tar文件压成Z文件&#xff0c;或是gz文件。
  • “TAGS” —— 这个伪目标功能是更新所有的目标&#xff0c;以备完整地重编译使用。
  • “check”和“test” —— 这两个伪目标一般用来测试makefile的流程。

另外&#xff0c;make 实际工作原理还是通过命令的方式使用 gcc 工具来完成的&#xff0c;所以一些 gcc 的参数也要了解

后 缀 名所对应的语言
-S只是编译不汇编&#xff0c;生成汇编代码
-E只进行预编译&#xff0c;不做其他处理
-g在可执行程序中包含标准调试信息
-o file把输出文件输出到file里
-v打印出编译器内部编译各过程的命令行信息和编译器的版本
-I dir在头文件的搜索路径列表中添加dir目录
-L dir在库文件的搜索路径列表中添加dir目录
-static链接静态库
-library连接名为library的库文件

选 项含 义
-ansi支持符合ANSI标准的C程序
-pedantic允许发出ANSI C标准所列的全部警告信息
-pedantic-error允许发出ANSI C标准所列的全部错误信息
-w关闭所有告警
-Wall允许发出Gcc提供的所有有用的报警信息
-werror把所有的告警信息转化为错误信息&#xff0c;并在告警发生时终止编译过程



编写makefile

通常情况下makefile 会通过宏指定程序安装位置、指定头文件路径&#xff08;用户自定义头文件&#xff09;、以及gcc编译时的一些参数等

# which compiler 编译器
CC &#61; gcc# Where to install 程序安装位置
# INSTDIR &#61; /user/local/bin
INSTDIR &#61; /home/tr/Desktop/test/bin# Where are include files kept 指定头文件路径
INCLUDE &#61; .# Options for development gcc编译器标志参数
CFLAGS &#61; -g -Wall -ansi# Options for release
CFLAGS &#61; -O -Wall -ansi# 如果在make时未指定目标&#xff0c;默认只创建all之后的
all: main cleanmain: main.o a.o b.o$(CC) -o main main.o a.o b.omain.o: main.c$(CC) -I$(INCLUDE) $(CFLAGS) -c main.ca.o: a.c$(CC) -I$(INCLUDE) $(CFLAGS) -c a.cb.o: b.c$(CC) -I$(INCLUDE) $(CFLAGS) -c b.c# -作用或略执行结果&#xff0c;即使目标文件不存在也不会发生错误
clean: -rm -rf *.oinstall: main&#64;if [ -d $(INSTDIR) ]; \then \cp main $(INSTDIR); \chmod a&#43;x $(INSTDIR)/main; \chmod og-w $(INSTDIR)/main; \echo "Installed in $(INSTDIR)"; \else \echo "Sorry, $(INSTDIR) does not exit"; \fi

一般来说&#xff0c;一个 makefile 文件中至少包含 all 、 install 、 clean 三个选项

  • make就是make all, 在 all 关键字后面加上要编译的文件&#xff0c;或者也可以带上某些选项&#xff0c;
    比如&#xff0c;“ all &#xff1a;main clean ” 表示&#xff0c;最终生成 “mian” 程序&#xff0c;并且执行 make clean 命令

  • make install就是把编译出来的二进制文件,库,配置文件等等放到相应目录下

  • make clean清除编译结果


执行 make

makefile 中&#xff0c; all 之后添加了 clean &#xff0c;all : main clean&#xff0c;在执行 make 时默认执行 all 之后所有内容&#xff0c;所以在编译完程序之后执行了 clean 中定义的命令。
在这里插入图片描述
通过宏定义的方式可以完成大多数的编译需求&#xff0c;另外。 make 命令本身带有大量的内置规则&#xff0c;他们可以极大的简化 makefile 文件内容。



make 内置规则

新建一个文件&#xff0c;命名为 foo.c&#xff0c;编写如下代码

#include
#include int main()
{printf("Hello World!\n");exit(EXIT_SUCCESS);
}

使用 make 工具编译&#xff0c;不指定任何 makefile 文件。我们发现也可以编译成功。
在这里插入图片描述
对于 foo.c 源文件没有编写 makefile文件&#xff0c;也没有指定编译器以及编译方式&#xff0c;可 make 知道如何去编译&#xff0c;因为 make 存在一种内置规则&#xff08;又称为推导规则&#xff09;&#xff0c;它们都会使用宏定义&#xff0c;因此可以通过给宏赋予新值来改变其默认行为。

make CC&#61;gcc CFLAGS&#61;"-Wall -g"

在这里插入图片描述
可以通过 make 的 -p 选项打印出 make 的所有内置规则&#xff0c;用于内容过多&#xff0c;这里只列出一部分

# makefile
SHELL &#61; /bin/sh
# 默认
RM &#61; rm -f
... ...OUTPUT_OPTION &#61; -o $&#64;
COMPILE.c &#61; $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
%.o: %.c
# recipe to execute (内置)&#xff1a;$(COMPILE.c) $(OUTPUT_OPTION) $<

考虑到存在内置规则&#xff0c;可以将文件 makefile 只用于制作目标的规则去掉&#xff0c;而只需指定依赖关系&#xff0c;从而达到简化 makefile 文件的目的。因此&#xff0c;之前 main 程序的 makefile 文件改写为

main: main.o a.o b.o
main.o: a.h b.h main.c
a.o: a.c
b.o: b.c

在这里插入图片描述
可以看到通过简化的 makefile3 文件依然可以使用 make 工具编译。

虽然上述 makefile 文件可以执行&#xff0c;当然还是不建议这么写&#xff0c;毕竟内置规则是通用性规则&#xff0c;不足以应对所有情况&#xff0c;因此&#xff0c;可以取折中的方法&#xff0c;将其中部分简化&#xff0c;如&#xff1a;

上部分省略... ...
# Options for release
CFLAGS &#61; -O -Wall -ansiall: mainmain: main.o a.o b.o$(CC) -o main main.o a.o b.o# ///
main.o: main.c
a.o: a.c
b.o: b.c# ///
clean: -rm -rf *.o
下部分省略... ...





后缀和模式规则

可以看到内置规则在使用时都利用了文件的后缀名&#xff08;这类似 Windows和MS-DOS的文件扩展名&#xff09;所以当给出带有某个特定后缀名的文件时&#xff0c;make命令知道应该用哪个规则来创建带有另一个不同后缀名的文件。最常见的一条规则是用于从一个以 .c 为后缀名的文件创建出一个以 .o 为后缀名的文件。该规则使用编译器进行编译&#xff0c;但并不对源文件进行链接。
在这里插入图片描述
有时&#xff0c;我们需要自己创建新规则。假设我们的系统中没有针对 C&#43;&#43; 的 .cpp 文件进行编译的规则。为解决这个问题&#xff0c;或者为每个单独的源文件指定一条规则&#xff0c;或者为make制定一条新的规则&#xff0c;专门用于从后缀名为cpp的源文件创建目标文件。假设这个项目中的源文件数量非常大&#xff0c;那么制定一条新规则将节省大量的键入时间&#xff0c;也使得为该项目增加新的源文件变得更加容易。

要想增加一条新的后缀规则&#xff0c;首先需要在 makefile文件中增加一行语句&#xff0c;告诉make命令这个新
的后缀名。然后即可用这个新的后缀名来定义规则。make使用特殊语法&#xff1a;

.. :

来定义一条通用规则&#xff0c;利用该规则可以从带有旧后缀名的文件创建带有新后缀名的文件&#xff0c;并保留原文件的前半部分。

下面是 makefile文件的一个片段&#xff0c;它用一个新的通用规则将 .cpp 文件编译为 .o 文件&#xff1b;

.SUFFIXES: .cpp
.cpp.o:$(CC) -xc&#43;&#43; $(CFLAGS) -I$(INCLUDE) -c $<

特殊依赖关系 .cpp.o&#xff1a;告诉 make&#xff0c;紧随其后的规则是用于将后缀名为 .cpp 的文件转换为后缀名为 .o 的文件。在定义这个依赖关系时&#xff0c;使用了特殊的宏名称&#xff0c;这是因为此时还不知道将要被转换的文件的名字。要想理解这条规则&#xff0c;只需要记住宏 s< 将被扩展为起始文件的名字&#xff08;包含旧的后缀名&#xff09;.

注意&#xff0c;只需告诉make如何从 .cpp 文件得到 .o 文件&#xff0c;make已经知道如何从一个目标文件得到一个二进制可执行文件了。

当调用make命令时&#xff0c;它将使用这条新规则从 bar.cpp 文件得到 bar.o 文件&#xff0c;然后再使用它的内置规则从 .o 文件得到二进制可执行文件。-xc&#43;&#43; 标志的作用是告诉 gcc 编译器这是一个C&#43;&#43;源文件。

如今的make版本已知道如何处理后缀名为 .cpp 的C&#43;&#43;源文件了&#xff0c;但当需要将一种类型的文件转换为另一种类型的文件时&#xff0c;这个技术仍然很有用。

最新的make版本还包含一个新的语法以实现同样的效果&#xff0c;而且功能更强大。例如&#xff0c;模式规则可以用 ‘%’ 通配符语法来匹配文件名&#xff0c;而不是仅依赖于文件的后缀名。

%.cpp: %o$(CC) -xc&#43;&#43; $(CFLAGS) -I$(INCLUDE) -c $<





用 make 管理函数库

对于大型项目&#xff0c;一种比较方便的做法是用函数库来管理多个编译产品。函数库实际上就是文件&#xff0c;它们通常以 .a&#xff08;a是英文 archive的首字母&#xff09;为后缀名&#xff0c;在该文件中包含了一组目标文件。make命令用一个特殊的语法来处理函数库&#xff0c;这使得函数库的管理工作变得非常容易。

静态库&#xff1a; lib库名.a

创建&#xff1a; ar crv lib库名.a 1.o 2.o ……
使用&#xff1a; gcc -o main main.o lib库名.a
gcc -o main main.o -L路径 -l库名

动态库: lib库名.so

创建&#xff1a; gcc -fPIC -c 1.c 2.c 3.c ……
gcc -shared -o libfoo.so 1.o 2.o 3.o ……
或gcc -shared -fPIC -o lib库名.so 1.c 2.c 3.c ……
使用&#xff1a; gcc -o main main.o lib库名.so
gcc -o main main.o -L路径 -l库名


用于管理函数库的语法是 lib(file.o)&#xff0c;它的含义是目标文件 file.o 是存储在函数库 lib.a 中的。make命令用一个内置规则来管理函数库&#xff0c;该规则的常见形式如下所示&#xff1a;

.c.a:$(CC) -c $(CFLAGS) $<$(AR) $(ARFLAGS) $&#64; $*.o

$(AR)$(ARFLAGS) 的默认取值通常分别是命令 ar 和选项 rv .这个相当简洁的语法告诉make要想从 .c 文件得到 .a 库文件&#xff0c;它必须应用上面两条规则。

  • 第一条规则告诉它必须编译源文件以生成目标文件
  • 第二条规则告诉它用 ar 命令将新的目标文件添加到函数库中

因此&#xff0c;如果有一个名为 fud 的函数库&#xff0c;其中包含目标文件 bas.o&#xff0c;则第一条规则中的 $< 将被替换为bas.c&#xff0c;而第二条规则中的 $&#64;$* 将被分别替换为库文件 fua.a 和名字 bas。

在实际应用中&#xff0c;管理函数库规则的使用非常简单。下面将文件 a.o 和 b.o 放入函数库mylib.a 中。只需对 makefile文件做很少的修改&#xff0c;命名为 makefile4 &#xff1a;

# which compiler 编译器
CC &#61; gcc# Where to install 程序安装位置
# INSTDIR &#61; /user/local/bin
INSTDIR &#61; /home/tr/Desktop/test/bin# Where are include files kept 指定头文件路径
INCLUDE &#61; .# Options for development gcc编译器标志参数
CFLAGS &#61; -g -Wall -ansi# Options for release
CFLAGS &#61; -O -Wall -ansiall: main# ///
# Local Libraries
MYLIB &#61; mylib.amain: main.o $(MYLIB)$(CC) -o main main.o $(MYLIB)# 创建函数库
$(MYLIB): $(MYLIB)(a.o) $(MYLIB)(b.o)
main.o: main.c a.h b.h
a.o: a.c
b.o: b.cclean: -rm -rf *.o $(MYLIB)# ///
install: main&#64;if [ -d $(INSTDIR) ]; \then \cp main $(INSTDIR); \chmod a&#43;x $(INSTDIR)/main; \chmod og-w $(INSTDIR)/main; \echo "Installed in $(INSTDIR)"; \else \echo "Sorry, $(INSTDIR) does not exit"; \fi


推荐阅读
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文为Codeforces 1294A题目的解析,主要讨论了Collecting Coins整除+不整除问题。文章详细介绍了题目的背景和要求,并给出了解题思路和代码实现。同时提供了在线测评地址和相关参考链接。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 摘要: 在测试数据中,生成中文姓名是一个常见的需求。本文介绍了使用C#编写的随机生成中文姓名的方法,并分享了相关代码。作者欢迎读者提出意见和建议。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
author-avatar
346182773_20da31
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有