makefile项目构建

news2024/11/29 12:53:20

makefile项目构建


OVERVIEW

  • makefile项目构建
      • 1.概念
      • 2.make选项
      • 3.makefile语法
        • (1)基本语法
        • (2)系统与自定变量
        • (3)常用函数
        • (4)模式匹配与伪目标
      • 4.makefile编译流程
        • (1)预处理
        • (2)编译
        • (3)汇编
        • (4)链接
        • (5)编译参数
      • 5.编译动态链接库
        • (1)编译动态库
        • (2)链接动态库
        • (3)运行时使用动态库
      • 6.编译静态链接库
        • (1)编译静态库
        • (2)链接静态库
        • (3)运行时使用静态库
      • 7.make install

  • GUN Make官方网站:https://www.gnu.org/software/make/
  • GUN Make官方文档下载地址:https://www.gnu.org/software/make/manual/
  • Makefile Tutorial:https://makefiletutorial.com/

1.概念

  • make命令工具

make是一个命令工具,用于解释makefile中的指令,

  • makefile文件

工程文件中的源文件不计其数,其按照类型、功能、模块分别存放在若干目录中,

makefile定义一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于更复杂的功能操作,

makefile文件中描述了整个工程所有文件的编译顺序、编译规则,

  • cmake编译工具

cmake是一个跨平台安装的编译工具,可以用简单的语句描述所有平台的编译安装过程,

其能够输出各种各样的makefile或project文件,能够测试编译器所支持的C++特性,类似unix下的automake,

其并不直接构建出最终的软件,而是产生标准的构建档(如unix的makefile或windows visual c++的projects/workspaces),然后再以一般的构建方式使用,

  • CMakeLists.txt文件

cmake是一个命令工具可用于生成makefile,但也要根据CMakeLists.txt中的内容来生成,而CMakeLists.txt就是写给cmake的规则,

  • 总结:

    make是一个命令工具,makefile是一个文件,make执行的时候需要读取makefile文件中的规则(makefile规则需要自己写),

    make是一个命令工具,CMakeLists.txt是一个文件,cmake执行的时候需要读取CMakeLists.txt文件中的规则(CMakeLists.txt规则需要自己写),

2.make选项

make常用选项:make [-f file] [options] [target],Make默认在当前目录中寻找GUNmakefile,

  • -v:显示版本号,
  • -f:指定除上述文件名之外的文件作为输入文件,
  • -n:只输出命令,但不执行,一般用来测试,
  • -s:只执行命令,但不显示具体命令,此处可在命令中用@符抑制命令输出,
  • -w:显示执行前执行后的路径,
  • -C dir:指定makefile所在的目录,

3.makefile语法

