CodeBlocks配置GoogleTest单元测试:从静态库编译到项目集成全攻略

很多用 CodeBlocks 写 C++ 的人,第一次接触单元测试时都会有点懵。IDE 很轻量,装上 MinGW 就能编译,但测试框架不会自己出现在菜单里;去网上搜 GoogleTest 配置,出来的基本是 Visual Studio 或者纯命令行的 CMake 教程,直接照搬根本跑不起来。我也在这个坑里翻了好几个晚上的文档,后来才总结出这套办法:先把 googletest 源码编成静态库,再回到 CodeBlocks 里把头文件路径、库路径、编译器参数一条条配好。这篇文章把整套流程完整记录下来,适合刚接触单元测试的 C++ 学习者,也适合换了电脑之后需要重新搭环境的老手。

1. 整体思路:CodeBlocks 和 GoogleTest 怎么搭起来

1.1 为什么选择这个组合

CodeBlocks 是一个不挑配置的 C++ IDE,对旧电脑尤其友好。它自带项目管理和编辑器,编译靠的是外部的 GCC 编译器,整个环境可以压缩到几百 MB。相比之下 Visual Studio 功能多,但启动速度慢,而且许可证和安装体积对很多学习场景来说都太重了。GoogleTest 是 C++ 生态里使用面很广的单元测试框架,它不依赖特定的 IDE,只要能编译 C++ 的编译器就能跑。这两个东西放在一起,等于保留了一个轻量开发环境,同时拿到了一个正规的测试框架,对于课程作业、内部工具、小规模项目维护来说非常合适。

我见过不少人觉得“测试框架是 CI 服务器上的东西,本地 IDE 里配什么测试”,其实恰恰相反。本地能跑单测,开发效率提升是最明显的。改一个函数,按一次编译,立刻知道 break 了哪里,比改完代码心里发虚强太多。

1.2 两种接入方式,我推荐静态库

GoogleTest 接入项目有两种主流方式,我两种都试过,说下实际感受。

方式一:把 googletest 源码直接加入 CodeBlocks 项目。

看起来最简单,把googletest/src下的源码全部拉进项目里,头文件路径指到googletest/include,然后一起编译。问题是,GoogleTest 源码对编译器标准比较敏感,如果 CodeBlocks 默认的编译标准还是老的 C++98/C++03,会出现大量模板和内存管理的报错。虽然可以在项目属性里强行打开 C++11,但每次新建测试项目都得重复配一遍这些文件,项目目录也会被一大堆测试框架代码塞满,看起来非常乱。

方式二:先把 GoogleTest 编译成静态库,测试项目里只链接库文件。

也就是先单独编译出自己的libgtest.a和libgtest_main.a,然后以后每个测试项目只需要在设置里指定头文件目录和库文件目录,再加一条-lgtest链接参数,代码里直接#include <gtest/gtest.h>就行。测试项目保持干净,依赖关系也明确。

我推荐方式二,原因有三个:

  • 编译一次,到处使用,不需要每个项目重新编译一遍框架源码。
  • 测试项目里的源码全是自己业务代码,看得清楚。
  • 排查问题简单,出现链接错误时,只需要检查路径和参数,不用怀疑框架源码编译环节。
对比项源码直接加入预编译静态库
首次配置速度快慢(需要多编译一次)
后续新建测试项目每项目都要配置源码只需要指定路径
项目目录整洁度被框架源码淹没干净
排错难度难,容易混入框架编译错误简单
推荐程度不推荐长期使用强烈推荐

1.3 需要提前准备的东西

在开始操作前,确认几个前提条件,缺一个后面都会卡壳:

  • 一个能正常工作的 CodeBlocks 环境,我以自带 GNU GCC Compiler 的情况为例。
  • googletest 源码包。可以从官方仓库直接下载打包好的 release,或者用 git 拉取最新的稳定分支。
  • 一个用来存放编译产物(静态库和头文件)的目录,建议路径不要包含空格和中文,避免后面的命令行操作出现奇怪问题。
  • 基本的命令行操作能力,能进目录、执行命令,仅此而已。

版本方面,我使用的是 1.10 以上的版本,文件结构和编译方式没有本质变化,下面这套操作适用于近几年的主流版本。

