FreeCAD二次开发:搭建开发环境与分支管理

本文详细记录在Windows下搭建FreeCAD二次开发环境及创建开发分支的完整流程。

1. 环境准备

组件 推荐版本/说明
操作系统 Windows 11
Visual Studio Visual Studio Community 2022
VS Code 1.92.1
Git 2.34.1
CMake 3.22.1
Python 3.11.0
GNU Bison win_flex_bison-2.5.25
7-Zip 官方下载

2. 编译安装依赖 LibPack

LibPack 是 FreeCAD 在 Windows 下的依赖集合包。除直接下载外,也可选择自行编译安装以获得更灵活的依赖管理。

2.1 获取 LibPack 源码

前往 FreeCAD/FreeCAD-LibPack 仓库,克隆源码:

bash 复制代码
git clone https://github.com/FreeCAD/FreeCAD-LibPack.git

2.2 配置与编译 LibPack

阅读仓库内的 README.md,根据说明准备好所需的编译工具(如 Visual Studio、CMake、Python、7-Zip 等)。

进入 LibPack 目录,运行构建脚本(如 build.batbuild.ps1,具体以仓库说明为准):

sh 复制代码
cd FreeCAD-LibPack
build.bat

注1 :自行编译 LibPack 过程较为复杂,可参考笔者博文Windows下编译FreeCAD 1.1 RC2
注2:笔者已将编译好的资料放到网盘,需要的朋友可联系笔者。

3. 下载 FreeCAD 源码

推荐使用 Git 克隆官方仓库:

sh 复制代码
git clone --recursive https://github.com/FreeCAD/FreeCAD.git

或使用 Gitee 镜像:

sh 复制代码
git clone --recursive https://gitee.com/freecad/FreeCAD.git

4. 创建开发分支与 worktree

基于 FreeCAD 进行二次开发,建议使用 Git worktree 管理多分支开发环境。

4.1 创建新分支并添加 worktree

sh 复制代码
git branch gdcad origin/releases/FreeCAD-1-1
git worktree add gdcad ../FreeCAD.worktrees/GDCAD gdcad

也可以使用下述命令,

sh 复制代码
git worktree add -b gdcad ../FreeCAD.worktrees/GDCAD origin/releases/FreeCAD-1-1

说明:

  • -b gdcad 创建并切换到新分支 gdcad
  • ../FreeCAD.worktrees/GDCAD 为新工作区目录
  • origin/releases/FreeCAD-1-1 为远程分支名

4.2 更新 worktree 中子模块

sh 复制代码
cd ../FreeCAD.worktrees/GDCAD
git submodule update --init --recursive

如需单独更新某些子模块:

sh 复制代码
git submodule update --init src/3rdParty/GSL/
git submodule update --init src/3rdParty/OndselSolver/
git submodule update --init src/Mod/AddonManager
git submodule update --init tests/lib

4.3 修改RelWithDbgInfo配置

编辑"cMake\FreeCadMacros.cmake",修改"SET_BIN_DIR",指定RelWithDbgInfo配置的输出,

bash 复制代码
# Macro to replace all the binary output locations.  Takes 2 optional parameters.
# ${ARGVN} is zero based so the 3rd element is ${ARGV2}.  When the 3rd element is missing,
# Runtime and Lib directories default to /bin and /lib.  When present, the 3rd element
# specifies both Runtime and Lib directories.  4th specifies linux install path.
MACRO(SET_BIN_DIR ProjectName OutputName)
    set_target_properties(${ProjectName} PROPERTIES OUTPUT_NAME ${OutputName})
    if(${ARGC} GREATER 2)
        # VS_IDE (and perhaps others) make Release and Debug subfolders.  This removes them.
        set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY         ${CMAKE_BINARY_DIR}${ARGV2})
        set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}${ARGV2})
        set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG   ${CMAKE_BINARY_DIR}${ARGV2})
        set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY         ${CMAKE_BINARY_DIR}${ARGV2})
        set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}${ARGV2})
        set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_DEBUG   ${CMAKE_BINARY_DIR}${ARGV2})
		
		set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO   ${CMAKE_BINARY_DIR}/lib)		
		set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO   ${CMAKE_BINARY_DIR}/lib)

    else(${ARGC} GREATER 2)
        set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY         ${CMAKE_BINARY_DIR}/bin)
        set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
        set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG   ${CMAKE_BINARY_DIR}/bin)
        set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY         ${CMAKE_BINARY_DIR}/lib)
        set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib)
        set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_DEBUG   ${CMAKE_BINARY_DIR}/lib)
		set_target_properties(${ProjectName} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY         ${CMAKE_BINARY_DIR}/lib)	
		
		set_target_properties(${ProjectName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO   ${CMAKE_BINARY_DIR}/bin)
		set_target_properties(${ProjectName} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO   ${CMAKE_BINARY_DIR}/lib)		
    endif(${ARGC} GREATER 2)

    if(WIN32)
        set_target_properties(${ProjectName} PROPERTIES DEBUG_OUTPUT_NAME ${OutputName}_d)
    else(WIN32)
        # FreeCADBase, SMDS, Driver and MEFISTO2 libs don't depend on parts from CMAKE_INSTALL_LIBDIR
        if(NOT ${ProjectName} MATCHES "^(FreeCADBase|SMDS|Driver|MEFISTO2)$")
            if(${ARGC} STREQUAL 4)
                set_property(TARGET ${ProjectName} APPEND PROPERTY INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${ARGV3})
            elseif(NOT IS_ABSOLUTE ${CMAKE_INSTALL_LIBDIR})
                set_property(TARGET ${ProjectName} APPEND PROPERTY INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
            else()
                set_property(TARGET ${ProjectName} APPEND PROPERTY INSTALL_RPATH ${CMAKE_INSTALL_LIBDIR})
            endif()
        endif()
    endif(WIN32)
ENDMACRO(SET_BIN_DIR)

编辑"src\Main\CMakeLists.txt",修改FreeCADGuiPy项目输出名字,防止与FreeCADGui项目冲突,

bash 复制代码
# SPDX-License-Identifier: LGPL-2.1-or-later

configure_file(freecad.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/freecad.rc)
configure_file(freecadCmd.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/freecadCmd.rc)
file(COPY icon.ico DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

######################## FreeCADMain ########################
if(BUILD_GUI)

    SET(FreeCAD_SRCS
        ${CMAKE_CURRENT_BINARY_DIR}/freecad.rc
        icon.ico
        MainGui.cpp
    )

    SET(FreeCAD_LIBS
        FreeCADGui
    )

    if(NOT BUILD_DYNAMIC_LINK_PYTHON)
        # executables have to be linked against python libraries,
        # because extension modules are not.
        list(APPEND FreeCAD_LIBS
            ${Python3_LIBRARIES}
        )
    endif(NOT BUILD_DYNAMIC_LINK_PYTHON)

    add_executable(FreeCADMain WIN32 ${FreeCAD_SRCS})
    target_link_libraries(FreeCADMain ${FreeCAD_LIBS})
    if (FREECAD_WARN_ERROR)
        target_compile_warn_error(FreeCADMain)
    endif()

    SET_BIN_DIR(FreeCADMain FreeCAD)

    if(WIN32)
        INSTALL(TARGETS FreeCADMain
            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        )
    elseif(APPLE AND NOT BUILD_WITH_CONDA)
        INSTALL(TARGETS FreeCADMain
        RUNTIME DESTINATION MacOS
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        )
    else()
        INSTALL(TARGETS FreeCADMain
            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        )
    endif()
endif(BUILD_GUI)
######################## FreeCADMainCmd ########################

SET(FreeCADMainCmd_SRCS
    ${CMAKE_CURRENT_BINARY_DIR}/freecadCmd.rc
    icon.ico
    MainCmd.cpp
)

add_executable(FreeCADMainCmd ${FreeCADMainCmd_SRCS})

SET(FreeCADMainCmd_LIBS
    FreeCADApp
    ${QtCore_LIBRARIES}
    ${QtXml_LIBRARIES}
)

if(NOT BUILD_DYNAMIC_LINK_PYTHON)
    # executables have to be linked against python libraries,
    # because extension modules are not.
    list(APPEND FreeCADMainCmd_LIBS
        ${Python3_LIBRARIES}
    )
endif(NOT BUILD_DYNAMIC_LINK_PYTHON)

target_link_libraries(FreeCADMainCmd
    ${FreeCADMainCmd_LIBS}
)
if (FREECAD_WARN_ERROR)
    target_compile_warn_error(FreeCADMainCmd)
endif()

SET_BIN_DIR(FreeCADMainCmd FreeCADCmd)

if(WIN32)
    INSTALL(TARGETS FreeCADMainCmd
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    )
elseif(APPLE AND NOT BUILD_WITH_CONDA)
    INSTALL(TARGETS FreeCADMainCmd
        RUNTIME DESTINATION MacOS
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    )
else()
    INSTALL(TARGETS FreeCADMainCmd
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    )
endif()

######################## FreeCADMainPy ########################

SET(FreeCADMainPy_SRCS
    MainPy.cpp
)

add_library(FreeCADMainPy SHARED ${FreeCADMainPy_SRCS})

target_link_libraries(FreeCADMainPy FreeCADApp)
if (FREECAD_WARN_ERROR)
    target_compile_warn_error(FreeCADMainPy)
endif()

SET_BIN_DIR(FreeCADMainPy FreeCAD)
SET_PYTHON_PREFIX_SUFFIX(FreeCADMainPy)

if(WIN32)
    INSTALL(TARGETS FreeCADMainPy
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    )
else(WIN32)
    INSTALL(TARGETS FreeCADMainPy
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    )
endif(WIN32)

######################## FreeCADGuiPy ########################
if(BUILD_GUI)

    SET(FreeCADGuiPy_SRCS
        FreeCADGuiPy.cpp
    )

    add_library(FreeCADGuiPy SHARED ${FreeCADGuiPy_SRCS})

    target_link_libraries(FreeCADGuiPy FreeCADGui)
    if (FREECAD_WARN_ERROR)
        target_compile_warn_error(FreeCADGuiPy)
    endif()

    SET_BIN_DIR(FreeCADGuiPy FreeCADGuiPy)
    SET_PYTHON_PREFIX_SUFFIX(FreeCADGuiPy)
    if(WIN32)
        # Name clash with target "FreeCADGui"
        # Must be called "FreeCADGuiPy_d" and "FreeCADGuiPy" to work so override default
        set_target_properties(FreeCADGuiPy PROPERTIES PDB_NAME_DEBUG "FreeCADGuiPy_d")
        set_target_properties(FreeCADGuiPy PROPERTIES PDB_NAME_RELEASE "FreeCADGuiPy")
        set_target_properties(FreeCADGuiPy PROPERTIES PDB_NAME_RELWITHDEBINFO "FreeCADGuiPy")        
    endif(WIN32)

    if(WIN32)
        INSTALL(TARGETS FreeCADGuiPy
            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        )
    else(WIN32)
        INSTALL(TARGETS FreeCADGuiPy
            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        )
    endif(WIN32)
endif(BUILD_GUI)

5. 配置与编译

5.1 配置相关环境命令

新建".../FreeCAD.worktrees/GDCAD/gdcad-dev.bat",添加以下内容

bat 复制代码
@ECHO off
@SET Current_DIR=%~dp0
@SET Parent_DIR=%Current_DIR%\..\
 
:: GDCAD Build
@SET GDCAD_BUILD=%Parent_DIR%BUILD\GDCAD
@SET GDCAD_BUILD_BIN=%GDCAD_BUILD%\bin
@SET GDCAD_BUILD_LIB=%GDCAD_BUILD%\lib
 
:: LibPack
@SET LIBPACK=%Parent_DIR%\YQ_LibPack-1.1.0-v3.1.1.3-Release
@SET LIBPACK_BIN=%LIBPACK%\bin
@SET LIBPACK_LIB=%LIBPACK%\lib
 
:: ==============================================================
:: Environment variables for Python
:: the location of the standard Python libraries.
@SET PYTHONHOME=%LIBPACK_BIN%
:: the default search path for module files.
@SET PYTHONPATH=%PYTHONHOME%;%PYTHONHOME%\Scripts;%PYTHONHOME%\Lib;%PYTHONHOME%\Lib\site-packages\shiboken6;%PYTHONHOME%\Lib\site-packages\PySide6
@SET FC_PYTHONHOME=%LIBPACK_BIN%
 
:: ==============================================================
:: System Enviroment variables
@PATH %GDCAD_BUILD_BIN%;%GDCAD_BUILD_LIB%;%LIBPACK_BIN%;%LIBPACK_LIB%;%LIBPACK%\win64\vc14\bin;%PYTHONPATH%;%PATH%
 
@CMD

5.2 CMake 配置工程

双击打开".../FreeCAD.worktrees/GDCAD/gdcad-dev.bat",运行

bash 复制代码
cmake-gui

按下表完成 CMake 配置,

配置项 示例值/说明
CMAKE_INSTALL_PREFIX D:/YouQuan/CaeFrameworks/FreeCAD/INSTALL/GDCAD
FREECAD_LIBPACK_DIR D:/YouQuan/CaeFrameworks/FreeCAD/FreeCAD-LibPack/working/LibPack-1.1.0-v3.1.1.3-Release
BUILD_DYNAMIC_LINK_PYTHON OFF
BUILD_TEST OFF
ENABLE_DEVELOPER_TESTS OFF

5.3 编译

在CMake中点击'Open Project',切换到'RelWithDbgInfo',进行编译。

6. 调试

新建"D:\YouQuan\CaeFrameworks\FreeCAD\BUILD\GDCAD\bin\qt.conf",添加以下内容,

bash 复制代码
[Paths]
Prefix=D:/YouQuan/CaeFrameworks/FreeCAD/FreeCAD-LibPack/working/LibPack-1.1.0-v3.1.1.3-Release
Documentation=doc
Headers=include
Libraries=lib
Binaries=bin
Plugins=plugins
QmlImports=qml
ArchData=.
Data=.
Translations=translations
Examples=examples
Tests=tests
Settings=.

将"D:\YouQuan\CaeFrameworks\FreeCAD\FreeCAD-LibPack\working\LibPack-1.1.0-v3.1.1.3-Release\win64\vc14\bin"拷贝到"D:\YouQuan\CaeFrameworks\FreeCAD\BUILD\GDCAD\bin"。

7. FAQs

Q: VS 2022 RelWithDbg调试,断点不生效,显示"The breakpoint will not currently be hit",

A: 编辑项目属性,在[C/C++]/[Optimization]中,将"Optimization"属性设为"Disabled(/Od)",重新编译即可。

8. 参考资料

相关推荐
老陈头聊SEO12 小时前
从零开始学习SEO,实现网站流量的突破与增长
其他·搜索引擎·seo优化
独孤九剑打醒他1 天前
【硬核计算】只靠阳光和水,一辆氢能车到底能不能日常代步?——光伏制氢 + 纯氢内燃机短途闭环的能量账与技术剖析
其他·制造
__Vincent_3 天前
科技史上的今天:5月3日-芯路历程 日新不息
其他
jiushiapwojdap3 天前
LU分解法求解线性方程组Matlab实现
数据结构·其他·算法·matlab
alphageek83 天前
Matlab linspace函数完全指南:从基础用法到进阶技巧
开发语言·其他·matlab
matlab_xiaowang4 天前
Redux 入门:JavaScript 可预测状态管理库
开发语言·javascript·其他·ecmascript
JiNan.YouQuan.Soft4 天前
FreeCAD源码分析:微内核架构
其他
老陈头聊SEO4 天前
生成引擎优化(GEO)在提升用户体验与内容创作效率中的创新应用
其他·搜索引擎·seo优化
老吴的商业笔记4 天前
2026年前瞻:杭州GEO优化源头服务商怎么选?深度解析AI搜索优化源头服务商避坑攻略
其他