Ubuntu(18.04) 编译运行C/C++的方式汇总--全网相对较全的汇总贴系列(一)

简介

相信大家目前使用Unix系列(Centos,Ubuntu.etc)的平台越来越多,如何编译运行C/C++成为了踏入该系列平台的第一步,最近抽空总结了目前主流的几种编译方式。总结来说大概可以分为:CMakeLists,MakeFile,g++ 还有部分使用IDE如Eclipse或者Qtcreator,都是目前ubuntu下相对较流行的平台。当然VScode,CLion,Pycharm,也可以,不过前者归结于还是代码归类软件,编译还是使用的CMakeLists或者其他方式,下面分别介绍四种编译运行方式,CMakeLists,MakeFile,g++,Qtcreator和Eclipse下编译。

方式一: CMakeLists 方式(官网手把手教程)下面介绍官网七步走,一步一步走上人生巅峰

Step1: 初入CMakeLists

初入第一步:上手玩一把

最简单的方式只需要两行即可,一行说明工程名,一行说明执行对象如下图:

1,先创建一个文件夹,名字随便这里选择Tutorial
$ mkdir Tutorial
2,touch ,gedit or vim/vi CMakeLists.txt,并写入下面两行。注意: CMakeLists.txt无所谓大小写。
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
add_executable(Tutorial tutorial.cpp)

或者: 可以使用如下版本,主动添加运行源文件的目录:

#注意大小写都可以,Cmake不分大小写
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
add_executable(Tutorial ${DIR_SRCS})

注意:add_executable添加一个可编译的目标到工程里面。

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               source1 [source2 ...])
name: 工程所要构建的目标名称
WIN32/Win64等: 目标app运行的平台
source1:构建目标App的源文件 
3,在创建CMakeLists.txt文件夹添加一个cxx文件,这里用官方的简单例子,实现求平方,使用CPP文件。
1,vim tutorial.cpp 写入如下代码
// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
  double inputValue = atof(argv[1]);
  double outputValue = sqrt(inputValue);
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}
4,按照如下编译运行。

注意build 最好和CMakeLists.txt在同一目录,cmake 是需要在源文件这一层目录进行编译的。下列代码…代表上一层目录,若不熟悉可恶补一下unix的文件结构和常用shell 命令。

$ mkdir build
$ cmake ..
$ make
$./Tutorial
初入第二步:添加版本号和头文件
1,修改CMakeLists.txt 添加版本号
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
 
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  )
 
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
 
# add the executable
add_executable(Tutorial tutorial.cpp)

注意 :configure_file 会拷贝一个文件到另一个目录并修改文件内容,其函数参数定义如下:

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
               
cmake会自动定义两个变量
${PROJECT_SOURCE_DIR}:  当前工程最上层的目录
${PROJECT_BINARY_DIR}: 当前工程的构建目录(文中即为build目录)

2,由于文中例子所使用的源文件是:TutorialConfig.h,手动创建一个如下,注意目录放到和CMakeLists.txt同一级即可,后面会进行目录分级。
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
3,由于使用了版本号我们可以让代码自己输出,按照官网例子修改代码如下:
// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
 
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"%s Version %d.%d\n",
            argv[0],
            Tutorial_VERSION_MAJOR,
            Tutorial_VERSION_MINOR);
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
  double inputValue = atof(argv[1]);
  double outputValue = sqrt(inputValue);
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}
4,最后一步,基本都一样
$ mkdir build
$ cmake ..
$ make
$./Tutorial
显示如下即可:
./Tutorial Version 1.0
Usage: ./Tutorial number

Step2: 添加库到CMakeLists

1. 现在我们添加一个库到我们的CMakeLists.参照官网添加一个求平方的函数,用来替换编译器自带的函数。这里把这个lib放入子文件夹MathFunctions,并且在目录下新建一个CMakeLists.txt文件,添加如下。
 aux_source_directory(. DIR_MATH_SRCS)
add_library(MathFunctions ${DIR_MATH_SRCS})

源代码如下:

#include "MathFunctions.h"
#include <stdio.h>

// a hack square root calculation using simple operations
double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }

  double result;
  double delta;
  result = x;

  // do ten iterations
  int i;
  for (i = 0; i < 10; ++i) {
    if (result <= 0) {
      result = 0.1;
    }
    delta = x - (result * result);
    result = result + 0.5 * delta / result;
    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
  }
  return result;
}

这里还需要一个头文件,头文件(MathFunctions.h)内容如下:

double mysqrt(double x);

目前目录结构如下:

├── CMakeLists.txt
├── MathFunctions
│   ├── CMakeLists.txt
│   ├── MathFunctions.h
│   └── mysqrt.cpp
├── TutorialConfig.h.in
└── tutorial.cpp

现在我们来更改最顶层的CMakeLists.txt

  1. 添加add_subdirectory (MathFunctions) 保证新加的library在工程中被编译
  2. 添加新的头文件路径MathFunctions/MathFunctions.h
  3. 添加新的library到executable
    新增加CMakeLists.txt如下
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions) 
 
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial MathFunctions)