1.4 整体步骤预览

整个配置过程可以拆成三条主线:

  1. 在命令行下把 googletest 源码编译成静态库。
  2. 在 CodeBlocks 里建立一个测试项目,并配置好两个搜索路径和链接参数。
  3. 在测试项目里写测试用例,编译运行,并学会看输出结果。

我在文章里会带着每个参数解释为什么这么写,而不是只丢命令。

2. 第一步:把 GoogleTest 源码编译成静态库

2.1 源码文件结构先搞清楚

拿到 googletest 源码后,解压出来能看到googlemock和googletest两个顶层目录。我们需要的核心内容在googletest这个目录下。

真正被编译的核心编译单元,我最早以为是每个 .cc 文件都要单独编译,后来才发现官方为了方便集成,专门提供了一个汇总文件叫gtest-all.cc,它把绝大多数测试框架实现都统一包含进来了,路径在googletest/src/gtest-all.cc。所以编译的时候,只需要处理两个文件:

  • googletest/src/gtest-all.cc:框架主体实现。
  • googletest/src/gtest_main.cc:一个可以直接使用的main函数实现,里面调用了InitGoogleTest和RUN_ALL_TESTS。

以后写测试文件的时候,你可以自己写main,也可以把gtest_main链接进去不写main。两者我都试过,建议前期你自己写一个main,这样以后如果需要在测试之前做初始化,方便修改。

2.2 在命令行里编译两个对象文件

打开命令行,进入 googletest 源码根目录所在的路径。以我本机目录为例子,源码解压在D:\thirdparty\googletest,我执行的命令如下:

cd D:\thirdparty\googletest g++ -std=c++11 -Wall -I googletest -I googletest/include -c googletest/src/gtest-all.cc -o gtest-all.o g++ -std=c++11 -Wall -I googletest -I googletest/include -c googletest/src/gtest_main.cc -o gtest_main.o

逐个解释一下参数:

  • -std=c++11:强制指定 C++11 标准。老版本的 GCC 默认标准可能不支持 googletest 里用到的某些特性,这一步必须做。
  • -I googletest:因为gtest-all.cc内部会按相对路径去包含其他实现文件,这个路径指向源码目录的上层,保证#include "src/gtest-internal-inl.h"这类包含能找到。
  • -I googletest/include:让编译系统能找到gtest/gtest.h这个大门口的头文件。
  • -c:只编译不链接,生成目标文件.o。

这一步如果顺利,你会得到gtest-all.o和gtest_main.o两个文件。如果出现找不到某个头文件,检查路径是不是写错了,尤其是googletest/include这一层必须包含进去。

2.3 用 ar 打包生成静态库

对象文件只是中间产物,还需要打包成静态库。标准做法是用ar命令:

ar rcs libgtest.a gtest-all.o ar rcs libgtest_main.a gtest_main.o

参数说明:

  • rcs表示如果没有库文件就创建,有文件就替换,并且生成索引。老手习惯直接这么用,新手不用深究。
  • libgtest.a是主测试框架库,所有断言和测试注册逻辑都在里面。
  • libgtest_main.a是带main的库,以后测试项目如果链接了这个库,就可以不用自己写main。

打包完成后,把这两个.a文件放到一个固定目录,比如D:\thirdparty\gtest\lib,并把googletest\include目录复制到D:\thirdparty\gtest\include。以后所有测试项目统一指向D:\thirdparty\gtest\include和D:\thirdparty\gtest\lib,路径统一,管理方便。

2.4 验证静态库是否真的能用

这一步很容易被跳过去,但我建议花一分钟做个冒烟测试,写一个小到不能再小的测试文件:

#include <gtest/gtest.h> TEST(SmokeTest, BasicAssertion) { EXPECT_EQ(1 + 1, 2); } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }

保存为smoke_test.cpp,然后命令行编译:

g++ -std=c++11 -I D:\thirdparty\gtest\include smoke_test.cpp -L D:\thirdparty\gtest\lib -lgtest -lgtest_main -o smoke_test.exe

