Skip to content

Commit

Permalink
feat: add makefile generator
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-soft committed Jan 9, 2021
1 parent 18b03a9 commit 0c05220
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 2 deletions.
111 changes: 111 additions & 0 deletions generators/makefile/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
const fs = require('fs')
const path = require('path')
const chalk = require('chalk')
const { pascalCase } = require('pascal-case')
const { format } = require('../../lib/utils')

const sourceFileExt = ['.c', 'cpp']
const cmakeFile = 'CMakeLists.txt'
const xmakeFile = 'xmake.lua'

class Generator {
constructor(name, options) {
this.name = name
this.cwd = options.cwd
this.templatesDir = path.join(__dirname, 'templates')
this.sourceDir = path.join(this.cwd, 'src')
}

writeFile(file, content) {
console.log(chalk.green('writing'), path.relative(this.cwd, file))
return fs.writeFileSync(file, content)
}

readTemplateFile(name) {
const templateFile = path.join(this.templatesDir, name)
return fs.readFileSync(templateFile, { encoding: 'utf-8' })
}

generateFile(input, output) {
this.writeFile(output, this.readTemplateFile(input))
}

generateCMakeFileForDirectory(dir, moduleNames, addSource = true) {
let dirs = []
const files = []
const dirPath = path.resolve(this.cwd, dir)

const id = dir.replace(/src[\\\/]/, '')
const moduleName = `App${pascalCase(id)}`
const varName = `DIR_${id.replace(/[^a-zA-Z]/g, '_').toUpperCase()}_SRC`

fs.readdirSync(dirPath).forEach((name) => {
if (fs.statSync(path.join(dirPath, name)).isDirectory()) {
dirs.push(name)
} else if (sourceFileExt.includes(path.parse(name).ext)) {
files.push(name)
}
})

let total = files.length

if (dirs.length < 1 && total < 1) {
return 0
}

dirs = dirs.filter((subDir) => {
const count = this.generateCMakeFileForDirectory(path.join(dir, subDir), moduleNames)
total += count
return count > 0
})

if (total > 0) {
const lines = dirs.map((name) => `add_subdirectory(${name})`)

if (addSource && files.length > 0) {
lines.push(`aux_source_directory(. ${varName})`)
lines.push(`add_library(${moduleName} \${${varName}})`)
}
if (dir !== 'src') {
moduleNames.push(moduleName)
}
this.writeFile(path.join(dirPath, cmakeFile), `${lines.join('\n')}\n`)
}
return total
}

generateCMakeFiles() {
const modules = []
const file = `${cmakeFile}.in`

if (!fs.existsSync(this.sourceDir)) {
console.log(chalk.yellow('warning:'), '\'src\' directory does not exist')
return
}

this.generateCMakeFileForDirectory('src', modules, false)
this.writeFile(
path.resolve(this.cwd, file),
format(
this.readTemplateFile(file),
{ modules: modules.map((name) => ` ${name}`).join('\n') },
['\\[\\[', '\\]\\]']
)
)
}

generateXMakeFiles() {
const file = `${xmakeFile}.in`
this.generateFile(file, path.resolve(this.cwd, file))
}

generate() {
if (this.name === 'xmake') {
this.generateXMakeFiles()
} else {
this.generateCMakeFiles()
}
}
}

module.exports = Generator
35 changes: 35 additions & 0 deletions generators/makefile/templates/CMakeLists.txt.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 2.8)
project(app)

set(app_VERSION {{version}})

configure_file(
"${PROJECT_SOURCE_DIR}/include/config.h.in"
"${PROJECT_SOURCE_DIR}/include/config.h"
)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/app")

if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS")
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_UNICODE)
else()
set(CMAKE_C_FLAGS "-Wall")
endif(WIN32)

link_directories("${PROJECT_SOURCE_DIR}/vendor/lib")
include_directories(
"${PROJECT_SOURCE_DIR}/include"
"${PROJECT_SOURCE_DIR}/src/lib"
"${PROJECT_SOURCE_DIR}/vendor/include"
)

aux_source_directory(src DIR_SRC)
add_subdirectory(src)
add_executable(app ${DIR_SRC})

target_link_libraries(
app
[[modules]]
{{libs | join_with_space}}
)
14 changes: 14 additions & 0 deletions generators/makefile/templates/xmake.lua.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
set_project("app")
set_version("{{version}}")
set_warnings("all")
add_rules("mode.debug", "mode.release")
add_configfiles("include/config.h.in", { prefix = "APP" })
add_linkdirs("vendor/lib")
add_includedirs("include", "src/lib", "vendor/include")
add_rpathdirs("./lib")
add_links({{libs | escape | join}})

target("app")
set_targetdir("app/")
set_kind("binary")
add_files("src/**.c")
4 changes: 2 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ function flat(obj) {
return props
}

function format(template, data) {
function format(template, data, brackets = ['{{', '}}']) {
let output = template
const props = flat(data)
const keys = Object.keys(props)
const regs = keys.map(k => new RegExp(`{{${k}}}`, 'g'))
const regs = keys.map(k => new RegExp(`${brackets[0]}${k}${brackets[1]}`, 'g'))

regs.forEach((reg, i) => {
output = output.replace(reg, props[keys[i]])
Expand Down

0 comments on commit 0c05220

Please sign in to comment.