最后修改tutorial.cpp如下:

// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
#include "MathFunctions.h" 
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"%s Version %d.%d\n",
            argv[0],
            Tutorial_VERSION_MAJOR,
            Tutorial_VERSION_MINOR);
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
  double inputValue = atof(argv[1]);
  double outputValue = mysqrt(inputValue);
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}
2,下面把库做成可以选择的形式

首先我们在最顶层的CMakeLists.txt加入一个option选项

# should we use our own math functions?
option (USE_MYMATH 
        "Use tutorial provided math implementation" ON) 

这个会在你运行cmake的时候GUI显示.用户可以根据需要来选择。下一个改变是添加是否编译和链接MathFuntions的库。
CMakeLists.txt更改如下。

# add the MathFunctions library?
#
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
  add_subdirectory (MathFunctions)
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
 
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial  ${EXTRA_LIBS})

其中使用到变量EXTRA_LIBS来收集后面可能用到的库,这样主要便于多个库的时候。
此时更新后的新代码tutorial.cpp如下,主要用宏定义进行区分:

// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "TutorialConfig.h"
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
 
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"%s Version %d.%d\n", argv[0],
            Tutorial_VERSION_MAJOR,
            Tutorial_VERSION_MINOR);
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
 
  double inputValue = atof(argv[1]);
 
#ifdef USE_MYMATH
  double outputValue = mysqrt(inputValue);
#else
  double outputValue = sqrt(inputValue);
#endif
 
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}

在源代码我们也可以直接使用USE_MYMATH只需要在TutorialConfig.h.in添加如下即可:

#cmakedefine USE_MYMATH

运行结果如下:

$ ./Tutorial 22
Computing sqrt of 22 to be 11.5
Computing sqrt of 22 to be 6.70652
Computing sqrt of 22 to be 4.99346
Computing sqrt of 22 to be 4.69961
Computing sqrt of 22 to be 4.69042
Computing sqrt of 22 to be 4.69042
Computing sqrt of 22 to be 4.69042
Computing sqrt of 22 to be 4.69042
Computing sqrt of 22 to be 4.69042
Computing sqrt of 22 to be 4.69042
The square root of 22 is 4.69042

Step3: 添加安装测试到CMakeLists

1,接下来我们加入install规则和testing支持到我们工程。对于install规则我们直接如下设置即可,在这里继续使用MathFunctions作为例子。在MathFunctions的CMakeLists.txt里加入如下即可。
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

对于应用程序我们还需要把下面两行加入到最顶层的CMakeLists.txt

# add the install targets
install (TARGETS Tutorial DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"        
         DESTINATION include)

这一步,install就配置完毕,可以进行编译链接,通过make install 即可,系统会自动安装对应的头文件,库和可执行文件。其中CMake变量CMAKE_INSTALL_PREFIX用来指定这些文件需要安装到哪个根目录。
添加测试用例,只需要在最上层的CMakeList.txt文件添加一系列的基础测试来验证应用程序是否正常工作,代码如下:

include(CTest)

# does the application run
add_test (TutorialRuns Tutorial 25)
# does it sqrt of 25
add_test (TutorialComp25 Tutorial 25)
set_tests_properties (TutorialComp25 PROPERTIES PASS_REGULAR_EXPRESSION "25 is 5")
# does it handle negative numbers
add_test (TutorialNegative Tutorial -25)
set_tests_properties (TutorialNegative PROPERTIES PASS_REGULAR_EXPRESSION "-25 is 0")
# does it handle small numbers
add_test (TutorialSmall Tutorial 0.0001)
set_tests_properties (TutorialSmall PROPERTIES PASS_REGULAR_EXPRESSION "0.0001 is 0.01")
# does the usage message work?
add_test (TutorialUsage Tutorial)
set_tests_properties (TutorialUsage PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number")

编译完毕后即可使用CTest来进行测试,如果你需要使用大量的测试,最好使用如下宏定义来精简代码。

#define a macro to simplify adding tests, then use it
macro (do_test arg result)
  add_test (TutorialComp${arg} Tutorial ${arg})
  set_tests_properties (TutorialComp${arg}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)
 
# do a bunch of result based tests
do_test (25 "25 is 5")
do_test (-25 "-25 is 0")

Step4: 添加系统相关检测(Introspection)到CMakeLists

1,这一步主要用于检测某些依赖,比如官网例子,假设不是所有平台都有log或者exp这个函数,这样需要提前检测,并做好planB也就是代替代码。首先通过CheckFunctionExists.cmake来测试一下是否有这些函数,在最上层的CMakeList文件中添加如下内容。
# does this system provide the log and exp functions?
include (CheckFunctionExists)
check_function_exists (log HAVE_LOG)
check_function_exists (exp HAVE_EXP)
2,然后我们更改TutorialConfig.h添加如下两行代码。
// does the platform provide exp and log functions?
#cmakedefine HAVE_LOG
#cmakedefine HAVE_EXP
3,最后要注意测试需要在配置TutorialConfig.h前完成,这里我们更改mysqrt,如果检测通过就使用log。
// if we have both log and exp then use them
#if defined (HAVE_LOG) && defined (HAVE_EXP)
  result = exp(log(x)*0.5);
#else // otherwise use an iterative approach
  . . .

Step5: 添加生成文件和生成器到CMakeLists

1,在这个部分我们来学如何添加一个生成的源文件到编译的进程中,在这里我们演示提前计算好的平分根加入到代码编译进程中。这里我们需要一个新的代码,用来生成这个表格,代码位置放置到MathFunctions这个文件夹中,(MakeTable.cpp)代码如下:
// A simple program that builds a sqrt table 
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
int main (int argc, char *argv[])
{
  int i;
  double result;
 
  // make sure we have enough arguments
  if (argc < 2)
    {
    return 1;
    }
  
  // open the output file
  FILE *fout = fopen(argv[1],"w");
  if (!fout)
    {
    return 1;
    }
  
  // create a source file with a table of square roots
  fprintf(fout,"double sqrtTable[] = {\n");
  for (i = 0; i < 10; ++i)
    {
    result = sqrt(static_cast<double>(i));
    fprintf(fout,"%g,\n",result);
    }
 
  // close the table with a zero
  fprintf(fout,"0};\n");
  fclose(fout);
  return 0;
}

注意:这里需要传递正确的文件名作为应用的变量才行。

2,接下来一步在MathFunctions目录下的CMakeLists.txt里添加如下代码,让该程序正确运行。
# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)
 
# add the command to generate the source code
add_custom_command (
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  DEPENDS MakeTable
  )
 
# add the binary tree directory to the search path for 
# include files
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
 
# add the main library
add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h  )

