我目前正在尝试为Project-Euler
设计一个可靠的文件夹结构。
我目前的想法是这种结构:
.
└── project-euler/
├── resources
│ ├── primes.h
│ ├── primes.c
│ ├── factors.h
│ ├── factors.c
│ └── ...
├── 001_name_of_procect_one.c
├── 001_name_of_project_one.o
├── 002_name_of_project_two.c
├── 002_name_of_project_two.o
└── ...
这种结构的问题是我将所有项目都放在一个文件夹中,但我不知道如何为这种结构编写Makefiles
。
我可以为每个项目创建一个单独的目录,但是随后我将不得不编写类似#include "../resources/primes.h"
的内容,而我却不喜欢这种方法。
在这种情况下使用的典型项目结构是什么?我如何能够为所有小型项目编写Makefile
,同时又将它们保留在同一目录中?
编辑:我使用clang
。
如果将实用程序文件保存在resources
子目录中,则可以在主目录中创建单个解决方案文件,这些文件的顶部包括必要的头文件,例如:
#include "resources/primes.h"
并在底部加上实际的代码
#include "resources/primes.c"
这样,您甚至不需要Makefile
,因为默认规则将使您可以直接从相应的源文件中建立每个目标:
make 002_name_of_project_two
make甚至不会生成目标文件,而只是可执行文件。
我个人命名更喜欢项目文件的简称,例如p42.c
Makefile
仍然对仅按make
或IDE的生成按钮很有用。一个衬板就足够了:
all: p42
但是您可能希望添加一些依赖项,以便仅更改实用程序源时目标可以重新编译。添加以下行:(在第二行的开头带有TAB)
%: %.c $(wildcard resources/*)
clang $(CFLAGS) $(LFLAGS) -o $@ $<
您仍然应该在CFLAGS
环境变量中添加适当的选项,以利用编译器捕获愚蠢错误的能力:-Wall -Wextra -Werror
为gcc
,-Weverything
为clang
。
如果使用g++
,则声明包含以下内容的目录:
g++ -I../resources #rest of command line
关于图书馆的扩展评论将是非利士人的答案,与通常的想法相反。早些年,我花了无数小时来维护我的可爱的库,但是这个好主意涉及一些问题。这样的库始终是一个进行中的工作,但是在项目签收并交付后,您不必更改库就可以避免破坏先前的项目,因此必须将其冻结。然后,您将拥有多个版本的库。现在,假设一个旧项目需要mods,这需要更改库函数吗?您仍然不能使用当前版本,因为您将不得不重新进行以前的产品测试和保证。另一个反对意见是,我本来应该很好的某些库函数从来都不是我在下一个项目中想要的。整个事情变成了维护的噩梦,我放弃了。我现在发现的是,在欧拉计划问题中,我可能需要阶乘函数。在一种情况下,简单的unsigned
功能会很好。在另一种情况下,我需要uint64_t
处于范围内。在另一种情况下,将是unsigned
或uint64_t
以某个常数取模。变化是无止境的,并且当函数可能需要调用数百万次时,通用的“一刀切”的方法是不合适的。因此,我只是使用复制/粘贴解决方案来选择其他问题所需的位。