善用GNU Make做开发

【善用工具】程序性能分析Gperftools初探(libwind+pprof+Kcachegrind) 善用工具: 主要试用了google的gperftools-2.0分析C/C++程序的性能: 并结合pprof和Kcachegrind进行了结果分析。 工具可以完成程序中每个函数执行时间和调用关系图的统计等等功能。 是进行程序性能提升的利器。 后续还会对其它同类的工具进行相应的探索。 阅读详情
 

作者:肖文鹏 发文时间:2004.11.16

    在编写小型的Linux应用程序时,一般情况下只会有少数几个源文件。这样程序员能够很容易地理清它们之间的包含和引用关系。但随着软件项目逐渐变大,对源文件的处理也将变得越来越复杂起来。此时单纯依赖手工方式进行管理的做法就显得有些力不从心了。为此,Linux专门为软件开发提供了一个自动化管理工具GNU make。通过它,程序员可以很方便地管理软件编译的内容、方式和时机,从而使程序员能够把主要精力集中在代码的编写上。

    make将整个软件项目的代码分开放在几个小的源文件里,在改动其中一个文件的时候,可以只对该文件重新进行编译,然后重新连接所有的目标文件。对于那些由许多源文件组成的大型软件项目来说,全部重新进行编译需要花费很长的时间,而采用这种项目管理方法则可以极大地提高工作效率,让原本复杂繁琐的开发工作变简单。

    Makefile文件

    GNU make是一个用来控制软件构建过程的自动工具,程序员通过定义构建规则来控制代码的创建过程。这些规则通常定义在一个名为Makefile的文件中。Makefile被用来告诉make编译哪些文件、怎样编译和何时编译。Makefile中的每条规则事实上都包含如下一些内容:
    ◆ 目标(target)是make最终需要创建的对象;
    ◆ 依赖(dependency)通常是一个列表,指明编译目标时需要用到的其它文件;
    ◆ 命令(command)也是一个列表,指明从依赖文件创建出目标对象所需要执行的命令。

    虽然Makefile中的目标通常都是可执行程序,但事实上可以是诸如文本文件和HTML页面等任何内容,甚至能够用来测试或设置环境变量。Makefile中的命令则不仅可以是编译命令,还可以是任何Shell命令。

    先来看一个例子。假设整个软件项目是由control.c、io.c和main.c三个源文件所构成的,编写的Makefile文件内容如下:

all : program
program : control.o ui.o main.o
gcc -o program control.o ui.o main.o
control.o : control.c
gcc -Wall -c -o control.o control.c
ui.o : ui.c
gcc -Wall -c -o ui.o ui.c
main.o : main.c
gcc -Wall -c -o main.o main.c
clean :
rm -f program *.o


    在将上述Makefile文件与源文件保存到同一目录之后,就可以在命令行中输入“make”命令来编译整个项目了。make在执行过程中,首先会查找到Makefile文件第一条规则中的目标,即上述文件中的all。根据设定好的规则,该目标需要依赖于program。由于all并不是一个已经存在的文件,所以每次在make被调用的时候,显然都需要先检查program。继续往下不难发现,program目标是依赖于control.o、ui.o和main.o的。这就意味着如果其中任何一个比生成的可执行文件要新,那么就需要重新构建可执行文件program,否则就没有必要执行这一步了。

    在Makefile文件的其余部分,为每一个中间生成的目标文件都专门定义了一条规则,用来指明创建过程中它们与C源文件的依赖性。也就是说,如果一个特定的C源文件被更新了,那么与之对应的目标文件也必须重新生成。下面是make在构建项目过程中的输出结果:

#make
gcc -Wall -c -o control.o control.c
gcc -Wall -c -o ui.o ui.c
gcc -Wall -c -o main.o main.c
gcc -o program control.o ui.o main.o


    不难看出,首先是C源文件被编译成目标文件,然后才是目标文件被连接成最终的可执行文件。由于相互间依赖关系的制约,这些步骤会被有条不紊地依次执行。最终可执行文件要求目标文件都被更新过,而每个目标文件则要求C源文件被更新过。如果此时重新执行“make”命令,会出现下面的结果。原因是程序已经被编译过了,并且没有做过任何改动,所以就没有再编译的必要了:

# make
make: Nothing to be done for 'all'.


    如果只是改变了其中的部分文件,那么make会自动检测出需要对哪些源文件重新进行编译,并连接成最后的可执行文件。用户可以参考下面的过程:

#touch main.c
# make
gcc -Wall -c -o main.o main.c
gcc -o program control.o ui.o main.o


    当make检测到main.o目标时,发现main.c文件已经被更新,于是main.o文件必须被重新编译,相应地program需要被重新连接。make的魅力就在于能够自动进行条件检测,并采取适当的行动。它永远也不会去编译那些没有改动过的源文件,因此大大节省了在开发大型软件项目时所浪费在编译上的时间。

    变量

    为了简化Makefile的编写,make引入了变量。变量实际上是为文本串在Makefile中定义一个便于记忆的名称。变量的定义和应用与Linux的环境变量一样,变量名大写,变量一旦定义之后,就可以通过将变量名用圆括号包起来,并在前面加上“$”符号来进行引用。

    变量一般都在Makefile的头部定义。如果变量的值发生了改变,很显然只需在一个地方进行修改就可以了,从而大大简化了Makefile的维护。下面是将前面用到的Makefile利用变量进行改写后的结果:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o program
control.o : control.c
$(CC) $(CFLAGS) -c -o control.o control.c
ui.o : ui.c
$(CC) $(CFLAGS) -c -o ui.o ui.c
main.o : main.c
$(CC) $(CFLAGS) -c -o main.o main.c
clean :
    rm -f program $(OBJS)


    make将其使用的变量细分为两类:递归展开变量和简单展开变量。递归展开变量在被引用时会逐层展开,即如果在展开式中包含了对其它变量的引用,则这些变量也会被展开,直到没有需要被展开的变量为止。假设变量TOPDIR和SUBDIR的定义如下:

TOPDIR = /home/xiaowp
SUBDIR = $(TOPDIR)/project


    此时变量SUBDIR的值在解析时会被正确地展开为/home/xiaowp/project,但对于下面的定义:

TOPDIR = /home/xiaowp
SUBDIR = $(TOPDIR)/project
SUBDIR = $(SUBDIR)/src


    很清楚,希望得到的结果是/home/xiaowp/project/src,但实际并非如此。SUBDIR在引用时会被递归展开,从而陷入一个无限循环当中,make能够检测到这个问题并报告如下错误:
    *** Recursive variable 'SUBDIR' references itself (eventually). Stop

    为了避免这个问题,可以使用简单展开变量。与递归展开变量在引用时展开不同,简单展开变量是在定义处展开的,并且只展开一次,从而消除了变量的嵌套引用。在定义时,其语法与递归展开变量有细微的不同:

TOPDIR = /home/xiaowp
SUBDIR := $(TOPDIR)/project
SUBDIR += /src


    SUBDIR在第一次定义时使用“:=”将其值设置为“/home/xiaowp/project”,而在第二次定义时则使用“+=”在已有的基础上添加“/src”,这样就使得SUBDIR的最终值变为“/home/xiaowp/project/src”。许多程序员在Makefile中只使用简单展开变量,以避免可能出现的错误。

    除了用户自定义变量之外,在Makefile中还可以使用环境变量、自动变量和预定义变量。使用环境变量的方法相对来讲比较简单,make在启动时会自动读取系统当前已经定义了的环境变量,并且会创建与之具有相同名称和数值的变量。需要注意的是,如果用户在Makefile中定义了相同名称的变量,那么用户自定义变量将会覆盖同名的环境变量。

表1 常用自动变量



    此外,make还提供了一些预定义变量和自动变量,但它们看起来都不如自定义变量那么直观。之所以称为自动变量是因为make会自动用特定的、熟知的值来替换它们,表1给出了常用的部分自动变量。

    利用make的自动变量和预定义变量,可以简化前面给出的那个Makefile文件:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