说明:

  1. 添加可执行的MakeTable
  2. 添加一个用户命令来生成这个表
  3. 把生成的Table.h添加到环境使CMake知道
  4. 最后编译mysqrt.cpp需要依赖Table.h这个库
3,最后更改最顶层的CMakeLists.txt如下:
cmake_minimum_required (VERSION 2.6)
project (Tutorial)
include(CTest)
 
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
 
# does this system provide the log and exp functions?
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
 
check_function_exists (log HAVE_LOG)
check_function_exists (exp HAVE_EXP)
 
# should we use our own math functions
option(USE_MYMATH 
  "Use tutorial provided math implementation" ON)
 
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  )
 
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories ("${PROJECT_BINARY_DIR}")
 
# add the MathFunctions library?
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
  add_subdirectory (MathFunctions)
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
 
# add the executable
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial  ${EXTRA_LIBS})
 
# add the install targets
install (TARGETS Tutorial DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"        
         DESTINATION include)
 
# does the application run
add_test (TutorialRuns Tutorial 25)
 
# does the usage message work?
add_test (TutorialUsage Tutorial)
set_tests_properties (TutorialUsage
  PROPERTIES 
  PASS_REGULAR_EXPRESSION "Usage:.*number"
  )
 
 
#define a macro to simplify adding tests
macro (do_test arg result)
  add_test (TutorialComp${arg} Tutorial ${arg})
  set_tests_properties (TutorialComp${arg}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
    )
endmacro (do_test)
 
# do a bunch of result based tests
do_test (4 "4 is 2")
do_test (9 "9 is 3")
do_test (5 "5 is 2.236")
do_test (7 "7 is 2.645")
do_test (25 "25 is 5")
do_test (-25 "-25 is 0")
do_test (0.0001 "0.0001 is 0.01")

Step6: 添加构建安装器到CMakeLists

最后我们希望把自己的代码或者工程发布给其他人用,这个时候我们希望提供不同平台的二进制文件和源文件.这里与我们之前在第三步中的安装有一些不同,那时我们安装我们已经从源代码构建出来的二进制文件.在这个例子中,我们将构建一个安装包,它支持二进制安装,以及cygwin、 debian、RPMs等工具的包管理特性.为了实现这个功能,我们会使用CPack来创建平台相关的安装包.我们需要在最顶层的CMakeLists.txt文件中的最后添加代码,更改后如下:

# build a CPack driven installer package
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE  
     "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set (CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
include (CPack)

接下来两步就是进行打包如下:

#针对二进制
cpack --config CPackConfig.cmake 
#针对源文件
cpack --config CPackSourceConfig.cmake

Step7: 添加支持Dashboard到CMakeLists

最后添加支持到Dashboard也非常简单,我们只需要添加测试模块并提交到dashborad即可。为了使用测试模块如上所用需要添加如下的代码到最顶层的CMakeLists.txt.

# enable dashboard scripting
include (CTest)

我们还需要添加一个 CTestConfig.cmake来指定工程名。内容如下:

set (CTEST_PROJECT_NAME "Tutorial")

最后:

写了三天终于写完了,边写边测试,有的地方有错误,欢迎指正。

参考链接:
[1]: https://cmake.org/cmake-tutorial/
[2]: https://blog.csdn.net/fengzhongluoleidehua/article/details/79809756
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值