注意这里的链接顺序。-lgtest_main放在-lgtest前面,因为gtest_main的实现会引用RUN_ALL_TESTS等符号,链接器处理的时候必须先把依赖方处理好。如果你把-lgtest放在前面,某些 GCC 版本会给出 undefined reference,后面排查半天也找不到原因。

如果能编译出smoke_test.exe,运行后看到类似[ RUN ] SmokeTest.BasicAssertion和[ OK ]的输出,说明静态库没问题。

3. 第二步:在 CodeBlocks 里建立测试项目

3.1 新建一个控制台项目

现在回到 CodeBlocks,开始建测试项目。选择菜单里的 New -> Project,模板选 Console Application,语言选 C++,然后按两步提示填写项目名称和保存路径。建议先建立一个空白项目目录,并且测试项目不要和你写的功能代码项目放在同一个工程里,逻辑上分离。

编译器选择这里需要确认一下,项目创建对话框的编译器下拉框里选中你常用的 GNU GCC Compiler。如果列表里没有,说明全局设置里还没配置好编译器,先去 Settings -> Compiler 里把 MinGW 的安装目录指向设置好。

3.2 配置头文件搜索目录和库搜索目录

项目建好之后,工具栏找到 Project -> Build options,也可以直接右键项目名,在弹出的菜单里选 Build options。左侧有两个常见的配置项:Compiler settings 和 Linker settings。

先在左侧选 Compiler settings,切到 Search directories 标签页,这个标签页下面是 Compiler 和 Linker 两个子页签。在 Compiler 子页签中,点击 Add 按钮,把D:\thirdparty\gtest\include加进去。这个路径就是告诉编译器,遇到#include <gtest/gtest.h>的时候,该去哪里找头文件。

然后切到 Linker 子页签,同样点 Add,把D:\thirdparty\gtest\lib加进去。这个路径是告诉链接器,-lgtest里的libgtest.a在哪个目录。

如果你的界面里找不到这两个子页签,也不用慌,可以直接把路径写到 Compiler settings 里的 Other options 框里。写的内容是:

-I D:\thirdparty\gtest\include -L D:\thirdparty\gtest\lib

这两种方式等价,本质都是给编译器和链接器传搜索路径。我更喜欢用 IDE 的 Search directories 界面,因为路径会被单独显示,看起来清楚。

3.3 链接参数和 C++ 标准

接下来还在同一个 Build options 窗口里,左侧切到 Linker settings。注意它下面有个 Link libraries 列表,这个列表是让你直接加.a或.lib文件的,很多新人在这里直接把整个路径加入,但这样配置方式比较脆弱,我推荐用底部的 Other linker options 文本框,手动写:

-lgtest -lgtest_main

顺序是有讲究的。lgtest_main在前,lgtest在后,原因我在前面冒烟测试的时候已经解释过了。如果以后你决定自己写main,不链接gtest_main,那么这里只需要写-lgtest。

然后还要确认 C++ 标准。回到左侧 Compiler settings,找到 Compiler flags 或 Standard 标签页,把 C++ standard 设置为 C++11 或更高。这一步经常被忽略,但千万要做,否则编译测试文件时会出现类似stdexcept解析异常、模板展开失败之类的问题。

3.4 第一版最小测试代码

在项目的 main.cpp 里写入如下代码:

#include <gtest/gtest.h> // 一个普通函数,后面我们用测试用例来验证它 int Add(int a, int b) { return a + b; } // 测试组名称是 AddTest,第一个测试用例叫 PositiveNumbers TEST(AddTest, PositiveNumbers) { EXPECT_EQ(Add(2, 3), 5); EXPECT_EQ(Add(10, 10), 20); } // 第二个测试用例 TEST(AddTest, NegativeNumbers) { EXPECT_EQ(Add(-1, -1), -2); } // 自己写的 main 入口 int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }

这里特别说一下InitGoogleTest这行。它的作用是让框架从命令行参数中识别 GTest 自己的控制参数,比如--gtest_filter=AddTest.*这种过滤测试用例的参数。如果少了这一行,命令行参数不会被解析,过滤功能就没法用。作为日常手写 main 的习惯,我建议把这一行保留。