clean :
    $(RM) program $(OBJS)


    伪目标

    在Makefile中,并不是所有的目标都对应于磁盘上的文件。有的目标存在只是为了形成一条规则,从而完成特定的工作,并不生成新的目标文件,这样的目标称为伪目标。它并不是真正意义上的目标文件,只是为了满足Makefile的语法规则而存在的。

    在已经给出的Makefile文件中,最后一个目标clean就是伪目标。它规定了make应该执行的命令。当make处理到目标clean时,会先查看其对应的依赖对象。由于clean没有任何依赖对象,所以make会认为该目标是最新的而不会执行任何操作。为了编译这个目标体,必须手工执行如下命令:# make clean

    作为惯例,clean目标一般用于删除最终生成的可执行文件和在编译过程中产生的所有目标文件。问题是,如果恰巧有一个名为clean的文件存在时该怎么办呢?此时因为在这个规则里没有任何依赖对象,所以目标文件肯定是最新的,规则中的命令无论如何也不会被执行,即使用命令“make clean”也无济于事。解决这一问题的方法是标明该规则中的目标是伪目标,并不对应于任何文件。这可以通过.PHONY目标实现。它告诉make不检查规则的目标文件是否存在于磁盘上,也不查找任何隐含规则,而直接假设指定的目标需要被更新就行了。在使用了.PHONY之后,前面的给出的Makefile文件就将变为如下的内容:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    其它规则

    除了可以在Makefile中明确指定规则(显示规则)之外,make还维护了一整套隐式规则。隐式规则可以在用户没有完整地给出某些命令的时候,自动执行恰当的操作。隐式规则最大的好处是可以简化Makefile的编写和维护,例如前面给出的Makefile运用隐式规则后可以简化为如下内容:

OBJS = control.o ui.o main.o
program : $(OBJS)
$(CC) $(OBJS) -o $@
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    默认目标program依赖于control.o、ui.o和main.o三个目标文件,但Makefile中并没有给出怎样编译生成这些目标的规则。此时make就会使用隐式规则,对每一个名为foo.o的目标文件,找到与之对应的源代码foo.c,然后使用“gcc -c foo.c -o foo.o”命令来生成对应的目标文件。

    除了系统预定义的隐式规则外,在Makefile中还可以定义自己的隐式规则,这种规则也被称为模式规则。模式规则类似于普通规则,但它的目标必须含有“%”这一通配符,以便能与任何非空字符相匹配,与目标对应的依赖文件中也必须使用通配符,例如下面的规则:

%.o : %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

    上面的规则将告诉make所有形为foo.o的目标文件,都应该根据指定的命令从源文件foo.c编译而来。

    小结

    在构建大型的软件项目时,make是一个优秀的持续集成工具。它对于软件开发过程来讲非常重要。本文介绍了基本的make命令,以及如何编写简单实用的Makefile文件,相信用户已经能够使用make来管理软件项目的创建和维护过程了。

表1 常用自动变量



    此外,make还提供了一些预定义变量和自动变量,但它们看起来都不如自定义变量那么直观。之所以称为自动变量是因为make会自动用特定的、熟知的值来替换它们,表1给出了常用的部分自动变量。

    利用make的自动变量和预定义变量,可以简化前面给出的那个Makefile文件:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
clean :
    $(RM) program $(OBJS)


    伪目标

    在Makefile中,并不是所有的目标都对应于磁盘上的文件。有的目标存在只是为了形成一条规则,从而完成特定的工作,并不生成新的目标文件,这样的目标称为伪目标。它并不是真正意义上的目标文件,只是为了满足Makefile的语法规则而存在的。

    在已经给出的Makefile文件中,最后一个目标clean就是伪目标。它规定了make应该执行的命令。当make处理到目标clean时,会先查看其对应的依赖对象。由于clean没有任何依赖对象,所以make会认为该目标是最新的而不会执行任何操作。为了编译这个目标体,必须手工执行如下命令:# make clean

    作为惯例,clean目标一般用于删除最终生成的可执行文件和在编译过程中产生的所有目标文件。问题是,如果恰巧有一个名为clean的文件存在时该怎么办呢?此时因为在这个规则里没有任何依赖对象,所以目标文件肯定是最新的,规则中的命令无论如何也不会被执行,即使用命令“make clean”也无济于事。解决这一问题的方法是标明该规则中的目标是伪目标,并不对应于任何文件。这可以通过.PHONY目标实现。它告诉make不检查规则的目标文件是否存在于磁盘上,也不查找任何隐含规则,而直接假设指定的目标需要被更新就行了。在使用了.PHONY之后,前面的给出的Makefile文件就将变为如下的内容:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    其它规则

    除了可以在Makefile中明确指定规则(显示规则)之外,make还维护了一整套隐式规则。隐式规则可以在用户没有完整地给出某些命令的时候,自动执行恰当的操作。隐式规则最大的好处是可以简化Makefile的编写和维护,例如前面给出的Makefile运用隐式规则后可以简化为如下内容:

OBJS = control.o ui.o main.o
program : $(OBJS)
$(CC) $(OBJS) -o $@
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    默认目标program依赖于control.o、ui.o和main.o三个目标文件,但Makefile中并没有给出怎样编译生成这些目标的规则。此时make就会使用隐式规则,对每一个名为foo.o的目标文件,找到与之对应的源代码foo.c,然后使用“gcc -c foo.c -o foo.o”命令来生成对应的目标文件。

    除了系统预定义的隐式规则外,在Makefile中还可以定义自己的隐式规则,这种规则也被称为模式规则。模式规则类似于普通规则,但它的目标必须含有“%”这一通配符,以便能与任何非空字符相匹配,与目标对应的依赖文件中也必须使用通配符,例如下面的规则:

%.o : %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

    上面的规则将告诉make所有形为foo.o的目标文件,都应该根据指定的命令从源文件foo.c编译而来。

    小结

    在构建大型的软件项目时,make是一个优秀的持续集成工具。它对于软件开发过程来讲非常重要。本文介绍了基本的make命令,以及如何编写简单实用的Makefile文件,相信用户已经能够使用make来管理软件项目的创建和维护过程了。

表1 常用自动变量



    此外,make还提供了一些预定义变量和自动变量,但它们看起来都不如自定义变量那么直观。之所以称为自动变量是因为make会自动用特定的、熟知的值来替换它们,表1给出了常用的部分自动变量。

    利用make的自动变量和预定义变量,可以简化前面给出的那个Makefile文件:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
clean :
    $(RM) program $(OBJS)


    伪目标

    在Makefile中,并不是所有的目标都对应于磁盘上的文件。有的目标存在只是为了形成一条规则,从而完成特定的工作,并不生成新的目标文件,这样的目标称为伪目标。它并不是真正意义上的目标文件,只是为了满足Makefile的语法规则而存在的。

    在已经给出的Makefile文件中,最后一个目标clean就是伪目标。它规定了make应该执行的命令。当make处理到目标clean时,会先查看其对应的依赖对象。由于clean没有任何依赖对象,所以make会认为该目标是最新的而不会执行任何操作。为了编译这个目标体,必须手工执行如下命令:# make clean

    作为惯例,clean目标一般用于删除最终生成的可执行文件和在编译过程中产生的所有目标文件。问题是,如果恰巧有一个名为clean的文件存在时该怎么办呢?此时因为在这个规则里没有任何依赖对象,所以目标文件肯定是最新的,规则中的命令无论如何也不会被执行,即使用命令“make clean”也无济于事。解决这一问题的方法是标明该规则中的目标是伪目标,并不对应于任何文件。这可以通过.PHONY目标实现。它告诉make不检查规则的目标文件是否存在于磁盘上,也不查找任何隐含规则,而直接假设指定的目标需要被更新就行了。在使用了.PHONY之后,前面的给出的Makefile文件就将变为如下的内容:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    其它规则

    除了可以在Makefile中明确指定规则(显示规则)之外,make还维护了一整套隐式规则。隐式规则可以在用户没有完整地给出某些命令的时候,自动执行恰当的操作。隐式规则最大的好处是可以简化Makefile的编写和维护,例如前面给出的Makefile运用隐式规则后可以简化为如下内容:

OBJS = control.o ui.o main.o
program : $(OBJS)
$(CC) $(OBJS) -o $@
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    默认目标program依赖于control.o、ui.o和main.o三个目标文件,但Makefile中并没有给出怎样编译生成这些目标的规则。此时make就会使用隐式规则,对每一个名为foo.o的目标文件,找到与之对应的源代码foo.c,然后使用“gcc -c foo.c -o foo.o”命令来生成对应的目标文件。

    除了系统预定义的隐式规则外,在Makefile中还可以定义自己的隐式规则,这种规则也被称为模式规则。模式规则类似于普通规则,但它的目标必须含有“%”这一通配符,以便能与任何非空字符相匹配,与目标对应的依赖文件中也必须使用通配符,例如下面的规则:

%.o : %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

    上面的规则将告诉make所有形为foo.o的目标文件,都应该根据指定的命令从源文件foo.c编译而来。

    小结

    在构建大型的软件项目时,make是一个优秀的持续集成工具。它对于软件开发过程来讲非常重要。本文介绍了基本的make命令,以及如何编写简单实用的Makefile文件,相信用户已经能够使用make来管理软件项目的创建和维护过程了。

表1 常用自动变量



    此外,make还提供了一些预定义变量和自动变量,但它们看起来都不如自定义变量那么直观。之所以称为自动变量是因为make会自动用特定的、熟知的值来替换它们,表1给出了常用的部分自动变量。

    利用make的自动变量和预定义变量,可以简化前面给出的那个Makefile文件:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
