用【Makefile】或【Cmake】编译【C/Fortran】程序文件
一、vimrc文件设置
set tabstop=4 "tab空格4
set expandtab "将tab扩展成空格
set softtabstop=4 "表示在编辑模式下按退格键时候退回缩进的长度
set shiftwidth=4 "每一级缩进是4个空格
set number "显示行号
filetype plugin on "Makefile空格 set fileencodings=utf-8,ucs-bom,gbk,cp936,gb2312,gb18030 "文件编码
"将.cuf文件用fortran的语法高亮配置进行高亮显示
au BufRead,BufNewFile *.cuf set filetype=fortran if has("persistent_undo")
let target_path = expand('~/.vim/undodir') if !isdirectory(target_path) "如果位置不存在,则创建目录
call mkdir(target_path, "p", 0700)
endif let &undodir=target_path "变量赋值
set undofile "开启撤销永久化
endif
二、用Makefile编译文件
1.1 C语言程序
创建Makefile文件(vim Makefile)
CC = sw9gcc
FC = sw9gfortran
MPI_C = /usr/sw/mpi/mpi_20210219_SEA/bin/mpicc
EXE = main_dnn
LIB = ./utils/libs/libswdnn_xu.a
OBJDIR = ./obj CFLAGS = -msimd -I./utils/include/ -mieee -g -O3 -funroll-nest-loops -mfma -fipa-type-escape -fipa-struct-peeling -fprefetch-loop-arrays
#CFLAGS += -DDEBUG
LIBFLAGS = -fcache-hint -mhybrid slavesrc = $(wildcard ./utils/slave/*.c)
mastersrc = $(wildcard ./utils/master/*.c)
utilsrc = $(wildcard ./utils/src/*.c)
LIBOBJ1 += $(patsubst %.c, %.o, $(slavesrc) $(mastersrc) $(utilsrc))
LIBOBJ2 = $(notdir $(LIBOBJ1))
OBJ += $(patsubst %.o, $(OBJDIR)/%.o, $(LIBOBJ2)) all: $(EXE)
ar: $(LIB)
$(EXE): $(OBJDIR)/main_dnn.o $(LIB)
$(CC) $(LIBFLAGS) -o $@ $^ -lm -lm_slave -L/usr/sw/yyzlib/xMath-SACA -lswblas
$(LIB): $(OBJ)
sw9ar rcs $@ $^
$(OBJDIR)/main_dnn.o: main_dnn.c
$(CC) -Dcheck_res $(CFLAGS) -mhost -c $^ -o $@
$(OBJDIR)/%.o: ./utils/master/%.c
$(CC) $(CFLAGS) -mhost -c $^ -o $@
$(OBJDIR)/%.o: ./utils/src/%.c
$(CC) $(CFLAGS) -mhost -c $^ -o $@
$(OBJDIR)/%.o: ./utils/slave/%.c
$(CC) $(CFLAGS) -mpws -mslave -Dperf -c $^ -o $@ .PHONY: clean
clean:
rm -f ${LIB} $(EXE) $(OBJDIR)/*.o
~
1.2 Fortran语言程序
创建Makefile文件(vim Makefile)
# 获取文件夹中所有.f90文件列表 notdir把展开的文件去除掉路径信息
SRCS_F90 = $(wildcard *.f90)
SRCS_F = $(wildcard ./*.f)
SRCS_DIR = $(notdir $(SRCS_F))
# 替换.f90后缀为.o后缀 得到.o文件列表 notdir用于去掉文件的绝对路径,只保留文件名
OBJS_F90 = $(patsubst %.f90, %.o, $(SRCS_F90))
OBJS_F = $(patsubst %.f, %.o, $(SRCS_DIR)) # module依赖文件
MOD_OBJS = variable.o mpi_variable.o mod_split_funs.o
MOD_SRCS = variable.f90 mpi_variable.f90 mod_split_funs.f90 # 定义编译器变量
F90= mpif90
FC = mpif90 FFLAGS = -O2 # 定义目标变量
EXE = main all:$(EXE)
# @echo $(SRCS_F)
# @echo $(SRCS_DIR)
# @echo $(OBJS_F) # $^表示所有依赖文件 $@--目标文件,$<第一个依赖文件
$(EXE): $(OBJS_F90) $(OBJS_F)
$(F90) -o $@ $^
# $(FC) -o $(EXE) $(OBJS) # %.o %.f90 %.mod 表示任意文件
%.o: %.f
$(FC) -c $< -o $@
%.o: %.f90 $(MOD_OBJS)
$(F90) $(CFLAGS) -c $< -o $@
$(MOD_OBJS): $(MOD_SRCS)
$(F90) -c $^ # *.o 表示所有.o文件
.PHONY: clean
clean:
rm -f *.o *.mod
~
三、用Cmake编译文件
2.1 C语言程序
1、创建CMakeLists.txt文件(vim CMakeLists.txt)
cmake_minimum_required(VERSION 3.16.2) # 声明使用CMAKE的最低版本要求
project(main_blas LANGUAGES C) # 定义项目的名字 #find_package(MPI REQUIRED) # 寻找 MPI
#include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/include) # 引入头文件目录
# 打印信息
message(WARNING "This application cannot compile without MPI end end ") # 设置编译目标类型是Debug、Release版还是RelWithDebInfo版本
#set(DEFAULT_BUILD_TYPE "RelWithDebInfo")
set(CMAKE_BUILD_TYPE Release) # 设置编译器选项
set(CMAKE_C_FLAGS "-msimd -mieee")
set(CMAKE_C_FLAGS_RELEASE "-O3 ") # Release版编译器选项
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O3")
# 静态库的输出目录
#set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/utils/libs) # 添加工作目录下子目录src中的源文件到SRC变量
file(GLOB SRC ${PROJECT_SOURCE_DIR}/utils/src/*.c)
file(GLOB MASTER_SRC ${PROJECT_SOURCE_DIR}/utils/master/*.c)
file(GLOB SLAVE_SRC ${PROJECT_SOURCE_DIR}/utils/slave/*.c) # 传递编译器选项
set_source_files_properties(${SRC} PROPERTIES COMPILE_FLAGS "-mhost")
set_source_files_properties(${MASTER_SRC} PROPERTIES COMPILE_FLAGS "-mhost")
set_source_files_properties(${SLAVE_SRC} PROPERTIES COMPILE_FLAGS "-mslave -mfma -mpws -Dperf") # 将SRCS编译为swdnn_xu这个静态链接库
add_library(swdnn_xu STATIC ${SRC} ${MASTER_SRC} ${SLAVE_SRC})
target_include_directories(swdnn_xu PRIVATE ${PROJECT_SOURCE_DIR}/utils/include)
set_target_properties(swdnn_xu PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/utils/libs) # 静态库的输出目录 link_directories("${PROJECT_SOURCE_DIR}/utils/libs" "/usr/sw/yyzlib/xMath-SACA/") # 指定静态库路径
# 生成可执行文件 ${CMAKE_PROJECT_NAME}指项目名 main_blas
add_executable(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/main_blas.c)
target_link_options(${PROJECT_NAME} PRIVATE "-mhybrid" "-Wl,-zmuldefs")
#set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-mhybrid -Wl,-zmuldefs") # 指定链接选项
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/utils/include) # 指定头文件路径
target_link_libraries(${PROJECT_NAME} swdnn_xu -lcblas -lswblas -lgfortran -lm -lm_slave) # 指定要链接的静态库
2、执行编译文件(./cm.sh)
#!/bin/sh
set -ex file=build rm -rf ${file} DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]})) # -DCMAKE_TOOLCHAIN_FILE=${DIR}/cmake/toolchain-sw_64.cmake
cmake . -B ${file} \
-DCMAKE_C_COMPILER=/usr/sw/mpi/mpi_20210219_SEA/bin/mpicc \
-DCMAKE_AR=/usr/sw/swgcc/swgcc710-tools-SEA-1307/usr/bin/sw9ar cd ${file}
make -j
3、编译器环境变量设置(不需要)
vim cmake/toolchain-sw_64.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR sw_64) set(CMAKE_C_COMPILER /usr/sw/mpi/mpi_20210219_SEA/bin/mpicc)
set(CMAKE_CXX_COMPILER /usr/sw/mpi/mpi_20210219_SEA/bin/mpicxx)
set(CMAKE_AR /usr/sw/swgcc/swgcc710-tools-SEA-1208/usr/bin/sw9ar)
set(MPI_C_COMPILER /usr/sw/mpi/mpi_20210219_SEA/bin/mpicc)
set(MPI_CXX_COMPILER /usr/sw/mpi/mpi_20210219_SEA/bin/mpicxx)
set(SW_C_COMPILER /usr/sw/swgcc/swgcc710-tools-SEA-1208/usr/bin/sw9gcc)
set(SW_CXX_COMPILER /usr/sw/swgcc/swgcc710-tools-SEA-1208/usr/bin/sw9g++)
~
2.2 Fortran语言程序
创建CMakeLists.txt文件(vim CMakeLists.txt)
简单版Cmake(FC=mpif90 cmake . -B build -DCMAKE_Fortran_COMPILER=/usr/local/bin/mpif90)
cmake_minimum_required(VERSION 3.21.4) # 声明使用CMAKE的最低版本要求
project(xu_main LANGUAGES Fortran) # 定义项目的名字 find_package(MPI REQUIRED) # 寻找 MPI
#include_directories(SYSTEM ${MPI_INCLUDE_PATH}) # 引入头文件目录 # 设置编译目标类型是release版还是debug版本
set(DEFAULT_BUILD_TYPE "Release") set(CMAKE_Fortran_FLAGS "-O2") # 设置编译器选项 # 添加工作目录下子目录src中的源文件到SRC变量
file(GLOB SRC ./funs9/*.f90 ${PROJECT_SOURCE_DIR}/funs9/*.f) # 生成可执行文件 ${CMAKE_PROJECT_NAME}指项目名 xu_main
add_executable(${CMAKE_PROJECT_NAME} ${SRC} )
2.3 命令简介
2.3.1 project
project命令用于指定cmake工程的名称,实际上,它还可以指定cmake工程的版本号(VERSION关键字)、简短的描述(DESCRIPTION关键字)、主页URL(HOMEPAGE_URL关键字)和编译工程使用的语言(LANGUAGES关键字)。
(1)参数project(<PROJECT_NAME> [VERSION <major>] [DESCRIPTION <project-description-string>] [HOMEPAGE_URL <url-string>] [LANGUAGES <language-name>])
PROJECT_NAME:将当前工程的名称赋值给PROJECT_NAME,同时${PROJECT_NAME}变量赋值为PROJECT_NAME。
VERSION:指定工程的版本号。
DESCRIPTION:对工程的文本描述。
HOMEPAGE_URL:指定工程的主页URL。
LANGUAGES选项:选择构建工程需要的编程语言。
(2)当定义了project()后,一些cmake自带变量会自动赋值
PROJECT_NAME:将当前工程的名称赋值给PROJECT_NAME。
PROJECT_SOURCE_DIR:当前工程的源码路径。
CMAKE_PROJECT_NAME:顶层工程的名称。例如当前调用的CMakeLists.txt位于顶层目录(可以理解为使用cmake命令首次调用的那个CMakeLists.txt),那么工程名还会赋值给CMAKE_PROJECT_NAME。
2.3.2 add_executable生成可执行文件
1、参数add_executable(<name> <EXCLUDE_FROM_ALL> <source1> <source2 ...>)
name:可执行目标文件的名字,在一个cmake工程中,这个名字必须全局唯一。
EXCLUDE_FROM_ALL:用于指定可执行目标是否会被构建,当该选项使用的时候,可执行目标不会被构建。
[source1] [source2 …]:构建可执行目标文件所需要的源文件。
2、EXCLUDE_FROM_ALL参数用法
project(test)
add_executable(test EXCLUDE_FROM_ALL test.f90)
// test加了EXCLUDE_FROM_ALL属性,在默认编译的时候,不会被编译,
// 如果要编译它,需要手动编译,比如make test指定编译名为test
make test
2.3.3 add_library编译出静态库和动态库
1、add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [source1 source2 ...])
STATIC、SHARED 和 MODULE 表示库文件的类型,分别表示静态库、动态库和可加载模块;
# 将SRCS编译为swdnn_xu这个静态链接库
add_library(swdnn_xu STATIC ${SRC} ${MASTER_SRC} ${SLAVE_SRC})
2.3.4 link_libraries 和 target_link_libraries 链接库
1、link_libraries(link_libraries 基本上被遗弃了,尽可能用 target_link_libraries)
link_libraries("/usr/sw/yyzlib/xMath-SACA/libswblas.a")
add_executable(${PROJECT_NAME} main.c)
2、target_link_libraries(<target> <PRIVATE | PUBLIC | INTERFACE> <item>...)
link_directories("/usr/sw/yyzlib/xMath-SACA") # 指定静态库路径
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} swzgemm_xu /usr/sw/yyzlib/xMath-SACA/libswblas.a) target_link_libraries(${PROJECT_NAME} libswzgemm_xu.a) #这些库名写法都可以。
target_link_libraries(${PROJECT_NAME} swzgemm_xu)
target_link_libraries(${PROJECT_NAME} -lswzgemm_xu)
【注】:调用link_directories必须在生成可执行文件之前调用,也就是在add_executable之前调用
target_link_libraries(PUBLIC target target1 target2)
target_link_libraries(PUBLIC target3 target target4)
//PUBLIC:表示target能够使用target1&target2库中内容,target3也能使用target1&target2库中内容;默认状态为PUBLIC。
target_link_libraries(PRIVATE target target1 target2)
target_link_libraries(PRIVATE target3 target target4)
//PRIVATE:表示target能够使用target1&target2库中内容,target3不能使用target1&target2中定义的内容,只能使用target中定义的内容。
target_link_libraries(INTERFACE target target1 target2)
target_link_libraries(INTERFACE target3 target target4)
//INTERFACE:表示target无法使用target1&target2库中内容,但是target3能使用target1&target2中内容。
3、link_libraries 和 target_link_libraries 区别
(1)link_libraries用在add_executable之前,target_link_libraries用在add_executable之后
(2)link_libraries用来链接静态库,target_link_libraries用来链接导入库,即按照header file + .lib + .dll方式隐式调用动态库的.lib库
(3)link_libraries 基本上被遗弃了,尽可能用 target_link_libraries
2.3.5 include_directories 和 target_include_directories引用头文件
1、include_directories([AFTER | BEFORE] [SYSTEM] [<dir1> <dir2> ...])
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/include) # 引入头文件目录
add_executable(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/main_blas.c)
默认情况下,指定的目录被追加到当前目录列表中。这个默认行为可以通过将CMAKE_INCLUDE_DIRECTORIES_BEFORE设置为ON来改变。通过显式使用AFTER或BEFORE,可以在appending和prepending之间进行选择,而不依赖于默认值。
如果给出了SYSTEM选项,编译器将被告知在某些平台上目录是系统包含目录。
2、target_include_directories(<target> [SYSTEM][AFTER|BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...][<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
add_executable(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/main_blas.c)
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/utils/include) # 指定头文件路径
3、区别
(1)include_directories:当前CMakeLists.txt的所有目标,以及之后添加的所有子目录的目标添加头文件搜索路径。因此,慎用include_directories,因为会影响全局target。
(2)target_include_directories:指定目标包含的头文件路径。如果想为不同目标设置不同的搜索路径,那么用target_include_directories更合适。
2.3.6 add_subdirectory添加子目录
1、语法:add_subdirectory (source_dir [binary_dir] [EXCLUDE_FROM_ALL])
2、作用:添加一个子目录并构建该子目录,告诉CMAKE我还有其它子目录的CMakeList.txt需要编译。
3、参数
(1)source_dir:必选参数。该参数指定一个子目录,子目录下应该包含CMakeLists.txt文件和代码文件。子目录可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前目录的一个相对路径。
(2)binary_dir:可选参数。该参数指定一个目录,用于存放输出文件。可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前输出目录的一个相对路径。如果该参数没有指定,则默认的输出目录使用source_dir。
(3)EXCLUDE_FROM_ALL:可选参数。当指定了该参数,则子目录下的目标不会被父目录下的目标文件包含进去,父目录的CMakeLists.txt不会构建子目录的目标文件,必须在子目录下显式去构建。例外情况:当父目录的目标依赖于子目录的目标,则子目录的目标仍然会被构建出来以满足依赖关系(例如使用了target_link_libraries)。
2.3.7 target_compile_options设置目标的编译选项
add_executable(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/main_blas.c)
target_compile_options(${PROJECT_NAME} PRIVATE "-O3")
2.3.8 将目标文件保存到指定目录下
1、设置输出目录
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) # 动态库
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/static) # 静态库
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) # 执行文件
2、指向性保存
同样是指定输出目录,但是不同的动态库文件指定不同的输出目录。(静态库和二进制执行文件也是同理)。目标文件可以大致分为三种类型:二进制执行文件、动态库、静态库。保存不同目标文件所用到的属性不一样。具体分类如下。
RUNTIME_OUTPUT_DIRECTORY:二进制执行文件
LIBRARY_OUTPUT_DIRECTORY:动态库
ARCHIVE_OUTPUT_DIRECTORY:静态库
add_library(swdnn_xu STATIC ${SRC} ${MASTER_SRC} ${SLAVE_SRC})
set_target_properties(swdnn_xu PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/utils/libs)
2.3.9 设置目标的链接选项
target_compile_options(${PROJECT_NAME} PRIVATE "-mhybrid -Wl,-zmuldefs")
target_link_options(${PROJECT_NAME} PRIVATE "-mhybrid" "-Wl,-zmuldefs")
aaaa
用【Makefile】或【Cmake】编译【C/Fortran】程序文件的更多相关文章
- Windows下使用mingw+cmake编译C/C++程序
按照正常流程安装好mingw和cmake后,仍然是无法直接使用cmake编译处MakeFile文件的,我们需要在CMakeLists.txt中做一些配置. 首先,在PROJECT之前,设置: SET( ...
- vscode, cmake编译多个C++文件
目的是利用vscode及相关插件编译多个C++文件. 我已经装好cmake和mingw并且将它们的路径添加到系统变量path中了. vscode装上如下几个插件: 点击vscode左上角 文件-& ...
- 在ubunt14.04(linux)下利用cmake编译运行opencv程序
今天在电脑上安装好了opencv环境,迫不及待的想写个程序来测试一下.但是在windows下我们用vs等集成开发工具.可是在linux下我们应该怎么办呢? 这里我们用了opencv推荐的cmake来编 ...
- [转]一个CMake编译问题的解决过程
问题的提出 公司的一个power-pc平台的产品,有个协议进行了修改,过程中出现了比较奇怪的情况.直接将修改后的动态库下载到设备上(原始设备是有文件系统和其他的依赖文件的,相当于部分更新应用),设备和 ...
- Ubuntu系统---编译opencv程序的几种方式g++、Makefile、Cmake
Ubuntu系统---编译opencv程序的几种方式g++.Makefile.Cmake 先建立一个工程(一个文件夹),写好xxx.cpp文件,可以是多个: //----------opencv.cp ...
- Linux 编译工具 gcc/g++、Make/Makefile、CMake/CMakeLists.txt、qmake
前言 编译器的主要工作流程: 源码(Source Code)>> 预处理器(Preprocessor)>> 编译器(Compiler)>> 汇编程序(Assembl ...
- Cmake知识----编写CMakeLists.txt文件编译C/C++程序
1.CMake编译原理 CMake是一种跨平台编译工具,比make更为高级,使用起来要方便得多.CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt ...
- linux 下 VSCODE 使用CMake编译STM32程序
项目在做什么 项目地址 本项目是为了研究MCU在linux下开发而做的 --build 存放cmake编译生成的文件 --cmake 存放cmake编译时会用到的文件,比如工具链检查.编译选项等 -- ...
- cmake编译c++程序
当在Linux系统下编写程序时候,如果没有类似于visual studio.vs code等IDE(集成开发环境)时,如何编译.运行程序呢?一种方法是编写makefile文件,用makefile文件管 ...
- Cmake知识----编写CMakeLists.txt文件编译C/C++程序(转)
1.CMake编译原理 CMake是一种跨平台编译工具,比make更为高级,使用起来要方便得多.CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt ...
随机推荐
- Seaborn分布数据可视化---箱型分布图
箱型分布图 boxplot() sns.boxplot( x=None, y=None, hue=None, data=None, order=None, hue_order=None, orient ...
- 【FAQ】HarmonyOS SDK 闭源开放能力 —IAP Kit
1.问题描述 根据https://developer.huawei.com/consumer/cn/doc/harmonyos-references/iap-data-model-0000001736 ...
- HarmonyOS实现静态与动态数据可视化图表
一. 样例介绍 本篇Codelab基于switch组件和chart组件,实现线形图.占比图.柱状图,并通过switch切换chart组件数据的动静态显示.要求实现以下功能: 1. 实现静态数据可视化 ...
- k8s 深入篇———— pod 实战[六]
前言 pod 实战一下,主要是一些例子. 正文 例子一 pod 实例的选择: NodeSelector:是一个供用户将 Pod 与 Node 进行绑定的字段 NodeName:一旦 Pod 的这个字段 ...
- locust分布式压测的Step Load及no web模式下的报表自动生成
Running Locust in Step Load ModeIf you want to monitor your service performance with different user ...
- 常用注解使用总结系列: @Order 注解
@Order 注解 @Order注解主要用来控制配置类的加载顺序示例代码: package com.runlion.tms.admin.constant; public class AService ...
- vue登录3D效果
实现的效果 登录动态效果很炫酷,话不多说直接上代码: 组件template <template> <div class="entrance"> <di ...
- 用百度和神策做埋点为何pv差异很大?
近期ClkLog收到一个客户反馈说我们与百度统计的PV数据差异很大.为了验证问题,开发进行了一次对页面浏览量统计的测试.针对同一个IP同一个时间的页面浏览量统计发现,百度的统计数据只有一条,而ClkL ...
- eclipse 汉化语言包/中文补丁/简中设置/中英互换
eclipse 汉化语言包/中文补丁/简中设置/中英互换 汉化很简单,使用eclipse内置的软件下载就可以,不需要下载压缩包 官方的说明 Open the install wizard with ' ...
- SAE助力「海底小纵队学英语」全面拥抱Serverless,节省25%以上成本
简介: 阿里云Serveless应用引擎SAE 具备免运维IaaS.按需使用.按量计费.低门槛服务应用上云,并且支持多种语言和高弹性能力等特点,刚好完美解决了客户长期以来运维复杂.资源利用率不高.开发 ...