我有一个由任务组成的项目。每个任务都有三个子目录:输入、代码和输出。代码目录中有一个 Makefile,其中包含从代码和输入生成输出所需的配方。每个 Makefile 都使用 Unix 命令。
许多任务都是相互关联的:一个任务的输出是另一个任务的输入。这些连接是通过 Unix 风格的符号链接(Makefile 中的 ln -s)完成的。
我希望能够将这个项目发布到任何操作系统(Windows、Mac、Linux)并运行它。符号链接在 Mac 和 Linux 上运行良好,但在 Windows 上不行。我知道 Windows 10 有自己的符号链接语法(mklink)。
我能想到一些潜在的解决方案,但我不确定它们是否可行,更不用说如何实施它们了。一种方法是让 Makefile 检测操作系统并相应地构建符号链接。另一种方法是让 Windows 用户将项目(例如 git clone)复制到类 Unix 文件系统(理想情况下是 WSL2,或 VM)中并在那里运行 Makefile。根据我的经验,第二种方法比第一种更糟糕,因为与使用本机文件系统相比,编辑文件会变得很麻烦。我在笔记本电脑上运行 Windows,因此编辑的简易性在我的列表中名列前茅。
总而言之,我认为这里有三个有序的问题:
- makefile 是否可以检测操作系统并创建正确的符号链接/是否可以创建与操作系统无关的符号链接?
- 如果没有,有没有办法在 WSL2 的 Linux 文件系统中完成所有这些操作?人们需要能够使用 Emacs 或 Atom 编辑文件并运行 Windows 可执行文件(否则我必须将 Stata、R、Matlab 和其他任何东西放入我的 WSL2 Ubuntu 发行版中)。我不是 VSCode 的忠实粉丝,所以我宁愿远离它,但我知道 Windows 在将其与 WSL2 集成方面取得了长足进步。
- 如果这些都不起作用,那么像 CMake 这样的工具是否有帮助,或者我应该切换到 Linux 并让 Windows 用户自生自灭?
答案1
有一种使用 makefile 检测操作系统的简单方法。以下是两个项目设置的示例。
首先,如果项目针对不同的操作系统有不同的目录,并且每个文件夹包含自己的 makefile,文件夹结构类似于以下内容:
/src
|
+-- folder_win
| |
| +-- makefile_win
|
+-- folder_linux
| |
| +-- makefile_linux
|
+-- folder_mac
| |
| +-- makefile_mac
|
+-- MAKEFILE
然后根 makefile(这里是 MAKEFILE)可以写成如下形式:
ifeq ($(OS), Windows_NT)
cd folder_win; $(MAKE) -f makefile_win
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S), Linux
cd folder_linux; $(MAKE) -f makefile_linux
endif
ifeq ($(UNAME_S), Darwin)
cd folder_mac; $(MAKE) -f makefile_mac
endif
endif
其次,如果有一个 makefile 并且相同的源代码依赖于操作系统,则按如下方式修改代码(使用 C/C++)并对其他代码重复这些操作:
#ifdef WIN_OS
// Do Windows things
#endif
makefile 将与以前一样,但略有变化:
ifeq ($(OS), Windows_NT)
CCOPT := -DWIN_OS
endif
$(CC) $(CCOPT) $(CFLAGS) file.c
然后添加其他操作系统选项,条件与之前相同。
来源: 操作系统检测 makefile