链接参数如果加了-lgtest_main,那这个 main 就可以不写。但我不推荐依赖它,至少在你还没完全熟悉框架的时候,自己写 main 会让交后的调试更直接。

4. 第三步:编译运行与结果分析

4.1 编译过程中可能遇到的小问题

在 CodeBlocks 里按 Ctrl+F9 编译项目,正常情况下控制台窗口会显示构建日志。如果代码没错,配置没错,你会看到类似Linking console executable...的成功提示。但第一次配置多多少少会有些状况,最常见的两种:

一种是编译时报错gtest/gtest.h: No such file or directory,这说明编译器搜索路径里的 include 没配好,或者路径写错了。去 Build options 里检查一下,路径结尾是不是多了一个斜杠、少了一个斜杠,或者把/include错写成了/includes。

另一种是链接时一堆undefined reference to ...,这种往往是静态库路径没配对,或者你在 Link libraries 里点选了错误的文件。回到 Search directories 的 Linker 页签检查确认。

4.2 看懂测试输出

编译成功后按 F9 运行。输出窗口会滚动出类似下面的内容:

[==========] Running 2 tests from 1 test suite. [----------] Global test environment set-up. [----------] 2 tests from AddTest [ RUN ] AddTest.PositiveNumbers [ OK ] AddTest.PositiveNumbers (0 ms) [ RUN ] AddTest.NegativeNumbers [ OK ] AddTest.NegativeNumbers (0 ms) [----------] 2 tests from AddTest (0 ms total) [----------] Global test environment tear-down [==========] 2 tests from 1 test suite ran. (1 ms total) [ PASSED ] 2 tests.

这个输出的信息量其实很大:

  • [ RUN ]表示接下来要运行某个测试用例。
  • [ OK ]表示这个测试用例通过。
  • [ FAILED ]表示断言失败,框架会标明具体哪个文件哪一行,以及两边的期望值和实际值。
  • 最后一行PASSED会统计通过数量,如果有失败,会显示FAILED的条数和明细。

如果你运行后只看到空白窗口或者弹出来一个独立的终端,就看日志输出的地方,CodeBlocks 在默认设置下会把 stdout 输出到一个黑框控制台里。如果你更习惯看 IDE 内部日志,可以在运行的设置里把“独立控制台”关掉,但我不建议这么做,因为 GTest 输出会很多,IDE 内部的日志缓冲反而不好追踪。

4.3 常用断言宏速记

GoogleTest 有两种断言风格,EXPECT_和ASSERT_,区别在于失败后的行为:

  • EXPECT_EQ(a, b):失败后继续运行当前测试用例。
  • ASSERT_EQ(a, b):失败后直接终止当前测试用例。

对于大多数测试场景,先用EXPECT_更稳妥,可以一次性看到多个断言失败信息。只有当前面的失败会导致后续代码出现空指针或越界等问题时,才需要用ASSERT_提前终止。下表列出我常用的断言:

断言检查内容
EXPECT_EQ(a, b)a 和 b 相等
EXPECT_NE(a, b)a 和 b 不等
EXPECT_GT(a, b)a 大于 b
EXPECT_LT(a, b)a 小于 b
EXPECT_STREQ(s1, s2)两个 C 风格字符串相等
EXPECT_FLOAT_EQ(a, b)浮点数近似相等,带默认精度控制
EXPECT_TRUE(expr)表达式为真
EXPECT_FALSE(expr)表达式为假

此外还有EXPECT_THROW(expr, MyException)可以测试某段代码是否抛出了指定类型的异常,这个在写健壮性测试时很常用。实际用过之后会发现,掌握这十个左右断言,日常测试需求就被全覆盖了。

4.4 测试失败时的退出码

运行完成后,CodeBlocks 的绿色标识可能不会告诉你测试是否通过,因为它只是看程序有没有正常退出。GoogleTest 在设计上很贴心:所有测试通过时,main返回 0;只要有测试没通过,RUN_ALL_TESTS返回非 0。这意味着如果以后你把测试接入自动构建脚本,只需要判断程序退出码即可。

有的同事喜欢写一排std::cout << "all good"来判断,这是不可靠的。正确做法是看最后一行PASSED的状态。如果测试有失败,CodeBlocks 的运行窗口可能一闪而过,这时可以在控制台程序末尾加一句system("pause")之类,但这只为了方便本地看,别带到正式环境。