GCC ?= gcc
CCMODE = PROGRAM
INCLUDES =  -I include
# CFLAGS =  -Wall $(MACRO)
TARGET = test.out
SRCS := $(wildcard src/*.cpp)
# LIBS = -lpthread -lncurses

ifeq ($(CCMODE),PROGRAM)
$(TARGET): $(LINKS) $(SRCS) 
	$(GCC) $(CFLAGS) $(INCLUDES) -o $(TARGET)  $(SRCS) $(LIBS)
	@chmod +x $(TARGET)
	@echo make $(TARGET) ok.
clean:
	rm -rf $(TARGET)
endif
(1)基本语法
[target]:[prerequisties]
	[command]
  • 目标TARGET:可以是需要进行编译的目标,也可以是一个动作(目标文件OBJECTFile、可执行文件、标签Label)
  • 依赖DEPENDE:执行当前目标所要依赖的选项,包括其他目标,某个具体文件或库等,
  • 命令command:该目标下要执行的具体命令,

makefile中都是先展开所有的变量,再调用指令进行相关的操作,

  • =:赋值操作,使用终值进行赋值操作,不论变量调用写在赋值前\后,调用时都是取最终值,
  • :=:赋值操作,只受当前行以及之前的代码的影响,而不会收到后面的赋值的影响,
  • ?=:默认赋值运算符,如果该变量已经定义则不进行任何操作、如果该变量尚未定义则求值并进行分配,
(2)系统与自定变量

变量在声明时需要赋予初值,而在使用时需要在变量名前加上 $ 符号,并使用小括号将变量括起来,

  • 系统变量:
    • $*:不包括扩展名的目标文件名称
    • $+:所有的依赖文件,以空格进行分割
    • $<:表示规则中的一个条件
    • $?:所有时间戳比目标文件晚的依赖文件,以空格分隔,
    • $@:目标文件的完整名称
    • $^:所有不重复的依赖文件,以空格进行分隔
    • $%:如果目标是归档成员,则该变量表示目标的归档成员名称,
  • 系统常量,make -p进行查看:
    • AS:as,汇编程序的名称
    • CC:cc,C编译器名称
    • CPP:cc -E,C预编译器名称
    • CXX:g++ ,C++编译器名称
    • RM:rm -f,文件删除别名
  • 自定义变量:
    • 定义:变量名 = 变量值
    • 使用:$(变量名)/${变量名}
# version1
# 分开书写 保证只编译有改动的代码
calc:add.o sub.o multi.o divide.o calc.o
	gcc add.o sub.o multi.o divide.o calc.o -o calc
add.o:add.cpp
	gcc -c add.cpp -o add.o
sub.o:sub.cpp
	gcc -c sub.cpp -o sub.o
multi.o:multi.cpp
	gcc -c multi.cpp -o multi.o
divide.o:divide.cpp
	gcc -c divide.cpp -o divide.o
calc.o:calc.cpp
	gcc -c calc.cpp -o calc.o
clean:
	rm -rf *.o calc
# version2
TARGET = calc
OBJ = add.o sub.o multi.o divide.o calc.o

$(TARGET):$(OBJ)
	gcc $(OBJ) -o $(TARGET)
add.o:add.cpp
	gcc -c add.cpp -o add.o
sub.o:sub.cpp
	gcc -c sub.cpp -o sub.o
multi.o:multi.cpp
	gcc -c multi.cpp -o multi.o
divide.o:divide.cpp
	gcc -c divide.cpp -o divide.o
calc.o:calc.cpp
	gcc -c calc.cpp -o calc.o
clean:
	rm -rf *.o calc
# version3
TARGET = calc
OBJ = add.o sub.o multi.o divide.o calc.o

$(TARGET):$(OBJ)
	$(CXX) $^ -o $@
add.o:add.cpp
	$(CXX) -c $^ -o $@
sub.o:sub.cpp
	$(CXX) -c $^ -o $@
multi.o:multi.cpp
	$(CXX) -c $^ -o $@
divide.o:divide.cpp
	$(CXX) -c $^ -o $@
calc.o:calc.cpp
	$(CXX) -c $^ -o $@
clean:
	$(RM) *.o $(TARGET)
(3)常用函数

函数调用与变量使用类似,也是以 $ 来标识的,其基本语法如下:

# fn 函数名 arguments 函数参数
$(fn, arguments) or ${fn, arguments}
  • shell函数:$(shell <command> <arguments>)

    调用shell命令command,

    函数返回shell命令command的执行结果,

    cpp_srcs:=$(shell find src -name "*.cpp")
    
  • subst函数:$(subst <from>, <to>, <text>)

    字符串替换函数subst,将字符串 <text> 中的 <from> 字符串替换成为 <to>

    函数返回被替换后的字符串结果,

  • patsubst函数:$(patsubst <pattern>, <replacement>, <text>)

    模式字符串替换函数,从text中提取出pattern,替换成replacement,

    函数返回被替换过后的字符串,

  • foreach函数:$(foreach <var>, <list>, <text>)

    循环函数,将字串 <list> 中的元素逐个取出,执行 <text> 包含的表达式,

    include_paths:= /usr/include \
    				/usr/include/opencv2/core \
    				/usr/include/mysql	\
    				/usr/include/redis
    include_paths:=$(foreach item, $(include_paths), -I $(item))
    debug:
    	echo $(include_paths)
    
    include_paths:= /usr/include \
    				/usr/include/opencv2/core \
    				/usr/include/mysql	\
    				/usr/include/redis
    include_paths:= $(include_paths:%=-I%)
    debug:
    	echo $(include_paths)
    

    在这里插入图片描述

  • dir函数:$(dir <names...>)

    取目录函数,从文件名序列中取出目录部分,目录部分是指最后一个反斜杠 / 之前的部分(如果没有反斜杠则直接返回 ./ ),

    函数返回文件名序列的目录部分

  • notdir、filter、basename函数,

    libs := $(shell find /usr/lib -name lib*)
    libs := $(notdir $(libs))
    
    a_libs := $(filter %.a, $(libs))
    so_libs := $(filter %.so, $(libs))
    
    libs := $(basename $(libs))
    libs := $(subst lib, , $(libs))
    
    debug:
    	echo $(libs)
    	# echo $(a_libs)
    	# echo $(so_libs)
    
(4)模式匹配与伪目标

伪目标:.PHONY:clean ,声明伪目标之后,makefile将不会判断目标是否存在 或 该目标是否需要进行更新

模式匹配:%目标:%依赖

  • %.o:%.cpp.0依赖于对应的.cpp文件,
  • wildcard$(wildcard ./*.cpp) 获取当前目录下所有的.cpp文件
  • patsubst$(patsubst %.cpp, %.o, ./*.cpp) 将对应的cpp文件名替换成为 .o 文件名,
# version4
.PHONY:clean
TARGET = calc
OBJ = $(patsubst %.cpp, %.o, $(wildcard ./*.cpp))
# OBJ = add.o sub.o multi.o divide.o calc.o

$(TARGET):$(OBJ)
	$(CXX) $^ -o $@
%.o:%.cpp
	$(CXX) -c $^ -o $@
clean:
	$(RM) *.o $(TARGET)

4.makefile编译流程

GCC是GUN编译程序集合(GUN Compile Collection),是最重要的开放源码软件,

其他所有开放源码软件都在某种层次上依赖它,甚至其他语言如python、都是由C语言开发的,由GUN编译程序编译的。

GCC包含的常见的软件,

  • ar:通过从文档中添加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理,连接程序使用的目标库文件,
  • as:GUN汇编器,实际上是一族汇编器,因为可以被编译或能够在各种不同的平台上工作,
  • gdb:GUN调试器,用于检测程序运行时的值和行为GNATS:GUN调试跟踪系统,
  • gprof:监督编译程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供的配置文件来优化程序,
  • ld:GUN连接程序,该程序将目标文件的集合组合成可执行程序,
  • libtool:一个基本库,支持make程序的描述文件使用的简化共享库用法的脚本,
  • make:一个工具程序,其会读取makefile脚本来确定程序中的哪个部分需要编译和连接,然后执行必要的命令,
  • 查看GCC默认头文件搜索路径:echo | gcc -v -x c -E -

在这里插入图片描述

#include <iostream>
using namespace std;

int main() {
	cout << "this is a test!~" << endl;
	return 0;
}

gcc -lstdc++ main.cpp,直接从源代码到可执行文件,将上述过程进行拆分为:预处理、编译、汇编、链接操作,

在这里插入图片描述

(1)预处理

预处理:gcc -E main.cpp>main.i 预处理

预处理后得到main.i文件,

# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"

# 1 "/usr/include/c++/7/iostream" 1 3
# 36 "/usr/include/c++/7/iostream" 3
       
# 37 "/usr/include/c++/7/iostream" 3

# 1 "/usr/include/x86_64-linux-gnu/c++/7/bits/c++config.h" 1 3
# 229 "/usr/include/x86_64-linux-gnu/c++/7/bits/c++config.h" 3

# 229 "/usr/include/x86_64-linux-gnu/c++/7/bits/c++config.h" 3
namespace std
{
  typedef long unsigned int size_t;
  typedef long int ptrdiff_t;


  typedef decltype(nullptr) nullptr_t;

}

......
    
namespace std __attribute__ ((__visibility__ ("default")))
{

# 60 "/usr/include/c++/7/iostream" 3
  extern istream cin;
  extern ostream cout;
  extern ostream cerr;
  extern ostream clog;


  extern wistream wcin;
  extern wostream wcout;
  extern wostream wcerr;
  extern wostream wclog;




  static ios_base::Init __ioinit;


}
# 9 "main.cpp" 2

# 9 "main.cpp"
using namespace std;

int main() {
 cout << "this is a test!~" << endl;
 return 0;
}
(2)编译

编译:gcc -S main.i

编译后得到 main.s文件

.file	"main.cpp"
	.text
	.section	.rodata
	.type	_ZStL19piecewise_construct, @object
	.size	_ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
	.zero	1
	.local	_ZStL8__ioinit
	.comm	_ZStL8__ioinit,1,1
.LC0:
	.string	"this is a test!~"
	.text
	.globl	main
	.type	main, @function
main:
.LFB1494:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	leaq	.LC0(%rip), %rsi
	leaq	_ZSt4cout(%rip), %rdi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
	movq	%rax, %rdx
	movq	_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rax
	movq	%rax, %rsi
	movq	%rdx, %rdi
	call	_ZNSolsEPFRSoS_E@PLT
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1494:
	.size	main, .-main
	.type	_Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB1983:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	%edi, -4(%rbp)
	movl	%esi, -8(%rbp)
	cmpl	$1, -4(%rbp)
	jne	.L5
	cmpl	$65535, -8(%rbp)
	jne	.L5
	leaq	_ZStL8__ioinit(%rip), %rdi
	call	_ZNSt8ios_base4InitC1Ev@PLT
	leaq	__dso_handle(%rip), %rdx
	leaq	_ZStL8__ioinit(%rip), %rsi
	movq	_ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rax
	movq	%rax, %rdi
	call	__cxa_atexit@PLT
.L5:
	nop
	leave
	.cfi_def_cfa 7, 8
	ret
(3)汇编

汇编:gcc -c main.s

汇编之后得到二进制文件 main.o(.obj)

在这里插入图片描述

(4)链接

链接:gcc -lstdc++ main.o -o main.out 得到可执行文件 main.out

在这里插入图片描述

(5)编译参数

编译选项:

  1. -m64:指定编译为 64/32 位应用程序

  2. -std=:指定编译标准,例如:-std=c++11、-std=c++14

  3. -g:包含调试信息

  4. -w:不显示警告

  5. -O:优化等级,通常使用:-O 3

  6. -I:加在头文件路径前

  7. -fPIC:Position-Independent Code,

    产生的没有绝对地址,全部使用相对地址,

    代码可以被加载到内存的任意位置,并且可以被正确执行,

    这正是共享库所需要的,共享库被加载时,在内存的位置不是固定的,

链接选项:

  1. -l:加在库名前面
  2. -L:加在库路径前面
  3. -Wl, <选项>:将逗号分隔的 <选项> 传递给链接器
  4. -rpath=:运行的时候去找的目录,要找找到 .so 文件,会从这个选项里指定的地方去找,

约定的变量名称:

  1. CC:Program for compiling C programs
  2. CXX:Program for compiling C++ programs
  3. CFLAGS:Extra flags to give to the C compiler
  4. CXXFLAGS:Extra flags to give to the C++ compiler
  5. CPPFLAGS:Extra flags to give to the C preprocessor
  6. LDFLAGS:Extra flags to give to compilers when they are supposed to invoke the linker

5.编译动态链接库

动态链接库:不会把代码编译到二级制文件中,而是在运行时才去加载,所以只需要维护一个地址即可,

动态库编译完成之后需要发布,否则程序运行时找不到,

windows环境下动态库为.dll、linux环境下动态库为.so

  1. 编译成 .o 文件:g++ -c -fpic soTest.cpp -o soTest.o

  2. 编译动态库:g++ -shared soTest.o -o libsoTest.so

    • -c:得到二进制文件aTest.o
    • -shared:共享
    • -fPIC:产生位置无关的代码,
    • -l:小写l,指定动态库,
    • -L:手动指定库文件搜索目录,默认只链接共享目录,
    • -I:大写i,指定头文件目录(默认当前目录),
  3. 链接成执行文件:

    g++ [.cpp] -l [libName] -L [libPath] -o [test.out]

g++ soTest.cpp -shared -fPIC -o libsoTest.so
(1)编译动态库

文件目录结构如下,将其打包成动态库,

在这里插入图片描述

// soTest.h
#ifndef _SOTEST_H
#define _SOTEST_H

#include <iostream>
using namespace std;

class soTest {
public:
    void func1();
    virtual void func2();
    virtual void func3() = 0;
};

#endif
// soTest.cpp
#include "soTest.h"

void soTest::func1()
{
    cout << "this is func1" << endl;
}

void soTest::func2()
{
    cout << "this is func2" << endl;
}
# makefile
libsoTest.so:
	$(CXX) soTest.cpp -shared -fPIC -L ./ -o libsoTest.so
clean:
	$(RM) libsoTest.so

使用make libsoTest.so 命令成功完成对 libsoTest.so 动态库的打包操作,

(2)链接动态库

在动态库成功打包出来之后,在其他项目中通过引入 soTest.hlibsoTest.so文件,来使用打包好的动态库,

文件目录结构如下,将第三方动态库动态载入,编译自己的项目,

在这里插入图片描述

//test.cpp
#include <iostream>
#include "soTest.h"
using namespace std;

class Test:public soTest{
public:
    void func2() {
        cout << "Test:this is func2" << endl;
    }
    void func3() {
        cout << "Test:this is func3" << endl;
    }
};

int main() {
    Test t1;
    t1.func1();
    t1.func2();
    t1.func3();
    return 0;
}
# makefile
test:
	$(CXX) test.cpp -lsoTest -L ./ -I ./ -o test.out
clean:
	$(RM) *.out

使用make test 命令成功完成第三方动态库的链接,编译成功目录下出现 test.out 的可执行文件,

(3)运行时使用动态库

由于动态库的特点,若只在编译时使用的动态库,而运行时没有指定动态库位置,则程序将无法正常运行,

即动态库编译完成之后需要进行发布操作,否则程序运行时会找不到动态库位置而产生报错,如下所示:

./a.out: error while loading shared libraries: libsoTest.so: cannot open shared object file: No such file or directory
  • 解决方案1:将动态库so文件拷贝到对应的目录下(发布),才能运行程序

    • linux下默认动态库路径配置文件:/etc/ld.so.conf/etc/ld.so.conf.d/*.conf

    • /usr/lib

    • /usr/local/lib

  • 解决方案2:运行时手动指定动态库的所在目录

    mac环境:

    • DYLD_LIBARY_PATH=./your_lib_path
    • export DYLD_LIBARY_PATH

    linux环境:

    • LD_LIBARY_PATH=./your_lib_path
    • export LD_LIBARY_PATH

在这里插入图片描述

6.编译静态链接库

静态链接库:会将库中的代码编译到二进制文件中,当程序编译完成后,该库文件可以删除,

与静态库不同的是,动态链接库必须与程序同时部署,还要保证程序能正常加载得到的库文件。静态库可以不用部署已经加载到程序中,而且运行时的速度更快,

但是会导致程序体积更大,并且库中的内容如果有更新,则需要重新编译生成程序,

windows环境下动态库为.lib、linux环境下动态库为.a

  1. 编译成 .o 文件:g++ -c aTest.cpp -o aTest.o

  2. 编译静态库:ar -r libaTest.a aTest.o

    • -c:得到二进制文件aTest.o
    • ar:备份压缩命令,将目标文件打包成静态链接库,
    • -r:将文件插入备存文件中,
  3. 链接成执行文件:

    g++ [.cpp] [.a] -o [test.out]

    g++ [.cpp] -l [libName] -L [libPath] -o [test.out]

(1)编译静态库

文件目录结构如下,将其打包成静态库,

在这里插入图片描述

// aTest.h
#ifndef _ATEST_H
#define _ATEST_H

#include<iostream>
using namespace std;

class aTest{
public:
	void func1();
};

#endif
// aTest.cpp
#include "aTest.h"

void aTest::func1()
{
	cout << "aTest:func1" << endl;
}
# makefile
libaTest.a:
	$(CXX) -c aTest.cpp -L ./ -I ./ -o aTest.o
	$(AR) -r libaTest.a aTest.o
clean:
	$(RM) *.a *.o

使用make libaTest.a 命令成功完成对 libaTest.a 静态库的打包操作,

(2)链接静态库

在静态库成功打包出来之后,在其他项目中通过引入 aTest.hlibaTest.a文件,来使用打包好的静态库,

文件目录结构如下,将第三方静态库动态载入,编译自己的项目,

在这里插入图片描述

// test.cpp
#include <iostream>
#include "aTest.h"
using namespace std;

int main() {
    aTest t1;
    t1.func1();
    return 0;
}
# makefile
test:
	$(CXX) test.cpp -laTest -L ./ -I ./ -o test.out
clean:
	$(RM) *.out 

使用make test 命令成功完成第三方静态库的链接,编译成功目录下出现 test.out 的可执行文件,

(3)运行时使用静态库

由于静态库的特点,在编译时已经将库中的代码编译到二进制文件中,当编译完成后,该库文件可以删除,并且程序可以直接运行,

在这里插入图片描述

7.make install

  1. make,编译链接:

    将源文件,编译成二进制的可执行文件(包括各种库文件)

  2. make install,配置相关的运行环境:

    创建目录,将可执行文件拷贝到指定目录(安装目录)

    加全局可执行的路径

    加全局的启动停止脚本

  3. make clean

    重置编译环境,删除无关文件

TARGET:=my_test
OBJ:=$(TARGET).os

CC:=g++

PATHS:=/tmp/test/
BIN:=/usr/local/bin/

START_SH:=$(PATHS)$(TARGET)
STOP_SH:=$(PATHS)$(TARGET)

$(TARGET):$(OBJ)

install:$(TARGET)
	if [ -d $(PATHS) ];						\
		then echo $(PATHS) exist;			\
	else 									\
		mkdir $(PATHS);						\
		cp $(TARGET) $(PATHS);				\
		ln -sv $(PATHS)$(TARGET) $(BIN);	\
		touch $(LOG);						\
		chmod a+rwx $(LOG);					\
		echo "$(TARGET)>$(LOG) & echo $(TARGET) running...">$(PATHS)$(START_SH);	\
		echo "killall $(TARGET)">$(PATHS)$(START_SH); 								\
		chmod a+x $(PATHS)$(START_SH);												\
		chmod a+x $(PATHS)$(STOP_SH);												\
		ln -sv $(PATHS)$(START_SH) $(BIN);											\
		ln -sv $(PATHS)$(STOP_SH) $(BIN);											\
	fi;

clean:
	$(RM) $(TARGET) $(OBJ) $(BIN)$(TARGET) $(BIN)$(START_SH) $(BIN)$(STOP_SH)
	$(RM) -rf $(PATHS)

.PHONY:clean install

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1253894.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习---贝叶斯网络与朴素贝叶斯

1. 贝叶斯法则 如何判定一个人是好人还是坏人&#xff1f; 当你无法准确的熟悉一个事物的本质时&#xff0c;你可以依靠与事物特定本质相关的事件出现的次数来判断 其本质属性的概率。如果你看到一个人总是做一些好事&#xff0c;那这个人就越可能是一个好人。 数学语言表达…

C# APS.NET CORE 6.0 WEB API IIS部署

1.创建 APS.NET CORE6.0 WEB API项目 默认选项即可 源代码&#xff1a; 项目文件展开&#xff1a; launchSettings.json {"$schema": "https://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication"…

记录华为云服务器(Linux 可视化 宝塔面板)-- Nginx篇

文章目录 配置Nginx服务器1、添加CentOS 7系统的Nginx yum资源库2、安装Nignx服务 设置Nginx安全级别&#xff08;感觉可以先不设置&#xff09;步骤一步骤二如有启发&#xff0c;可点赞收藏哟~ 配置Nginx服务器 1、添加CentOS 7系统的Nginx yum资源库 先安装rpm apt instal…

Linux 中的 ls 命令使用教程

目录 前言 如何运用 ls 命令 1、列出带有所有权的文件和目录 2、获取以人类可读的方式显示的信息 3、列出隐藏文件 4、递归列出文件 5、在使用 ls 时对文件和目录做区分 6、列出指定扩展名的文件 7、基于大小对输出内容排序 8、根据日期和时间排序文件 让我们来总结…

Nginx:配置文件详解

一、Nginx配置文件 main配置段&#xff1a;全局配置 events段&#xff1a;定义event工作模式 http {}&#xff1a;定义http协议配置 支持使用变量&#xff1a; 内置变量&#xff1a;模块会提供内建变脸定义 自定义变量&#xff1a;set var_name value 二、 主…

动态规划学习——斐波那契数列

目录 最长的斐波那契数列子序列的长度 1.题目 2.题目接口 3.解题思路及其代码 最长的斐波那契数列子序列的长度 1.题目 如果序列x_1&#xff0c;X_2&#xff0c;...&#xff0c;x_n 满足下列条件&#xff0c;就说它是斐波那契式的: 1.n > 3 2.对于所有i2 <n&a…

中间件介绍

一、中间件介绍 官方的说法&#xff1a;中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统&#xff0c;用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。 但是由于其影响的是全局&#xff0c;所以需…

HashMap的实现原;HashMap的工作原理;HashMap存储结构; HashMap 构造函数

文章目录 说一下HashMap的实现原理(非常重要)①HashMap的工作原理HashMap存储结构常用的变量HashMap 构造函数tableSizeFor() put()方法详解hash()计算原理resize() 扩容机制get()方法为什么HashMap链表会形成死循环 HashMap是我们在工作中使用到存储数据特别频繁的数据结构&am…

韵达快递查询,韵达快递单号查询,一键筛选出单号中的退回件

批量查询韵达快递单号的物流信息&#xff0c;并将其中的退回件一键筛选出来。 所需工具&#xff1a; 一个【快递批量查询高手】软件 韵达快递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;第一次使用的朋友记得先注册&#xff…

短期的规划

大方向&#xff1a; 学习编程的前期 大二上学期&#xff1a; 前期追求知识点的广度&#xff1a; 对各类数据结构的了解 熟悉数据库的各类操作&#xff0c;JDBC熟练使用 与此同时&#xff0c;提高写作能力&#xff0c;学习沉淀&#xff0c;提高技术影响力 大二的寒假&…

Java中的异常语法知识居然这么好玩!后悔没有早点学习

学习异常后&#xff0c;发现异常的知识是多么的吸引人&#xff01;不仅可以用来标记错误&#xff0c;还可以自己定义一个异常&#xff0c;用来实现自己想完成的业务逻辑&#xff0c;接下来一起去学习吧 目录 一、异常的概念及体系结构 1.异常的概念 2.异常的体系结构 3.异常…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《前景导向的主动配电网智能储能软开关规划方法》

这个标题涉及到电力系统中的主动配电网&#xff08;Active Distribution Network&#xff09;以及与之相关的智能储能软开关的规划方法。下面是对标题中各个关键词的解释&#xff1a; 前景导向的&#xff08;Future-oriented&#xff09;&#xff1a; 这表明该方法是以未来发展…

2022年全国硕士研究生入学统一考试管理类专业学位联考数学试题——解析版

文章目录 2022 年全国硕士研究生入学统一考试管理类专业学位联考数学试题一、问题求解&#xff1a;第 1∼15 小题&#xff0c;每小题 3 分&#xff0c;共 45 分。下列每题给出的 A、B、C、D、E 五个选项中&#xff0c;只有一项是符合试题要求的&#xff0c;请在答&#xff0e;题…

strlen和sizeof练习题(以64位机器为例)

例一 一般情况下&#xff0c;数组名表示首元素地址&#xff0c;只有在以下的情况中数组名表示整个数组的地址&#xff1a; 1.sizeof&#xff08;数组名&#xff09;&#xff1a;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小 2.&数组名&#xff1a;这里的…

五种多目标优化算法(MOPSO、MOAHA、NSGA2、NSGA3、MOGWO)求解微电网多目标优化调度(MATLAB)

一、多目标优化算法简介 &#xff08;1&#xff09;多目标粒子群优化算法MOPSO 多目标应用&#xff1a;基于多目标粒子群优化算法MOPSO求解微电网多目标优化调度&#xff08;MATLAB代码&#xff09;-CSDN博客 &#xff08;2&#xff09;多目标人工蜂鸟算法&#xff08;MOAHA…

C语言进阶之笔试题详解(1)

引言&#xff1a; 对指针知识进行简单的回顾&#xff0c;然后再完成笔试题。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》 &#x1f388;跟着猪巴戒&#xff0c;一起学习C语言&#x1f388; 目录 引言&#xff1a; 知识简单回顾 指针是什么 指针变…

分布式篇---第七篇

系列文章目录 文章目录 系列文章目录前言一、如何将长链接转换成短链接,并发送短信?二、长链接和短链接如何互相转换?三、长链接和短链接的对应关系如何存储?四、如何提高系统的并发能力?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一…

航天宏图——宏图1号样例数据0.5米-5米分辨率(上海部分)

简介&#xff1a; 作为航天宏图“女娲星座”建设计划的首发卫星&#xff0c;航天宏图-1号可获取0.5米-5米的分辨率影像&#xff0c;具备高精度地形测绘、高精度形变检测、高分辨率宽幅成像以及三维立体成像等能力&#xff0c;在自然资源、应急管理、水利等行业与领域具有极高的…

【开源】基于Vue和SpringBoot的数字化社区网格管理系统

项目编号&#xff1a; S 042 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S042&#xff0c;文末获取源码。} 项目编号&#xff1a;S042&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、开发背景四、系统展示五、核心源码5…

LCM-LoRA模型推理简明教程

潜在一致性模型 (LCM) 通常可以通过 2-4 个步骤生成高质量图像&#xff0c;从而可以在几乎实时的设置中使用扩散模型。 来自官方网站&#xff1a; LCM 只需 4,000 个训练步骤&#xff08;约 32 个 A100 GPU 小时&#xff09;即可从任何预训练的稳定扩散 (SD) 中提取出来&#…