如何以较少的样板形式编写我的CMakeLists.txt?

时间:2017-09-13 09:05:34

标签: cmake

在下面的例子中,我发现模式set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} xxx")非常模板。 include_directories("${CMAKE_CURRENT_SOURCE_DIR}/...")的情况相同。

是否可以简化写作?

cmake_minimum_required(VERSION 3.6)

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CROSS_COMPILE arm-none-eabi- )

set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc.exe)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++.exe)
set(CMAKE_ASM_COMPILER ${CROSS_COMPILE}as.exe)

set(CMAKR_C_FLAGS "${CMAKR_C_FLAGS} -mlittle-endian")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-m4")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfpv4")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mabi=aapcs")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsigned-char")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmessage-length=0")

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nosys.specs")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mthumb")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mcpu=cortex-m4")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g" CACHE INTERNAL "")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

project("project" C)

add_definitions(-DBLE_STACK_SUPPORT_REQD)
add_definitions(-DS132)
add_definitions(-DNRF_LOG_USES_RTT=1)
add_definitions(-DSWI_DISABLE0)
add_definitions(-DSOFTDEVICE_PRESENT)
add_definitions(-DNRF52)
add_definitions(-DAC_ACC_RAW_SAMPLING_FREQUENCY_25Hz)
add_definitions(-DDEBUG)
add_definitions(-DENABLE_DEBUG_LOG_SUPPORT)
add_definitions(-DNRF_LOG_USES_COLORS=0)

include_directories("${CMAKE_CURRENT_SOURCE_DIR}/foo")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/bar")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/baz")

list(
    APPEND src
    ${CMAKE_CURRENT_SOURCE_DIR}/foo/foo.c
    ${CMAKE_CURRENT_SOURCE_DIR}/bar/bar.c
    ${CMAKE_CURRENT_SOURCE_DIR}/baz/baz.c
)

add_executable(
    project
    ${src}
)

2 个答案:

答案 0 :(得分:2)