5. 常见问题与排查实录

5.1 undefined reference 错误

这是最让人头疼的错误,也是我当年花了最多时间的地方。症状是编译正常通过,但链接阶段报出一长串:

undefined reference to `testing::UnitTest::Run()' undefined reference to `testing::InitGoogleTest(int*, char**)'

排查思路:

  • 先确认是否真的链接了静态库。在 Build options 的 Other linker options 里有没有-lgtest。
  • 然后确认库路径是否设置正确。如果libgtest.a在D:\thirdparty\gtest\lib,那-L参数必须指向这个目录,注意是包含.a文件的上一层目录,不是这一层目录。
  • 再看链接顺序。-lgtest_main -lgtest这个顺序里,lgtest_main必须在前面。如果你自己写了 main,只链接-lgtest即可,不用链接 gtest_main。

有一次我套用了旧教程还在链接参数里写了-lpthread,在 Windows 的 MinGW 环境里这个问题不太需要,但在 Linux 下是必须的。如果你在 Linux 上遇到 undefined reference 到pthread_*符号,只需要在最后补一个-lpthread,位置同样是放在-lgtest之后。

5.2 找不到头文件

编译时出现:

gtest.h: No such file or directory

通常是编译器的 include 搜索路径没有正确指向include目录。要检查的地方不是你想的那个“项目目录”,而是 Build options -> Compiler settings -> Search directories -> Compiler 或 Other options 里的-I参数。如果你复制了我前面命令里的路径,注意把盘符替换成你自己的路径。

还有一个容易踩的坑:手动把 googletest 源码中的include/gtest目录复制到其他位置时,目录层级可能发生变化。你需要保证最终路径是你的目录/gtest/gtest.h,因为代码里写的是<gtest/gtest.h>。如果把头文件直接铺平放,路径对不上,照样找不到。

5.3 程序一运行就崩溃,但没有编译错误

这种情况多半是 C++ 运行时初始化阶段的问题,常见于在 32 位和 64 位库之间发生了混搭。比如你的 CodeBlocks 编译器是 32 位,但 bochuang 的库目录里放着一个用 64 位 MinGW 编译出来的libgtest.a,链接不会报错,运行时会直接崩溃。

排查办法很简单:重新用当前 CodeBlocks 对应的编译器编译一遍静态库。也可以查看编译器和库文件的架构是否一致,GCC 编译时加上-m32或-m64可以强制指定位数。我曾经同时装过 32 位和 64 位两个版本的 MinGW,有一次配置错路径导致整体编译非常离奇,最后发现就是静态库架构不匹配。

5.4 C++ 标准未开启产生的疑难杂症

如果忘了打开 C++11 或者更高标准,有可能链接都能通过,但运行测试时输出非常诡异,比如模板实例化失败,或者断言比较出现明显错误。实际上某些 GCC 版本在缺省标准下,std::unique_ptr这类特性的行为并不一致。

我的建议是直接把编译标准设成 C++17,因为新版本 googletest 已经大量用到 C++14 的特性,老默认标准容易出问题。在 Build options 的 Compiler settings 里找到 C++ standard 下拉菜单,选 C++17,省心。

5.5 路径带空格或中文目录名

CodeBlocks 项目路径如果出现在带空格的目录,比如C:\My Projects\TestProject,某些源码内部会做字符串拼接,就可能出现引号缺失导致找不到文件的问题。更麻烦的是中文目录,某些旧版 MinGW 对中文路径的编码支持并不好。

最稳妥的办法是把测试代码和依赖库全部放在纯英文、无空格的路径下。这一点在开头准备阶段就要注意,不要等出了问题再改。

5.6 要不要单独建一个测试工程文件

我的做法是:主功能项目一个工程,测试项目单独一个工程。原因很简单,测试工程需要链接 GoogleTest 静态库,加上过滤器和输出参数,构建配置和主项目差异很大。如果把测试直接丢进主项目,主项目每次编译都要跑一遍全套测试,而且一加测试代码,主项目的可执行文件变成测试驱动,严重影响调试流程。

