简介FreeCAD 1.0 完整源代码包是面向CAD开发者、软件学习者及有插件扩展需求团队的珍贵学习材料。该版本以C编写并遵循GPL协议涵盖参数化三维建模、完整二维图纸、任务工作台等核心功能代码模块化程度高适合用于编译实践、源码阅读和二次开发研究。压缩包共2000个文件以915个cpp、754个h源码文件为主体另含98个py脚本、63个xml配置、36个hpp头文件、29个md文档及14个sh构建脚本等总大小约97.18MB目录结构清晰完整便于按模块定位目前已有411人学习/下载。通过研读核心源码可以梳理对象建模流程、表达式解析与单位解析机制理解工作台扩展和宏系统的实现方式并可借助Python接口编写自定义功能与自动化操作流程对于希望深入掌握CAD内核结构或参与FreeCAD生态开发的读者这份源代码提供了从底层实现到上层接口的完整参考。1. 从 freecad1.0源代码 开始先学会“定位”再谈“读懂”把 freecad1.0源代码 下载到本地后多数人第一反应是翻开 src 目录然后被几十个子目录和上万源文件劝退。这是典型的“源码焦虑”不读源码照样能用 FreeCAD但想搞清一个命令为什么那样工作、想改个界面文案、想加内部工具源代码才是唯一能给确定答案的地方。FreeCAD 1.0 是这个项目二十多年来的第一个 1.0 正式版代码规模和依赖复杂度都远超 0.20、0.21 时代。读它不需要从零通读而是学会在源码里定位三样东西对象怎么定义、命令怎么注册、属性怎么暴露给 Python 控制台。拿到这三个定位点就拿到了二次开发的入口。这篇文章按我实际摸索的顺序给一条动线先地图式扫目录再在本地编译出可执行文件然后做两个最小改动最后用 FreeCADCmd 做回归验证。适合已经在用 FreeCAD、想向源码层再走半步的工程师也适合要在团队内部做可控构建的人。2. FreeCAD 1.0 源码地图先定位 src/App、src/Gui、src/Mod 三层2.1 顶层目录看起来乱但三层结构十年没变过下好源码先别急着读文件在仓库根目录把目录树拉出来用几秒钟建立整体感。cd freecad-src ls -1 ls -1 src第一条命令看仓库根第二条看源码主体。src下面常见的顶层模块是Base、App、Gui、Mod、Tools这几个它们的分工非常明确目录职责什么时候需要动它src/Base基础类型、容器、几何类、文件读写、XML 配置极少碰除非要改 Placement、Vector 这类底层结构src/App文档与对象模型核心Application、Document、DocumentObject、参数属性系统加新对象、新属性时看这里src/Gui窗口、命令框架、工具栏、视图提供者改菜单项、命令 ID、工具栏按钮时src/Mod各工作台Part、PartDesign、Sketcher、Draft、TechDraw、Path 等绝大多数二次开发工作都在这里src/Tools编译辅助、打包、模板、第三方依赖脚本出安装包或排查构建问题时理解这套结构的关键是 App 与 Gui 分离。FreeCAD 的命令行版本 FreeCADCmd 不加载 Gui 也能完整建模说明建模逻辑大量放在 App 和 Mod 的 App 侧界面只是壳。这个设计决定了你的二次开发路径优先在 App 侧实现能力Gui 侧只做命令注册和视图呈现。2.2 属性系统Python 控制台里看到的不是“另一个对象”用 FreeCAD 的人都知道 Python 控制台能操作文档对象但很容易误以为那是一套独立的 Python API。实际上你看到的是 C 对象的绑定视图。FreeCAD 的文档对象继承自DocumentObject属性通过ADD_PROPERTY之类的宏注册绑定层再把它们暴露给 Python。在源码里验证这个关系rg -n class DocumentObject src/App rg -n ADD_PROPERTY src/Mod/Part | head -20第一条命令定位DocumentObject类声明第二条在 Part 模块里找属性注册的例子。rg比grep -r快得多输出带行号是读 FreeCAD 源码的首选工具。这些属性注册宏是 FreeCAD 二次开发性价比最高的地方你在 C 侧加一个属性Python 控制台和属性面板会同步出现不需要额外写胶水代码。所以想搞清“某个属性从哪来”就去 C 类里找注册宏而不是去翻文档。2.3 用 grep 在源码里定位功能折角与公差标注的定位演示定位一个具体功能的标准步骤是先在 Python 控制台拿到对象的 TypeId再去源码里搜这个字符串。举两个真实场景。场景一对应很多人在查的“freecad 如何将物体折一个角度”。把一个物体绕轴旋转指定角度在 FreeCAD 里的本质是改 Placement 的 Rotation不是把网格切开。先看 Placement 类的定义rg -n class Placement src/Base rg -n Rotation src/Mod/Part | head -40第一条命令确认 Placement 在 src/Base 下第二条看 Part 模块里哪些代码引用旋转。搜索命中多时优先看src/Base/Placement.cpp这个文件它是旋转、镜像等变换操作的源头。场景二对应“freecad标注公差”。公差显示集中在 TechDraw 制图模块rg -n -i tolerance src/Mod/TechDraw | head -30-i让搜索忽略大小写因为源码里同名功能可能写成Tolerance、tolerance两种风格。看完输出后注意区分命中在 App 侧还是 Gui 侧。如果只落在 Gui 侧说明公差基本是显示层的事不污染底层几何数据这在做图纸导出时是个重要结论。以后再遇到“某个功能在哪里”的问题就用这套方法Python 控制台打TypeId拿 TypeId 去源码里搜再看命中文件分布确定它在建模层还是界面层。3. 在 Ubuntu 上把 freecad1.0源代码 编译成可执行文件3.1 依赖清单与版本选择Qt、OCCT、Python 的组合要一致FreeCAD 是 Qt OpenCASCADEOCCT Coin3D Python boost 的组合。OCCT 是几何内核Coin3D 负责 3D 视图Qt 管窗口Python 绑定依赖 SWIG 和 PyCXXxerces-c 处理 XML 配置文件。任何一个版本错配都会在 configure 或链接阶段爆雷。以 Ubuntu 22.04 为例先装系统依赖sudo apt update sudo apt install build-essential cmake git \ qtbase5-dev libqt5svg5-dev \ libocct-data-exchange-dev libocct-draw-dev libocct-foundation-dev \ libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev \ libocct-visualization-dev libcoin-dev libeigen3-dev libxerces-c-dev \ libboost-dev libboost-filesystem-dev libboost-program-options-dev \ libboost-regex-dev libboost-serialization-dev \ python3-dev swig这一长串里libocct-*系列是几何内核libcoin-dev是三维视图库libeigen3-dev提供线性代数基础python3-dev和swig解决 Python 绑定。没有这些CMake 配置阶段就会直接失败。版本组合上我在 22.04 上验证过的顺手组合是 Qt 5.15 OCCT 7.6/7.7 Python 3.10。不要因为系统软件源里有 Python 3.12 就去用最新版FreeCAD 的绑定层对过新的 CPython API 支持总是慢半拍后文避坑部分会细讲。Windows 上则优先用官方 LibPack 依赖包它把 Qt、OCCT、Coin3D 的版本锁死在配套状态比自己拼装省很多时间。3.2 拉取源码与 CMake 配置别拿 master 分支做生产构建源码从官方 Git 仓库拉取之后先把版本锁定在 1.0 相关 tag 上而不是直接编 master。master 每天都在变你今天编过的行为下周可能就没了。git clone https://github.com/FreeCAD/FreeCAD.git freecad-src cd freecad-src git tag | grep -E ^1\.[0-9]先看有哪些 1.0 相关的 tag再选一个固定的 checkout。用 tag 而不是分支做构建遇到问题时能跟其他人对得上版本号排查也容易。配置阶段的命令是最短的一版cmake -B build \ -DCMAKE_BUILD_TYPERelease \ -DPYTHON_EXECUTABLE$(which python3)-B build指定构建目录所有产物都放这里不污染源码目录CMAKE_BUILD_TYPERelease影响优化等级Debug 版本体积大、运行慢但能给你更详细的崩溃信息PYTHON_EXECUTABLE显式指定 Python 解释器避免 CMake 选错系统里的另一个版本。配置完成后别急着开始编译先看一下有哪些模块开关cmake -LA -N build | grep -E BUILD|FREECAD | head -50这个命令列出本次配置里所有可调项能看到BUILD_GUI、BUILD_PART、BUILD_PARTDESIGN、BUILD_TECHDRAW这一批开关。如果机器内存小、只想快速跑通核心可以把重型工作台关掉一部分cmake -B build -DBUILD_ARCHOFF -DBUILD_BIMOFF注意Part和PartDesign尽量保留很多工作台依赖它们。做最小编译验证时只留BUILD_GUI和BUILD_PART也够用。3.3 编译与首次运行FreeCADCmd 是验证源码生效的最佳入口编译命令很直白cmake --build build -j 8-j 8是并行编译任务数按 CPU 核心数调整。内存 16G 以下建议用 4避免链接阶段内存被撑爆。首次全量编译在性能不错的机器上约二十分钟到四十分钟中途报错不用慌看错误信息里是哪个模块、哪个符号。编译完成后的验证分两步。先验证命令行版本build/bin/FreeCADCmd -c import FreeCAD; print(FreeCAD.Version())-c让 FreeCADCmd 启动后直接执行后面的 Python 字符串不进入交互模式。输出里会包含 1.0 的版本号和 Git 修订号看到修订号就能确认这是你自己编出来的不是系统预装的。再验证图形版本build/bin/FreeCAD远程服务器没有图形环境时FreeCADCmd 是你唯一能依赖的验证入口这也解释了为什么 App/Gui 分离的设计对自动化测试这么重要。第一次启动 GUI 如果立刻闪退先检查显卡驱动和 OpenGL 支持这是图形环境问题跟源码关系不大。4. 读源码之后做二次开发从对象映射到改命令文案的三个入口4.1 入口一用 TypeId 打通 Python 对象和 C 实现在自编译版本里打开 Python 控制台创建一个最简单的立方体看对象的类型标记import FreeCAD as App doc App.newDocument(Test) box doc.addObject(Part::Box, Box) print(box.TypeId) print(box.PropertiesList) print(box.getPropertyByName(Length))TypeId是 C 类的完整名称PropertiesList列出这个对象注册的全部属性getPropertyByName取单个属性当前值。输出的 TypeId 就是你接下来搜源码的钥匙rg -n Part::Box src/Mod/Part搜索命中的文件就是这个对象的 C 实现。能看到它的头文件里用属性宏注册了 Length、Width、Height。理解这个映射关系后你会明白一个关键结论Python 控制台不是“另一个 FreeCAD”它就是 C 对象的一层皮。回到“freecad 如何将物体折一个角度”的场景在 Python 里旋转物体就是改 Placementbox.Placement App.Placement( App.Vector(0, 0, 0), App.Rotation(App.Vector(0, 0, 1), 45) ) doc.recompute()这里App.Rotation(轴向量, 角度)构造一个绕 Z 轴旋转 45 度的姿态。对应源码里src/Base/Placement类几何变换、坐标映射都从这里来。知道这个底你在 GUI 里用鼠标拖旋转时的数值变化本质就是这段 C 逻辑在响应用户输入。4.2 入口二最小改动——改一个命令的 ToolTip 后增量重编不改数学逻辑只改一段界面文案是最安全的源码初体验。先找一个命令的提示文案在哪rg -n ToolTip src/Mod/PartDesign/Gui | head -20ToolTip是命令注册时设置的悬停提示在 Gui 层。把命中的某个 cpp 文件里对应的英文提示字符串替换成你自己的中文文案保存后回到构建目录增量编译cmake --build build -j 8增量编译只重编受影响的源文件比全量快得多。改动属于 Gui 层时通常不需要重编 App 层几十秒到几分钟就能完成。再次启动build/bin/FreeCAD把鼠标悬停到对应命令上中文提示就出来了。这里有个容易忽略的要点直接往源码里写中文没问题但文件编码必须是 UTF-8并在源码文件开头确保源文件本身是 UTF-8 保存的。真正要进入官方发布流程时不应该硬改源码而是去改翻译文件自编译版本里直接改源码胜在零依赖、立刻生效。4.3 入口三“FreeCAD 没有螺旋”这类问题的源码级答案网上经常有人问“freecad没有螺旋”词条热度很高。先在源码里搜一遍rg -n -i helix src/Mod/Part src/Mod/PartDesign | head -30搜索结果显示螺旋在源码里是存在的而且有两处Part 工作台的基础螺旋线对象和 PartDesign 里的螺旋特征。大部分用户说“没有螺旋”不是因为功能缺失而是工具入口折叠在工作台的下拉菜单里界面上没有独立按钮。这是使用层的问题不改源码也能解决。但从源码角度能挖到更深的结构如果一个工具只有 App 侧实现、没有 Gui 侧命令类它就不会出现在工作台界面反过来搜索为空时先怀疑编译时模块没开再怀疑功能真的没有。任何工作台工具都由“对象类 命令类 界面入口”三段构成缺一段就表现为“源码里有但界面上看不到”。想给自定义工作台加一个螺旋按钮需要同时补 App 侧数据类和 Gui 侧命令类这是 FreeCAD 二次开发的完整最小单元。5. 编译与改源码避坑指南五条翻车记录5.1 改了源码重新编译运行后没有任何变化现象改了 ToolTip 或某个参数增量编译成功打开程序看到的还是旧样子。原因你启动的根本不是本次编译的产物。最常见的是 PATH 里先命中了/usr/bin/freecad或者双击了系统中的启动器图标。解决直接运行构建目录里的可执行文件不要走系统路径。which freecad build/bin/FreeCAD如果which显示的是系统路径说明你一直在跑旧程序。还有另一种情况CMake 没有检测到源码变化增量构建跳过了你的文件。这时检查文件的修改时间确认编辑的是源码目录里的文件而不是构建目录里的副本。实在不行就把 build 目录整个删掉重新配置这是最后的后悔药源码目录不受影响。5.2 系统 OCCT 版本太新配置或链接阶段报错现象CMake 配置时报Could NOT find OpenCASCADE或者编译到一半出现大量 OCCT undefined symbol。原因Ubuntu 最新软件源里的 libocct 版本比 FreeCAD 1.0 预期的高头文件接口变了链接时符号对不上。解决先看构建缓存里实际找到的 OCCT 路径grep -i occt build/CMakeCache.txt确认是系统版本问题后用 apt 安装软件源里的稳定版或手动编译一个较老版本的 OCCT并把它作为独立安装目录通过CMAKE_PREFIX_PATH传给 FreeCADcmake -B build \ -DCMAKE_PREFIX_PATH$HOME/occt-install \ -DCMAKE_BUILD_TYPERelease这里CMAKE_PREFIX_PATH告诉 CMake 去哪里找 OCCT多个路径用分号分隔。版本锁定要以 FreeCAD 源码里 README 的依赖表为准不要凭感觉追新。5.3 Python 版本过新导致绑定层编译失败现象编译src/App相关绑定代码时出现大段 Python C API 报错比如PyUnicode相关函数找不到。原因FreeCAD 的 PyCXX 绑定层更新跟不上 CPython 的版本节奏。Python 3.12 移除了一些旧 C API源码里还在用。解决不要跟系统默认可选包较劲安装指定版本的 Python 开发头文件再显式指定解释器sudo apt install python3.10-dev cmake -B build -DPYTHON_EXECUTABLE/usr/bin/python3.10PYTHON_EXECUTABLE必须指向带 dev 头的解释器否则后续 Python 模块编译依然会失败。这个坑很典型源码本身没问题是环境版本太新造成的兼容缺口。5.4 源码路径带中文或空格构建期文件找不到现象CMake 配置能过但编译时断言某些文件不存在或者生成文件被放到莫名其妙的位置。原因FreeCAD 的构建系统对路径转义处理不彻底路径里的空格和全角字符会打断 CMake 与编译器的路径拼接。解决把仓库放到/home/用户名/下的纯英文目录不要放桌面、不要放在带空格的盘符路径。这是玄学最少的一次排查先检查路径再检查源码。5.5 GUI 启动即崩溃报 “Cannot mix incompatible Qt library”现象自编译版本运行 FreeCAD 图形界面还没出窗口就崩溃终端输出 Qt 库不匹配。原因存在两套 Qt。系统安装包里自带 Qt第三方 Python 包也链接了自己的 Qt运行时LD_LIBRARY_PATH把它们混在一起。解决检查实际加载的动态库ldd build/bin/FreeCAD | grep -i qt看这些 Qt 库是否都指向同一个前缀。混了的话启动前固定环境变量export LD_LIBRARY_PATH$PWD/build/lib:$LD_LIBRARY_PATH核心原则是让自编译产物最优先被找到。排查动态库问题时ldd和grep配合使用几乎能定位所有这类加载冲突。6. 回归验证用 FreeCADCmd 跑自动化用例证明改动生效二次开发做到一半最容易出现的幻觉是“好像改对了”。真正靠谱的验证方式是写一段可重复执行的脚本用 FreeCADCmd 在命令行里跑通。下面是我常用的最小回归用例import FreeCAD as App doc App.newDocument(RegressionTest) box doc.addObject(Part::Box, Box) box.Length 10 box.Width 20 box.Height 30 doc.recompute() assert abs(box.Shape.Volume - 6000.0) 1e-6, box.Shape.Volume assert Part::Box in box.TypeId print(PASS: volume , box.Shape.Volume)脚本创建了一个长宽高为 10、20、30 的立方体体积应为 10×20×306000。断言用abs(...) 1e-6而不是直接等于是因为浮点数计算有误差这在几何内核里是常态。TypeId 的断言确保对象类型绑定正常。运行它build/bin/FreeCADCmd -c /path/to/regression_test.py-c参数接受脚本文件路径。进程退出码为 0 且输出PASS时说明你的自编译版本在这个功能上没有回退。如果你想验证的是界面文案改动可以换一种思路strings build/lib/libFreeCADGui.so | grep 你的中文提示strings提取二进制中的可读文本能确认改动确实进了产物而不是只存在源码里。这套验证习惯帮我解决过一个大问题有一回我改了 Placement 的旋转逻辑界面拖拽看上去正常但回归脚本跑出体积为负的异常情况。后来定位到是新代码破坏了坐标系转换方向。自那以后我坚持所有二次改动都配一个最小断言脚本不靠肉眼判断对错。这个习惯让我少走了很多弯路希望帮到你。本文还有配套的精品资源点击获取