clean :
    $(RM) program $(OBJS)


    伪目标

    在Makefile中,并不是所有的目标都对应于磁盘上的文件。有的目标存在只是为了形成一条规则,从而完成特定的工作,并不生成新的目标文件,这样的目标称为伪目标。它并不是真正意义上的目标文件,只是为了满足Makefile的语法规则而存在的。

    在已经给出的Makefile文件中,最后一个目标clean就是伪目标。它规定了make应该执行的命令。当make处理到目标clean时,会先查看其对应的依赖对象。由于clean没有任何依赖对象,所以make会认为该目标是最新的而不会执行任何操作。为了编译这个目标体,必须手工执行如下命令:# make clean

    作为惯例,clean目标一般用于删除最终生成的可执行文件和在编译过程中产生的所有目标文件。问题是,如果恰巧有一个名为clean的文件存在时该怎么办呢?此时因为在这个规则里没有任何依赖对象,所以目标文件肯定是最新的,规则中的命令无论如何也不会被执行,即使用命令“make clean”也无济于事。解决这一问题的方法是标明该规则中的目标是伪目标,并不对应于任何文件。这可以通过.PHONY目标实现。它告诉make不检查规则的目标文件是否存在于磁盘上,也不查找任何隐含规则,而直接假设指定的目标需要被更新就行了。在使用了.PHONY之后,前面的给出的Makefile文件就将变为如下的内容:

OBJS = control.o ui.o main.o
CC = GCC
CFLAGS = -Wall
all : program
program : $(OBJS)
$(CC) $(OBJS) -o $@
control.o : control.c
$(CC) $(CFLAGS) -c -o $@ $<
ui.o : ui.c
$(CC) $(CFLAGS) -c -o $@ $<
main.o : main.c
$(CC) $(CFLAGS) -c -o $@ $<
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    其它规则

    除了可以在Makefile中明确指定规则(显示规则)之外,make还维护了一整套隐式规则。隐式规则可以在用户没有完整地给出某些命令的时候,自动执行恰当的操作。隐式规则最大的好处是可以简化Makefile的编写和维护,例如前面给出的Makefile运用隐式规则后可以简化为如下内容:

OBJS = control.o ui.o main.o
program : $(OBJS)
$(CC) $(OBJS) -o $@
.PHONY : clean
clean :
    $(RM) program $(OBJS)


    默认目标program依赖于control.o、ui.o和main.o三个目标文件,但Makefile中并没有给出怎样编译生成这些目标的规则。此时make就会使用隐式规则,对每一个名为foo.o的目标文件,找到与之对应的源代码foo.c,然后使用“gcc -c foo.c -o foo.o”命令来生成对应的目标文件。

    除了系统预定义的隐式规则外,在Makefile中还可以定义自己的隐式规则,这种规则也被称为模式规则。模式规则类似于普通规则,但它的目标必须含有“%”这一通配符,以便能与任何非空字符相匹配,与目标对应的依赖文件中也必须使用通配符,例如下面的规则:

%.o : %.c
    $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

    上面的规则将告诉make所有形为foo.o的目标文件,都应该根据指定的命令从源文件foo.c编译而来。

    小结

    在构建大型的软件项目时,make是一个优秀的持续集成工具。它对于软件开发过程来讲非常重要。本文介绍了基本的make命令,以及如何编写简单实用的Makefile文件,相信用户已经能够使用make来管理软件项目的创建和维护过程了。
Linux系统CUDA安装报错:找不到make命令的完整解决方案 在Linux环境下进行软件编译和安装时,构建工具链是基础且关键的开发环境组件。make作为自动化构建工具,通过读取Makefile文件来管理源代码的编译、链接流程,是C/C++项目构建的核心。其技术价值在于简化复杂项目的编译过程,确保依赖关系正确执行,广泛应用于驱动开发、内核模块编译和高性能计算库安装等场景。本文针对CUDA安装过程中出现的“Unable to find the development tool `make`”错误,深入解析其根本原因——系统缺少完整的开发工具链,并提供跨发行版的解决方案。通 阅读详情

相关推荐

BLE开发环境搭建指南:从工具链到实战验证的完整流程