很多同事会问为什么不在主项目里右键添加一个 main 文件,看这里:CodeBlocks 的 Console Application 只有一个入口,你加了自己的 main,原有的 main 就会冲突。拆成两个项目,主项目调什么函数,测试项目链接主项目的源代码或静态库,这种结构想复杂都难。

6. 我后面一直沿用的实践习惯

6.1 把所有外部依赖固定在同一个目录结构下

我在第 2 节提到的目录结构,实际用了很久:

D:\thirdparty\ gtest\ include\ gtest\ lib\ libgtest.a libgtest_main.a

所有项目都统一指向这里。这样一来,每换一台机器,只要把这个目录拷过去,重新配置一下 CodeBlocks 里的路径,测试项目立刻就能跑。不要每个项目单独复制一份 googletest 源码,那样升级的时候就要改 N 个项目。

6.2 使用 TestFixture 组织重复的测试数据

平时测简单函数可以直接用TEST宏,但当测试场景里需要构造相同的对象、相同的初始状态,重复代码就会爆炸。GoogleTest 提供了TestFixture,基本玩法是把公共的初始化数据放在继承testing::Test的子类里,然后用TEST_F宏写用例。代码看起来大概是:

class StackTest : public testing::Test { protected: void SetUp() override { stack_.push(1); } MyStack stack_; }; TEST_F(StackTest, PopAfterPush) { EXPECT_EQ(stack_.pop(), 1); }

这里SetUp会在每个测试用例执行前被调用,避免每个测试里都重复写建栈逻辑。在配置完 GoogleTest 之后,下一个值得花时间学的就是它。

6.3 测试命名尽量带上业务模块前缀

我已经吃够了一个项目一大堆测试部分散乱的亏。负责任的做法是使用结构化的命名,像OrderModuleTest.CheckDiscount、UserModuleTest.LoginFailure,这样测试失败时,一看名字就知道属于哪个模块。GTest 的--gtest_filter参数还可以按模块前缀过滤,连续跑测试的时候特别有用,比如:

--gtest_filter=UserModuleTest.*

这个功能在 IDE 里同样可以传参,方法是在 Project -> Set programs arguments 里把过滤规则填进去,运行测试时只关心自己模块的用例,效率高不少。

6.4 顺手引入一个简单的回归命令脚本

CodeBlocks 里鼠标点运行很方便,但真正让我体会到测试价值的是在命令行下做一个快速回归。

写完一批测试,我通常在测试项目目录下开一个终端,执行:

./测试目标可执行文件名.exe --gtest_color=no

加上--gtest_color=no是为了避免终端不支持颜色时看到的乱码。然后把输出重定向到日志文件里,直接用文本对比确认是否有新的 fail 关键字。这种流水线式检查对改动频繁的模块帮助很大,而且不需要打开 IDE,编译和测试都是自动化的。

我一直觉得,单元测试框架的配置只是折腾过程中的一小步,真正有价值的是把“跑了没”变成“跑了对不对”。本地 IDE 配上 GoogleTest 之后,写代码的安全感会明显不一样,尤其是重构代码时,改完一编译、一测试,几分钟就能确认没有把老功能弄坏。配置过程不难,但第一次总会踩些莫名其妙的坑,希望这篇记录能给你省下我当初浪费的晚上。

相关新闻

C++多线程开发入门:从std::thread到线程池的同步与并发实践

C++多线程开发入门:从std::thread到线程池的同步与并发实践

写多线程代码难在哪&#xff1f;难在它不像单线程那样能靠“从上往下读”预测程序行为。很多初学者把我问得最多的一个问题就是&#xff1a;“C 多线程开发到底该怎么开始&#xff1f;”不瞒你说&#xff0c;我自己第一次写多线程程序时也踩过不少坑&#xff0c;比如双击运行没…

2026/10/20 17:07:31 阅读更多 →
军人体能五项标准化评分引擎:规则驱动、版本可控、可审计的轻量计算系统

军人体能五项标准化评分引擎:规则驱动、版本可控、可审计的轻量计算系统