中的所有值都存储为字符串,因此您可以更轻松地set CMAKE_C_FLAGSset(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \ -mlittle-endian \ -mcpu=cortex-m4 \ -mthumb \ -mfpu=vfpv4 \ -g3 \ -Wall \ -Werror \ -mabi=aapcs \ -O2 \ -std=c99 \ -fsigned-char \ -ffunction-sections \ -fdata-sections \ -fmessage-length=0 \ ") 标记,如下所示:

CMAKE_C_FLAGS

上面的代码会将\变量的值替换为上面定义的新字符串。要检查结果,您始终可以使用message命令。

注意:上面所有行末尾的include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/foo" "${CMAKE_CURRENT_SOURCE_DIR}/bar" "${CMAKE_CURRENT_SOURCE_DIR}/baz" ) 个字符用于续行。您可以在CMake documentation

中详细了解相关信息

同样可以应用于include_directories命令但使用lists

;

中的列表也是字符串,但它们的元素由const Docker = require('dockerode'); const docker = new Docker({ socketPath: '/var/run/docker.sock' }); // CONSTRUCTOR function SearchUtils() { this.listContainersPromise = docker.listContainers({all: true}); this.scraperListId = []; } // "METHODS" SearchUtils.prototype.run = function() { this.getScraperContainersListPromise() .then((containers) => { for (let i = 0; i < containers.length; i++) { if (containers[i].Names.toString().indexOf("scraper") !== -1) { this.addToScraperList(containers[i].Id, "wait"); } } }, (err)=>{console.log(err)}) .then(()=>{ this.checkReadyScraper(); },(err)=>{console.log(err)}) .then(() => { this.scrap(); }, (err)=>{console.log(err)}); }; SearchUtils.prototype.checkReadyScraper = function() { for (let i = 0; i < this.scraperListId.length; i++) { this.exec("getStatus", this.scraperListId[i].id); } }; SearchUtils.prototype.getScraperContainersListPromise = function() { return this.listContainersPromise; // <- Not working }; SearchUtils.prototype.exec = function(type, containerId){ let container = docker.getContainer(containerId); if (type === "getStatus"){ this.runExec(container, 'cat /home/immobot/status'); } else if (type === "scrap") { this.runExec(container, 'torify scrapy crawl seloger -o seloger.json'); } }; SearchUtils.prototype.scrap = function() { let localRdyScraperList = []; for (let i = 0; i < this.scraperListId.length; i++) { if(this.scraperListId[i].status.toString('utf8').indexOf("ready") !== -1){ localRdyScraperList.push(this.scraperListId[i].id); } } console.log("test de localRdyScraperList : "+localRdyScraperList); // this.exec("scrap", this.scraperListId[i].id); }; SearchUtils.prototype.addToScraperList = function(containerId,status) { this.scraperListId.push({id: containerId, status: status}); }; SearchUtils.prototype.getScraperList = function() { return this.scraperListId; }; SearchUtils.prototype.getScraperList = function() { return this.scraperListId; }; SearchUtils.prototype.runExec = function (container, cmd) { let options = { Cmd: [ '/bin/bash', '-c', cmd ], AttachStdout: true, AttachStderr: true }; container.exec(options, (err, exec) => { if (err) return; exec.start((err, stream) => { if (err){ console.log("error : "+err); return; } // container.modem.demuxStream(stream, process.stdout, process.stderr) if (cmd === "cat /home/immobot/status"){ let newStream = require('stream'); let logStream = new newStream.PassThrough(); logStream.on('data', (chunk) => { // console.log(chunk.toString('utf8')); if (chunk.toString('utf8').indexOf("ready") !== -1){ console.log("CONTAINER READY !!"); //EDIT CONTAINER STATUS IN SCRAPERLIST TO READY this.changeStatusToReady(container.id); } }); container.modem.demuxStream(stream, logStream, process.stderr); } else if (cmd === "torify scrapy crawl seloger -o seloger.json"){ console.log("on lance le scrape sur un des scraper rdy"); container.modem.demuxStream(stream, process.stdout, process.stderr) } // container.modem.demuxStream(stream, logStream, process.stderr); exec.inspect(function(err, data) { if (err){ console.log("error : "+err); return; } }); }); }); }; SearchUtils.prototype.changeStatusToReady = function (containerId){ for (let i = 0; i < this.scraperListId.length; i++) { if(this.scraperListId[i].id === containerId){ this.scraperListId[i].status = "ready"; } } // console.log(this.getScraperList()); }; module.exports = SearchUtils; 个字符分隔。指定多个参数时,它们将作为列表连接。

答案 1 :(得分:2)

首先,您的大多数CMakeLists.txt更适合工具链文件

关于你的问题:

编译标志

可以通过add_compile_options()添加编译标记:

add_compile_options(
    -mlittle-endian
    -mcpu=cortex-m4
    -mthumb
    ...
)

或者,您可以执行Akira suggested

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
    -mlittle-endian \
    -mcpu=cortex-m4 \
    -mthumb \
    ... \
")

不幸的是,你不能list(APPEND...),因为CMAKE_C_FLAGS是字符串而不是列表。

如果您需要传递复合选项,例如--section .text=FOO,请使用后一种方法。有关详细信息,请参阅此问题:Pass compound compiler options using cmake

包含目录

include_directories()可以有多个参数,例如:

include_directories(
    foo
    bar
    baz
)

注意,您无需明确指定${CMAKE_CURRENT_SOURCE_DIR},因为:

  

相对路径被解释为相对于当前源目录。

对于更复杂的项目,请考虑target_include_directories()作为替代方案。

<强>杂

  1. 您不需要将所有内容都放在引号中。
  2. 您无需明确指定${CMAKE_CURRENT_SOURCE_DIR}。大多数命令将相对路径解释为相对于当前源目录。
  3. add_definitions()也接受多个参数。