嵌入式开发中,开发环境搭建是项目成功的基础,尤其对于蓝牙低功耗(BLE)这类涉及无线协议栈的技术。其核心在于理解工具链、IDE、协议栈与调试工具等组件的协同原理。工具链负责将高级语言代码交叉编译为目标芯片的机器码,而集成开发环境则提供代码编写、构建和调试的一体化界面。BLE协议栈作为通信的灵魂,实现了广播、连接、数据交换等底层规范。正确的环境配置能显著提升开发效率,减少因工具链版本不匹配、路径设置错误导致的编译失败。在物联网、智能穿戴等应用场景中,稳定的开发环境是快速迭代和产品化的前提。本文以nRF5284

weixin_33895475的博客 395

GNU Make:一个开源的构建自动化工具,用于管理和协调软件项目编译

GNU Make是一个开源的构建自动化工具,用于管理和协调软件项目的编译过程。它通过读取Makefile文件中的规则,确定哪些文件需要重建,并发出相应的命令。GNU Make极大地简化了大型软件项目的构建过程,并提供了灵活且强大的功能,使其成为许多开发者和组织的首选工具。GNUMake:一个开源的构建自动化工具,用于管理和协调软件项目编译资源-优快云文库。

新华编程特战队 1483

手把手用LTspice仿真运算放大器电路:从虚短虚断到频响分析

本文通过LTspice仿真软件,手把手教你从搭建基础运算放大器电路开始,验证虚短虚断原理,并逐步深入频响分析与稳定性探究。内容涵盖反相/同相放大器、积分器仿真,导入真实运放模型进行蒙特卡洛分析,以及利用交流分析和波特图评估电路性能,帮助工程师和学生将抽象理论转化为直观、可测量的仿真结果,提升电路设计实战能力。

salt9的博客 1095

make 执行过程简单概述

    make的引入,使得一个大型复杂的linux 可以被裁剪定制为都有功能的项目,这也很容易理解,不可能任何一个项目都要包含linux的所有功能。功能类似于C语言程序中的"条件编译"。    make的执行过程可以简单的分为2个阶段,第一个阶段,它会读取所有的Makefile文件以及包含的Makefile文件等,记录所有的变量和其值,隐式或显式的规则,并构造出所有的目标对象以及其先决条件的一幅...

猪哥的专栏 2943

VBA常见错误 - “错误3706,未找到提供程序,该程序可能未正确安装”解决方法

1、问题描述 在利用VBA编程时,引用其它表格数据,出现以下问题: (1)运行“错误3706,未找到提供程序,该程序可能未正确安装”。 (2)引用数据失败 2、解决方法 下载“Access 2010 数据库引擎”,并安装即可。 https://www.microsoft.com/en-us/download/details.aspx?id=54920 AccessDatabaseEngine 2010 官方安装包,官网下载不了的可以来这里下载。(1)运行“错误3706,未找到提..

Nemuel的博客 3万+

ICESat-2数据下载的两种方法

ICESat-2数据下载

weixin_46341898的博客 2900

GNU Make工具(一)简介

GNU Make是什么1 Make有很多版本,其中GNU Make是一个自由软件。这里介绍一下它。 GNU Make是一个控制计算机程序从代码源文件到可执行文件或其他非源文件生成过程的工具。 控制命令通过称为makefile的文件传递给make工具。makefile记录了如何生成可执行文件等命令。 Capabilities of Make Make enables the end user t...

深空深蓝的博客 1万+

IGV实战指南:从数据导入到Peak可视化的全流程解析

本文提供了一份IGV实战指南,详细解析了从数据导入到Peak可视化的全流程。内容包括软件安装、参考基因组加载、测序数据处理、信号调整以及如何精准定位和可视化Peak区域,并分享了导出出版级矢量图的高级技巧,帮助用户高效完成基因组数据可视化分析。

weixin_29212867的博客 149

make的执行流程

make 的执行过程如下: 1. 依次读取变量“MAKEFILES”定义的 makefile 文件列表 2. 读取工作目录下的 makefile 文件(根据命名的查找顺序“GNUmakefile”,“makefile”,“Makefile”,首先找到那个就读取那个) 3. 依次读取工作目录 makefile 文件中使用指示符“include”包含的文件 4. 查找重建所有已读取的 makefile...

mlove编程 3565

手把手教你学PCIE--PCIe架构详解 - 物理层结构

在前一篇文章中,我们对PCIe与其他总线协议进行了对比分析。本文将深入探讨PCIe的物理层结构,这是PCIe协议的核心组成部分之一。物理层负责实际的电气信号传输,理解其工作原理对于设计和调试PCIe系统至关重要。PCIe的物理层是协议栈的最底层,负责将数据从链路层转换为电信号进行传输,并在接收端将电信号还原为数据。差分信号传输:通过一对差分信号线实现高速、低噪声的数据传输。时钟恢复:从数据流中提取时钟信号以同步收发双方。均衡与预加重:补偿信号在传输过程中的损耗,提高链路可靠性。

MHD0815的博客 363

【HFSS】仿真目录

Author: JiJi\textrm{Author: JiJi}Author: JiJi Created Time: 2026.04.27\textrm{Created Time: 2026.04.27}Created Time: 2026.04.27 Modified Time: 2026.04.27\textrm{Modified Time: 2026.04.27}Modified Time: 2026.04.27如果大家觉得有用,就点个赞吧,在阅读过程中存在任何困惑,可在下方评论区留言~

u011699626的博客 310

【Linux-命令】--make、makefile作用到底是什么

先先看一下什么是makefile  makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。  makefile带来的好处就是--“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率

yg_2012的专栏 1万+

数据分析案例-电影数据可视化分析

数据介绍数据为2011-2021电影数据可视化分析首先导入本次项目需要的包和数据 数据预处理 可视化

m0_64336780的博客 2万+

善用vim

善用vim                                       Vi是Unix下最常用的文本编辑器。VIM(Vi IMproved)则是它的增强版。有人常常拿VIM和emacs比较,VIM尽管不象emacs那样有那么多的功能,但是比emacs更方便、好用。用过emacs的人肯定会为emacs的一些快捷键感到烦恼,有时候用真希望自己有八只手。VIM的学习曲线也不象

JMP $的专栏 1232

STM32(HAL库)驱动HC-SR04测距模块

本文介绍通过STM32F103C8T6单片机对HC-SR04测距模块进行驱动,并且通过串口对数据进行打印。

weixin_44597885的博客 2204

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Buildroot构建机制深度解析:make、Config.in、.mk与.hash全链路

在嵌入式Linux开发中,构建系统负责将源码转化为可运行的镜像。其核心原理基于GNU make的依赖调度与增量判断,通过Kconfig配置系统生成.config文件,再由.mk文件定义各软件包的构建规则,并利用.hash文件校验源码完整性。理解这一机制能显著提升构建效率与问题排查能力,适用于定制根文件系统、交叉工具链集成及镜像生成等场景。本文深入剖析Buildroot中make、Config.in、.mk和.hash的协同工作流程,揭示从配置到镜像的完整链路。

weixin_33861800的博客 399

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

3步搞定GNU Octave:从零基础到科学计算高手的完整指南

GNU Octave 是一个功能强大的开源数值计算平台,提供与MATLAB高度兼容的语法和丰富的科学计算功能。无论你是数据分析新手、工程专业学生,还是需要高性能数值计算的科研人员,Octave都能为你提供强大的支持。🚀 ## 项目速览:为什么选择GNU Octave? 在开始之前,让我们快速了解GNU Octave的核心优势: | 特性 | 描述 | 适用场景 | |------|----

gitblog_00481的博客 876

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Makefile Tutor权威指南:GNU Makefile语法与最佳实践解析

Makefile Tutor是一个专注于GNU Makefile教学的开源项目,通过清晰的实例和逐步进阶的项目结构,帮助开发者掌握Makefile的核心语法与工程化最佳实践。本文将系统讲解从基础到高级的Makefile编写技巧,让你轻松驾驭这一构建工具。 ## 📚 什么是Makefile?为什么它如此重要? Makefile是GNU Make工具的配置文件,用于定义项目的构建规则。它通过声明

gitblog_01020的博客 469

ARM嵌入式Linux系统下GNU tar命令交叉编译移植实战指南

交叉编译是嵌入式Linux开发中的核心技术,它允许开发者在x86架构的宿主机上为ARM、MIPS等不同架构的目标平台生成可执行程序。其核心原理在于使用专门针对目标平台优化的工具链(如arm-linux-gnueabihf-gcc),通过配置构建系统,将源代码编译链接为目标平台的二进制格式。这项技术的价值在于解决了嵌入式设备资源受限、无法本地编译的难题,极大地提升了开发效率。在构建定制化Linux系统、部署应用程序或解压源码包等场景中,一个可靠的基础工具如tar命令至关重要。本文聚焦于GNU tar这一基础工

weixin_30614109的博客 349