简介&#xff1a;这是一套专为军队体能考核设计的Python自动化评分系统&#xff0c;面向基层部队训练骨干、新兵连教官及军事体育教学人员&#xff0c;解决五项体能成绩&#xff08;单杠、仰卧起坐、蛇形跑、3公里跑、体型&#xff09;人工汇总耗时长、标准易偏差、跨性别/年龄…

2026/10/20 17:06:30 阅读更多 →
npm依赖安全审计实战:从工具链到CI阻断的完整方案

npm依赖安全审计实战:从工具链到CI阻断的完整方案

“第三方库怎么也会被攻破&#xff1f;”这是很多团队在做依赖安全审计时&#xff0c;最先问出口的问题。高频考点这个词我很少在技术文章里用&#xff0c;但它放在“npm包安全审计”前面&#xff0c;确实贴切。近两年供应链安全已经成了前端和后端 Node 服务里绕不开的话题&am…

2026/10/20 17:06:30 阅读更多 →

最新新闻

Claude Code实战:宠物健康管理系统全栈开发复盘

Claude Code实战:宠物健康管理系统全栈开发复盘

1. 项目概述&#xff1a;这不是一个“AI写代码”的演示&#xff0c;而是一次真实产品级开发的完整复盘“Claude Code从零搭建新项目全流程AI实现-宠物生命周期管理App”——这个标题里藏着三个关键信息点&#xff1a;Claude Code是核心工具链&#xff0c;从零搭建强调过程完整性…

2026/10/20 18:30:19 阅读更多 →
DeepSeek本地部署避坑指南:Ollama安装与模型尺寸选择

DeepSeek本地部署避坑指南:Ollama安装与模型尺寸选择

简介&#xff1a;这份PDF资料面向对大模型感兴趣的技术爱好者与研发人员&#xff0c;聚焦DeepSeek在本地环境下的部署方法与核心训练原理&#xff0c;帮助读者以低成本方式搭建可离线运行的大模型应用。内容从本地部署的三个实操步骤切入&#xff0c;逐步延伸至LLM基础概念、Tr…

2026/10/20 18:30:19 阅读更多 →
AI培训不是一门课,而是四条职业轨道的选择题

AI培训不是一门课,而是四条职业轨道的选择题

1. 别急着报班&#xff1a;先拆解“AI培训”这个词到底在指什么很多人点开“AI培训”广告时&#xff0c;脑子里浮现的是同一个画面&#xff1a;一个穿格子衬衫的年轻人&#xff0c;在黑底白字的终端前敲出一行python train.py --modelllm&#xff0c;然后模型精度飙升、工资翻倍…

2026/10/20 18:30:19 阅读更多 →
多模态SCA与全周期协同:中间件开源风险治理实践解析

多模态SCA与全周期协同:中间件开源风险治理实践解析

最近行业中公布了一轮开源安全与风险治理优秀案例评选&#xff0c;某AI安全公司基于“多模态SCA全周期协同”的中间件开源风险治理实践&#xff0c;成功入选了“开源安全及风险治理”类别的典型案例。这不算一个堆了一堆安全工具的“面子工程”&#xff0c;而是把软件成分分析&…

2026/10/20 18:30:19 阅读更多 →
Java实现节假日/周末/工作日全量落库方案

Java实现节假日/周末/工作日全量落库方案

简介&#xff1a;本资源是一份面向Java后端开发者与数据库应用学习者的实用工具型代码包&#xff0c;解决企业级排班系统、考勤管理或日历服务中需动态生成并持久化年度工作日/周末/节假日数据的核心需求。压缩包为7z格式&#xff0c;仅含1个核心Java源文件&#xff08;SaveYea…

2026/10/20 18:30:19 阅读更多 →
微信小程序小闹钟:状态机设计与本地定时实战指南

微信小程序小闹钟:状态机设计与本地定时实战指南

简介&#xff1a;这是一份面向微信小程序初学者的练手项目资源&#xff0c;聚焦基础功能开发实践&#xff0c;特别适合刚掌握WXML/WXSS/JS三件套、希望通过完整小应用巩固开发流程的学习者。项目实现了一个具备时间设置、闹铃触发、界面交互与音效反馈的小闹钟功能&#xff0c;…

2026/10/20 18:29:17 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →