{"author":{"address":"0x2b624faC1616D08684Cf1d21793c2f39CC1895a0","user":"https://learnblockchain.cn/people/2540"},"content":{"body":"当你第一次看到`anchor init`初始化的项目里有那么多文件夹和文件，你什么感觉？\r\n\r\n我特别想重命名一些文件，想删除一些文件，但是做不到啊……因为编译会报错！我心一横，干脆把每个目录都搞清楚，当足够了解就可以自如的控制它们的去留……呵呵。\r\n\r\n接下来，我们拆解所有目录和文件，把初学者不必关心的全部清理掉，专注于学习智能合约的开发。\r\n\r\n\u003e 在solana中，`智能合约`称为`程序`，这和evm中编写的solidity智能合约叫法不同。因此，在你阅读本系列文章的时候，无论见到`solana智能合约`还是`solana程序`，它们都是指的同一个东西。\r\n\r\n## 目录结构\r\n\r\n下面是我们初始化生成的目录结构：\r\n\r\n![初始化目录](https://img.learnblockchain.cn/attachments/2024/12/5Qc54pIV6756c11f3bf5a.png)\r\n\r\n我先按顺序给出一个简单解释：\r\n\r\n|目录或文件|简要说明|\r\n--|--\r\n|app|存放前端项目，html、css、js等  |\r\n|migrations|存放部署脚本|\r\n|node_modules|yarn命令自动生成的js依赖库|\r\n|programs|solana主程序目录，写合约的地方|\r\n|target|anchor命令自动生成的目标文件|\r\n|tests|写合约测试代码的地方|\r\n|.gitignore|git仓库忽略文件|\r\n|.prettierignore|prettier忽略文件|\r\n|Anchor.toml|anchor项目的主配置文件|\r\n|Cargo.toml|rust项目的主配置文件|\r\n|package.json|nodejs依赖包管理|\r\n|tsconfig.json|typescript配置|\r\n|yarn.lock|yarn命令自动生成|\r\n\r\n对于一个刚开始学习solana开发的人员，以上哪些文件和目录不是必须的？如果要删除一些目录和文件，减少初学者不必要的注意力，该删除哪些？\r\n\r\n`app`目录是前端代码的存放位置，初学者可以直接删除。\r\n\r\n`node_modules`, `target`, `yarn.lock` 都是由相应工具管理并自动生成的，忽略即可。\r\n\r\n`.gitignore`, `.prettierignore` 已经在初始化项目的时候自动写好了忽略文件和目录，提交Git仓库必须要的文件。\r\n\r\n`package.json`, `tsconfig.json` 这是nodejs依赖管理，和typescript配置，必须保留，因为要测试solana程序，需要编写ts脚本。\r\n\r\n以上都比较简单，了解一下即可，接下来我们就要详细说说剩余的目录了。\r\n\r\n### migrations\r\n\r\n先给出结论：**migrations这个文件夹可以放心地删除**，下面我们说说原因。\r\n\r\n`migrations/deploy.ts` 的作用是**允许用户自定义部署逻辑**。例如：\r\n\r\n\u003e 1.配置更复杂的部署流程（如多程序依赖）。  \r\n\u003e \r\n\u003e 2.执行额外的操作（如为程序分配初始账户、设置状态等）。  \r\n\u003e \r\n\u003e 3.自定义部署顺序（例如多个程序需要按顺序部署）。  \r\n\r\n然而对于初学者，我们暂时不需要那么复杂的部署流程，等到我们学到一定程度，**需要的时候再增加这个目录**即可。\r\n\r\n也许你会有疑问：删除之后，会影响到`anchor deploy` 和 `anchor test`命令的执行吗？\r\n\r\n答案是：**不会**！我们分别看一下它们的执行原理：\r\n\r\n对于`anchor deploy`，它的行为主要有三步：\r\n\r\n\u003e 1.读取 Anchor.toml 中定义的程序路径。  \r\n\u003e \r\n\u003e 2.自动编译 programs/ 下的所有程序。  \r\n\u003e \r\n\u003e 3.将程序部署到配置的 Solana 网络（如 localnet 或 devnet）。  \r\n\r\n对于`anchor test`，它的行为主要有两步：\r\n\r\n\u003e 1.编译和部署 programs/ 下的程序。  \r\n\u003e \r\n\u003e 2.在 tests/ 目录中查找测试脚本（例如 solana-guide.ts），并运行其中的测试。  \r\n\r\n以上两个过程都与 migrations/deploy.ts 完全无关，tests/ 和 migrations/ 也是独立的，因此，删除migrations文件夹不会影响正常的部署和测试。\r\n\r\n### Anchor.toml\r\n\r\n上面提到了 Anchor.toml，所以我们先来说这个文件。从前面的叙述可以看到，它们都是依赖根目录下的 Anchor.toml 定义的程序路径，直接读取并自动编译 programs/ 下的所有程序，这是项目的**核心配置文件**。\r\n\r\n至于里面的配置信息，我们这一讲先不关心，你只记住它必须保留即可。\r\n\r\n### programs\r\n\r\n`programs`是主程序目录，是编写solana智能合约的地方。下面是它的目录结构：\r\n\r\n\r\n![programs目录](https://img.learnblockchain.cn/attachments/2024/12/1Yli4K0Y6756c1aea0f51.png)\r\n\r\n**敲黑板**！重点来了，我们需要修改的东西主要都在这个目录下，接下来就要详细讲讲这里面的知识。\r\n\r\n**1.这些文件夹名称能修改吗？**\r\n\r\n`programs`不能修改，这是anchor框架预定义好的，每次编译都会自动找这个目录，它下面的每一个子目录都代表一个solana程序（智能合约）。子目录`solana-guide`可以修改，本文末尾会给出修改的流程，将目录改为`guide_1`方便按学习顺序扩展多个程序。\r\n\r\n**2.如何界定哪些代码属于同一个智能合约？**\r\n\r\n在solidity中，智能合约是用关键字`contract`界定边界，每个 contract 是一个独立的逻辑单元，部署为单独的合约地址。然而，在solana中没有 contract 这一概念，`按照anchor框架的标准，programs下面的每一个子目录都会编译为一个二进制文件，即一个智能合约`。\r\n\r\n**3.删除src目录可以吗？rust代码都必须放在src目录下吗？**\r\n\r\n不是必须，但最好这样。src目录存放源文件，删除src目录后，将`.rs文件`和`.toml文件`放在同级目录并不是一个好主意。虽然你可以这么做，但这只适用于简单代码，一旦需要模块化，有多个.rs文件，就不好管理了，也无法和标准的项目兼容。\r\n\r\n**4.这个目录下的 Cargo.toml 和 根目录下的Cargo.toml有什么区别？**\r\n\r\n当前目录下的`Cargo.toml`是这个`Solana程序`的专用配置文件，不会影响到其他的子程序。根目录下的`Cargo.toml`管理整个项目的依赖，工作区配置，跨所有程序的依赖。\r\n\r\n**5.Xargo.toml是什么？**\r\n\r\n这是针对solana的交叉编译配置文件，当你需要把程序嵌入到设备或其他情况下才有用，一般不需要修改，可以删除。\r\n\r\n### tests\r\n\r\n这个目录存放测试代码，用typescript编写，我们需要学习测试solana程序，需要保留。\r\n\r\n\r\n## 自定义目录结构\r\n\r\n我们在学习的过程中，要开发多个程序，总不能每次都执行`anchor init {项目名}`来生成新的目录，所以在这里修改子程序目录命名，以适合多程序开发。\r\n\r\n\u003e `anchor init` 生成的目录布局是**推荐的标准布局**。如果要自定义目录布局，需要遵守anchor的规则：\r\n\u003e   \r\n\u003e 1.Anchor.toml必须位于项目根目录，这是 Anchor 的核心配置文件，用于定义项目名称、程序路径、部署地址等。  \r\n\u003e \r\n\u003e 2.每个 Solana 程序必须放在 programs/ 子目录中。  \r\n\u003e \r\n\u003e 3.tests/ 目录存放测试代码，不要修改。  \r\n\r\n接下来，我们将`programs/solana-guide`改为`programs/guide_1`，我们按照 guide_{1...}这样的子程序目录来讲解每一部分的内容。\r\n\r\n**修改目录名之后，需要把程序的入口函数名也同步修改，保持一致**。打开`src/lib.rs`修改如下：\r\n\r\n```rust\r\n#[program]  \r\npub mod guide_1 {  \r\n    // ...  \r\n}  \r\n```\r\n\r\n\u003e 如果`目录名`和`程序入口函数名称`不一致，虽然可以正常编译、正常测试程序，但是会有一些莫名奇妙的错误信息打印，如：Error: No such file or directory (os error 2)...  \r\n\u003e \r\n\u003e 保持目录名和程序入口函数名称一致是一个好习惯。  \r\n\r\n改完名称后，我们还需要做一些配置的修改：\r\n\r\n**1.根目录 Cargo.toml 中的 members 配置**\r\n\r\n```\r\nmembers = [  \r\n    # 因为是通配符，所以不用修改。如果你的配置是具体的子程序目录名，请修改。  \r\n    \"programs/*\"   \r\n]  \r\n```\r\n\r\n**2.programs/guide_1/Cargo.toml中的name字段（有两处）**\r\n\r\n```\r\n[package]  \r\nname = \"guide_1\"  \r\n\r\n[lib]  \r\nname = \"guide_1\"  \r\n```\r\n\r\n**3.Anchor.toml中的程序名称配置**\r\n\r\n```\r\n[programs.localnet]  \r\n# 修改前  \r\nsolana_guide = \"6n9iWA5k17ajMtWk3U6jsHcBaH4Wrh1gUXurtVq1GPGs\"  \r\n\r\n# 修改后（将solana_guide改为guide_1）  \r\nguide_1 = \"6n9iWA5k17ajMtWk3U6jsHcBaH4Wrh1gUXurtVq1GPGs\"  \r\n```\r\n\r\n**4.测试文件中的程序名称**\r\n\r\n将文件名`tests/solana_guide.ts`改为`tests/guide_1.ts`，这是非必须的，推荐修改保持一致。\r\n\r\n打开`tests/guide_1.ts`修改下面的内容：\r\n\r\n```javascript\r\n// ...  \r\nimport { Guide1 } from \"../target/types/guide_1\";  \r\n\r\ndescribe(\"guide_1\", () =\u003e {  \r\n    // ...   \r\n}  \r\n```\r\n\r\n**5.清理并重新构建**\r\n\r\n```shell\r\nanchor clean   # 清理项目  \r\nanchor build   # 重新构建  \r\nanchor test --skip-local-validator # 测试\r\n```\r\n\r\n\u003e 如果你遇到了错误：  \r\n\u003e \r\n\u003e Error Number: 4100. Error Message: The declared program id does not match the actual program id.  \r\n\u003e \r\n\u003e 请在项目根目录下执行`anchor keys sync`同步程序ID就好了。  \r\n\r\n\r\n## 总结\r\n\r\n最后，对本文的内容做一个总结：\r\n\r\n**1.必须保留的目录和文件（Anchor和solana开发的核心）** \r\n\r\n\u003e 1.Anchor.toml 项目配置文件，定义了程序路径、Program ID、网络配置等。  \r\n\u003e \r\n\u003e 2.programs/\u003cprogram_name\u003e/ 主程序代码目录，必须保留，包括（src/lib.rs：程序的主要逻辑入口； Cargo.toml：Rust 程序的配置文件。）  \r\n\u003e \r\n\u003e 3.tests/ 保留至少一个文件以便学习如何测试 Solana 程序。  \r\n\u003e \r\n\u003e 4.package.json 保留node环境，以便于运行测试脚本。  \r\n\r\n**2.可以删除的目录和文件（随着学习的深入，可以进一步添加）**\r\n\r\n\u003e 1.app 当需要前端页面交互时，增加这个目录即可。  \r\n\u003e\r\n\u003e 2.migrations/ 默认生成的 migrations/deploy.ts 是一个模板，这里用于自定义部署流程的脚本，但对初学者来说非必需。  \r\n\u003e \r\n\u003e 3.programs/\u003cprogram_name\u003e/Xargo.toml 暂时不需要了解Xargo，直接删除。  \r\n\r\n**3.我们也修改了子程序目录为`guide_1`**\r\n\r\n现在你的目录结构看起来应该是这样（除去隐藏和忽略的目录）：\r\n\r\n\r\n![精简后的目录](https://img.learnblockchain.cn/attachments/2024/12/xyWKqRcp6756c1ffd5343.png)\r\n\r\n到这里，本文就讲完了。如果你想提前看到我的更新，可以关注我的公众号：`认知那些事`。","title":"Solana笔记 02.认识目录结构"},"history":null,"timestamp":1733739153,"version":1}