善用并行,让构建倍速进行

我们先来回顾一下独立于 CI 系统的并行化解决方案案例。这种方案的特点是,无论构建系统如何,都能快速、便捷地解决问题。接下来,我将重点介绍 Linux 环境中的常用工具,这些工具包括 Bash、Python 和 GNU Parallel,想必大家也都不陌生。 这些工具相对容易操作,依赖项少。不过,也有一些局限性,我将重点指出。在后续的博客中,我会详细介绍如何使用主流 CI 系统中的功能来打破这些限制。

讨论软件开发加速、持续集成/持续交付(CI/CD)、C++、开发者生产力以及所有相关话题。 331

善用backtrace解决大问题

本文读者 请支持一次  超级搜索引擎  http://www.sugoogle.com   其实这个里面很简单 .     1   编译 动态库的话  加入 -rdynamic -ldl  选项.     2   用  *函数名+出错偏移地址方法.      定位 行. 例如 :     Stack Trace: => 12: 0x403de2ec (el_parse+0x

su_ocean16的专栏 1203

GLEW与GLUT、GLFW集成:现代OpenGL开发的终极指南 [特殊字符]

GLEW(OpenGL Extension Wrangler Library)是现代OpenGL开发中不可或缺的扩展加载库,它为开发者提供了高效的运行时机制来检测目标平台支持的OpenGL扩展。本文将深入探讨如何将GLEW与GLUT、GLFW完美集成,实现快速、稳定的图形应用程序开发。无论你是初学者还是经验丰富的开发者,这份完整指南都将帮助你掌握现代OpenGL开发的最佳实践。 ## 🤔 为什

gitblog_00150的博客 928

C语言Makefile编写教程:从入门到工程实践

在C/C++开发中,自动化构建工具是提升开发效率、管理复杂依赖关系的关键技术。Makefile作为经典的构建工具,其核心原理基于依赖关系和增量编译机制,通过定义目标、依赖和命令来实现自动化编译流程。这一技术价值在于显著减少重复劳动,加速大型项目的构建过程,尤其适用于嵌入式开发、系统软件等场景。通过掌握变量、函数和模式规则等高级用法,开发者可以编写出高效、可维护的构建脚本,实现多目录项目管理和头文件依赖自动处理,从而将Makefile应用于实际工程中,优化C语言项目的构建流程。

weixin_30824599的博客 492

HiGHS 线性优化求解器使用指南:LP、MIP、QP 三种模型如何用一个工具求解

HiGHS 是一款 MIT 许可的开源线性优化求解器,面向大规模稀疏问题,同时覆盖线性规划(LP)、凸二次规划(QP)和混合整数规划(MIP)三类模型。它的主体用 C++ 编写,提供 Python、C、C# 和 Fortran 接口。适合需要在本地或服务器上批量求解优化问题、又不想依赖商业求解器的开发者和研究者。本文按"安装—能力—实战—调优—排错"的顺序,带你把它跑起来。 ## 快速上手:安装

gitblog_00695的博客 731

C语言项目构建实战:从零编写健壮Makefile实现自动化编译

在C/C++项目开发中,构建系统是连接源代码与可执行程序的关键桥梁。其核心原理是通过定义目标文件、依赖关系和构建命令,实现智能化的增量编译机制。这一技术价值在于显著提升大型项目的开发效率,通过只重新编译修改过的文件,将构建时间从分钟级降至秒级,同时确保头文件变更引发的连锁编译正确执行。在工程实践中,构建系统广泛应用于需要跨平台部署、持续集成或命令行操作的中大型C语言项目。本文以Makefile这一经典工具为例,深入讲解如何为多模块项目搭建自动化构建流程,涵盖目录结构设计、变量定义、模式规则等关键概念,并重点

weixin_30567225的博客 447

为什么数据科学项目需要标准化结构:Cookiecutter Data Science(CCDS)的设计哲学与实践解析

> 数据科学代码的质量,归根结底只有两个词:**正确性(Correctness)** 与 **可复现性(Reproducibility)**。本文基于 Cookiecutter Data Science(CCDS)官方文档《Why use this project structure?》,结合仓库源码与配套文档,深入剖析这套项目结构背后的设计动机、协作价值与落地方式,帮助你理解并善用这套"逻辑清晰

gitblog_00465的博客 347
上一篇: 下一代版本控制工具Subversion
下一篇: 硬件基础知识大全
chengbd
博客等级 码龄25年 46粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值